egl_dri2: Export glapi symbols for DRI drivers.
[mesa.git] / src / egl / drivers / dri2 / egl_dri2.c
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
61 struct dri2_egl_driver
62 {
63 _EGLDriver base;
64
65 void *handle;
66 _EGLProc (*get_proc_address)(const char *procname);
67 void (*glFlush)(void);
68 };
69
70 struct dri2_egl_display
71 {
72 xcb_connection_t *conn;
73 int dri2_major;
74 int dri2_minor;
75 __DRIscreen *dri_screen;
76 const __DRIconfig **driver_configs;
77 void *driver;
78 __DRIcoreExtension *core;
79 __DRIdri2Extension *dri2;
80 __DRI2flushExtension *flush;
81 __DRItexBufferExtension *tex_buffer;
82 __DRIimageExtension *image;
83 int fd;
84
85 char *device_name;
86 char *driver_name;
87
88 __DRIdri2LoaderExtension loader_extension;
89 const __DRIextension *extensions[3];
90 };
91
92 struct dri2_egl_context
93 {
94 _EGLContext base;
95 __DRIcontext *dri_context;
96 };
97
98 struct dri2_egl_surface
99 {
100 _EGLSurface base;
101 __DRIdrawable *dri_drawable;
102 xcb_drawable_t drawable;
103 __DRIbuffer buffers[5];
104 int buffer_count;
105 xcb_xfixes_region_t region;
106 int have_fake_front;
107 int swap_interval;
108 };
109
110 struct dri2_egl_config
111 {
112 _EGLConfig base;
113 const __DRIconfig *dri_config;
114 };
115
116 struct dri2_egl_image
117 {
118 _EGLImage base;
119 __DRIimage *dri_image;
120 };
121
122 /* standard typecasts */
123 _EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
124 _EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
125
126 static const __DRIuseInvalidateExtension use_invalidate = {
127 { __DRI_USE_INVALIDATE, 1 }
128 };
129
130 EGLint dri2_to_egl_attribute_map[] = {
131 0,
132 EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */
133 EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */
134 EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */
135 EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */
136 EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */
137 EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */
138 EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */
139 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */
140 EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */
141 EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */
142 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */
143 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
144 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
145 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
146 EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */
147 EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */
148 0, /* __DRI_ATTRIB_RENDER_TYPE, */
149 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */
150 0, /* __DRI_ATTRIB_CONFORMANT */
151 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */
152 0, /* __DRI_ATTRIB_STEREO */
153 0, /* __DRI_ATTRIB_AUX_BUFFERS */
154 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */
155 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
156 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
157 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
158 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
159 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
160 0, /* __DRI_ATTRIB_FLOAT_MODE */
161 0, /* __DRI_ATTRIB_RED_MASK */
162 0, /* __DRI_ATTRIB_GREEN_MASK */
163 0, /* __DRI_ATTRIB_BLUE_MASK */
164 0, /* __DRI_ATTRIB_ALPHA_MASK */
165 EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
166 EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
167 EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
168 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
169 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
170 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
171 0, /* __DRI_ATTRIB_SWAP_METHOD */
172 EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
173 EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
174 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
175 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
176 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
177 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
178 EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */
179 };
180
181 static struct dri2_egl_config *
182 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
183 int depth, EGLint surface_type)
184 {
185 struct dri2_egl_config *conf;
186 struct dri2_egl_display *dri2_dpy;
187 _EGLConfig base;
188 unsigned int attrib, value, double_buffer;
189 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
190 int i;
191
192 dri2_dpy = disp->DriverData;
193 _eglInitConfig(&base, disp, id);
194
195 i = 0;
196 double_buffer = 0;
197 bind_to_texture_rgb = 0;
198 bind_to_texture_rgba = 0;
199
200 while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
201 switch (attrib) {
202 case __DRI_ATTRIB_RENDER_TYPE:
203 if (value & __DRI_ATTRIB_RGBA_BIT)
204 value = EGL_RGB_BUFFER;
205 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
206 value = EGL_LUMINANCE_BUFFER;
207 else
208 /* not valid */;
209 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
210 break;
211
212 case __DRI_ATTRIB_CONFIG_CAVEAT:
213 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
214 value = EGL_NON_CONFORMANT_CONFIG;
215 else if (value & __DRI_ATTRIB_SLOW_BIT)
216 value = EGL_SLOW_CONFIG;
217 else
218 value = EGL_NONE;
219 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
220 break;
221
222 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
223 bind_to_texture_rgb = value;
224 break;
225
226 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
227 bind_to_texture_rgba = value;
228 break;
229
230 case __DRI_ATTRIB_DOUBLE_BUFFER:
231 double_buffer = value;
232 break;
233
234 default:
235 key = dri2_to_egl_attribute_map[attrib];
236 if (key != 0)
237 _eglSetConfigKey(&base, key, value);
238 break;
239 }
240 }
241
242 /* In EGL, double buffer or not isn't a config attribute. Pixmaps
243 * surfaces are always single buffered, pbuffer surfaces are always
244 * back buffers and windows can be either, selected by passing an
245 * attribute at window surface construction time. To support this
246 * we ignore all double buffer configs and manipulate the buffer we
247 * return in the getBuffer callback to get the behaviour we want. */
248
249 if (double_buffer)
250 return NULL;
251
252 if (depth > 0 && depth != base.BufferSize)
253 return NULL;
254
255 base.NativeRenderable = EGL_TRUE;
256
257 base.SurfaceType = surface_type;
258 if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) {
259 base.BindToTextureRGB = bind_to_texture_rgb;
260 if (base.AlphaSize > 0)
261 base.BindToTextureRGBA = bind_to_texture_rgba;
262 }
263
264 base.RenderableType = disp->ClientAPIs;
265 base.Conformant = disp->ClientAPIs;
266
267 if (!_eglValidateConfig(&base, EGL_FALSE)) {
268 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
269 return NULL;
270 }
271
272 conf = malloc(sizeof *conf);
273 if (conf != NULL) {
274 memcpy(&conf->base, &base, sizeof base);
275 conf->dri_config = dri_config;
276 _eglLinkConfig(&conf->base);
277 }
278
279 return conf;
280 }
281
282 /**
283 * Process list of buffer received from the server
284 *
285 * Processes the list of buffers received in a reply from the server to either
286 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
287 */
288 static void
289 dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
290 xcb_dri2_dri2_buffer_t *buffers, unsigned count)
291 {
292 struct dri2_egl_display *dri2_dpy =
293 dri2_egl_display(dri2_surf->base.Resource.Display);
294 xcb_rectangle_t rectangle;
295 unsigned i;
296
297 dri2_surf->buffer_count = count;
298 dri2_surf->have_fake_front = 0;
299
300 /* This assumes the DRI2 buffer attachment tokens matches the
301 * __DRIbuffer tokens. */
302 for (i = 0; i < count; i++) {
303 dri2_surf->buffers[i].attachment = buffers[i].attachment;
304 dri2_surf->buffers[i].name = buffers[i].name;
305 dri2_surf->buffers[i].pitch = buffers[i].pitch;
306 dri2_surf->buffers[i].cpp = buffers[i].cpp;
307 dri2_surf->buffers[i].flags = buffers[i].flags;
308
309 /* We only use the DRI drivers single buffer configs. This
310 * means that if we try to render to a window, DRI2 will give us
311 * the fake front buffer, which we'll use as a back buffer.
312 * Note that EGL doesn't require that several clients rendering
313 * to the same window must see the same aux buffers. */
314 if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
315 dri2_surf->have_fake_front = 1;
316 }
317
318 if (dri2_surf->region != XCB_NONE)
319 xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
320
321 rectangle.x = 0;
322 rectangle.y = 0;
323 rectangle.width = dri2_surf->base.Width;
324 rectangle.height = dri2_surf->base.Height;
325 dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
326 xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
327 }
328
329 static __DRIbuffer *
330 dri2_get_buffers(__DRIdrawable * driDrawable,
331 int *width, int *height,
332 unsigned int *attachments, int count,
333 int *out_count, void *loaderPrivate)
334 {
335 struct dri2_egl_surface *dri2_surf = loaderPrivate;
336 struct dri2_egl_display *dri2_dpy =
337 dri2_egl_display(dri2_surf->base.Resource.Display);
338 xcb_dri2_dri2_buffer_t *buffers;
339 xcb_dri2_get_buffers_reply_t *reply;
340 xcb_dri2_get_buffers_cookie_t cookie;
341
342 (void) driDrawable;
343
344 cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
345 dri2_surf->drawable,
346 count, count, attachments);
347 reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
348 buffers = xcb_dri2_get_buffers_buffers (reply);
349 if (buffers == NULL)
350 return NULL;
351
352 *out_count = reply->count;
353 dri2_surf->base.Width = *width = reply->width;
354 dri2_surf->base.Height = *height = reply->height;
355 dri2_process_buffers(dri2_surf, buffers, *out_count);
356
357 free(reply);
358
359 return dri2_surf->buffers;
360 }
361
362 static void
363 dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
364 {
365 (void) driDrawable;
366
367 /* FIXME: Does EGL support front buffer rendering at all? */
368
369 #if 0
370 struct dri2_egl_surface *dri2_surf = loaderPrivate;
371
372 dri2WaitGL(dri2_surf);
373 #else
374 (void) loaderPrivate;
375 #endif
376 }
377
378 static __DRIimage *
379 dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
380 {
381 _EGLDisplay *disp = data;
382 struct dri2_egl_image *dri2_img;
383 _EGLImage *img;
384
385 (void) screen;
386
387 img = _eglLookupImage(image, disp);
388 if (img == NULL) {
389 _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
390 return NULL;
391 }
392
393 dri2_img = dri2_egl_image(image);
394
395 return dri2_img->dri_image;
396 }
397
398 static const __DRIimageLookupExtension image_lookup_extension = {
399 { __DRI_IMAGE_LOOKUP, 1 },
400 dri2_lookup_egl_image
401 };
402
403 static __DRIbuffer *
404 dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
405 int *width, int *height,
406 unsigned int *attachments, int count,
407 int *out_count, void *loaderPrivate)
408 {
409 struct dri2_egl_surface *dri2_surf = loaderPrivate;
410 struct dri2_egl_display *dri2_dpy =
411 dri2_egl_display(dri2_surf->base.Resource.Display);
412 xcb_dri2_dri2_buffer_t *buffers;
413 xcb_dri2_get_buffers_with_format_reply_t *reply;
414 xcb_dri2_get_buffers_with_format_cookie_t cookie;
415 xcb_dri2_attach_format_t *format_attachments;
416
417 (void) driDrawable;
418
419 format_attachments = (xcb_dri2_attach_format_t *) attachments;
420 cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
421 dri2_surf->drawable,
422 count, count,
423 format_attachments);
424
425 reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
426 cookie, NULL);
427 if (reply == NULL)
428 return NULL;
429
430 buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
431 dri2_surf->base.Width = *width = reply->width;
432 dri2_surf->base.Height = *height = reply->height;
433 *out_count = reply->count;
434 dri2_process_buffers(dri2_surf, buffers, *out_count);
435
436 free(reply);
437
438 return dri2_surf->buffers;
439 }
440
441 static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
442
443 struct dri2_extension_match {
444 const char *name;
445 int version;
446 int offset;
447 };
448
449 static struct dri2_extension_match dri2_driver_extensions[] = {
450 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
451 { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) },
452 { NULL, 0, 0 }
453 };
454
455 static struct dri2_extension_match dri2_core_extensions[] = {
456 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
457 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
458 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
459 { NULL, 0, 0 }
460 };
461
462 static EGLBoolean
463 dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
464 struct dri2_extension_match *matches,
465 const __DRIextension **extensions)
466 {
467 int i, j, ret = EGL_TRUE;
468 void *field;
469
470 for (i = 0; extensions[i]; i++) {
471 _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
472 for (j = 0; matches[j].name; j++) {
473 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
474 extensions[i]->version >= matches[j].version) {
475 field = ((char *) dri2_dpy + matches[j].offset);
476 *(const __DRIextension **) field = extensions[i];
477 _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
478 extensions[i]->name, extensions[i]->version);
479 }
480 }
481 }
482
483 for (j = 0; matches[j].name; j++) {
484 field = ((char *) dri2_dpy + matches[j].offset);
485 if (*(const __DRIextension **) field == NULL) {
486 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
487 matches[j].name, matches[j].version);
488 ret = EGL_FALSE;
489 }
490 }
491
492 return ret;
493 }
494
495 static char *
496 dri2_strndup(const char *s, int length)
497 {
498 char *d;
499
500 d = malloc(length + 1);
501 if (d == NULL)
502 return NULL;
503
504 memcpy(d, s, length);
505 d[length] = '\0';
506
507 return d;
508 }
509
510 static EGLBoolean
511 dri2_connect(struct dri2_egl_display *dri2_dpy)
512 {
513 xcb_xfixes_query_version_reply_t *xfixes_query;
514 xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
515 xcb_dri2_query_version_reply_t *dri2_query;
516 xcb_dri2_query_version_cookie_t dri2_query_cookie;
517 xcb_dri2_connect_reply_t *connect;
518 xcb_dri2_connect_cookie_t connect_cookie;
519 xcb_generic_error_t *error;
520 xcb_screen_iterator_t s;
521
522 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
523 xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
524
525 xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
526 XCB_XFIXES_MAJOR_VERSION,
527 XCB_XFIXES_MINOR_VERSION);
528
529 dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
530 XCB_DRI2_MAJOR_VERSION,
531 XCB_DRI2_MINOR_VERSION);
532
533 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
534 connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
535 s.data->root,
536 XCB_DRI2_DRIVER_TYPE_DRI);
537
538 xfixes_query =
539 xcb_xfixes_query_version_reply (dri2_dpy->conn,
540 xfixes_query_cookie, &error);
541 if (xfixes_query == NULL ||
542 error != NULL || xfixes_query->major_version < 2) {
543 _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version");
544 free(error);
545 return EGL_FALSE;
546 }
547 free(xfixes_query);
548
549 dri2_query =
550 xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
551 if (dri2_query == NULL || error != NULL) {
552 _eglLog(_EGL_FATAL, "DRI2: failed to query version");
553 free(error);
554 return EGL_FALSE;
555 }
556 dri2_dpy->dri2_major = dri2_query->major_version;
557 dri2_dpy->dri2_minor = dri2_query->minor_version;
558 free(dri2_query);
559
560 connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
561 if (connect == NULL ||
562 connect->driver_name_length + connect->device_name_length == 0) {
563 _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
564 return EGL_FALSE;
565 }
566
567 dri2_dpy->device_name =
568 dri2_strndup(xcb_dri2_connect_device_name (connect),
569 xcb_dri2_connect_device_name_length (connect));
570
571 dri2_dpy->driver_name =
572 dri2_strndup(xcb_dri2_connect_driver_name (connect),
573 xcb_dri2_connect_driver_name_length (connect));
574
575 if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
576 free(dri2_dpy->device_name);
577 free(dri2_dpy->driver_name);
578 free(connect);
579 return EGL_FALSE;
580 }
581 free(connect);
582
583 return EGL_TRUE;
584 }
585
586 static EGLBoolean
587 dri2_authenticate(struct dri2_egl_display *dri2_dpy)
588 {
589 xcb_dri2_authenticate_reply_t *authenticate;
590 xcb_dri2_authenticate_cookie_t authenticate_cookie;
591 xcb_screen_iterator_t s;
592 drm_magic_t magic;
593
594 if (drmGetMagic(dri2_dpy->fd, &magic)) {
595 _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic");
596 return EGL_FALSE;
597 }
598
599 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
600 authenticate_cookie =
601 xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic);
602 authenticate =
603 xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
604 if (authenticate == NULL || !authenticate->authenticated) {
605 _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
606 free(authenticate);
607 return EGL_FALSE;
608 }
609
610 free(authenticate);
611
612 return EGL_TRUE;
613 }
614
615 static EGLBoolean
616 dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
617 _EGLDisplay *disp)
618 {
619 xcb_screen_iterator_t s;
620 xcb_depth_iterator_t d;
621 xcb_visualtype_t *visuals;
622 int i, j, id;
623 struct dri2_egl_config *conf;
624 EGLint surface_type;
625
626 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
627 d = xcb_screen_allowed_depths_iterator(s.data);
628 id = 1;
629
630 surface_type =
631 EGL_WINDOW_BIT |
632 EGL_PIXMAP_BIT |
633 EGL_PBUFFER_BIT |
634 EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
635
636 while (d.rem > 0) {
637 EGLBoolean class_added[6] = { 0, };
638
639 visuals = xcb_depth_visuals(d.data);
640 for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
641 if (class_added[visuals[i]._class])
642 continue;
643
644 class_added[visuals[i]._class] = EGL_TRUE;
645 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
646 conf = dri2_add_config(disp, dri2_dpy->driver_configs[j],
647 id++, d.data->depth, surface_type);
648 if (conf == NULL)
649 continue;
650 _eglSetConfigKey(&conf->base,
651 EGL_NATIVE_VISUAL_ID, visuals[i].visual_id);
652 _eglSetConfigKey(&conf->base,
653 EGL_NATIVE_VISUAL_TYPE, visuals[i]._class);
654 }
655 }
656
657 xcb_depth_next(&d);
658 }
659
660 if (!_eglGetArraySize(disp->Configs)) {
661 _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
662 return EGL_FALSE;
663 }
664
665 return EGL_TRUE;
666 }
667
668 static EGLBoolean
669 dri2_load_driver(_EGLDisplay *disp)
670 {
671 struct dri2_egl_display *dri2_dpy = disp->DriverData;
672 const __DRIextension **extensions;
673 char path[PATH_MAX], *search_paths, *p, *next, *end;
674
675 search_paths = NULL;
676 if (geteuid() == getuid()) {
677 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
678 search_paths = getenv("LIBGL_DRIVERS_PATH");
679 }
680 if (search_paths == NULL)
681 search_paths = DEFAULT_DRIVER_DIR;
682
683 dri2_dpy->driver = NULL;
684 end = search_paths + strlen(search_paths);
685 for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
686 int len;
687 next = strchr(p, ':');
688 if (next == NULL)
689 next = end;
690
691 len = next - p;
692 #if GLX_USE_TLS
693 snprintf(path, sizeof path,
694 "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
695 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
696 #endif
697 if (dri2_dpy->driver == NULL) {
698 snprintf(path, sizeof path,
699 "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
700 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
701 if (dri2_dpy->driver == NULL)
702 _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
703 }
704 }
705
706 if (dri2_dpy->driver == NULL) {
707 _eglLog(_EGL_WARNING,
708 "DRI2: failed to open any driver (search paths %s)",
709 search_paths);
710 return EGL_FALSE;
711 }
712
713 _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
714 extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
715 if (extensions == NULL) {
716 _eglLog(_EGL_WARNING,
717 "DRI2: driver exports no extensions (%s)", dlerror());
718 dlclose(dri2_dpy->driver);
719 return EGL_FALSE;
720 }
721
722 if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
723 dlclose(dri2_dpy->driver);
724 return EGL_FALSE;
725 }
726
727 return EGL_TRUE;
728 }
729
730 static EGLBoolean
731 dri2_create_screen(_EGLDisplay *disp)
732 {
733 const __DRIextension **extensions;
734 struct dri2_egl_display *dri2_dpy;
735 unsigned int api_mask;
736
737 dri2_dpy = disp->DriverData;
738 dri2_dpy->dri_screen =
739 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
740 &dri2_dpy->driver_configs, disp);
741
742 if (dri2_dpy->dri_screen == NULL) {
743 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
744 return EGL_FALSE;
745 }
746
747 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
748 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
749 goto cleanup_dri_screen;
750
751 if (dri2_dpy->dri2->base.version >= 2)
752 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
753 else
754 api_mask = 1 << __DRI_API_OPENGL;
755
756 disp->ClientAPIs = 0;
757 if (api_mask & (1 <<__DRI_API_OPENGL))
758 disp->ClientAPIs |= EGL_OPENGL_BIT;
759 if (api_mask & (1 <<__DRI_API_GLES))
760 disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
761 if (api_mask & (1 << __DRI_API_GLES2))
762 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
763
764 if (dri2_dpy->dri2->base.version >= 2) {
765 disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
766 disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
767 disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
768 }
769
770 return EGL_TRUE;
771
772 cleanup_dri_screen:
773 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
774
775 return EGL_FALSE;
776 }
777
778 static EGLBoolean
779 dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
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 disp->VersionMajor = 1;
859 disp->VersionMinor = 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
881 struct dri2_driver_map {
882 int vendor_id;
883 const char *driver;
884 const int *chip_ids;
885 int num_chips_ids;
886 };
887
888 const 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
906 const 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
931 const 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
954 const 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
978 const 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
1184 const 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
1354 const 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
1363 static char *
1364 dri2_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
1417 static EGLBoolean
1418 dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
1419 {
1420 struct dri2_egl_display *dri2_dpy;
1421 int i;
1422
1423 dri2_dpy = malloc(sizeof *dri2_dpy);
1424 if (!dri2_dpy)
1425 return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1426
1427 disp->DriverData = (void *) dri2_dpy;
1428 dri2_dpy->fd = (int) disp->PlatformDisplay;
1429
1430 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
1431 if (dri2_dpy->driver_name == NULL)
1432 return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
1433
1434 if (!dri2_load_driver(disp))
1435 goto cleanup_driver_name;
1436
1437 dri2_dpy->extensions[0] = &image_lookup_extension.base;
1438 dri2_dpy->extensions[1] = &use_invalidate.base;
1439 dri2_dpy->extensions[2] = NULL;
1440
1441 if (!dri2_create_screen(disp))
1442 goto cleanup_driver;
1443
1444 for (i = 0; dri2_dpy->driver_configs[i]; i++)
1445 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
1446
1447 disp->Extensions.MESA_drm_image = EGL_TRUE;
1448 disp->Extensions.KHR_image_base = EGL_TRUE;
1449 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
1450 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
1451
1452 /* we're supporting EGL 1.4 */
1453 disp->VersionMajor = 1;
1454 disp->VersionMinor = 4;
1455
1456 return EGL_TRUE;
1457
1458 cleanup_driver:
1459 dlclose(dri2_dpy->driver);
1460 cleanup_driver_name:
1461 free(dri2_dpy->driver_name);
1462
1463 return EGL_FALSE;
1464 }
1465
1466 #endif
1467
1468 /**
1469 * Called via eglInitialize(), GLX_drv->API.Initialize().
1470 */
1471 static EGLBoolean
1472 dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
1473 {
1474 /* not until swrast_dri is supported */
1475 if (disp->Options.UseFallback)
1476 return EGL_FALSE;
1477
1478 switch (disp->Platform) {
1479 case _EGL_PLATFORM_X11:
1480 if (disp->Options.TestOnly)
1481 return EGL_TRUE;
1482 return dri2_initialize_x11(drv, disp);
1483
1484 #ifdef HAVE_LIBUDEV
1485 case _EGL_PLATFORM_DRM:
1486 if (disp->Options.TestOnly)
1487 return EGL_TRUE;
1488 return dri2_initialize_drm(drv, disp);
1489 #endif
1490
1491 default:
1492 return EGL_FALSE;
1493 }
1494 }
1495
1496 /**
1497 * Called via eglTerminate(), drv->API.Terminate().
1498 */
1499 static EGLBoolean
1500 dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
1501 {
1502 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1503
1504 _eglReleaseDisplayResources(drv, disp);
1505 _eglCleanupDisplay(disp);
1506
1507 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1508 close(dri2_dpy->fd);
1509 dlclose(dri2_dpy->driver);
1510 if (disp->PlatformDisplay == NULL)
1511 xcb_disconnect(dri2_dpy->conn);
1512 free(dri2_dpy);
1513 disp->DriverData = NULL;
1514
1515 return EGL_TRUE;
1516 }
1517
1518
1519 /**
1520 * Called via eglCreateContext(), drv->API.CreateContext().
1521 */
1522 static _EGLContext *
1523 dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
1524 _EGLContext *share_list, const EGLint *attrib_list)
1525 {
1526 struct dri2_egl_context *dri2_ctx;
1527 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1528 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
1529 struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
1530 const __DRIconfig *dri_config;
1531 int api;
1532
1533 (void) drv;
1534
1535 dri2_ctx = malloc(sizeof *dri2_ctx);
1536 if (!dri2_ctx) {
1537 _eglError(EGL_BAD_ALLOC, "eglCreateContext");
1538 return NULL;
1539 }
1540
1541 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
1542 goto cleanup;
1543
1544 switch (dri2_ctx->base.ClientAPI) {
1545 case EGL_OPENGL_ES_API:
1546 switch (dri2_ctx->base.ClientVersion) {
1547 case 1:
1548 api = __DRI_API_GLES;
1549 break;
1550 case 2:
1551 api = __DRI_API_GLES2;
1552 break;
1553 default:
1554 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1555 return NULL;
1556 }
1557 break;
1558 case EGL_OPENGL_API:
1559 api = __DRI_API_OPENGL;
1560 break;
1561 default:
1562 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
1563 return NULL;
1564 }
1565
1566 if (conf != NULL)
1567 dri_config = dri2_config->dri_config;
1568 else
1569 dri_config = NULL;
1570
1571 if (dri2_dpy->dri2->base.version >= 2) {
1572 dri2_ctx->dri_context =
1573 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
1574 api,
1575 dri_config,
1576 dri2_ctx_shared ?
1577 dri2_ctx_shared->dri_context : NULL,
1578 dri2_ctx);
1579 } else if (api == __DRI_API_OPENGL) {
1580 dri2_ctx->dri_context =
1581 dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
1582 dri2_config->dri_config,
1583 dri2_ctx_shared ?
1584 dri2_ctx_shared->dri_context : NULL,
1585 dri2_ctx);
1586 } else {
1587 /* fail */
1588 }
1589
1590 if (!dri2_ctx->dri_context)
1591 goto cleanup;
1592
1593 return &dri2_ctx->base;
1594
1595 cleanup:
1596 free(dri2_ctx);
1597 return NULL;
1598 }
1599
1600 static EGLBoolean
1601 dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
1602 {
1603 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1604 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1605
1606 (void) drv;
1607
1608 if (!_eglPutSurface(surf))
1609 return EGL_TRUE;
1610
1611 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
1612
1613 xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
1614
1615 if (surf->Type == EGL_PBUFFER_BIT)
1616 xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
1617
1618 free(surf);
1619
1620 return EGL_TRUE;
1621 }
1622
1623 /**
1624 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
1625 */
1626 static EGLBoolean
1627 dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
1628 _EGLSurface *rsurf, _EGLContext *ctx)
1629 {
1630 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1631 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1632 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
1633 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
1634 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1635 _EGLContext *old_ctx;
1636 _EGLSurface *old_dsurf, *old_rsurf;
1637 __DRIdrawable *ddraw, *rdraw;
1638 __DRIcontext *cctx;
1639
1640 /* make new bindings */
1641 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
1642 return EGL_FALSE;
1643
1644 /* flush before context switch */
1645 if (old_ctx && dri2_drv->glFlush)
1646 dri2_drv->glFlush();
1647
1648 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
1649 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
1650 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
1651
1652 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
1653 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
1654 dri2_destroy_surface(drv, disp, old_dsurf);
1655 dri2_destroy_surface(drv, disp, old_rsurf);
1656 if (old_ctx) {
1657 /* unbind the old context only when there is no new context bound */
1658 if (!ctx) {
1659 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
1660 dri2_dpy->core->unbindContext(old_cctx);
1661 }
1662 /* no destroy? */
1663 _eglPutContext(old_ctx);
1664 }
1665
1666 return EGL_TRUE;
1667 } else {
1668 /* undo the previous _eglBindContext */
1669 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
1670 assert(&dri2_ctx->base == ctx &&
1671 &dri2_dsurf->base == dsurf &&
1672 &dri2_rsurf->base == rsurf);
1673
1674 _eglPutSurface(dsurf);
1675 _eglPutSurface(rsurf);
1676 _eglPutContext(ctx);
1677
1678 _eglPutSurface(old_dsurf);
1679 _eglPutSurface(old_rsurf);
1680 _eglPutContext(old_ctx);
1681
1682 return EGL_FALSE;
1683 }
1684 }
1685
1686 /**
1687 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
1688 */
1689 static _EGLSurface *
1690 dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
1691 _EGLConfig *conf, EGLNativeWindowType window,
1692 const EGLint *attrib_list)
1693 {
1694 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1695 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
1696 struct dri2_egl_surface *dri2_surf;
1697 xcb_get_geometry_cookie_t cookie;
1698 xcb_get_geometry_reply_t *reply;
1699 xcb_screen_iterator_t s;
1700 xcb_generic_error_t *error;
1701
1702 (void) drv;
1703
1704 dri2_surf = malloc(sizeof *dri2_surf);
1705 if (!dri2_surf) {
1706 _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
1707 return NULL;
1708 }
1709
1710 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
1711 goto cleanup_surf;
1712
1713 dri2_surf->region = XCB_NONE;
1714 if (type == EGL_PBUFFER_BIT) {
1715 dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
1716 s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
1717 xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
1718 dri2_surf->drawable, s.data->root,
1719 dri2_surf->base.Width, dri2_surf->base.Height);
1720 } else {
1721 dri2_surf->drawable = window;
1722 }
1723
1724 dri2_surf->dri_drawable =
1725 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
1726 dri2_conf->dri_config, dri2_surf);
1727 if (dri2_surf->dri_drawable == NULL) {
1728 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
1729 goto cleanup_pixmap;
1730 }
1731
1732 xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
1733
1734 if (type != EGL_PBUFFER_BIT) {
1735 cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
1736 reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
1737 if (reply == NULL || error != NULL) {
1738 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
1739 free(error);
1740 goto cleanup_dri_drawable;
1741 }
1742
1743 dri2_surf->base.Width = reply->width;
1744 dri2_surf->base.Height = reply->height;
1745 free(reply);
1746 }
1747
1748 return &dri2_surf->base;
1749
1750 cleanup_dri_drawable:
1751 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
1752 cleanup_pixmap:
1753 if (type == EGL_PBUFFER_BIT)
1754 xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
1755 cleanup_surf:
1756 free(dri2_surf);
1757
1758 return NULL;
1759 }
1760
1761 /**
1762 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
1763 */
1764 static _EGLSurface *
1765 dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
1766 _EGLConfig *conf, EGLNativeWindowType window,
1767 const EGLint *attrib_list)
1768 {
1769 return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
1770 window, attrib_list);
1771 }
1772
1773 static _EGLSurface *
1774 dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
1775 _EGLConfig *conf, EGLNativePixmapType pixmap,
1776 const EGLint *attrib_list)
1777 {
1778 return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
1779 pixmap, attrib_list);
1780 }
1781
1782 static _EGLSurface *
1783 dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
1784 _EGLConfig *conf, const EGLint *attrib_list)
1785 {
1786 return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
1787 XCB_WINDOW_NONE, attrib_list);
1788 }
1789
1790 static EGLBoolean
1791 dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
1792 _EGLSurface *draw, xcb_xfixes_region_t region)
1793 {
1794 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1795 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1796 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1797 _EGLContext *ctx;
1798 xcb_dri2_copy_region_cookie_t cookie;
1799
1800 if (dri2_drv->glFlush) {
1801 ctx = _eglGetCurrentContext();
1802 if (ctx && ctx->DrawSurface == &dri2_surf->base)
1803 dri2_drv->glFlush();
1804 }
1805
1806 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
1807
1808 #if 0
1809 /* FIXME: Add support for dri swapbuffers, that'll give us swap
1810 * interval and page flipping (at least for fullscreen windows) as
1811 * well as the page flip event. Unless surface->SwapBehavior is
1812 * EGL_BUFFER_PRESERVED. */
1813 #if __DRI2_FLUSH_VERSION >= 2
1814 if (pdraw->psc->f)
1815 (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
1816 #endif
1817 #endif
1818
1819 if (!dri2_surf->have_fake_front)
1820 return EGL_TRUE;
1821
1822 cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
1823 dri2_surf->drawable,
1824 region,
1825 XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
1826 XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
1827 free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
1828
1829 return EGL_TRUE;
1830 }
1831
1832 static EGLBoolean
1833 dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
1834 {
1835 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1836
1837 return dri2_copy_region(drv, disp, draw, dri2_surf->region);
1838 }
1839
1840 static EGLBoolean
1841 dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
1842 EGLint numRects, const EGLint *rects)
1843 {
1844 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1845 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
1846 EGLBoolean ret;
1847 xcb_xfixes_region_t region;
1848 xcb_rectangle_t rectangles[16];
1849 int i;
1850
1851 if (numRects > (int)ARRAY_SIZE(rectangles))
1852 return dri2_copy_region(drv, disp, draw, dri2_surf->region);
1853
1854 /* FIXME: Invert y here? */
1855 for (i = 0; i < numRects; i++) {
1856 rectangles[i].x = rects[i * 4];
1857 rectangles[i].y = rects[i * 4 + 1];
1858 rectangles[i].width = rects[i * 4 + 2];
1859 rectangles[i].height = rects[i * 4 + 3];
1860 }
1861
1862 region = xcb_generate_id(dri2_dpy->conn);
1863 xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
1864 ret = dri2_copy_region(drv, disp, draw, region);
1865 xcb_xfixes_destroy_region(dri2_dpy->conn, region);
1866
1867 return ret;
1868 }
1869
1870 /*
1871 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
1872 */
1873 static _EGLProc
1874 dri2_get_proc_address(_EGLDriver *drv, const char *procname)
1875 {
1876 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1877
1878 return dri2_drv->get_proc_address(procname);
1879 }
1880
1881 static EGLBoolean
1882 dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
1883 {
1884 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1885 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
1886
1887 (void) drv;
1888
1889 /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
1890 * we need to copy fake to real here.*/
1891
1892 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
1893
1894 return EGL_TRUE;
1895 }
1896
1897 static EGLBoolean
1898 dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
1899 {
1900 (void) drv;
1901 (void) disp;
1902
1903 if (engine != EGL_CORE_NATIVE_ENGINE)
1904 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
1905 /* glXWaitX(); */
1906
1907 return EGL_TRUE;
1908 }
1909
1910 static EGLBoolean
1911 dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
1912 EGLNativePixmapType target)
1913 {
1914 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1915 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1916 xcb_gcontext_t gc;
1917
1918 (void) drv;
1919
1920 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
1921
1922 gc = xcb_generate_id(dri2_dpy->conn);
1923 xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
1924 xcb_copy_area(dri2_dpy->conn,
1925 dri2_surf->drawable,
1926 target,
1927 gc,
1928 0, 0,
1929 0, 0,
1930 dri2_surf->base.Width,
1931 dri2_surf->base.Height);
1932 xcb_free_gc(dri2_dpy->conn, gc);
1933
1934 return EGL_TRUE;
1935 }
1936
1937 static EGLBoolean
1938 dri2_bind_tex_image(_EGLDriver *drv,
1939 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1940 {
1941 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1942 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1943 struct dri2_egl_context *dri2_ctx;
1944 _EGLContext *ctx;
1945 GLint format, target;
1946
1947 ctx = _eglGetCurrentContext();
1948 dri2_ctx = dri2_egl_context(ctx);
1949
1950 if (!_eglBindTexImage(drv, disp, surf, buffer))
1951 return EGL_FALSE;
1952
1953 switch (dri2_surf->base.TextureFormat) {
1954 case EGL_TEXTURE_RGB:
1955 format = __DRI_TEXTURE_FORMAT_RGB;
1956 break;
1957 case EGL_TEXTURE_RGBA:
1958 format = __DRI_TEXTURE_FORMAT_RGBA;
1959 break;
1960 default:
1961 assert(0);
1962 }
1963
1964 switch (dri2_surf->base.TextureTarget) {
1965 case EGL_TEXTURE_2D:
1966 target = GL_TEXTURE_2D;
1967 break;
1968 default:
1969 assert(0);
1970 }
1971
1972 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
1973 target, format,
1974 dri2_surf->dri_drawable);
1975
1976 return EGL_TRUE;
1977 }
1978
1979 static EGLBoolean
1980 dri2_release_tex_image(_EGLDriver *drv,
1981 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
1982 {
1983 #if __DRI_TEX_BUFFER_VERSION >= 3
1984 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1985 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
1986 struct dri2_egl_context *dri2_ctx;
1987 _EGLContext *ctx;
1988 GLint target;
1989
1990 ctx = _eglGetCurrentContext();
1991 dri2_ctx = dri2_egl_context(ctx);
1992
1993 if (!_eglReleaseTexImage(drv, disp, surf, buffer))
1994 return EGL_FALSE;
1995
1996 switch (dri2_surf->base.TextureTarget) {
1997 case EGL_TEXTURE_2D:
1998 target = GL_TEXTURE_2D;
1999 break;
2000 default:
2001 assert(0);
2002 }
2003 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
2004 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
2005 target,
2006 dri2_surf->dri_drawable);
2007 #endif
2008
2009 return EGL_TRUE;
2010 }
2011
2012 static _EGLImage *
2013 dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
2014 EGLClientBuffer buffer, const EGLint *attr_list)
2015 {
2016 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2017 struct dri2_egl_image *dri2_img;
2018 unsigned int attachments[1];
2019 xcb_drawable_t drawable;
2020 xcb_dri2_get_buffers_cookie_t buffers_cookie;
2021 xcb_dri2_get_buffers_reply_t *buffers_reply;
2022 xcb_dri2_dri2_buffer_t *buffers;
2023 xcb_get_geometry_cookie_t geometry_cookie;
2024 xcb_get_geometry_reply_t *geometry_reply;
2025 xcb_generic_error_t *error;
2026 int stride, format;
2027
2028 (void) ctx;
2029
2030 drawable = (xcb_drawable_t) buffer;
2031 xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
2032 attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
2033 buffers_cookie =
2034 xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
2035 drawable, 1, 1, attachments);
2036 geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
2037 buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
2038 buffers_cookie, NULL);
2039 buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
2040 if (buffers == NULL) {
2041 return NULL;
2042 }
2043
2044 geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
2045 geometry_cookie, &error);
2046 if (geometry_reply == NULL || error != NULL) {
2047 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
2048 free(error);
2049 free(buffers_reply);
2050 }
2051
2052 switch (geometry_reply->depth) {
2053 case 16:
2054 format = __DRI_IMAGE_FORMAT_RGB565;
2055 break;
2056 case 24:
2057 format = __DRI_IMAGE_FORMAT_XRGB8888;
2058 break;
2059 case 32:
2060 format = __DRI_IMAGE_FORMAT_ARGB8888;
2061 break;
2062 default:
2063 _eglError(EGL_BAD_PARAMETER,
2064 "dri2_create_image_khr: unsupported pixmap depth");
2065 free(buffers_reply);
2066 free(geometry_reply);
2067 return NULL;
2068 }
2069
2070 dri2_img = malloc(sizeof *dri2_img);
2071 if (!dri2_img) {
2072 free(buffers_reply);
2073 free(geometry_reply);
2074 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2075 return EGL_NO_IMAGE_KHR;
2076 }
2077
2078 if (!_eglInitImage(&dri2_img->base, disp)) {
2079 free(buffers_reply);
2080 free(geometry_reply);
2081 return EGL_NO_IMAGE_KHR;
2082 }
2083
2084 stride = buffers[0].pitch / buffers[0].cpp;
2085 dri2_img->dri_image =
2086 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2087 buffers_reply->width,
2088 buffers_reply->height,
2089 format,
2090 buffers[0].name,
2091 stride,
2092 dri2_img);
2093
2094 free(buffers_reply);
2095 free(geometry_reply);
2096
2097 return &dri2_img->base;
2098 }
2099
2100 static _EGLImage *
2101 dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
2102 EGLClientBuffer buffer,
2103 const EGLint *attr_list)
2104 {
2105 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2106 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
2107 struct dri2_egl_image *dri2_img;
2108 GLuint renderbuffer = (GLuint) buffer;
2109
2110 if (renderbuffer == 0) {
2111 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2112 return EGL_NO_IMAGE_KHR;
2113 }
2114
2115 dri2_img = malloc(sizeof *dri2_img);
2116 if (!dri2_img) {
2117 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2118 return EGL_NO_IMAGE_KHR;
2119 }
2120
2121 if (!_eglInitImage(&dri2_img->base, disp))
2122 return EGL_NO_IMAGE_KHR;
2123
2124 dri2_img->dri_image =
2125 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
2126 renderbuffer,
2127 dri2_img);
2128
2129 return &dri2_img->base;
2130 }
2131
2132 static _EGLImage *
2133 dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
2134 EGLClientBuffer buffer, const EGLint *attr_list)
2135 {
2136 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2137 struct dri2_egl_image *dri2_img;
2138 EGLint format, name, pitch, err;
2139 _EGLImageAttribs attrs;
2140
2141 (void) ctx;
2142
2143 name = (EGLint) buffer;
2144
2145 err = _eglParseImageAttribList(&attrs, disp, attr_list);
2146 if (err != EGL_SUCCESS)
2147 return NULL;
2148
2149 if (attrs.Width <= 0 || attrs.Height <= 0 ||
2150 attrs.DRMBufferStrideMESA <= 0) {
2151 _eglError(EGL_BAD_PARAMETER,
2152 "bad width, height or stride");
2153 return NULL;
2154 }
2155
2156 switch (attrs.DRMBufferFormatMESA) {
2157 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2158 format = __DRI_IMAGE_FORMAT_ARGB8888;
2159 pitch = attrs.DRMBufferStrideMESA;
2160 break;
2161 default:
2162 _eglError(EGL_BAD_PARAMETER,
2163 "dri2_create_image_khr: unsupported pixmap depth");
2164 return NULL;
2165 }
2166
2167 dri2_img = malloc(sizeof *dri2_img);
2168 if (!dri2_img) {
2169 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
2170 return NULL;
2171 }
2172
2173 if (!_eglInitImage(&dri2_img->base, disp)) {
2174 free(dri2_img);
2175 return NULL;
2176 }
2177
2178 dri2_img->dri_image =
2179 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
2180 attrs.Width,
2181 attrs.Height,
2182 format,
2183 name,
2184 pitch,
2185 dri2_img);
2186 if (dri2_img->dri_image == NULL) {
2187 free(dri2_img);
2188 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
2189 return NULL;
2190 }
2191
2192 return &dri2_img->base;
2193 }
2194
2195 static _EGLImage *
2196 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
2197 _EGLContext *ctx, EGLenum target,
2198 EGLClientBuffer buffer, const EGLint *attr_list)
2199 {
2200 (void) drv;
2201
2202 switch (target) {
2203 case EGL_NATIVE_PIXMAP_KHR:
2204 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
2205 case EGL_GL_RENDERBUFFER_KHR:
2206 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
2207 case EGL_DRM_BUFFER_MESA:
2208 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
2209 default:
2210 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
2211 return EGL_NO_IMAGE_KHR;
2212 }
2213 }
2214
2215 static EGLBoolean
2216 dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
2217 {
2218 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2219 struct dri2_egl_image *dri2_img = dri2_egl_image(image);
2220
2221 (void) drv;
2222
2223 dri2_dpy->image->destroyImage(dri2_img->dri_image);
2224 free(dri2_img);
2225
2226 return EGL_TRUE;
2227 }
2228
2229 static _EGLImage *
2230 dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
2231 const EGLint *attr_list)
2232 {
2233 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2234 struct dri2_egl_image *dri2_img;
2235 _EGLImageAttribs attrs;
2236 unsigned int dri_use, valid_mask;
2237 int format;
2238 EGLint err = EGL_SUCCESS;
2239
2240 (void) drv;
2241
2242 dri2_img = malloc(sizeof *dri2_img);
2243 if (!dri2_img) {
2244 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
2245 return EGL_NO_IMAGE_KHR;
2246 }
2247
2248 if (!attr_list) {
2249 err = EGL_BAD_PARAMETER;
2250 goto cleanup_img;
2251 }
2252
2253 if (!_eglInitImage(&dri2_img->base, disp)) {
2254 err = EGL_BAD_PARAMETER;
2255 goto cleanup_img;
2256 }
2257
2258 err = _eglParseImageAttribList(&attrs, disp, attr_list);
2259 if (err != EGL_SUCCESS)
2260 goto cleanup_img;
2261
2262 if (attrs.Width <= 0 || attrs.Height <= 0) {
2263 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
2264 attrs.Width, attrs.Height);
2265 goto cleanup_img;
2266 }
2267
2268 switch (attrs.DRMBufferFormatMESA) {
2269 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
2270 format = __DRI_IMAGE_FORMAT_ARGB8888;
2271 break;
2272 default:
2273 _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
2274 attrs.DRMBufferFormatMESA);
2275 goto cleanup_img;
2276 }
2277
2278 valid_mask =
2279 EGL_DRM_BUFFER_USE_SCANOUT_MESA |
2280 EGL_DRM_BUFFER_USE_SHARE_MESA;
2281 if (attrs.DRMBufferUseMESA & ~valid_mask) {
2282 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
2283 attrs.DRMBufferUseMESA & ~valid_mask);
2284 goto cleanup_img;
2285 }
2286
2287 dri_use = 0;
2288 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
2289 dri_use |= __DRI_IMAGE_USE_SHARE;
2290 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
2291 dri_use |= __DRI_IMAGE_USE_SCANOUT;
2292
2293 dri2_img->dri_image =
2294 dri2_dpy->image->createImage(dri2_dpy->dri_screen,
2295 attrs.Width, attrs.Height,
2296 format, dri_use, dri2_img);
2297 if (dri2_img->dri_image == NULL) {
2298 err = EGL_BAD_ALLOC;
2299 goto cleanup_img;
2300 }
2301
2302 return &dri2_img->base;
2303
2304 cleanup_img:
2305 free(dri2_img);
2306 _eglError(err, "dri2_create_drm_image_mesa");
2307
2308 return EGL_NO_IMAGE_KHR;
2309 }
2310
2311 static EGLBoolean
2312 dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
2313 EGLint *name, EGLint *handle, EGLint *stride)
2314 {
2315 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
2316 struct dri2_egl_image *dri2_img = dri2_egl_image(img);
2317
2318 (void) drv;
2319
2320 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
2321 __DRI_IMAGE_ATTRIB_NAME, name)) {
2322 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
2323 return EGL_FALSE;
2324 }
2325
2326 if (handle)
2327 dri2_dpy->image->queryImage(dri2_img->dri_image,
2328 __DRI_IMAGE_ATTRIB_HANDLE, handle);
2329
2330 if (stride)
2331 dri2_dpy->image->queryImage(dri2_img->dri_image,
2332 __DRI_IMAGE_ATTRIB_STRIDE, stride);
2333
2334 return EGL_TRUE;
2335 }
2336
2337 static void
2338 dri2_unload(_EGLDriver *drv)
2339 {
2340 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2341
2342 if (dri2_drv->handle)
2343 dlclose(dri2_drv->handle);
2344 free(dri2_drv);
2345 }
2346
2347 static EGLBoolean
2348 dri2_load(_EGLDriver *drv)
2349 {
2350 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
2351 #ifdef HAVE_SHARED_GLAPI
2352 const char *libname = "libglapi.so.0";
2353 #else
2354 /*
2355 * Both libGL.so and libglapi.so are glapi providers. There is no way to
2356 * tell which one to load.
2357 */
2358 const char *libname = NULL;
2359 #endif
2360 void *handle;
2361
2362 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
2363 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
2364 if (handle) {
2365 dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
2366 dlsym(handle, "_glapi_get_proc_address");
2367 if (!dri2_drv->get_proc_address || !libname) {
2368 /* no need to keep a reference */
2369 dlclose(handle);
2370 handle = NULL;
2371 }
2372 }
2373
2374 /* if glapi is not available, loading DRI drivers will fail */
2375 if (!dri2_drv->get_proc_address) {
2376 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
2377 return EGL_FALSE;
2378 }
2379
2380 dri2_drv->glFlush = (void (*)(void))
2381 dri2_drv->get_proc_address("glFlush");
2382
2383 dri2_drv->handle = handle;
2384
2385 return EGL_TRUE;
2386 }
2387
2388 /**
2389 * This is the main entrypoint into the driver, called by libEGL.
2390 * Create a new _EGLDriver object and init its dispatch table.
2391 */
2392 _EGLDriver *
2393 _EGL_MAIN(const char *args)
2394 {
2395 struct dri2_egl_driver *dri2_drv;
2396
2397 (void) args;
2398
2399 dri2_drv = malloc(sizeof *dri2_drv);
2400 if (!dri2_drv)
2401 return NULL;
2402
2403 memset(dri2_drv, 0, sizeof *dri2_drv);
2404
2405 if (!dri2_load(&dri2_drv->base))
2406 return NULL;
2407
2408 _eglInitDriverFallbacks(&dri2_drv->base);
2409 dri2_drv->base.API.Initialize = dri2_initialize;
2410 dri2_drv->base.API.Terminate = dri2_terminate;
2411 dri2_drv->base.API.CreateContext = dri2_create_context;
2412 dri2_drv->base.API.MakeCurrent = dri2_make_current;
2413 dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
2414 dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
2415 dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
2416 dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
2417 dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
2418 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
2419 dri2_drv->base.API.WaitClient = dri2_wait_client;
2420 dri2_drv->base.API.WaitNative = dri2_wait_native;
2421 dri2_drv->base.API.CopyBuffers = dri2_copy_buffers;
2422 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
2423 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
2424 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
2425 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
2426 dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
2427 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
2428 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
2429
2430 dri2_drv->base.Name = "DRI2";
2431 dri2_drv->base.Unload = dri2_unload;
2432
2433 return &dri2_drv->base;
2434 }