Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright © 2011 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 
26
 */
27
 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
 
40
#include "egl_dri2.h"
41
 
42
/* From xmlpool/options.h, user exposed so should be stable */
43
#define DRI_CONF_VBLANK_NEVER 0
44
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
45
#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
46
#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
47
 
48
static void
49
swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
50
                     struct dri2_egl_surface * dri2_surf,
51
                     int depth)
52
{
53
   uint32_t           mask;
54
   const uint32_t     function = GXcopy;
55
   uint32_t           valgc[2];
56
 
57
   /* create GC's */
58
   dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
59
   mask = XCB_GC_FUNCTION;
60
   xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->drawable, mask, &function);
61
 
62
   dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
63
   mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
64
   valgc[0] = function;
65
   valgc[1] = False;
66
   xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->drawable, mask, valgc);
67
   dri2_surf->depth = depth;
68
   switch (depth) {
69
      case 32:
70
      case 24:
71
         dri2_surf->bytes_per_pixel = 4;
72
         break;
73
      case 16:
74
         dri2_surf->bytes_per_pixel = 2;
75
         break;
76
      case 8:
77
         dri2_surf->bytes_per_pixel = 1;
78
         break;
79
      case 0:
80
         dri2_surf->bytes_per_pixel = 0;
81
         break;
82
      default:
83
         _eglLog(_EGL_WARNING, "unsupported depth %d", depth);
84
   }
85
}
86
 
87
static void
88
swrastDestroyDrawable(struct dri2_egl_display * dri2_dpy,
89
                      struct dri2_egl_surface * dri2_surf)
90
{
91
   xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
92
   xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
93
}
94
 
95
static void
96
swrastGetDrawableInfo(__DRIdrawable * draw,
97
                      int *x, int *y, int *w, int *h,
98
                      void *loaderPrivate)
99
{
100
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
101
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
102
 
103
   xcb_get_geometry_cookie_t cookie;
104
   xcb_get_geometry_reply_t *reply;
105
   xcb_generic_error_t *error;
106
 
107
   *w = *h = 0;
108
   cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
109
   reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
110
   if (reply == NULL)
111
      return;
112
 
113
   if (error != NULL) {
114
      _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
115
      free(error);
116
   } else {
117
      *w = reply->width;
118
      *h = reply->height;
119
   }
120
   free(reply);
121
}
122
 
123
static void
124
swrastPutImage(__DRIdrawable * draw, int op,
125
               int x, int y, int w, int h,
126
               char *data, void *loaderPrivate)
127
{
128
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
129
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
130
 
131
   xcb_gcontext_t gc;
132
 
133
   switch (op) {
134
   case __DRI_SWRAST_IMAGE_OP_DRAW:
135
      gc = dri2_surf->gc;
136
      break;
137
   case __DRI_SWRAST_IMAGE_OP_SWAP:
138
      gc = dri2_surf->swapgc;
139
      break;
140
   default:
141
      return;
142
   }
143
 
144
   xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->drawable,
145
                 gc, w, h, x, y, 0, dri2_surf->depth,
146
                 w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
147
}
148
 
149
static void
150
swrastGetImage(__DRIdrawable * read,
151
               int x, int y, int w, int h,
152
               char *data, void *loaderPrivate)
153
{
154
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
155
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display);
156
 
157
   xcb_get_image_cookie_t cookie;
158
   xcb_get_image_reply_t *reply;
159
   xcb_generic_error_t *error;
160
 
161
   cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
162
                           dri2_surf->drawable, x, y, w, h, ~0);
163
   reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
164
   if (reply == NULL)
165
      return;
166
 
167
   if (error != NULL) {
168
      _eglLog(_EGL_WARNING, "error in xcb_get_image");
169
      free(error);
170
   } else {
171
      uint32_t bytes = xcb_get_image_data_length(reply);
172
      uint8_t *idata = xcb_get_image_data(reply);
173
      memcpy(data, idata, bytes);
174
   }
175
   free(reply);
176
}
177
 
178
 
179
/**
180
 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
181
 */
182
static _EGLSurface *
183
dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
184
		    _EGLConfig *conf, EGLNativeWindowType native_window,
185
		    const EGLint *attrib_list)
186
{
187
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
188
   struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
189
   struct dri2_egl_surface *dri2_surf;
190
   xcb_get_geometry_cookie_t cookie;
191
   xcb_get_geometry_reply_t *reply;
192
   xcb_screen_iterator_t s;
193
   xcb_generic_error_t *error;
194
   xcb_drawable_t window = (uintptr_t )native_window;
195
 
196
   (void) drv;
197
 
198
   dri2_surf = malloc(sizeof *dri2_surf);
199
   if (!dri2_surf) {
200
      _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
201
      return NULL;
202
   }
203
 
204
   if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
205
      goto cleanup_surf;
206
 
207
   dri2_surf->region = XCB_NONE;
208
   if (type == EGL_PBUFFER_BIT) {
209
      dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
210
      s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
211
      xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
212
			dri2_surf->drawable, s.data->root,
213
			dri2_surf->base.Width, dri2_surf->base.Height);
214
   } else {
215
      dri2_surf->drawable = window;
216
   }
