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