egl_dri2.c revision fef5d14494ff19ea302e247ba593e189a8ab62bd
1/* 2 * Copyright © 2010 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Kristian Høgsberg <krh@bitplanet.net> 26 */ 27 28#include <stdlib.h> 29#include <string.h> 30#include <stdio.h> 31#include <limits.h> 32#include <dlfcn.h> 33#include <fcntl.h> 34#include <errno.h> 35#include <unistd.h> 36#include <xf86drm.h> 37#include <GL/gl.h> 38#include <GL/internal/dri_interface.h> 39#include <xcb/xcb.h> 40#include <xcb/dri2.h> 41#include <xcb/xfixes.h> 42#include <X11/Xlib-xcb.h> 43#include <sys/types.h> 44#include <sys/stat.h> 45 46#ifdef HAVE_LIBUDEV 47#include <libudev.h> 48#endif 49 50#include "eglconfig.h" 51#include "eglcontext.h" 52#include "egldisplay.h" 53#include "egldriver.h" 54#include "eglcurrent.h" 55#include "egllog.h" 56#include "eglsurface.h" 57#include "eglimage.h" 58 59#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 60 61struct dri2_egl_driver 62{ 63 _EGLDriver base; 64 65 _EGLProc (*get_proc_address)(const char *procname); 66 void (*glFlush)(void); 67}; 68 69struct dri2_egl_display 70{ 71 xcb_connection_t *conn; 72 int dri2_major; 73 int dri2_minor; 74 __DRIscreen *dri_screen; 75 const __DRIconfig **driver_configs; 76 void *driver; 77 __DRIcoreExtension *core; 78 __DRIdri2Extension *dri2; 79 __DRI2flushExtension *flush; 80 __DRItexBufferExtension *tex_buffer; 81 __DRIimageExtension *image; 82 int fd; 83 84 char *device_name; 85 char *driver_name; 86 87 __DRIdri2LoaderExtension loader_extension; 88 const __DRIextension *extensions[3]; 89}; 90 91struct dri2_egl_context 92{ 93 _EGLContext base; 94 __DRIcontext *dri_context; 95}; 96 97struct dri2_egl_surface 98{ 99 _EGLSurface base; 100 __DRIdrawable *dri_drawable; 101 xcb_drawable_t drawable; 102 __DRIbuffer buffers[5]; 103 int buffer_count; 104 xcb_xfixes_region_t region; 105 int have_fake_front; 106 int swap_interval; 107}; 108 109struct dri2_egl_config 110{ 111 _EGLConfig base; 112 const __DRIconfig *dri_config; 113}; 114 115struct dri2_egl_image 116{ 117 _EGLImage base; 118 __DRIimage *dri_image; 119}; 120 121/* standard typecasts */ 122_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) 123_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) 124 125static const __DRIuseInvalidateExtension use_invalidate = { 126 { __DRI_USE_INVALIDATE, 1 } 127}; 128 129EGLint dri2_to_egl_attribute_map[] = { 130 0, 131 EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */ 132 EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */ 133 EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */ 134 EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */ 135 EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */ 136 EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */ 137 EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */ 138 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */ 139 EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */ 140 EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */ 141 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */ 142 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */ 143 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */ 144 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */ 145 EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */ 146 EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */ 147 0, /* __DRI_ATTRIB_RENDER_TYPE, */ 148 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */ 149 0, /* __DRI_ATTRIB_CONFORMANT */ 150 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */ 151 0, /* __DRI_ATTRIB_STEREO */ 152 0, /* __DRI_ATTRIB_AUX_BUFFERS */ 153 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */ 154 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */ 155 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */ 156 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */ 157 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */ 158 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */ 159 0, /* __DRI_ATTRIB_FLOAT_MODE */ 160 0, /* __DRI_ATTRIB_RED_MASK */ 161 0, /* __DRI_ATTRIB_GREEN_MASK */ 162 0, /* __DRI_ATTRIB_BLUE_MASK */ 163 0, /* __DRI_ATTRIB_ALPHA_MASK */ 164 EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */ 165 EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */ 166 EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */ 167 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */ 168 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */ 169 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */ 170 0, /* __DRI_ATTRIB_SWAP_METHOD */ 171 EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */ 172 EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */ 173 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ 174 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ 175 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */ 176 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */ 177 EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */ 178}; 179 180static struct dri2_egl_config * 181dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 182 int depth, EGLint surface_type) 183{ 184 struct dri2_egl_config *conf; 185 struct dri2_egl_display *dri2_dpy; 186 _EGLConfig base; 187 unsigned int attrib, value, double_buffer; 188 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 189 int i; 190 191 dri2_dpy = disp->DriverData; 192 _eglInitConfig(&base, disp, id); 193 194 i = 0; 195 double_buffer = 0; 196 bind_to_texture_rgb = 0; 197 bind_to_texture_rgba = 0; 198 199 while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { 200 switch (attrib) { 201 case __DRI_ATTRIB_RENDER_TYPE: 202 if (value & __DRI_ATTRIB_RGBA_BIT) 203 value = EGL_RGB_BUFFER; 204 else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 205 value = EGL_LUMINANCE_BUFFER; 206 else 207 /* not valid */; 208 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); 209 break; 210 211 case __DRI_ATTRIB_CONFIG_CAVEAT: 212 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 213 value = EGL_NON_CONFORMANT_CONFIG; 214 else if (value & __DRI_ATTRIB_SLOW_BIT) 215 value = EGL_SLOW_CONFIG; 216 else 217 value = EGL_NONE; 218 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); 219 break; 220 221 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 222 bind_to_texture_rgb = value; 223 break; 224 225 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 226 bind_to_texture_rgba = value; 227 break; 228 229 case __DRI_ATTRIB_DOUBLE_BUFFER: 230 double_buffer = value; 231 break; 232 233 default: 234 key = dri2_to_egl_attribute_map[attrib]; 235 if (key != 0) 236 _eglSetConfigKey(&base, key, value); 237 break; 238 } 239 } 240 241 /* In EGL, double buffer or not isn't a config attribute. Pixmaps 242 * surfaces are always single buffered, pbuffer surfaces are always 243 * back buffers and windows can be either, selected by passing an 244 * attribute at window surface construction time. To support this 245 * we ignore all double buffer configs and manipulate the buffer we 246 * return in the getBuffer callback to get the behaviour we want. */ 247 248 if (double_buffer) 249 return NULL; 250 251 if (depth > 0 && depth != base.BufferSize) 252 return NULL; 253 254 base.NativeRenderable = EGL_TRUE; 255 256 base.SurfaceType = surface_type; 257 if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) { 258 base.BindToTextureRGB = bind_to_texture_rgb; 259 if (base.AlphaSize > 0) 260 base.BindToTextureRGBA = bind_to_texture_rgba; 261 } 262 263 base.RenderableType = disp->ClientAPIsMask; 264 base.Conformant = disp->ClientAPIsMask; 265 266 if (!_eglValidateConfig(&base, EGL_FALSE)) { 267 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 268 return NULL; 269 } 270 271 conf = malloc(sizeof *conf); 272 if (conf != NULL) { 273 memcpy(&conf->base, &base, sizeof base); 274 conf->dri_config = dri_config; 275 _eglLinkConfig(&conf->base); 276 } 277 278 return conf; 279} 280 281/** 282 * Process list of buffer received from the server 283 * 284 * Processes the list of buffers received in a reply from the server to either 285 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat. 286 */ 287static void 288dri2_process_buffers(struct dri2_egl_surface *dri2_surf, 289 xcb_dri2_dri2_buffer_t *buffers, unsigned count) 290{ 291 struct dri2_egl_display *dri2_dpy = 292 dri2_egl_display(dri2_surf->base.Resource.Display); 293 xcb_rectangle_t rectangle; 294 unsigned i; 295 296 dri2_surf->buffer_count = count; 297 dri2_surf->have_fake_front = 0; 298 299 /* This assumes the DRI2 buffer attachment tokens matches the 300 * __DRIbuffer tokens. */ 301 for (i = 0; i < count; i++) { 302 dri2_surf->buffers[i].attachment = buffers[i].attachment; 303 dri2_surf->buffers[i].name = buffers[i].name; 304 dri2_surf->buffers[i].pitch = buffers[i].pitch; 305 dri2_surf->buffers[i].cpp = buffers[i].cpp; 306 dri2_surf->buffers[i].flags = buffers[i].flags; 307 308 /* We only use the DRI drivers single buffer configs. This 309 * means that if we try to render to a window, DRI2 will give us 310 * the fake front buffer, which we'll use as a back buffer. 311 * Note that EGL doesn't require that several clients rendering 312 * to the same window must see the same aux buffers. */ 313 if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT) 314 dri2_surf->have_fake_front = 1; 315 } 316 317 if (dri2_surf->region != XCB_NONE) 318 xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region); 319 320 rectangle.x = 0; 321 rectangle.y = 0; 322 rectangle.width = dri2_surf->base.Width; 323 rectangle.height = dri2_surf->base.Height; 324 dri2_surf->region = xcb_generate_id(dri2_dpy->conn); 325 xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle); 326} 327 328static __DRIbuffer * 329dri2_get_buffers(__DRIdrawable * driDrawable, 330 int *width, int *height, 331 unsigned int *attachments, int count, 332 int *out_count, void *loaderPrivate) 333{ 334 struct dri2_egl_surface *dri2_surf = loaderPrivate; 335 struct dri2_egl_display *dri2_dpy = 336 dri2_egl_display(dri2_surf->base.Resource.Display); 337 xcb_dri2_dri2_buffer_t *buffers; 338 xcb_dri2_get_buffers_reply_t *reply; 339 xcb_dri2_get_buffers_cookie_t cookie; 340 341 (void) driDrawable; 342 343 cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, 344 dri2_surf->drawable, 345 count, count, attachments); 346 reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL); 347 buffers = xcb_dri2_get_buffers_buffers (reply); 348 if (buffers == NULL) 349 return NULL; 350 351 *out_count = reply->count; 352 dri2_surf->base.Width = *width = reply->width; 353 dri2_surf->base.Height = *height = reply->height; 354 dri2_process_buffers(dri2_surf, buffers, *out_count); 355 356 free(reply); 357 358 return dri2_surf->buffers; 359} 360 361static void 362dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 363{ 364 (void) driDrawable; 365 366 /* FIXME: Does EGL support front buffer rendering at all? */ 367 368#if 0 369 struct dri2_egl_surface *dri2_surf = loaderPrivate; 370 371 dri2WaitGL(dri2_surf); 372#else 373 (void) loaderPrivate; 374#endif 375} 376 377static __DRIimage * 378dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 379{ 380 _EGLDisplay *disp = data; 381 struct dri2_egl_image *dri2_img; 382 _EGLImage *img; 383 384 (void) screen; 385 386 img = _eglLookupImage(image, disp); 387 if (img == NULL) { 388 _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); 389 return NULL; 390 } 391 392 dri2_img = dri2_egl_image(image); 393 394 return dri2_img->dri_image; 395} 396 397static const __DRIimageLookupExtension image_lookup_extension = { 398 { __DRI_IMAGE_LOOKUP, 1 }, 399 dri2_lookup_egl_image 400}; 401 402static __DRIbuffer * 403dri2_get_buffers_with_format(__DRIdrawable * driDrawable, 404 int *width, int *height, 405 unsigned int *attachments, int count, 406 int *out_count, void *loaderPrivate) 407{ 408 struct dri2_egl_surface *dri2_surf = loaderPrivate; 409 struct dri2_egl_display *dri2_dpy = 410 dri2_egl_display(dri2_surf->base.Resource.Display); 411 xcb_dri2_dri2_buffer_t *buffers; 412 xcb_dri2_get_buffers_with_format_reply_t *reply; 413 xcb_dri2_get_buffers_with_format_cookie_t cookie; 414 xcb_dri2_attach_format_t *format_attachments; 415 416 (void) driDrawable; 417 418 format_attachments = (xcb_dri2_attach_format_t *) attachments; 419 cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn, 420 dri2_surf->drawable, 421 count, count, 422 format_attachments); 423 424 reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn, 425 cookie, NULL); 426 if (reply == NULL) 427 return NULL; 428 429 buffers = xcb_dri2_get_buffers_with_format_buffers (reply); 430 dri2_surf->base.Width = *width = reply->width; 431 dri2_surf->base.Height = *height = reply->height; 432 *out_count = reply->count; 433 dri2_process_buffers(dri2_surf, buffers, *out_count); 434 435 free(reply); 436 437 return dri2_surf->buffers; 438} 439 440static const char dri_driver_path[] = DEFAULT_DRIVER_DIR; 441 442struct dri2_extension_match { 443 const char *name; 444 int version; 445 int offset; 446}; 447 448static struct dri2_extension_match dri2_driver_extensions[] = { 449 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 450 { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) }, 451 { NULL, 0, 0 } 452}; 453 454static struct dri2_extension_match dri2_core_extensions[] = { 455 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 456 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 457 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 458 { NULL, 0, 0 } 459}; 460 461static EGLBoolean 462dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 463 struct dri2_extension_match *matches, 464 const __DRIextension **extensions) 465{ 466 int i, j, ret = EGL_TRUE; 467 void *field; 468 469 for (i = 0; extensions[i]; i++) { 470 _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); 471 for (j = 0; matches[j].name; j++) { 472 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 473 extensions[i]->version >= matches[j].version) { 474 field = ((char *) dri2_dpy + matches[j].offset); 475 *(const __DRIextension **) field = extensions[i]; 476 _eglLog(_EGL_INFO, "DRI2: found extension %s version %d", 477 extensions[i]->name, extensions[i]->version); 478 } 479 } 480 } 481 482 for (j = 0; matches[j].name; j++) { 483 field = ((char *) dri2_dpy + matches[j].offset); 484 if (*(const __DRIextension **) field == NULL) { 485 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d", 486 matches[j].name, matches[j].version); 487 ret = EGL_FALSE; 488 } 489 } 490 491 return ret; 492} 493 494static char * 495dri2_strndup(const char *s, int length) 496{ 497 char *d; 498 499 d = malloc(length + 1); 500 if (d == NULL) 501 return NULL; 502 503 memcpy(d, s, length); 504 d[length] = '\0'; 505 506 return d; 507} 508 509static EGLBoolean 510dri2_connect(struct dri2_egl_display *dri2_dpy) 511{ 512 xcb_xfixes_query_version_reply_t *xfixes_query; 513 xcb_xfixes_query_version_cookie_t xfixes_query_cookie; 514 xcb_dri2_query_version_reply_t *dri2_query; 515 xcb_dri2_query_version_cookie_t dri2_query_cookie; 516 xcb_dri2_connect_reply_t *connect; 517 xcb_dri2_connect_cookie_t connect_cookie; 518 xcb_generic_error_t *error; 519 xcb_screen_iterator_t s; 520 521 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id); 522 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id); 523 524 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn, 525 XCB_XFIXES_MAJOR_VERSION, 526 XCB_XFIXES_MINOR_VERSION); 527 528 dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn, 529 XCB_DRI2_MAJOR_VERSION, 530 XCB_DRI2_MINOR_VERSION); 531 532 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); 533 connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn, 534 s.data->root, 535 XCB_DRI2_DRIVER_TYPE_DRI); 536 537 xfixes_query = 538 xcb_xfixes_query_version_reply (dri2_dpy->conn, 539 xfixes_query_cookie, &error); 540 if (xfixes_query == NULL || 541 error != NULL || xfixes_query->major_version < 2) { 542 _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version"); 543 free(error); 544 return EGL_FALSE; 545 } 546 free(xfixes_query); 547 548 dri2_query = 549 xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error); 550 if (dri2_query == NULL || error != NULL) { 551 _eglLog(_EGL_FATAL, "DRI2: failed to query version"); 552 free(error); 553 return EGL_FALSE; 554 } 555 dri2_dpy->dri2_major = dri2_query->major_version; 556 dri2_dpy->dri2_minor = dri2_query->minor_version; 557 free(dri2_query); 558 559 connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL); 560 if (connect == NULL || 561 connect->driver_name_length + connect->device_name_length == 0) { 562 _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); 563 return EGL_FALSE; 564 } 565 566 dri2_dpy->device_name = 567 dri2_strndup(xcb_dri2_connect_device_name (connect), 568 xcb_dri2_connect_device_name_length (connect)); 569 570 dri2_dpy->driver_name = 571 dri2_strndup(xcb_dri2_connect_driver_name (connect), 572 xcb_dri2_connect_driver_name_length (connect)); 573 574 if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) { 575 free(dri2_dpy->device_name); 576 free(dri2_dpy->driver_name); 577 free(connect); 578 return EGL_FALSE; 579 } 580 free(connect); 581 582 return EGL_TRUE; 583} 584 585static EGLBoolean 586dri2_authenticate(struct dri2_egl_display *dri2_dpy) 587{ 588 xcb_dri2_authenticate_reply_t *authenticate; 589 xcb_dri2_authenticate_cookie_t authenticate_cookie; 590 xcb_screen_iterator_t s; 591 drm_magic_t magic; 592 593 if (drmGetMagic(dri2_dpy->fd, &magic)) { 594 _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic"); 595 return EGL_FALSE; 596 } 597 598 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); 599 authenticate_cookie = 600 xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic); 601 authenticate = 602 xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL); 603 if (authenticate == NULL || !authenticate->authenticated) { 604 _eglLog(_EGL_FATAL, "DRI2: failed to authenticate"); 605 free(authenticate); 606 return EGL_FALSE; 607 } 608 609 free(authenticate); 610 611 return EGL_TRUE; 612} 613 614static EGLBoolean 615dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy, 616 _EGLDisplay *disp) 617{ 618 xcb_screen_iterator_t s; 619 xcb_depth_iterator_t d; 620 xcb_visualtype_t *visuals; 621 int i, j, id; 622 struct dri2_egl_config *conf; 623 EGLint surface_type; 624 625 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); 626 d = xcb_screen_allowed_depths_iterator(s.data); 627 id = 1; 628 629 surface_type = 630 EGL_WINDOW_BIT | 631 EGL_PIXMAP_BIT | 632 EGL_PBUFFER_BIT | 633 EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 634 635 while (d.rem > 0) { 636 EGLBoolean class_added[6] = { 0, }; 637 638 visuals = xcb_depth_visuals(d.data); 639 for (i = 0; i < xcb_depth_visuals_length(d.data); i++) { 640 if (class_added[visuals[i]._class]) 641 continue; 642 643 class_added[visuals[i]._class] = EGL_TRUE; 644 for (j = 0; dri2_dpy->driver_configs[j]; j++) { 645 conf = dri2_add_config(disp, dri2_dpy->driver_configs[j], 646 id++, d.data->depth, surface_type); 647 if (conf == NULL) 648 continue; 649 _eglSetConfigKey(&conf->base, 650 EGL_NATIVE_VISUAL_ID, visuals[i].visual_id); 651 _eglSetConfigKey(&conf->base, 652 EGL_NATIVE_VISUAL_TYPE, visuals[i]._class); 653 } 654 } 655 656 xcb_depth_next(&d); 657 } 658 659 if (!_eglGetArraySize(disp->Configs)) { 660 _eglLog(_EGL_WARNING, "DRI2: failed to create any config"); 661 return EGL_FALSE; 662 } 663 664 return EGL_TRUE; 665} 666 667static EGLBoolean 668dri2_load_driver(_EGLDisplay *disp) 669{ 670 struct dri2_egl_display *dri2_dpy = disp->DriverData; 671 const __DRIextension **extensions; 672 char path[PATH_MAX], *search_paths, *p, *next, *end; 673 674 search_paths = NULL; 675 if (geteuid() == getuid()) { 676 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 677 search_paths = getenv("LIBGL_DRIVERS_PATH"); 678 } 679 if (search_paths == NULL) 680 search_paths = DEFAULT_DRIVER_DIR; 681 682 dri2_dpy->driver = NULL; 683 end = search_paths + strlen(search_paths); 684 for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { 685 int len; 686 next = strchr(p, ':'); 687 if (next == NULL) 688 next = end; 689 690 len = next - p; 691#if GLX_USE_TLS 692 snprintf(path, sizeof path, 693 "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name); 694 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 695#endif 696 if (dri2_dpy->driver == NULL) { 697 snprintf(path, sizeof path, 698 "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name); 699 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 700 if (dri2_dpy->driver == NULL) 701 _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror()); 702 } 703 } 704 705 if (dri2_dpy->driver == NULL) { 706 _eglLog(_EGL_WARNING, 707 "DRI2: failed to open any driver (search paths %s)", 708 search_paths); 709 return EGL_FALSE; 710 } 711 712 _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); 713 extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS); 714 if (extensions == NULL) { 715 _eglLog(_EGL_WARNING, 716 "DRI2: driver exports no extensions (%s)", dlerror()); 717 dlclose(dri2_dpy->driver); 718 return EGL_FALSE; 719 } 720 721 if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { 722 dlclose(dri2_dpy->driver); 723 return EGL_FALSE; 724 } 725 726 return EGL_TRUE; 727} 728 729static EGLBoolean 730dri2_create_screen(_EGLDisplay *disp) 731{ 732 const __DRIextension **extensions; 733 struct dri2_egl_display *dri2_dpy; 734 unsigned int api_mask; 735 736 dri2_dpy = disp->DriverData; 737 dri2_dpy->dri_screen = 738 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, 739 &dri2_dpy->driver_configs, disp); 740 741 if (dri2_dpy->dri_screen == NULL) { 742 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 743 return EGL_FALSE; 744 } 745 746 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 747 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) 748 goto cleanup_dri_screen; 749 750 if (dri2_dpy->dri2->base.version >= 2) 751 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 752 else 753 api_mask = 1 << __DRI_API_OPENGL; 754 755 disp->ClientAPIsMask = 0; 756 if (api_mask & (1 <<__DRI_API_OPENGL)) 757 disp->ClientAPIsMask |= EGL_OPENGL_BIT; 758 if (api_mask & (1 <<__DRI_API_GLES)) 759 disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT; 760 if (api_mask & (1 << __DRI_API_GLES2)) 761 disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT; 762 763 if (dri2_dpy->dri2->base.version >= 2) { 764 disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; 765 disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; 766 disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; 767 } 768 769 return EGL_TRUE; 770 771 cleanup_dri_screen: 772 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 773 774 return EGL_FALSE; 775} 776 777static EGLBoolean 778dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp, 779 EGLint *major, EGLint *minor) 780{ 781 struct dri2_egl_display *dri2_dpy; 782 783 (void) drv; 784 785 dri2_dpy = malloc(sizeof *dri2_dpy); 786 if (!dri2_dpy) 787 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 788 789 disp->DriverData = (void *) dri2_dpy; 790 if (disp->PlatformDisplay == NULL) { 791 dri2_dpy->conn = xcb_connect(0, 0); 792 } else { 793 dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay); 794 } 795 796 if (xcb_connection_has_error(dri2_dpy->conn)) { 797 _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed"); 798 goto cleanup_dpy; 799 } 800 801 if (dri2_dpy->conn) { 802 if (!dri2_connect(dri2_dpy)) 803 goto cleanup_conn; 804 } 805 806 if (!dri2_load_driver(disp)) 807 goto cleanup_conn; 808 809 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); 810 if (dri2_dpy->fd == -1) { 811 _eglLog(_EGL_WARNING, 812 "DRI2: could not open %s (%s)", dri2_dpy->device_name, 813 strerror(errno)); 814 goto cleanup_driver; 815 } 816 817 if (dri2_dpy->conn) { 818 if (!dri2_authenticate(dri2_dpy)) 819 goto cleanup_fd; 820 } 821 822 if (dri2_dpy->dri2_minor >= 1) { 823 dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER; 824 dri2_dpy->loader_extension.base.version = 3; 825 dri2_dpy->loader_extension.getBuffers = dri2_get_buffers; 826 dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer; 827 dri2_dpy->loader_extension.getBuffersWithFormat = 828 dri2_get_buffers_with_format; 829 } else { 830 dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER; 831 dri2_dpy->loader_extension.base.version = 2; 832 dri2_dpy->loader_extension.getBuffers = dri2_get_buffers; 833 dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer; 834 dri2_dpy->loader_extension.getBuffersWithFormat = NULL; 835 } 836 837 dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base; 838 dri2_dpy->extensions[1] = &image_lookup_extension.base; 839 dri2_dpy->extensions[2] = NULL; 840 841 if (!dri2_create_screen(disp)) 842 goto cleanup_fd; 843 844 if (dri2_dpy->conn) { 845 if (!dri2_add_configs_for_visuals(dri2_dpy, disp)) 846 goto cleanup_configs; 847 } 848 849 disp->Extensions.MESA_drm_image = EGL_TRUE; 850 disp->Extensions.KHR_image_base = EGL_TRUE; 851 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 852 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 853 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 854 disp->Extensions.NOK_swap_region = EGL_TRUE; 855 disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE; 856 857 /* we're supporting EGL 1.4 */ 858 *major = 1; 859 *minor = 4; 860 861 return EGL_TRUE; 862 863 cleanup_configs: 864 _eglCleanupDisplay(disp); 865 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 866 cleanup_fd: 867 close(dri2_dpy->fd); 868 cleanup_driver: 869 dlclose(dri2_dpy->driver); 870 cleanup_conn: 871 if (disp->PlatformDisplay == NULL) 872 xcb_disconnect(dri2_dpy->conn); 873 cleanup_dpy: 874 free(dri2_dpy); 875 876 return EGL_FALSE; 877} 878 879#ifdef HAVE_LIBUDEV 880 881struct dri2_driver_map { 882 int vendor_id; 883 const char *driver; 884 const int *chip_ids; 885 int num_chips_ids; 886}; 887 888const int i915_chip_ids[] = { 889 0x3577, /* PCI_CHIP_I830_M */ 890 0x2562, /* PCI_CHIP_845_G */ 891 0x3582, /* PCI_CHIP_I855_GM */ 892 0x2572, /* PCI_CHIP_I865_G */ 893 0x2582, /* PCI_CHIP_I915_G */ 894 0x258a, /* PCI_CHIP_E7221_G */ 895 0x2592, /* PCI_CHIP_I915_GM */ 896 0x2772, /* PCI_CHIP_I945_G */ 897 0x27a2, /* PCI_CHIP_I945_GM */ 898 0x27ae, /* PCI_CHIP_I945_GME */ 899 0x29b2, /* PCI_CHIP_Q35_G */ 900 0x29c2, /* PCI_CHIP_G33_G */ 901 0x29d2, /* PCI_CHIP_Q33_G */ 902 0xa001, /* PCI_CHIP_IGD_G */ 903 0xa011, /* Pineview */ 904}; 905 906const int i965_chip_ids[] = { 907 0x0042, /* PCI_CHIP_ILD_G */ 908 0x0046, /* PCI_CHIP_ILM_G */ 909 0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */ 910 0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */ 911 0x010a, /* PCI_CHIP_SANDYBRIDGE_S */ 912 0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */ 913 0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */ 914 0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */ 915 0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */ 916 0x29a2, /* PCI_CHIP_I965_G */ 917 0x2992, /* PCI_CHIP_I965_Q */ 918 0x2982, /* PCI_CHIP_I965_G_1 */ 919 0x2972, /* PCI_CHIP_I946_GZ */ 920 0x2a02, /* PCI_CHIP_I965_GM */ 921 0x2a12, /* PCI_CHIP_I965_GME */ 922 0x2a42, /* PCI_CHIP_GM45_GM */ 923 0x2e02, /* PCI_CHIP_IGD_E_G */ 924 0x2e12, /* PCI_CHIP_Q45_G */ 925 0x2e22, /* PCI_CHIP_G45_G */ 926 0x2e32, /* PCI_CHIP_G41_G */ 927 0x2e42, /* PCI_CHIP_B43_G */ 928 0x2e92, /* PCI_CHIP_B43_G1 */ 929}; 930 931const int r100_chip_ids[] = { 932 0x4C57, /* PCI_CHIP_RADEON_LW */ 933 0x4C58, /* PCI_CHIP_RADEON_LX */ 934 0x4C59, /* PCI_CHIP_RADEON_LY */ 935 0x4C5A, /* PCI_CHIP_RADEON_LZ */ 936 0x5144, /* PCI_CHIP_RADEON_QD */ 937 0x5145, /* PCI_CHIP_RADEON_QE */ 938 0x5146, /* PCI_CHIP_RADEON_QF */ 939 0x5147, /* PCI_CHIP_RADEON_QG */ 940 0x5159, /* PCI_CHIP_RADEON_QY */ 941 0x515A, /* PCI_CHIP_RADEON_QZ */ 942 0x5157, /* PCI_CHIP_RV200_QW */ 943 0x5158, /* PCI_CHIP_RV200_QX */ 944 0x515E, /* PCI_CHIP_RN50_515E */ 945 0x5969, /* PCI_CHIP_RN50_5969 */ 946 0x4136, /* PCI_CHIP_RS100_4136 */ 947 0x4336, /* PCI_CHIP_RS100_4336 */ 948 0x4137, /* PCI_CHIP_RS200_4137 */ 949 0x4337, /* PCI_CHIP_RS200_4337 */ 950 0x4237, /* PCI_CHIP_RS250_4237 */ 951 0x4437, /* PCI_CHIP_RS250_4437 */ 952}; 953 954const int r200_chip_ids[] = { 955 0x5148, /* PCI_CHIP_R200_QH */ 956 0x514C, /* PCI_CHIP_R200_QL */ 957 0x514D, /* PCI_CHIP_R200_QM */ 958 0x4242, /* PCI_CHIP_R200_BB */ 959 0x4243, /* PCI_CHIP_R200_BC */ 960 0x4966, /* PCI_CHIP_RV250_If */ 961 0x4967, /* PCI_CHIP_RV250_Ig */ 962 0x4C64, /* PCI_CHIP_RV250_Ld */ 963 0x4C66, /* PCI_CHIP_RV250_Lf */ 964 0x4C67, /* PCI_CHIP_RV250_Lg */ 965 0x5960, /* PCI_CHIP_RV280_5960 */ 966 0x5961, /* PCI_CHIP_RV280_5961 */ 967 0x5962, /* PCI_CHIP_RV280_5962 */ 968 0x5964, /* PCI_CHIP_RV280_5964 */ 969 0x5965, /* PCI_CHIP_RV280_5965 */ 970 0x5C61, /* PCI_CHIP_RV280_5C61 */ 971 0x5C63, /* PCI_CHIP_RV280_5C63 */ 972 0x5834, /* PCI_CHIP_RS300_5834 */ 973 0x5835, /* PCI_CHIP_RS300_5835 */ 974 0x7834, /* PCI_CHIP_RS350_7834 */ 975 0x7835, /* PCI_CHIP_RS350_7835 */ 976}; 977 978const int r300_chip_ids[] = { 979 0x4144, /* PCI_CHIP_R300_AD */ 980 0x4145, /* PCI_CHIP_R300_AE */ 981 0x4146, /* PCI_CHIP_R300_AF */ 982 0x4147, /* PCI_CHIP_R300_AG */ 983 0x4E44, /* PCI_CHIP_R300_ND */ 984 0x4E45, /* PCI_CHIP_R300_NE */ 985 0x4E46, /* PCI_CHIP_R300_NF */ 986 0x4E47, /* PCI_CHIP_R300_NG */ 987 0x4E48, /* PCI_CHIP_R350_NH */ 988 0x4E49, /* PCI_CHIP_R350_NI */ 989 0x4E4B, /* PCI_CHIP_R350_NK */ 990 0x4148, /* PCI_CHIP_R350_AH */ 991 0x4149, /* PCI_CHIP_R350_AI */ 992 0x414A, /* PCI_CHIP_R350_AJ */ 993 0x414B, /* PCI_CHIP_R350_AK */ 994 0x4E4A, /* PCI_CHIP_R360_NJ */ 995 0x4150, /* PCI_CHIP_RV350_AP */ 996 0x4151, /* PCI_CHIP_RV350_AQ */ 997 0x4152, /* PCI_CHIP_RV350_AR */ 998 0x4153, /* PCI_CHIP_RV350_AS */ 999 0x4154, /* PCI_CHIP_RV350_AT */ 1000 0x4155, /* PCI_CHIP_RV350_AU */ 1001 0x4156, /* PCI_CHIP_RV350_AV */ 1002 0x4E50, /* PCI_CHIP_RV350_NP */ 1003 0x4E51, /* PCI_CHIP_RV350_NQ */ 1004 0x4E52, /* PCI_CHIP_RV350_NR */ 1005 0x4E53, /* PCI_CHIP_RV350_NS */ 1006 0x4E54, /* PCI_CHIP_RV350_NT */ 1007 0x4E56, /* PCI_CHIP_RV350_NV */ 1008 0x5460, /* PCI_CHIP_RV370_5460 */ 1009 0x5462, /* PCI_CHIP_RV370_5462 */ 1010 0x5464, /* PCI_CHIP_RV370_5464 */ 1011 0x5B60, /* PCI_CHIP_RV370_5B60 */ 1012 0x5B62, /* PCI_CHIP_RV370_5B62 */ 1013 0x5B63, /* PCI_CHIP_RV370_5B63 */ 1014 0x5B64, /* PCI_CHIP_RV370_5B64 */ 1015 0x5B65, /* PCI_CHIP_RV370_5B65 */ 1016 0x3150, /* PCI_CHIP_RV380_3150 */ 1017 0x3152, /* PCI_CHIP_RV380_3152 */ 1018 0x3154, /* PCI_CHIP_RV380_3154 */ 1019 0x3155, /* PCI_CHIP_RV380_3155 */ 1020 0x3E50, /* PCI_CHIP_RV380_3E50 */ 1021 0x3E54, /* PCI_CHIP_RV380_3E54 */ 1022 0x4A48, /* PCI_CHIP_R420_JH */ 1023 0x4A49, /* PCI_CHIP_R420_JI */ 1024 0x4A4A, /* PCI_CHIP_R420_JJ */ 1025 0x4A4B, /* PCI_CHIP_R420_JK */ 1026 0x4A4C, /* PCI_CHIP_R420_JL */ 1027 0x4A4D, /* PCI_CHIP_R420_JM */ 1028 0x4A4E, /* PCI_CHIP_R420_JN */ 1029 0x4A4F, /* PCI_CHIP_R420_JO */ 1030 0x4A50, /* PCI_CHIP_R420_JP */ 1031 0x4A54, /* PCI_CHIP_R420_JT */ 1032 0x5548, /* PCI_CHIP_R423_UH */ 1033 0x5549, /* PCI_CHIP_R423_UI */ 1034 0x554A, /* PCI_CHIP_R423_UJ */ 1035 0x554B, /* PCI_CHIP_R423_UK */ 1036 0x5550, /* PCI_CHIP_R423_5550 */ 1037 0x5551, /* PCI_CHIP_R423_UQ */ 1038 0x5552, /* PCI_CHIP_R423_UR */ 1039 0x5554, /* PCI_CHIP_R423_UT */ 1040 0x5D57, /* PCI_CHIP_R423_5D57 */ 1041 0x554C, /* PCI_CHIP_R430_554C */ 1042 0x554D, /* PCI_CHIP_R430_554D */ 1043 0x554E, /* PCI_CHIP_R430_554E */ 1044 0x554F, /* PCI_CHIP_R430_554F */ 1045 0x5D48, /* PCI_CHIP_R430_5D48 */ 1046 0x5D49, /* PCI_CHIP_R430_5D49 */ 1047 0x5D4A, /* PCI_CHIP_R430_5D4A */ 1048 0x5D4C, /* PCI_CHIP_R480_5D4C */ 1049 0x5D4D, /* PCI_CHIP_R480_5D4D */ 1050 0x5D4E, /* PCI_CHIP_R480_5D4E */ 1051 0x5D4F, /* PCI_CHIP_R480_5D4F */ 1052 0x5D50, /* PCI_CHIP_R480_5D50 */ 1053 0x5D52, /* PCI_CHIP_R480_5D52 */ 1054 0x4B49, /* PCI_CHIP_R481_4B49 */ 1055 0x4B4A, /* PCI_CHIP_R481_4B4A */ 1056 0x4B4B, /* PCI_CHIP_R481_4B4B */ 1057 0x4B4C, /* PCI_CHIP_R481_4B4C */ 1058 0x564A, /* PCI_CHIP_RV410_564A */ 1059 0x564B, /* PCI_CHIP_RV410_564B */ 1060 0x564F, /* PCI_CHIP_RV410_564F */ 1061 0x5652, /* PCI_CHIP_RV410_5652 */ 1062 0x5653, /* PCI_CHIP_RV410_5653 */ 1063 0x5657, /* PCI_CHIP_RV410_5657 */ 1064 0x5E48, /* PCI_CHIP_RV410_5E48 */ 1065 0x5E4A, /* PCI_CHIP_RV410_5E4A */ 1066 0x5E4B, /* PCI_CHIP_RV410_5E4B */ 1067 0x5E4C, /* PCI_CHIP_RV410_5E4C */ 1068 0x5E4D, /* PCI_CHIP_RV410_5E4D */ 1069 0x5E4F, /* PCI_CHIP_RV410_5E4F */ 1070 0x5A41, /* PCI_CHIP_RS400_5A41 */ 1071 0x5A42, /* PCI_CHIP_RS400_5A42 */ 1072 0x5A61, /* PCI_CHIP_RC410_5A61 */ 1073 0x5A62, /* PCI_CHIP_RC410_5A62 */ 1074 0x5954, /* PCI_CHIP_RS480_5954 */ 1075 0x5955, /* PCI_CHIP_RS480_5955 */ 1076 0x5974, /* PCI_CHIP_RS482_5974 */ 1077 0x5975, /* PCI_CHIP_RS482_5975 */ 1078 0x7100, /* PCI_CHIP_R520_7100 */ 1079 0x7101, /* PCI_CHIP_R520_7101 */ 1080 0x7102, /* PCI_CHIP_R520_7102 */ 1081 0x7103, /* PCI_CHIP_R520_7103 */ 1082 0x7104, /* PCI_CHIP_R520_7104 */ 1083 0x7105, /* PCI_CHIP_R520_7105 */ 1084 0x7106, /* PCI_CHIP_R520_7106 */ 1085 0x7108, /* PCI_CHIP_R520_7108 */ 1086 0x7109, /* PCI_CHIP_R520_7109 */ 1087 0x710A, /* PCI_CHIP_R520_710A */ 1088 0x710B, /* PCI_CHIP_R520_710B */ 1089 0x710C, /* PCI_CHIP_R520_710C */ 1090 0x710E, /* PCI_CHIP_R520_710E */ 1091 0x710F, /* PCI_CHIP_R520_710F */ 1092 0x7140, /* PCI_CHIP_RV515_7140 */ 1093 0x7141, /* PCI_CHIP_RV515_7141 */ 1094 0x7142, /* PCI_CHIP_RV515_7142 */ 1095 0x7143, /* PCI_CHIP_RV515_7143 */ 1096 0x7144, /* PCI_CHIP_RV515_7144 */ 1097 0x7145, /* PCI_CHIP_RV515_7145 */ 1098 0x7146, /* PCI_CHIP_RV515_7146 */ 1099 0x7147, /* PCI_CHIP_RV515_7147 */ 1100 0x7149, /* PCI_CHIP_RV515_7149 */ 1101 0x714A, /* PCI_CHIP_RV515_714A */ 1102 0x714B, /* PCI_CHIP_RV515_714B */ 1103 0x714C, /* PCI_CHIP_RV515_714C */ 1104 0x714D, /* PCI_CHIP_RV515_714D */ 1105 0x714E, /* PCI_CHIP_RV515_714E */ 1106 0x714F, /* PCI_CHIP_RV515_714F */ 1107 0x7151, /* PCI_CHIP_RV515_7151 */ 1108 0x7152, /* PCI_CHIP_RV515_7152 */ 1109 0x7153, /* PCI_CHIP_RV515_7153 */ 1110 0x715E, /* PCI_CHIP_RV515_715E */ 1111 0x715F, /* PCI_CHIP_RV515_715F */ 1112 0x7180, /* PCI_CHIP_RV515_7180 */ 1113 0x7181, /* PCI_CHIP_RV515_7181 */ 1114 0x7183, /* PCI_CHIP_RV515_7183 */ 1115 0x7186, /* PCI_CHIP_RV515_7186 */ 1116 0x7187, /* PCI_CHIP_RV515_7187 */ 1117 0x7188, /* PCI_CHIP_RV515_7188 */ 1118 0x718A, /* PCI_CHIP_RV515_718A */ 1119 0x718B, /* PCI_CHIP_RV515_718B */ 1120 0x718C, /* PCI_CHIP_RV515_718C */ 1121 0x718D, /* PCI_CHIP_RV515_718D */ 1122 0x718F, /* PCI_CHIP_RV515_718F */ 1123 0x7193, /* PCI_CHIP_RV515_7193 */ 1124 0x7196, /* PCI_CHIP_RV515_7196 */ 1125 0x719B, /* PCI_CHIP_RV515_719B */ 1126 0x719F, /* PCI_CHIP_RV515_719F */ 1127 0x7200, /* PCI_CHIP_RV515_7200 */ 1128 0x7210, /* PCI_CHIP_RV515_7210 */ 1129 0x7211, /* PCI_CHIP_RV515_7211 */ 1130 0x71C0, /* PCI_CHIP_RV530_71C0 */ 1131 0x71C1, /* PCI_CHIP_RV530_71C1 */ 1132 0x71C2, /* PCI_CHIP_RV530_71C2 */ 1133 0x71C3, /* PCI_CHIP_RV530_71C3 */ 1134 0x71C4, /* PCI_CHIP_RV530_71C4 */ 1135 0x71C5, /* PCI_CHIP_RV530_71C5 */ 1136 0x71C6, /* PCI_CHIP_RV530_71C6 */ 1137 0x71C7, /* PCI_CHIP_RV530_71C7 */ 1138 0x71CD, /* PCI_CHIP_RV530_71CD */ 1139 0x71CE, /* PCI_CHIP_RV530_71CE */ 1140 0x71D2, /* PCI_CHIP_RV530_71D2 */ 1141 0x71D4, /* PCI_CHIP_RV530_71D4 */ 1142 0x71D5, /* PCI_CHIP_RV530_71D5 */ 1143 0x71D6, /* PCI_CHIP_RV530_71D6 */ 1144 0x71DA, /* PCI_CHIP_RV530_71DA */ 1145 0x71DE, /* PCI_CHIP_RV530_71DE */ 1146 0x7281, /* PCI_CHIP_RV560_7281 */ 1147 0x7283, /* PCI_CHIP_RV560_7283 */ 1148 0x7287, /* PCI_CHIP_RV560_7287 */ 1149 0x7290, /* PCI_CHIP_RV560_7290 */ 1150 0x7291, /* PCI_CHIP_RV560_7291 */ 1151 0x7293, /* PCI_CHIP_RV560_7293 */ 1152 0x7297, /* PCI_CHIP_RV560_7297 */ 1153 0x7280, /* PCI_CHIP_RV570_7280 */ 1154 0x7288, /* PCI_CHIP_RV570_7288 */ 1155 0x7289, /* PCI_CHIP_RV570_7289 */ 1156 0x728B, /* PCI_CHIP_RV570_728B */ 1157 0x728C, /* PCI_CHIP_RV570_728C */ 1158 0x7240, /* PCI_CHIP_R580_7240 */ 1159 0x7243, /* PCI_CHIP_R580_7243 */ 1160 0x7244, /* PCI_CHIP_R580_7244 */ 1161 0x7245, /* PCI_CHIP_R580_7245 */ 1162 0x7246, /* PCI_CHIP_R580_7246 */ 1163 0x7247, /* PCI_CHIP_R580_7247 */ 1164 0x7248, /* PCI_CHIP_R580_7248 */ 1165 0x7249, /* PCI_CHIP_R580_7249 */ 1166 0x724A, /* PCI_CHIP_R580_724A */ 1167 0x724B, /* PCI_CHIP_R580_724B */ 1168 0x724C, /* PCI_CHIP_R580_724C */ 1169 0x724D, /* PCI_CHIP_R580_724D */ 1170 0x724E, /* PCI_CHIP_R580_724E */ 1171 0x724F, /* PCI_CHIP_R580_724F */ 1172 0x7284, /* PCI_CHIP_R580_7284 */ 1173 0x793F, /* PCI_CHIP_RS600_793F */ 1174 0x7941, /* PCI_CHIP_RS600_7941 */ 1175 0x7942, /* PCI_CHIP_RS600_7942 */ 1176 0x791E, /* PCI_CHIP_RS690_791E */ 1177 0x791F, /* PCI_CHIP_RS690_791F */ 1178 0x796C, /* PCI_CHIP_RS740_796C */ 1179 0x796D, /* PCI_CHIP_RS740_796D */ 1180 0x796E, /* PCI_CHIP_RS740_796E */ 1181 0x796F, /* PCI_CHIP_RS740_796F */ 1182}; 1183 1184const int r600_chip_ids[] = { 1185 0x9400, /* PCI_CHIP_R600_9400 */ 1186 0x9401, /* PCI_CHIP_R600_9401 */ 1187 0x9402, /* PCI_CHIP_R600_9402 */ 1188 0x9403, /* PCI_CHIP_R600_9403 */ 1189 0x9405, /* PCI_CHIP_R600_9405 */ 1190 0x940A, /* PCI_CHIP_R600_940A */ 1191 0x940B, /* PCI_CHIP_R600_940B */ 1192 0x940F, /* PCI_CHIP_R600_940F */ 1193 0x94C0, /* PCI_CHIP_RV610_94C0 */ 1194 0x94C1, /* PCI_CHIP_RV610_94C1 */ 1195 0x94C3, /* PCI_CHIP_RV610_94C3 */ 1196 0x94C4, /* PCI_CHIP_RV610_94C4 */ 1197 0x94C5, /* PCI_CHIP_RV610_94C5 */ 1198 0x94C6, /* PCI_CHIP_RV610_94C6 */ 1199 0x94C7, /* PCI_CHIP_RV610_94C7 */ 1200 0x94C8, /* PCI_CHIP_RV610_94C8 */ 1201 0x94C9, /* PCI_CHIP_RV610_94C9 */ 1202 0x94CB, /* PCI_CHIP_RV610_94CB */ 1203 0x94CC, /* PCI_CHIP_RV610_94CC */ 1204 0x94CD, /* PCI_CHIP_RV610_94CD */ 1205 0x9580, /* PCI_CHIP_RV630_9580 */ 1206 0x9581, /* PCI_CHIP_RV630_9581 */ 1207 0x9583, /* PCI_CHIP_RV630_9583 */ 1208 0x9586, /* PCI_CHIP_RV630_9586 */ 1209 0x9587, /* PCI_CHIP_RV630_9587 */ 1210 0x9588, /* PCI_CHIP_RV630_9588 */ 1211 0x9589, /* PCI_CHIP_RV630_9589 */ 1212 0x958A, /* PCI_CHIP_RV630_958A */ 1213 0x958B, /* PCI_CHIP_RV630_958B */ 1214 0x958C, /* PCI_CHIP_RV630_958C */ 1215 0x958D, /* PCI_CHIP_RV630_958D */ 1216 0x958E, /* PCI_CHIP_RV630_958E */ 1217 0x958F, /* PCI_CHIP_RV630_958F */ 1218 0x9500, /* PCI_CHIP_RV670_9500 */ 1219 0x9501, /* PCI_CHIP_RV670_9501 */ 1220 0x9504, /* PCI_CHIP_RV670_9504 */ 1221 0x9505, /* PCI_CHIP_RV670_9505 */ 1222 0x9506, /* PCI_CHIP_RV670_9506 */ 1223 0x9507, /* PCI_CHIP_RV670_9507 */ 1224 0x9508, /* PCI_CHIP_RV670_9508 */ 1225 0x9509, /* PCI_CHIP_RV670_9509 */ 1226 0x950F, /* PCI_CHIP_RV670_950F */ 1227 0x9511, /* PCI_CHIP_RV670_9511 */ 1228 0x9515, /* PCI_CHIP_RV670_9515 */ 1229 0x9517, /* PCI_CHIP_RV670_9517 */ 1230 0x9519, /* PCI_CHIP_RV670_9519 */ 1231 0x95C0, /* PCI_CHIP_RV620_95C0 */ 1232 0x95C2, /* PCI_CHIP_RV620_95C2 */ 1233 0x95C4, /* PCI_CHIP_RV620_95C4 */ 1234 0x95C5, /* PCI_CHIP_RV620_95C5 */ 1235 0x95C6, /* PCI_CHIP_RV620_95C6 */ 1236 0x95C7, /* PCI_CHIP_RV620_95C7 */ 1237 0x95C9, /* PCI_CHIP_RV620_95C9 */ 1238 0x95CC, /* PCI_CHIP_RV620_95CC */ 1239 0x95CD, /* PCI_CHIP_RV620_95CD */ 1240 0x95CE, /* PCI_CHIP_RV620_95CE */ 1241 0x95CF, /* PCI_CHIP_RV620_95CF */ 1242 0x9590, /* PCI_CHIP_RV635_9590 */ 1243 0x9591, /* PCI_CHIP_RV635_9591 */ 1244 0x9593, /* PCI_CHIP_RV635_9593 */ 1245 0x9595, /* PCI_CHIP_RV635_9595 */ 1246 0x9596, /* PCI_CHIP_RV635_9596 */ 1247 0x9597, /* PCI_CHIP_RV635_9597 */ 1248 0x9598, /* PCI_CHIP_RV635_9598 */ 1249 0x9599, /* PCI_CHIP_RV635_9599 */ 1250 0x959B, /* PCI_CHIP_RV635_959B */ 1251 0x9610, /* PCI_CHIP_RS780_9610 */ 1252 0x9611, /* PCI_CHIP_RS780_9611 */ 1253 0x9612, /* PCI_CHIP_RS780_9612 */ 1254 0x9613, /* PCI_CHIP_RS780_9613 */ 1255 0x9614, /* PCI_CHIP_RS780_9614 */ 1256 0x9615, /* PCI_CHIP_RS780_9615 */ 1257 0x9616, /* PCI_CHIP_RS780_9616 */ 1258 0x9710, /* PCI_CHIP_RS880_9710 */ 1259 0x9711, /* PCI_CHIP_RS880_9711 */ 1260 0x9712, /* PCI_CHIP_RS880_9712 */ 1261 0x9713, /* PCI_CHIP_RS880_9713 */ 1262 0x9714, /* PCI_CHIP_RS880_9714 */ 1263 0x9715, /* PCI_CHIP_RS880_9715 */ 1264 0x9440, /* PCI_CHIP_RV770_9440 */ 1265 0x9441, /* PCI_CHIP_RV770_9441 */ 1266 0x9442, /* PCI_CHIP_RV770_9442 */ 1267 0x9443, /* PCI_CHIP_RV770_9443 */ 1268 0x9444, /* PCI_CHIP_RV770_9444 */ 1269 0x9446, /* PCI_CHIP_RV770_9446 */ 1270 0x944A, /* PCI_CHIP_RV770_944A */ 1271 0x944B, /* PCI_CHIP_RV770_944B */ 1272 0x944C, /* PCI_CHIP_RV770_944C */ 1273 0x944E, /* PCI_CHIP_RV770_944E */ 1274 0x9450, /* PCI_CHIP_RV770_9450 */ 1275 0x9452, /* PCI_CHIP_RV770_9452 */ 1276 0x9456, /* PCI_CHIP_RV770_9456 */ 1277 0x945A, /* PCI_CHIP_RV770_945A */ 1278 0x945B, /* PCI_CHIP_RV770_945B */ 1279 0x945E, /* PCI_CHIP_RV770_945E */ 1280 0x9460, /* PCI_CHIP_RV790_9460 */ 1281 0x9462, /* PCI_CHIP_RV790_9462 */ 1282 0x946A, /* PCI_CHIP_RV770_946A */ 1283 0x946B, /* PCI_CHIP_RV770_946B */ 1284 0x947A, /* PCI_CHIP_RV770_947A */ 1285 0x947B, /* PCI_CHIP_RV770_947B */ 1286 0x9480, /* PCI_CHIP_RV730_9480 */ 1287 0x9487, /* PCI_CHIP_RV730_9487 */ 1288 0x9488, /* PCI_CHIP_RV730_9488 */ 1289 0x9489, /* PCI_CHIP_RV730_9489 */ 1290 0x948A, /* PCI_CHIP_RV730_948A */ 1291 0x948F, /* PCI_CHIP_RV730_948F */ 1292 0x9490, /* PCI_CHIP_RV730_9490 */ 1293 0x9491, /* PCI_CHIP_RV730_9491 */ 1294 0x9495, /* PCI_CHIP_RV730_9495 */ 1295 0x9498, /* PCI_CHIP_RV730_9498 */ 1296 0x949C, /* PCI_CHIP_RV730_949C */ 1297 0x949E, /* PCI_CHIP_RV730_949E */ 1298 0x949F, /* PCI_CHIP_RV730_949F */ 1299 0x9540, /* PCI_CHIP_RV710_9540 */ 1300 0x9541, /* PCI_CHIP_RV710_9541 */ 1301 0x9542, /* PCI_CHIP_RV710_9542 */ 1302 0x954E, /* PCI_CHIP_RV710_954E */ 1303 0x954F, /* PCI_CHIP_RV710_954F */ 1304 0x9552, /* PCI_CHIP_RV710_9552 */ 1305 0x9553, /* PCI_CHIP_RV710_9553 */ 1306 0x9555, /* PCI_CHIP_RV710_9555 */ 1307 0x9557, /* PCI_CHIP_RV710_9557 */ 1308 0x955F, /* PCI_CHIP_RV710_955F */ 1309 0x94A0, /* PCI_CHIP_RV740_94A0 */ 1310 0x94A1, /* PCI_CHIP_RV740_94A1 */ 1311 0x94A3, /* PCI_CHIP_RV740_94A3 */ 1312 0x94B1, /* PCI_CHIP_RV740_94B1 */ 1313 0x94B3, /* PCI_CHIP_RV740_94B3 */ 1314 0x94B4, /* PCI_CHIP_RV740_94B4 */ 1315 0x94B5, /* PCI_CHIP_RV740_94B5 */ 1316 0x94B9, /* PCI_CHIP_RV740_94B9 */ 1317 0x68E0, /* PCI_CHIP_CEDAR_68E0 */ 1318 0x68E1, /* PCI_CHIP_CEDAR_68E1 */ 1319 0x68E4, /* PCI_CHIP_CEDAR_68E4 */ 1320 0x68E5, /* PCI_CHIP_CEDAR_68E5 */ 1321 0x68E8, /* PCI_CHIP_CEDAR_68E8 */ 1322 0x68E9, /* PCI_CHIP_CEDAR_68E9 */ 1323 0x68F1, /* PCI_CHIP_CEDAR_68F1 */ 1324 0x68F8, /* PCI_CHIP_CEDAR_68F8 */ 1325 0x68F9, /* PCI_CHIP_CEDAR_68F9 */ 1326 0x68FE, /* PCI_CHIP_CEDAR_68FE */ 1327 0x68C0, /* PCI_CHIP_REDWOOD_68C0 */ 1328 0x68C1, /* PCI_CHIP_REDWOOD_68C1 */ 1329 0x68C8, /* PCI_CHIP_REDWOOD_68C8 */ 1330 0x68C9, /* PCI_CHIP_REDWOOD_68C9 */ 1331 0x68D8, /* PCI_CHIP_REDWOOD_68D8 */ 1332 0x68D9, /* PCI_CHIP_REDWOOD_68D9 */ 1333 0x68DA, /* PCI_CHIP_REDWOOD_68DA */ 1334 0x68DE, /* PCI_CHIP_REDWOOD_68DE */ 1335 0x68A0, /* PCI_CHIP_JUNIPER_68A0 */ 1336 0x68A1, /* PCI_CHIP_JUNIPER_68A1 */ 1337 0x68A8, /* PCI_CHIP_JUNIPER_68A8 */ 1338 0x68A9, /* PCI_CHIP_JUNIPER_68A9 */ 1339 0x68B0, /* PCI_CHIP_JUNIPER_68B0 */ 1340 0x68B8, /* PCI_CHIP_JUNIPER_68B8 */ 1341 0x68B9, /* PCI_CHIP_JUNIPER_68B9 */ 1342 0x68BE, /* PCI_CHIP_JUNIPER_68BE */ 1343 0x6880, /* PCI_CHIP_CYPRESS_6880 */ 1344 0x6888, /* PCI_CHIP_CYPRESS_6888 */ 1345 0x6889, /* PCI_CHIP_CYPRESS_6889 */ 1346 0x688A, /* PCI_CHIP_CYPRESS_688A */ 1347 0x6898, /* PCI_CHIP_CYPRESS_6898 */ 1348 0x6899, /* PCI_CHIP_CYPRESS_6899 */ 1349 0x689E, /* PCI_CHIP_CYPRESS_689E */ 1350 0x689C, /* PCI_CHIP_HEMLOCK_689C */ 1351 0x689D, /* PCI_CHIP_HEMLOCK_689D */ 1352}; 1353 1354const struct dri2_driver_map driver_map[] = { 1355 { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) }, 1356 { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) }, 1357 { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) }, 1358 { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) }, 1359 { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) }, 1360 { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) }, 1361}; 1362 1363static char * 1364dri2_get_driver_for_fd(int fd) 1365{ 1366 struct udev *udev; 1367 struct udev_device *device, *parent; 1368 struct stat buf; 1369 const char *pci_id; 1370 char *driver = NULL; 1371 int vendor_id, chip_id, i, j; 1372 1373 udev = udev_new(); 1374 if (fstat(fd, &buf) < 0) { 1375 _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd); 1376 goto out; 1377 } 1378 1379 device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); 1380 if (device == NULL) { 1381 _eglLog(_EGL_WARNING, 1382 "EGL-DRI2: could not create udev device for fd %d", fd); 1383 goto out; 1384 } 1385 1386 parent = udev_device_get_parent(device); 1387 if (parent == NULL) { 1388 _eglLog(_EGL_WARNING, "DRI2: could not get parent device"); 1389 goto out; 1390 } 1391 1392 pci_id = udev_device_get_property_value(parent, "PCI_ID"); 1393 if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) { 1394 _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID"); 1395 goto out; 1396 } 1397 1398 for (i = 0; i < ARRAY_SIZE(driver_map); i++) { 1399 if (vendor_id != driver_map[i].vendor_id) 1400 continue; 1401 for (j = 0; j < driver_map[i].num_chips_ids; j++) 1402 if (driver_map[i].chip_ids[j] == chip_id) { 1403 driver = strdup(driver_map[i].driver); 1404 _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s", 1405 fd, vendor_id, chip_id, driver); 1406 goto out; 1407 } 1408 } 1409 1410 out: 1411 udev_device_unref(device); 1412 udev_unref(udev); 1413 1414 return driver; 1415} 1416 1417static EGLBoolean 1418dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp, 1419 EGLint *major, EGLint *minor) 1420{ 1421 struct dri2_egl_display *dri2_dpy; 1422 int i; 1423 1424 dri2_dpy = malloc(sizeof *dri2_dpy); 1425 if (!dri2_dpy) 1426 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 1427 1428 disp->DriverData = (void *) dri2_dpy; 1429 dri2_dpy->fd = (int) disp->PlatformDisplay; 1430 1431 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); 1432 if (dri2_dpy->driver_name == NULL) 1433 return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); 1434 1435 if (!dri2_load_driver(disp)) 1436 goto cleanup_driver_name; 1437 1438 dri2_dpy->extensions[0] = &image_lookup_extension.base; 1439 dri2_dpy->extensions[1] = &use_invalidate.base; 1440 dri2_dpy->extensions[2] = NULL; 1441 1442 if (!dri2_create_screen(disp)) 1443 goto cleanup_driver; 1444 1445 for (i = 0; dri2_dpy->driver_configs[i]; i++) 1446 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0); 1447 1448 disp->Extensions.MESA_drm_image = EGL_TRUE; 1449 disp->Extensions.KHR_image_base = EGL_TRUE; 1450 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 1451 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 1452 1453 /* we're supporting EGL 1.4 */ 1454 *major = 1; 1455 *minor = 4; 1456 1457 return EGL_TRUE; 1458 1459 cleanup_driver: 1460 dlclose(dri2_dpy->driver); 1461 cleanup_driver_name: 1462 free(dri2_dpy->driver_name); 1463 1464 return EGL_FALSE; 1465} 1466 1467#endif 1468 1469/** 1470 * Called via eglInitialize(), GLX_drv->API.Initialize(). 1471 */ 1472static EGLBoolean 1473dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp, 1474 EGLint *major, EGLint *minor) 1475{ 1476 switch (disp->Platform) { 1477 case _EGL_PLATFORM_X11: 1478 return dri2_initialize_x11(drv, disp, major, minor); 1479 1480#ifdef HAVE_LIBUDEV 1481 case _EGL_PLATFORM_DRM: 1482 return dri2_initialize_drm(drv, disp, major, minor); 1483#endif 1484 1485 default: 1486 return EGL_FALSE; 1487 } 1488} 1489 1490/** 1491 * Called via eglTerminate(), drv->API.Terminate(). 1492 */ 1493static EGLBoolean 1494dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 1495{ 1496 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1497 1498 _eglReleaseDisplayResources(drv, disp); 1499 _eglCleanupDisplay(disp); 1500 1501 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 1502 close(dri2_dpy->fd); 1503 dlclose(dri2_dpy->driver); 1504 if (disp->PlatformDisplay == NULL) 1505 xcb_disconnect(dri2_dpy->conn); 1506 free(dri2_dpy); 1507 disp->DriverData = NULL; 1508 1509 return EGL_TRUE; 1510} 1511 1512 1513/** 1514 * Called via eglCreateContext(), drv->API.CreateContext(). 1515 */ 1516static _EGLContext * 1517dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 1518 _EGLContext *share_list, const EGLint *attrib_list) 1519{ 1520 struct dri2_egl_context *dri2_ctx; 1521 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1522 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 1523 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 1524 const __DRIconfig *dri_config; 1525 int api; 1526 1527 (void) drv; 1528 1529 dri2_ctx = malloc(sizeof *dri2_ctx); 1530 if (!dri2_ctx) { 1531 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 1532 return NULL; 1533 } 1534 1535 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 1536 goto cleanup; 1537 1538 switch (dri2_ctx->base.ClientAPI) { 1539 case EGL_OPENGL_ES_API: 1540 switch (dri2_ctx->base.ClientVersion) { 1541 case 1: 1542 api = __DRI_API_GLES; 1543 break; 1544 case 2: 1545 api = __DRI_API_GLES2; 1546 break; 1547 default: 1548 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1549 return NULL; 1550 } 1551 break; 1552 case EGL_OPENGL_API: 1553 api = __DRI_API_OPENGL; 1554 break; 1555 default: 1556 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1557 return NULL; 1558 } 1559 1560 if (conf != NULL) 1561 dri_config = dri2_config->dri_config; 1562 else 1563 dri_config = NULL; 1564 1565 if (dri2_dpy->dri2->base.version >= 2) { 1566 dri2_ctx->dri_context = 1567 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 1568 api, 1569 dri_config, 1570 dri2_ctx_shared ? 1571 dri2_ctx_shared->dri_context : NULL, 1572 dri2_ctx); 1573 } else if (api == __DRI_API_OPENGL) { 1574 dri2_ctx->dri_context = 1575 dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen, 1576 dri2_config->dri_config, 1577 dri2_ctx_shared ? 1578 dri2_ctx_shared->dri_context : NULL, 1579 dri2_ctx); 1580 } else { 1581 /* fail */ 1582 } 1583 1584 if (!dri2_ctx->dri_context) 1585 goto cleanup; 1586 1587 return &dri2_ctx->base; 1588 1589 cleanup: 1590 free(dri2_ctx); 1591 return NULL; 1592} 1593 1594static EGLBoolean 1595dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1596{ 1597 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1598 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1599 1600 (void) drv; 1601 1602 if (!_eglPutSurface(surf)) 1603 return EGL_TRUE; 1604 1605 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); 1606 1607 xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable); 1608 1609 if (surf->Type == EGL_PBUFFER_BIT) 1610 xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable); 1611 1612 free(surf); 1613 1614 return EGL_TRUE; 1615} 1616 1617/** 1618 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 1619 */ 1620static EGLBoolean 1621dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 1622 _EGLSurface *rsurf, _EGLContext *ctx) 1623{ 1624 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1625 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1626 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 1627 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 1628 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1629 _EGLContext *old_ctx; 1630 _EGLSurface *old_dsurf, *old_rsurf; 1631 __DRIdrawable *ddraw, *rdraw; 1632 __DRIcontext *cctx; 1633 1634 /* make new bindings */ 1635 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 1636 return EGL_FALSE; 1637 1638 /* flush before context switch */ 1639 if (old_ctx && dri2_drv->glFlush) 1640 dri2_drv->glFlush(); 1641 1642 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 1643 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 1644 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 1645 1646 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 1647 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 1648 dri2_destroy_surface(drv, disp, old_dsurf); 1649 dri2_destroy_surface(drv, disp, old_rsurf); 1650 if (old_ctx) { 1651 /* unbind the old context only when there is no new context bound */ 1652 if (!ctx) { 1653 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 1654 dri2_dpy->core->unbindContext(old_cctx); 1655 } 1656 /* no destroy? */ 1657 _eglPutContext(old_ctx); 1658 } 1659 1660 return EGL_TRUE; 1661 } else { 1662 /* undo the previous _eglBindContext */ 1663 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 1664 assert(&dri2_ctx->base == ctx && 1665 &dri2_dsurf->base == dsurf && 1666 &dri2_rsurf->base == rsurf); 1667 1668 _eglPutSurface(dsurf); 1669 _eglPutSurface(rsurf); 1670 _eglPutContext(ctx); 1671 1672 _eglPutSurface(old_dsurf); 1673 _eglPutSurface(old_rsurf); 1674 _eglPutContext(old_ctx); 1675 1676 return EGL_FALSE; 1677 } 1678} 1679 1680/** 1681 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 1682 */ 1683static _EGLSurface * 1684dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 1685 _EGLConfig *conf, EGLNativeWindowType window, 1686 const EGLint *attrib_list) 1687{ 1688 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1689 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 1690 struct dri2_egl_surface *dri2_surf; 1691 xcb_get_geometry_cookie_t cookie; 1692 xcb_get_geometry_reply_t *reply; 1693 xcb_screen_iterator_t s; 1694 xcb_generic_error_t *error; 1695 1696 (void) drv; 1697 1698 dri2_surf = malloc(sizeof *dri2_surf); 1699 if (!dri2_surf) { 1700 _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 1701 return NULL; 1702 } 1703 1704 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 1705 goto cleanup_surf; 1706 1707 dri2_surf->region = XCB_NONE; 1708 if (type == EGL_PBUFFER_BIT) { 1709 dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn); 1710 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn)); 1711 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize, 1712 dri2_surf->drawable, s.data->root, 1713 dri2_surf->base.Width, dri2_surf->base.Height); 1714 } else { 1715 dri2_surf->drawable = window; 1716 } 1717 1718 dri2_surf->dri_drawable = 1719 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, 1720 dri2_conf->dri_config, dri2_surf); 1721 if (dri2_surf->dri_drawable == NULL) { 1722 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 1723 goto cleanup_pixmap; 1724 } 1725 1726 xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable); 1727 1728 if (type != EGL_PBUFFER_BIT) { 1729 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable); 1730 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error); 1731 if (reply == NULL || error != NULL) { 1732 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); 1733 free(error); 1734 goto cleanup_dri_drawable; 1735 } 1736 1737 dri2_surf->base.Width = reply->width; 1738 dri2_surf->base.Height = reply->height; 1739 free(reply); 1740 } 1741 1742 return &dri2_surf->base; 1743 1744 cleanup_dri_drawable: 1745 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 1746 cleanup_pixmap: 1747 if (type == EGL_PBUFFER_BIT) 1748 xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable); 1749 cleanup_surf: 1750 free(dri2_surf); 1751 1752 return NULL; 1753} 1754 1755/** 1756 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 1757 */ 1758static _EGLSurface * 1759dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 1760 _EGLConfig *conf, EGLNativeWindowType window, 1761 const EGLint *attrib_list) 1762{ 1763 return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 1764 window, attrib_list); 1765} 1766 1767static _EGLSurface * 1768dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, 1769 _EGLConfig *conf, EGLNativePixmapType pixmap, 1770 const EGLint *attrib_list) 1771{ 1772 return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, 1773 pixmap, attrib_list); 1774} 1775 1776static _EGLSurface * 1777dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 1778 _EGLConfig *conf, const EGLint *attrib_list) 1779{ 1780 return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf, 1781 XCB_WINDOW_NONE, attrib_list); 1782} 1783 1784static EGLBoolean 1785dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp, 1786 _EGLSurface *draw, xcb_xfixes_region_t region) 1787{ 1788 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1789 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1790 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 1791 _EGLContext *ctx; 1792 xcb_dri2_copy_region_cookie_t cookie; 1793 1794 if (dri2_drv->glFlush) { 1795 ctx = _eglGetCurrentContext(); 1796 if (ctx && ctx->DrawSurface == &dri2_surf->base) 1797 dri2_drv->glFlush(); 1798 } 1799 1800 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 1801 1802#if 0 1803 /* FIXME: Add support for dri swapbuffers, that'll give us swap 1804 * interval and page flipping (at least for fullscreen windows) as 1805 * well as the page flip event. Unless surface->SwapBehavior is 1806 * EGL_BUFFER_PRESERVED. */ 1807#if __DRI2_FLUSH_VERSION >= 2 1808 if (pdraw->psc->f) 1809 (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); 1810#endif 1811#endif 1812 1813 if (!dri2_surf->have_fake_front) 1814 return EGL_TRUE; 1815 1816 cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn, 1817 dri2_surf->drawable, 1818 region, 1819 XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, 1820 XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT); 1821 free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL)); 1822 1823 return EGL_TRUE; 1824} 1825 1826static EGLBoolean 1827dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 1828{ 1829 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 1830 1831 return dri2_copy_region(drv, disp, draw, dri2_surf->region); 1832} 1833 1834static EGLBoolean 1835dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw, 1836 EGLint numRects, const EGLint *rects) 1837{ 1838 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1839 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 1840 EGLBoolean ret; 1841 xcb_xfixes_region_t region; 1842 xcb_rectangle_t rectangles[16]; 1843 int i; 1844 1845 if (numRects > (int)ARRAY_SIZE(rectangles)) 1846 return dri2_copy_region(drv, disp, draw, dri2_surf->region); 1847 1848 /* FIXME: Invert y here? */ 1849 for (i = 0; i < numRects; i++) { 1850 rectangles[i].x = rects[i * 4]; 1851 rectangles[i].y = rects[i * 4 + 1]; 1852 rectangles[i].width = rects[i * 4 + 2]; 1853 rectangles[i].height = rects[i * 4 + 3]; 1854 } 1855 1856 region = xcb_generate_id(dri2_dpy->conn); 1857 xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles); 1858 ret = dri2_copy_region(drv, disp, draw, region); 1859 xcb_xfixes_destroy_region(dri2_dpy->conn, region); 1860 1861 return ret; 1862} 1863 1864/* 1865 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 1866 */ 1867static _EGLProc 1868dri2_get_proc_address(_EGLDriver *drv, const char *procname) 1869{ 1870 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1871 1872 return dri2_drv->get_proc_address(procname); 1873} 1874 1875static EGLBoolean 1876dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 1877{ 1878 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1879 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 1880 1881 (void) drv; 1882 1883 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 1884 * we need to copy fake to real here.*/ 1885 1886 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 1887 1888 return EGL_TRUE; 1889} 1890 1891static EGLBoolean 1892dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 1893{ 1894 (void) drv; 1895 (void) disp; 1896 1897 if (engine != EGL_CORE_NATIVE_ENGINE) 1898 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 1899 /* glXWaitX(); */ 1900 1901 return EGL_TRUE; 1902} 1903 1904static EGLBoolean 1905dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1906 EGLNativePixmapType target) 1907{ 1908 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1909 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1910 xcb_gcontext_t gc; 1911 1912 (void) drv; 1913 1914 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 1915 1916 gc = xcb_generate_id(dri2_dpy->conn); 1917 xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL); 1918 xcb_copy_area(dri2_dpy->conn, 1919 dri2_surf->drawable, 1920 target, 1921 gc, 1922 0, 0, 1923 0, 0, 1924 dri2_surf->base.Width, 1925 dri2_surf->base.Height); 1926 xcb_free_gc(dri2_dpy->conn, gc); 1927 1928 return EGL_TRUE; 1929} 1930 1931static EGLBoolean 1932dri2_bind_tex_image(_EGLDriver *drv, 1933 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1934{ 1935 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1936 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1937 struct dri2_egl_context *dri2_ctx; 1938 _EGLContext *ctx; 1939 GLint format, target; 1940 1941 ctx = _eglGetCurrentContext(); 1942 dri2_ctx = dri2_egl_context(ctx); 1943 1944 if (!_eglBindTexImage(drv, disp, surf, buffer)) 1945 return EGL_FALSE; 1946 1947 switch (dri2_surf->base.TextureFormat) { 1948 case EGL_TEXTURE_RGB: 1949 format = __DRI_TEXTURE_FORMAT_RGB; 1950 break; 1951 case EGL_TEXTURE_RGBA: 1952 format = __DRI_TEXTURE_FORMAT_RGBA; 1953 break; 1954 default: 1955 assert(0); 1956 } 1957 1958 switch (dri2_surf->base.TextureTarget) { 1959 case EGL_TEXTURE_2D: 1960 target = GL_TEXTURE_2D; 1961 break; 1962 default: 1963 assert(0); 1964 } 1965 1966 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 1967 target, format, 1968 dri2_surf->dri_drawable); 1969 1970 return EGL_TRUE; 1971} 1972 1973static EGLBoolean 1974dri2_release_tex_image(_EGLDriver *drv, 1975 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1976{ 1977#if __DRI_TEX_BUFFER_VERSION >= 3 1978 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1979 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1980 struct dri2_egl_context *dri2_ctx; 1981 _EGLContext *ctx; 1982 GLint target; 1983 1984 ctx = _eglGetCurrentContext(); 1985 dri2_ctx = dri2_egl_context(ctx); 1986 1987 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 1988 return EGL_FALSE; 1989 1990 switch (dri2_surf->base.TextureTarget) { 1991 case EGL_TEXTURE_2D: 1992 target = GL_TEXTURE_2D; 1993 break; 1994 default: 1995 assert(0); 1996 } 1997 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL) 1998 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 1999 target, 2000 dri2_surf->dri_drawable); 2001#endif 2002 2003 return EGL_TRUE; 2004} 2005 2006static _EGLImage * 2007dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, 2008 EGLClientBuffer buffer, const EGLint *attr_list) 2009{ 2010 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2011 struct dri2_egl_image *dri2_img; 2012 unsigned int attachments[1]; 2013 xcb_drawable_t drawable; 2014 xcb_dri2_get_buffers_cookie_t buffers_cookie; 2015 xcb_dri2_get_buffers_reply_t *buffers_reply; 2016 xcb_dri2_dri2_buffer_t *buffers; 2017 xcb_get_geometry_cookie_t geometry_cookie; 2018 xcb_get_geometry_reply_t *geometry_reply; 2019 xcb_generic_error_t *error; 2020 int stride, format; 2021 2022 (void) ctx; 2023 2024 drawable = (xcb_drawable_t) buffer; 2025 xcb_dri2_create_drawable (dri2_dpy->conn, drawable); 2026 attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT; 2027 buffers_cookie = 2028 xcb_dri2_get_buffers_unchecked (dri2_dpy->conn, 2029 drawable, 1, 1, attachments); 2030 geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable); 2031 buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, 2032 buffers_cookie, NULL); 2033 buffers = xcb_dri2_get_buffers_buffers (buffers_reply); 2034 if (buffers == NULL) { 2035 return NULL; 2036 } 2037 2038 geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn, 2039 geometry_cookie, &error); 2040 if (geometry_reply == NULL || error != NULL) { 2041 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry"); 2042 free(error); 2043 free(buffers_reply); 2044 } 2045 2046 switch (geometry_reply->depth) { 2047 case 16: 2048 format = __DRI_IMAGE_FORMAT_RGB565; 2049 break; 2050 case 24: 2051 format = __DRI_IMAGE_FORMAT_XRGB8888; 2052 break; 2053 case 32: 2054 format = __DRI_IMAGE_FORMAT_ARGB8888; 2055 break; 2056 default: 2057 _eglError(EGL_BAD_PARAMETER, 2058 "dri2_create_image_khr: unsupported pixmap depth"); 2059 free(buffers_reply); 2060 free(geometry_reply); 2061 return NULL; 2062 } 2063 2064 dri2_img = malloc(sizeof *dri2_img); 2065 if (!dri2_img) { 2066 free(buffers_reply); 2067 free(geometry_reply); 2068 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2069 return EGL_NO_IMAGE_KHR; 2070 } 2071 2072 if (!_eglInitImage(&dri2_img->base, disp)) { 2073 free(buffers_reply); 2074 free(geometry_reply); 2075 return EGL_NO_IMAGE_KHR; 2076 } 2077 2078 stride = buffers[0].pitch / buffers[0].cpp; 2079 dri2_img->dri_image = 2080 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 2081 buffers_reply->width, 2082 buffers_reply->height, 2083 format, 2084 buffers[0].name, 2085 stride, 2086 dri2_img); 2087 2088 free(buffers_reply); 2089 free(geometry_reply); 2090 2091 return &dri2_img->base; 2092} 2093 2094static _EGLImage * 2095dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 2096 EGLClientBuffer buffer, 2097 const EGLint *attr_list) 2098{ 2099 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2100 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2101 struct dri2_egl_image *dri2_img; 2102 GLuint renderbuffer = (GLuint) buffer; 2103 2104 if (renderbuffer == 0) { 2105 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2106 return EGL_NO_IMAGE_KHR; 2107 } 2108 2109 dri2_img = malloc(sizeof *dri2_img); 2110 if (!dri2_img) { 2111 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2112 return EGL_NO_IMAGE_KHR; 2113 } 2114 2115 if (!_eglInitImage(&dri2_img->base, disp)) 2116 return EGL_NO_IMAGE_KHR; 2117 2118 dri2_img->dri_image = 2119 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 2120 renderbuffer, 2121 dri2_img); 2122 2123 return &dri2_img->base; 2124} 2125 2126static _EGLImage * 2127dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 2128 EGLClientBuffer buffer, const EGLint *attr_list) 2129{ 2130 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2131 struct dri2_egl_image *dri2_img; 2132 EGLint format, name, pitch, err; 2133 _EGLImageAttribs attrs; 2134 2135 (void) ctx; 2136 2137 name = (EGLint) buffer; 2138 2139 err = _eglParseImageAttribList(&attrs, disp, attr_list); 2140 if (err != EGL_SUCCESS) 2141 return NULL; 2142 2143 if (attrs.Width <= 0 || attrs.Height <= 0 || 2144 attrs.DRMBufferStrideMESA <= 0) { 2145 _eglError(EGL_BAD_PARAMETER, 2146 "bad width, height or stride"); 2147 return NULL; 2148 } 2149 2150 switch (attrs.DRMBufferFormatMESA) { 2151 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2152 format = __DRI_IMAGE_FORMAT_ARGB8888; 2153 pitch = attrs.DRMBufferStrideMESA; 2154 break; 2155 default: 2156 _eglError(EGL_BAD_PARAMETER, 2157 "dri2_create_image_khr: unsupported pixmap depth"); 2158 return NULL; 2159 } 2160 2161 dri2_img = malloc(sizeof *dri2_img); 2162 if (!dri2_img) { 2163 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm"); 2164 return NULL; 2165 } 2166 2167 if (!_eglInitImage(&dri2_img->base, disp)) { 2168 free(dri2_img); 2169 return NULL; 2170 } 2171 2172 dri2_img->dri_image = 2173 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 2174 attrs.Width, 2175 attrs.Height, 2176 format, 2177 name, 2178 pitch, 2179 dri2_img); 2180 if (dri2_img->dri_image == NULL) { 2181 free(dri2_img); 2182 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm"); 2183 return NULL; 2184 } 2185 2186 return &dri2_img->base; 2187} 2188 2189static _EGLImage * 2190dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 2191 _EGLContext *ctx, EGLenum target, 2192 EGLClientBuffer buffer, const EGLint *attr_list) 2193{ 2194 (void) drv; 2195 2196 switch (target) { 2197 case EGL_NATIVE_PIXMAP_KHR: 2198 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 2199 case EGL_GL_RENDERBUFFER_KHR: 2200 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 2201 case EGL_DRM_BUFFER_MESA: 2202 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 2203 default: 2204 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2205 return EGL_NO_IMAGE_KHR; 2206 } 2207} 2208 2209static EGLBoolean 2210dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 2211{ 2212 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2213 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 2214 2215 (void) drv; 2216 2217 dri2_dpy->image->destroyImage(dri2_img->dri_image); 2218 free(dri2_img); 2219 2220 return EGL_TRUE; 2221} 2222 2223static _EGLImage * 2224dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 2225 const EGLint *attr_list) 2226{ 2227 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2228 struct dri2_egl_image *dri2_img; 2229 _EGLImageAttribs attrs; 2230 unsigned int dri_use, valid_mask; 2231 int format; 2232 EGLint err = EGL_SUCCESS; 2233 2234 (void) drv; 2235 2236 dri2_img = malloc(sizeof *dri2_img); 2237 if (!dri2_img) { 2238 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2239 return EGL_NO_IMAGE_KHR; 2240 } 2241 2242 if (!attr_list) { 2243 err = EGL_BAD_PARAMETER; 2244 goto cleanup_img; 2245 } 2246 2247 if (!_eglInitImage(&dri2_img->base, disp)) { 2248 err = EGL_BAD_PARAMETER; 2249 goto cleanup_img; 2250 } 2251 2252 err = _eglParseImageAttribList(&attrs, disp, attr_list); 2253 if (err != EGL_SUCCESS) 2254 goto cleanup_img; 2255 2256 if (attrs.Width <= 0 || attrs.Height <= 0) { 2257 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 2258 attrs.Width, attrs.Height); 2259 goto cleanup_img; 2260 } 2261 2262 switch (attrs.DRMBufferFormatMESA) { 2263 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2264 format = __DRI_IMAGE_FORMAT_ARGB8888; 2265 break; 2266 default: 2267 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 2268 attrs.DRMBufferFormatMESA); 2269 goto cleanup_img; 2270 } 2271 2272 valid_mask = 2273 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 2274 EGL_DRM_BUFFER_USE_SHARE_MESA; 2275 if (attrs.DRMBufferUseMESA & ~valid_mask) { 2276 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 2277 attrs.DRMBufferUseMESA & ~valid_mask); 2278 goto cleanup_img; 2279 } 2280 2281 dri_use = 0; 2282 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 2283 dri_use |= __DRI_IMAGE_USE_SHARE; 2284 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 2285 dri_use |= __DRI_IMAGE_USE_SCANOUT; 2286 2287 dri2_img->dri_image = 2288 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 2289 attrs.Width, attrs.Height, 2290 format, dri_use, dri2_img); 2291 if (dri2_img->dri_image == NULL) { 2292 err = EGL_BAD_ALLOC; 2293 goto cleanup_img; 2294 } 2295 2296 return &dri2_img->base; 2297 2298 cleanup_img: 2299 free(dri2_img); 2300 _eglError(err, "dri2_create_drm_image_mesa"); 2301 2302 return EGL_NO_IMAGE_KHR; 2303} 2304 2305static EGLBoolean 2306dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 2307 EGLint *name, EGLint *handle, EGLint *stride) 2308{ 2309 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2310 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 2311 2312 (void) drv; 2313 2314 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 2315 __DRI_IMAGE_ATTRIB_NAME, name)) { 2316 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 2317 return EGL_FALSE; 2318 } 2319 2320 if (handle) 2321 dri2_dpy->image->queryImage(dri2_img->dri_image, 2322 __DRI_IMAGE_ATTRIB_HANDLE, handle); 2323 2324 if (stride) 2325 dri2_dpy->image->queryImage(dri2_img->dri_image, 2326 __DRI_IMAGE_ATTRIB_STRIDE, stride); 2327 2328 return EGL_TRUE; 2329} 2330 2331static void 2332dri2_unload(_EGLDriver *drv) 2333{ 2334 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 2335 free(dri2_drv); 2336} 2337 2338static EGLBoolean 2339dri2_load(_EGLDriver *drv) 2340{ 2341 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 2342 void *handle; 2343 2344 handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); 2345 if (handle) { 2346 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 2347 dlsym(handle, "_glapi_get_proc_address"); 2348 /* no need to keep a reference */ 2349 dlclose(handle); 2350 } 2351 2352 /* 2353 * If glapi is not available, loading DRI drivers will fail. Ideally, we 2354 * should load one of libGL, libGLESv1_CM, or libGLESv2 and go on. But if 2355 * the app has loaded another one of them with RTLD_LOCAL, there may be 2356 * unexpected behaviors later because there will be two copies of glapi 2357 * (with global variables of the same names!) in the memory. 2358 */ 2359 if (!dri2_drv->get_proc_address) { 2360 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 2361 return EGL_FALSE; 2362 } 2363 2364 dri2_drv->glFlush = (void (*)(void)) 2365 dri2_drv->get_proc_address("glFlush"); 2366 2367 return EGL_TRUE; 2368} 2369 2370/** 2371 * This is the main entrypoint into the driver, called by libEGL. 2372 * Create a new _EGLDriver object and init its dispatch table. 2373 */ 2374_EGLDriver * 2375_eglMain(const char *args) 2376{ 2377 struct dri2_egl_driver *dri2_drv; 2378 2379 (void) args; 2380 2381 dri2_drv = malloc(sizeof *dri2_drv); 2382 if (!dri2_drv) 2383 return NULL; 2384 2385 if (!dri2_load(&dri2_drv->base)) 2386 return NULL; 2387 2388 memset(dri2_drv, 0, sizeof *dri2_drv); 2389 _eglInitDriverFallbacks(&dri2_drv->base); 2390 dri2_drv->base.API.Initialize = dri2_initialize; 2391 dri2_drv->base.API.Terminate = dri2_terminate; 2392 dri2_drv->base.API.CreateContext = dri2_create_context; 2393 dri2_drv->base.API.MakeCurrent = dri2_make_current; 2394 dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface; 2395 dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface; 2396 dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface; 2397 dri2_drv->base.API.DestroySurface = dri2_destroy_surface; 2398 dri2_drv->base.API.SwapBuffers = dri2_swap_buffers; 2399 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 2400 dri2_drv->base.API.WaitClient = dri2_wait_client; 2401 dri2_drv->base.API.WaitNative = dri2_wait_native; 2402 dri2_drv->base.API.CopyBuffers = dri2_copy_buffers; 2403 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 2404 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 2405 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; 2406 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 2407 dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region; 2408 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 2409 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 2410 2411 dri2_drv->base.Name = "DRI2"; 2412 dri2_drv->base.Unload = dri2_unload; 2413 2414 return &dri2_drv->base; 2415} 2416