217
 
218
   if (dri2_dpy->dri2) {
219
      dri2_surf->dri_drawable =
220
	 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
221
					       type == EGL_WINDOW_BIT ?
222
					       dri2_conf->dri_double_config :
223
					       dri2_conf->dri_single_config,
224
					       dri2_surf);
225
   } else {
226
      assert(dri2_dpy->swrast);
227
      dri2_surf->dri_drawable =
228
	 (*dri2_dpy->swrast->createNewDrawable) (dri2_dpy->dri_screen,
229
						 dri2_conf->dri_double_config,
230
						 dri2_surf);
231
   }
232
 
233
   if (dri2_surf->dri_drawable == NULL) {
234
      _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
235
      goto cleanup_pixmap;
236
   }
237
 
238
   if (dri2_dpy->dri2) {
239
      xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
240
   } else {
241
      swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_BUFFER_SIZE));
242
   }
243
 
244
   if (type != EGL_PBUFFER_BIT) {
245
      cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
246
      reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
247
      if (reply == NULL || error != NULL) {
248
	 _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
249
	 free(error);
250
	 goto cleanup_dri_drawable;
251
      }
252
 
253
      dri2_surf->base.Width = reply->width;
254
      dri2_surf->base.Height = reply->height;
255
      free(reply);
256
   }
257
 
258
   /* we always copy the back buffer to front */
259
   dri2_surf->base.PostSubBufferSupportedNV = EGL_TRUE;
260
 
261
   return &dri2_surf->base;
262
 
263
 cleanup_dri_drawable:
264
   dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
265
 cleanup_pixmap:
266
   if (type == EGL_PBUFFER_BIT)
267
      xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
268
 cleanup_surf:
269
   free(dri2_surf);
270
 
271
   return NULL;
272
}
273
 
274
/**
275
 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
276
 */
277
static _EGLSurface *
278
dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
279
			   _EGLConfig *conf, EGLNativeWindowType window,
280
			   const EGLint *attrib_list)
281
{
282
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
283
   _EGLSurface *surf;
284
 
285
   surf = dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
286
                              window, attrib_list);
287
   if (surf != NULL) {
288
      /* When we first create the DRI2 drawable, its swap interval on the
289
       * server side is 1.
290
       */
291
      surf->SwapInterval = 1;
292
 
293
      /* Override that with a driconf-set value. */
294
      drv->API.SwapInterval(drv, disp, surf, dri2_dpy->default_swap_interval);
295
   }
296
 
297
   return surf;
298
}
299
 
300
static _EGLSurface *
301
dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
302
			   _EGLConfig *conf, EGLNativePixmapType pixmap,
303
			   const EGLint *attrib_list)
304
{
305
   return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
306
			      pixmap, attrib_list);
307
}
308
 
309
static _EGLSurface *
310
dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
311
			    _EGLConfig *conf, const EGLint *attrib_list)
312
{
313
   return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
314
			      XCB_WINDOW_NONE, attrib_list);
315
}
316
 
317
static EGLBoolean
318
dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
319
{
320
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
321
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
322
 
323
   (void) drv;
324
 
325
   if (!_eglPutSurface(surf))
326
      return EGL_TRUE;
327
 
328
   (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
329
 
330
   if (dri2_dpy->dri2) {
331
      xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
332
   } else {
333
      assert(dri2_dpy->swrast);
334
      swrastDestroyDrawable(dri2_dpy, dri2_surf);
335
   }
336
 
337
   if (surf->Type == EGL_PBUFFER_BIT)
338
      xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
339
 
340
   free(surf);
341
 
342
   return EGL_TRUE;
343
}
344
 
345
/**
346
 * Process list of buffer received from the server
347
 *
348
 * Processes the list of buffers received in a reply from the server to either
349
 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
350
 */
351
static void
352
dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
353
		     xcb_dri2_dri2_buffer_t *buffers, unsigned count)
354
{
355
   struct dri2_egl_display *dri2_dpy =
356
      dri2_egl_display(dri2_surf->base.Resource.Display);
357
   xcb_rectangle_t rectangle;
358
   unsigned i;
359
 
360
   dri2_surf->buffer_count = count;
361
   dri2_surf->have_fake_front = 0;
362
 
363
   /* This assumes the DRI2 buffer attachment tokens matches the
364
    * __DRIbuffer tokens. */
365
   for (i = 0; i < count; i++) {
366
      dri2_surf->buffers[i].attachment = buffers[i].attachment;
367
      dri2_surf->buffers[i].name = buffers[i].name;
368
      dri2_surf->buffers[i].pitch = buffers[i].pitch;
369
      dri2_surf->buffers[i].cpp = buffers[i].cpp;
370
      dri2_surf->buffers[i].flags = buffers[i].flags;
371
 
372
      /* We only use the DRI drivers single buffer configs.  This
373
       * means that if we try to render to a window, DRI2 will give us
374
       * the fake front buffer, which we'll use as a back buffer.
375
       * Note that EGL doesn't require that several clients rendering
376
       * to the same window must see the same aux buffers. */
377
      if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
378
         dri2_surf->have_fake_front = 1;
379
   }
380
 
381
   if (dri2_surf->region != XCB_NONE)
382
      xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
383
 
384
   rectangle.x = 0;
385
   rectangle.y = 0;
386
   rectangle.width = dri2_surf->base.Width;
387
   rectangle.height = dri2_surf->base.Height;
388
   dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
389
   xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
390
}
391
 
392
static __DRIbuffer *
393
dri2_get_buffers(__DRIdrawable * driDrawable,
394
		int *width, int *height,
395
		unsigned int *attachments, int count,
396
		int *out_count, void *loaderPrivate)
397
{
398
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
399
   struct dri2_egl_display *dri2_dpy =
400
      dri2_egl_display(dri2_surf->base.Resource.Display);
401
   xcb_dri2_dri2_buffer_t *buffers;
402
   xcb_dri2_get_buffers_reply_t *reply;
403
   xcb_dri2_get_buffers_cookie_t cookie;
404
 
405
   (void) driDrawable;
406
 
407
   cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
408
					    dri2_surf->drawable,
409
					    count, count, attachments);
410
   reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
411
   buffers = xcb_dri2_get_buffers_buffers (reply);
412
   if (buffers == NULL)
413
      return NULL;
414
 
415
   *out_count = reply->count;
416
   dri2_surf->base.Width = *width = reply->width;
417
   dri2_surf->base.Height = *height = reply->height;
418
   dri2_process_buffers(dri2_surf, buffers, *out_count);
419
 
420
   free(reply);
421
 
422
   return dri2_surf->buffers;
423
}
424
 
425
static __DRIbuffer *
426
dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
427
			     int *width, int *height,
428
			     unsigned int *attachments, int count,
429
			     int *out_count, void *loaderPrivate)
430
{
431
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
432
   struct dri2_egl_display *dri2_dpy =
433
      dri2_egl_display(dri2_surf->base.Resource.Display);
434
   xcb_dri2_dri2_buffer_t *buffers;
435
   xcb_dri2_get_buffers_with_format_reply_t *reply;
436
   xcb_dri2_get_buffers_with_format_cookie_t cookie;
437
   xcb_dri2_attach_format_t *format_attachments;
438
 
439
   (void) driDrawable;
440
 
441
   format_attachments = (xcb_dri2_attach_format_t *) attachments;
442
   cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
443
							dri2_surf->drawable,
444
							count, count,
445
							format_attachments);
446
 
447
   reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
448
						   cookie, NULL);
449
   if (reply == NULL)
450
      return NULL;
451
 
452
   buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
453
   dri2_surf->base.Width = *width = reply->width;
454
   dri2_surf->base.Height = *height = reply->height;
455
   *out_count = reply->count;
456
   dri2_process_buffers(dri2_surf, buffers, *out_count);
457
 
458
   free(reply);
459
 
460
   return dri2_surf->buffers;
461
}
462
 
463
static void
464
dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
465
{
466
   (void) driDrawable;
467
 
468
   /* FIXME: Does EGL support front buffer rendering at all? */
469
 
470
#if 0
471
   struct dri2_egl_surface *dri2_surf = loaderPrivate;
472
 
473
   dri2WaitGL(dri2_surf);
474
#else
475
   (void) loaderPrivate;
476
#endif
477
}
478
 
479
static char *
480
dri2_strndup(const char *s, int length)
481
{
482
   char *d;
483
 
484
   d = malloc(length + 1);
485
   if (d == NULL)
486
      return NULL;
487
 
488
   memcpy(d, s, length);
489
   d[length] = '\0';
490
 
491
   return d;
492
}
493
 
494
static EGLBoolean
495
dri2_connect(struct dri2_egl_display *dri2_dpy)
496
{
497
   xcb_xfixes_query_version_reply_t *xfixes_query;
498
   xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
499
   xcb_dri2_query_version_reply_t *dri2_query;
500
   xcb_dri2_query_version_cookie_t dri2_query_cookie;
501
   xcb_dri2_connect_reply_t *connect;
502
   xcb_dri2_connect_cookie_t connect_cookie;
503
   xcb_generic_error_t *error;
504
   xcb_screen_iterator_t s;
505
   char *driver_name, *device_name;
506
   const xcb_query_extension_reply_t *extension;
507
 
508
   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
509
   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
510
 
511
   extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
512
   if (!(extension && extension->present))
513
      return EGL_FALSE;
514
 
515
   extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri2_id);
516
   if (!(extension && extension->present))
517
      return EGL_FALSE;
518
 
519
   xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
520
						  XCB_XFIXES_MAJOR_VERSION,
521
						  XCB_XFIXES_MINOR_VERSION);
522
 
523
   dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
524
					       XCB_DRI2_MAJOR_VERSION,
525
					       XCB_DRI2_MINOR_VERSION);
526
 
527
   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
528
   connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
529
						s.data->root,
530
						XCB_DRI2_DRIVER_TYPE_DRI);
531
 
532
   xfixes_query =
533
      xcb_xfixes_query_version_reply (dri2_dpy->conn,
534
				      xfixes_query_cookie, &error);
535
   if (xfixes_query == NULL ||
536
       error != NULL || xfixes_query->major_version < 2) {
537
      _eglLog(_EGL_WARNING, "DRI2: failed to query xfixes version");
538
      free(error);
539
      return EGL_FALSE;
540
   }
541
   free(xfixes_query);
542
 
543
   dri2_query =
544
      xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
545
   if (dri2_query == NULL || error != NULL) {
546
      _eglLog(_EGL_WARNING, "DRI2: failed to query version");
547
      free(error);
548
      return EGL_FALSE;
549
   }
550
   dri2_dpy->dri2_major = dri2_query->major_version;
551
   dri2_dpy->dri2_minor = dri2_query->minor_version;
552
   free(dri2_query);
553
 
554
   connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
555
   if (connect == NULL ||
556
       connect->driver_name_length + connect->device_name_length == 0) {
557
      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
558
      return EGL_FALSE;
559
   }
560
 
561
   driver_name = xcb_dri2_connect_driver_name (connect);
562
   dri2_dpy->driver_name =
563
      dri2_strndup(driver_name,
564
		   xcb_dri2_connect_driver_name_length (connect));
565
 
566
   device_name = xcb_dri2_connect_device_name (connect);
567
 
568
   dri2_dpy->device_name =
569
      dri2_strndup(device_name,
570
		   xcb_dri2_connect_device_name_length (connect));
571
 
572
   if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
573
      free(dri2_dpy->device_name);
574
      free(dri2_dpy->driver_name);
575
      free(connect);
576
      return EGL_FALSE;
577
   }
578
   free(connect);
579
 
580
   return EGL_TRUE;
581
}
582
 
583
static int
584
dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
585
{
586
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
587
   xcb_dri2_authenticate_reply_t *authenticate;
588
   xcb_dri2_authenticate_cookie_t authenticate_cookie;
589
   xcb_screen_iterator_t s;
590
   int ret = 0;
591
 
592
   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
593
   authenticate_cookie =
594
      xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, id);
595
   authenticate =
596
      xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
597
 
598
   if (authenticate == NULL || !authenticate->authenticated)
599
      ret = -1;
600
 
601
   free(authenticate);
602
 
603
   return ret;
604
}
605
 
606
static EGLBoolean
607
dri2_authenticate(_EGLDisplay *disp)
608
{
609
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
610
   drm_magic_t magic;
611
 
612
   if (drmGetMagic(dri2_dpy->fd, &magic)) {
613
      _eglLog(_EGL_WARNING, "DRI2: failed to get drm magic");
614
      return EGL_FALSE;
615
   }
616
 
617
   if (dri2_x11_authenticate(disp, magic) < 0) {
618
      _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
619
      return EGL_FALSE;
620
   }
621
 
622
   return EGL_TRUE;
623
}
624
 
625
static EGLBoolean
626
dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
627
			     _EGLDisplay *disp)
628
{
629
   xcb_screen_iterator_t s;
630
   xcb_depth_iterator_t d;
631
   xcb_visualtype_t *visuals;
632
   int i, j, id;
633
   EGLint surface_type;
634
   EGLint config_attrs[] = {
635
	   EGL_NATIVE_VISUAL_ID,   0,
636
	   EGL_NATIVE_VISUAL_TYPE, 0,
637
	   EGL_NONE
638
   };
639
 
640
   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
641
   d = xcb_screen_allowed_depths_iterator(s.data);
642
   id = 1;
643
 
644
   surface_type =
645
      EGL_WINDOW_BIT |
646
      EGL_PIXMAP_BIT |
647
      EGL_PBUFFER_BIT |
648
      EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
649
 
650
   while (d.rem > 0) {
651
      EGLBoolean class_added[6] = { 0, };
652
 
653
      visuals = xcb_depth_visuals(d.data);
654
      for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
655
	 if (class_added[visuals[i]._class])
656
	    continue;
657
 
658
	 class_added[visuals[i]._class] = EGL_TRUE;
659
	 for (j = 0; dri2_dpy->driver_configs[j]; j++) {
660
            config_attrs[1] = visuals[i].visual_id;
661
            config_attrs[3] = visuals[i]._class;
662
 
663
	    dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
664
			    d.data->depth, surface_type, config_attrs, NULL);
665
	 }
666
      }
667
 
668
      xcb_depth_next(&d);
669
   }
670
 
671
   if (!_eglGetArraySize(disp->Configs)) {
672
      _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
673
      return EGL_FALSE;
674
   }
675
 
676
   return EGL_TRUE;
677
}
678
 
679
static EGLBoolean
680
dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
681
		 _EGLSurface *draw, xcb_xfixes_region_t region)
682
{
683
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
684
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
685
   enum xcb_dri2_attachment_t render_attachment;
686
   xcb_dri2_copy_region_cookie_t cookie;
687
 
688
   /* No-op for a pixmap or pbuffer surface */
689
   if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
690
      return EGL_TRUE;
691
 
692
   if (dri2_dpy->flush)
693
      (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
694
 
695
   if (dri2_surf->have_fake_front)
696
      render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT;
697
   else
698
      render_attachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
699
 
700
   cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
701
					   dri2_surf->drawable,
702
					   region,
703
					   XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
704
					   render_attachment);
705
   free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
706
 
707
   return EGL_TRUE;
708
}
709
 
710
static int64_t
711
dri2_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
712
                      int64_t msc, int64_t divisor, int64_t remainder)
713
{
714
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
715
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
716
   uint32_t msc_hi = msc >> 32;
717
   uint32_t msc_lo = msc & 0xffffffff;
718
   uint32_t divisor_hi = divisor >> 32;
719
   uint32_t divisor_lo = divisor & 0xffffffff;
720
   uint32_t remainder_hi = remainder >> 32;
721
   uint32_t remainder_lo = remainder & 0xffffffff;
722
   xcb_dri2_swap_buffers_cookie_t cookie;
723
   xcb_dri2_swap_buffers_reply_t *reply;
724
   int64_t swap_count = -1;
725
 
726
   /* No-op for a pixmap or pbuffer surface */
727
   if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
728
      return 0;
729
 
730
   if (draw->SwapBehavior == EGL_BUFFER_PRESERVED || !dri2_dpy->swap_available)
731
      return dri2_copy_region(drv, disp, draw, dri2_surf->region) ? 0 : -1;
732
 
733
   if (dri2_dpy->flush)
734
      (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
735
 
736
   cookie = xcb_dri2_swap_buffers_unchecked(dri2_dpy->conn, dri2_surf->drawable,
737
                  msc_hi, msc_lo, divisor_hi, divisor_lo, remainder_hi, remainder_lo);
738
 
739
   reply = xcb_dri2_swap_buffers_reply(dri2_dpy->conn, cookie, NULL);
740
 
741
   if (reply) {
742
      swap_count = (((int64_t)reply->swap_hi) << 32) | reply->swap_lo;
743
      free(reply);
744
   }
745
 
746
   /* Since we aren't watching for the server's invalidate events like we're
747
    * supposed to (due to XCB providing no mechanism for filtering the events
748
    * the way xlib does), and SwapBuffers is a common cause of invalidate
749
    * events, just shove one down to the driver, even though we haven't told
750
    * the driver that we're the kind of loader that provides reliable
751
    * invalidate events.  This causes the driver to request buffers again at
752
    * its next draw, so that we get the correct buffers if a pageflip
753
    * happened.  The driver should still be using the viewport hack to catch
754
    * window resizes.
755
    */
756
   if (dri2_dpy->flush &&
757
       dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
758
      (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
759
 
760
   return swap_count;
761
}
762
 
763
static EGLBoolean
764
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
765
{
766
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
767
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
768
 
769
   if (dri2_dpy->dri2) {
770
      return dri2_swap_buffers_msc(drv, disp, draw, 0, 0, 0) != -1;
771
   } else {
772
      assert(dri2_dpy->swrast);
773
 
774
      dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable);
775
      return EGL_TRUE;
776
   }
777
}
778
 
779
static EGLBoolean
780
dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
781
			 EGLint numRects, const EGLint *rects)
782
{
783
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
784
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
785
   EGLBoolean ret;
786
   xcb_xfixes_region_t region;
787
   xcb_rectangle_t rectangles[16];
788
   int i;
789
 
790
   if (numRects > (int)ARRAY_SIZE(rectangles))
791
      return dri2_copy_region(drv, disp, draw, dri2_surf->region);
792
 
793
   for (i = 0; i < numRects; i++) {
794
      rectangles[i].x = rects[i * 4];
795
      rectangles[i].y = dri2_surf->base.Height - rects[i * 4 + 1] - rects[i * 4 + 3];
796
      rectangles[i].width = rects[i * 4 + 2];
797
      rectangles[i].height = rects[i * 4 + 3];
798
   }
799
 
800
   region = xcb_generate_id(dri2_dpy->conn);
801
   xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
802
   ret = dri2_copy_region(drv, disp, draw, region);
803
   xcb_xfixes_destroy_region(dri2_dpy->conn, region);
804
 
805
   return ret;
806
}
807
 
808
static EGLBoolean
809
dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
810
		     EGLint x, EGLint y, EGLint width, EGLint height)
811
{
812
   const EGLint rect[4] = { x, y, width, height };
813
 
814
   if (x < 0 || y < 0 || width < 0 || height < 0)
815
      _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
816
 
817
   return dri2_swap_buffers_region(drv, disp, draw, 1, rect);
818
}
819
 
820
static EGLBoolean
821
dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
822
{
823
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
824
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
825
 
826
   if (interval > surf->Config->MaxSwapInterval)
827
      interval = surf->Config->MaxSwapInterval;
828
   else if (interval < surf->Config->MinSwapInterval)
829
      interval = surf->Config->MinSwapInterval;
830
 
831
   if (interval != surf->SwapInterval && dri2_dpy->swap_available)
832
      xcb_dri2_swap_interval(dri2_dpy->conn, dri2_surf->drawable, interval);
833
 
834
   surf->SwapInterval = interval;
835
 
836
   return EGL_TRUE;
837
}
838
 
839
static EGLBoolean
840
dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
841
		  EGLNativePixmapType native_target)
842
{
843
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
844
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
845
   xcb_gcontext_t gc;
846
   xcb_pixmap_t target = (uintptr_t )native_target;
847
 
848
   (void) drv;
849
 
850
   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
851
 
852
   gc = xcb_generate_id(dri2_dpy->conn);
853
   xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
854
   xcb_copy_area(dri2_dpy->conn,
855
		  dri2_surf->drawable,
856
		  target,
857
		  gc,
858
		  0, 0,
859
		  0, 0,
860
		  dri2_surf->base.Width,
861
		  dri2_surf->base.Height);
862
   xcb_free_gc(dri2_dpy->conn, gc);
863
 
864
   return EGL_TRUE;
865
}
866
 
867
static _EGLImage *
868
dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
869
			     EGLClientBuffer buffer, const EGLint *attr_list)
870
{
871
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
872
   struct dri2_egl_image *dri2_img;
873
   unsigned int attachments[1];
874
   xcb_drawable_t drawable;
875
   xcb_dri2_get_buffers_cookie_t buffers_cookie;
876
   xcb_dri2_get_buffers_reply_t *buffers_reply;
877
   xcb_dri2_dri2_buffer_t *buffers;
878
   xcb_get_geometry_cookie_t geometry_cookie;
879
   xcb_get_geometry_reply_t *geometry_reply;
880
   xcb_generic_error_t *error;
881
   int stride, format;
882
 
883
   (void) ctx;
884
 
885
   drawable = (xcb_drawable_t) (uintptr_t) buffer;
886
   xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
887
   attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
888
   buffers_cookie =
889
      xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
890
				      drawable, 1, 1, attachments);
891
   geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
892
   buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
893
					       buffers_cookie, NULL);
894
   buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
895
   if (buffers == NULL) {
896
      return NULL;
897
   }
898
 
899
   geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
900
					    geometry_cookie, &error);
901
   if (geometry_reply == NULL || error != NULL) {
902
      _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
903
      free(error);
904
      free(buffers_reply);
905
      return NULL;
906
   }
907
 
908
   switch (geometry_reply->depth) {
909
   case 16:
910
      format = __DRI_IMAGE_FORMAT_RGB565;
911
      break;
912
   case 24:
913
      format = __DRI_IMAGE_FORMAT_XRGB8888;
914
      break;
915
   case 32:
916
      format = __DRI_IMAGE_FORMAT_ARGB8888;
917
      break;
918
   default:
919
      _eglError(EGL_BAD_PARAMETER,
920
		"dri2_create_image_khr: unsupported pixmap depth");
921
      free(buffers_reply);
922
      free(geometry_reply);
923
      return NULL;
924
   }
925
 
926
   dri2_img = malloc(sizeof *dri2_img);
927
   if (!dri2_img) {
928
      free(buffers_reply);
929
      free(geometry_reply);
930
      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
931
      return EGL_NO_IMAGE_KHR;
932
   }
933
 
934
   if (!_eglInitImage(&dri2_img->base, disp)) {
935
      free(buffers_reply);
936
      free(geometry_reply);
937
      free(dri2_img);
938
      return EGL_NO_IMAGE_KHR;
939
   }
940
 
941
   stride = buffers[0].pitch / buffers[0].cpp;
942
   dri2_img->dri_image =
943
      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
944
					   buffers_reply->width,
945
					   buffers_reply->height,
946
					   format,
947
					   buffers[0].name,
948
					   stride,
949
					   dri2_img);
950
 
951
   free(buffers_reply);
952
   free(geometry_reply);
953
 
954
   return &dri2_img->base;
955
}
956
 
957
static _EGLImage *
958
dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
959
			  _EGLContext *ctx, EGLenum target,
960
			  EGLClientBuffer buffer, const EGLint *attr_list)
961
{
962
   (void) drv;
963
 
964
   switch (target) {
965
   case EGL_NATIVE_PIXMAP_KHR:
966
      return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
967
   default:
968
      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
969
   }
970
}
971
 
972
static EGLBoolean
973
dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
974
{
975
   struct dri2_egl_display *dri2_dpy;
976
 
977
   drv->API.CreateWindowSurface = dri2_create_window_surface;
978
   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
979
   drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
980
   drv->API.DestroySurface = dri2_destroy_surface;
981
   drv->API.SwapBuffers = dri2_swap_buffers;
982
   drv->API.CopyBuffers = dri2_copy_buffers;
983
 
984
   drv->API.SwapBuffersRegionNOK = NULL;
985
   drv->API.CreateImageKHR  = NULL;
986
   drv->API.DestroyImageKHR = NULL;
987
   drv->API.CreateDRMImageMESA = NULL;
988
   drv->API.ExportDRMImageMESA = NULL;
989
 
990
   dri2_dpy = calloc(1, sizeof *dri2_dpy);
991
   if (!dri2_dpy)
992
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
993
 
994
   disp->DriverData = (void *) dri2_dpy;
995
   if (disp->PlatformDisplay == NULL) {
996
      dri2_dpy->conn = xcb_connect(0, 0);
997
   } else {
998
      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
999
   }
1000
 
1001
   if (xcb_connection_has_error(dri2_dpy->conn)) {
1002
      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1003
      goto cleanup_dpy;
1004
   }
1005
 
1006
   if (!dri2_load_driver_swrast(disp))
1007
      goto cleanup_conn;
1008
 
1009
   dri2_dpy->swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
1010
   dri2_dpy->swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION;
1011
   dri2_dpy->swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
1012
   dri2_dpy->swrast_loader_extension.putImage = swrastPutImage;
1013
   dri2_dpy->swrast_loader_extension.getImage = swrastGetImage;
1014
 
1015
   dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
1016
   dri2_dpy->extensions[1] = NULL;
1017
   dri2_dpy->extensions[2] = NULL;
1018
 
1019
   if (!dri2_create_screen(disp))
1020
      goto cleanup_driver;
1021
 
1022
   if (dri2_dpy->conn) {
1023
      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
1024
         goto cleanup_configs;
1025
   }
1026
 
1027
   /* we're supporting EGL 1.4 */
1028
   disp->VersionMajor = 1;
1029
   disp->VersionMinor = 4;
1030
 
1031
   return EGL_TRUE;
1032
 
1033
 cleanup_configs:
1034
   _eglCleanupDisplay(disp);
1035
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1036
 cleanup_driver:
1037
   dlclose(dri2_dpy->driver);
1038
 cleanup_conn:
1039
   if (disp->PlatformDisplay == NULL)
1040
      xcb_disconnect(dri2_dpy->conn);
1041
 cleanup_dpy:
1042
   free(dri2_dpy);
1043
 
1044
   return EGL_FALSE;
1045
}
1046
 
1047
static void
1048
dri2_setup_swap_interval(struct dri2_egl_display *dri2_dpy)
1049
{
1050
   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
1051
   int arbitrary_max_interval = 1000;
1052
 
1053
   /* default behavior for no SwapBuffers support: no vblank syncing
1054
    * either.
1055
    */
1056
   dri2_dpy->min_swap_interval = 0;
1057
   dri2_dpy->max_swap_interval = 0;
1058
 
1059
   if (!dri2_dpy->swap_available)
1060
      return;
1061
 
1062
   /* If we do have swapbuffers, then we can support pretty much any swap
1063
    * interval, but we allow driconf to override applications.
1064
    */
1065
   if (dri2_dpy->config)
1066
      dri2_dpy->config->configQueryi(dri2_dpy->dri_screen,
1067
                                     "vblank_mode", &vblank_mode);
1068
   switch (vblank_mode) {
1069
   case DRI_CONF_VBLANK_NEVER:
1070
      dri2_dpy->min_swap_interval = 0;
1071
      dri2_dpy->max_swap_interval = 0;
1072
      dri2_dpy->default_swap_interval = 0;
1073
      break;
1074
   case DRI_CONF_VBLANK_ALWAYS_SYNC:
1075
      dri2_dpy->min_swap_interval = 1;
1076
      dri2_dpy->max_swap_interval = arbitrary_max_interval;
1077
      dri2_dpy->default_swap_interval = 1;
1078
      break;
1079
   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
1080
      dri2_dpy->min_swap_interval = 0;
1081
      dri2_dpy->max_swap_interval = arbitrary_max_interval;
1082
      dri2_dpy->default_swap_interval = 0;
1083
      break;
1084
   default:
1085
   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
1086
      dri2_dpy->min_swap_interval = 0;
1087
      dri2_dpy->max_swap_interval = arbitrary_max_interval;
1088
      dri2_dpy->default_swap_interval = 1;
1089
      break;
1090
   }
1091
}
1092
 
1093
static EGLBoolean
1094
dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
1095
{
1096
   struct dri2_egl_display *dri2_dpy;
1097
 
1098
   drv->API.CreateWindowSurface = dri2_create_window_surface;
1099
   drv->API.CreatePixmapSurface = dri2_create_pixmap_surface;
1100
   drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface;
1101
   drv->API.DestroySurface = dri2_destroy_surface;
1102
   drv->API.SwapBuffers = dri2_swap_buffers;
1103
   drv->API.CopyBuffers = dri2_copy_buffers;
1104
   drv->API.CreateImageKHR = dri2_x11_create_image_khr;
1105
   drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
1106
   drv->API.PostSubBufferNV = dri2_post_sub_buffer;
1107
   drv->API.SwapInterval = dri2_swap_interval;
1108
 
1109
   dri2_dpy = calloc(1, sizeof *dri2_dpy);
1110
   if (!dri2_dpy)
1111
      return _eglError(EGL_BAD_ALLOC, "eglInitialize");
1112
 
1113
   disp->DriverData = (void *) dri2_dpy;
1114
   if (disp->PlatformDisplay == NULL) {
1115
      dri2_dpy->conn = xcb_connect(0, 0);
1116
   } else {
1117
      dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
1118
   }
1119
 
1120
   if (xcb_connection_has_error(dri2_dpy->conn)) {
1121
      _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
1122
      goto cleanup_dpy;
1123
   }
1124
 
1125
   if (dri2_dpy->conn) {
1126
      if (!dri2_connect(dri2_dpy))
1127
	 goto cleanup_conn;
1128
   }
1129
 
1130
   if (!dri2_load_driver(disp))
1131
      goto cleanup_conn;
1132
 
1133
#ifdef O_CLOEXEC
1134
   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR | O_CLOEXEC);
1135
   if (dri2_dpy->fd == -1 && errno == EINVAL)
1136
#endif
1137
   {
1138
      dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
1139
      if (dri2_dpy->fd != -1)
1140
         fcntl(dri2_dpy->fd, F_SETFD, fcntl(dri2_dpy->fd, F_GETFD) |
1141
            FD_CLOEXEC);
1142
   }
1143
   if (dri2_dpy->fd == -1) {
1144
      _eglLog(_EGL_WARNING,
1145
	      "DRI2: could not open %s (%s)", dri2_dpy->device_name,
1146
              strerror(errno));
1147
      goto cleanup_driver;
1148
   }
1149
 
1150
   if (dri2_dpy->conn) {
1151
      if (!dri2_authenticate(disp))
1152
	 goto cleanup_fd;
1153
   }
1154
 
1155
   if (dri2_dpy->dri2_minor >= 1) {
1156
      dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
1157
      dri2_dpy->dri2_loader_extension.base.version = 3;
1158
      dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
1159
      dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
1160
      dri2_dpy->dri2_loader_extension.getBuffersWithFormat =
1161
	 dri2_get_buffers_with_format;
1162
   } else {
1163
      dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
1164
      dri2_dpy->dri2_loader_extension.base.version = 2;
1165
      dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers;
1166
      dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
1167
      dri2_dpy->dri2_loader_extension.getBuffersWithFormat = NULL;
1168
   }
1169
 
1170
   dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base;
1171
   dri2_dpy->extensions[1] = &image_lookup_extension.base;
1172
   dri2_dpy->extensions[2] = NULL;
1173
 
1174
   dri2_dpy->swap_available = (dri2_dpy->dri2_minor >= 2);
1175
   dri2_dpy->invalidate_available = (dri2_dpy->dri2_minor >= 3);
1176
 
1177
   if (!dri2_create_screen(disp))
1178
      goto cleanup_fd;
1179
 
1180
   dri2_setup_swap_interval(dri2_dpy);
1181
 
1182
   if (dri2_dpy->conn) {
1183
      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
1184
	 goto cleanup_configs;
1185
   }
1186
 
1187
   disp->Extensions.KHR_image_pixmap = EGL_TRUE;
1188
   disp->Extensions.NOK_swap_region = EGL_TRUE;
1189
   disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
1190
   disp->Extensions.NV_post_sub_buffer = EGL_TRUE;
1191
 
1192
#ifdef HAVE_WAYLAND_PLATFORM
1193
   disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
1194
#endif
1195
   dri2_dpy->authenticate = dri2_x11_authenticate;
1196
 
1197
   /* we're supporting EGL 1.4 */
1198
   disp->VersionMajor = 1;
1199
   disp->VersionMinor = 4;
1200
 
1201
   return EGL_TRUE;
1202
 
1203
 cleanup_configs:
1204
   _eglCleanupDisplay(disp);
1205
   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
1206
 cleanup_fd:
1207
   close(dri2_dpy->fd);
1208
 cleanup_driver:
1209
   dlclose(dri2_dpy->driver);
1210
 cleanup_conn:
1211
   if (disp->PlatformDisplay == NULL)
1212
      xcb_disconnect(dri2_dpy->conn);
1213
 cleanup_dpy:
1214
   free(dri2_dpy);
1215
 
1216
   return EGL_FALSE;
1217
}
1218
 
1219
EGLBoolean
1220
dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp)
1221
{
1222
   EGLBoolean initialized = EGL_TRUE;
1223
 
1224
   int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
1225
 
1226
   if (x11_dri2_accel) {
1227
      if (!dri2_initialize_x11_dri2(drv, disp)) {
1228
         initialized = dri2_initialize_x11_swrast(drv, disp);
1229
      }
1230
   } else {
1231
      initialized = dri2_initialize_x11_swrast(drv, disp);
1232
   }
1233
 
1234
   return initialized;
1235
}
1236