Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2008 Red Hat, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Soft-
6
 * ware"), to deal in the Software without restriction, including without
7
 * limitation the rights to use, copy, modify, merge, publish, distribute,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, provided that the above copyright
10
 * notice(s) and this permission notice appear in all copies of the Soft-
11
 * ware and that both the above copyright notice(s) and this permission
12
 * notice appear in supporting documentation.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16
 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17
 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18
 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19
 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22
 * MANCE OF THIS SOFTWARE.
23
 *
24
 * Except as contained in this notice, the name of a copyright holder shall
25
 * not be used in advertising or otherwise to promote the sale, use or
26
 * other dealings in this Software without prior written authorization of
27
 * the copyright holder.
28
 *
29
 * Authors:
30
 *   Kristian Høgsberg (krh@redhat.com)
31
 */
32
 
33
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
34
 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
#include "glxclient.h"
41
#include 
42
#include 
43
#include 
44
#include 
45
#include 
46
#include 
47
#include 
48
#include "dri2.h"
49
#include "dri_common.h"
50
#include "dri2_priv.h"
51
#include "loader.h"
52
 
53
/* From xmlpool/options.h, user exposed so should be stable */
54
#define DRI_CONF_VBLANK_NEVER 0
55
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
56
#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
57
#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
58
 
59
#undef DRI2_MINOR
60
#define DRI2_MINOR 1
61
 
62
struct dri2_display
63
{
64
   __GLXDRIdisplay base;
65
 
66
   /*
67
    ** XFree86-DRI version information
68
    */
69
   int driMajor;
70
   int driMinor;
71
   int driPatch;
72
   int swapAvailable;
73
   int invalidateAvailable;
74
 
75
   __glxHashTable *dri2Hash;
76
 
77
   const __DRIextension *loader_extensions[4];
78
};
79
 
80
struct dri2_context
81
{
82
   struct glx_context base;
83
   __DRIcontext *driContext;
84
};
85
 
86
struct dri2_drawable
87
{
88
   __GLXDRIdrawable base;
89
   __DRIdrawable *driDrawable;
90
   __DRIbuffer buffers[5];
91
   int bufferCount;
92
   int width, height;
93
   int have_back;
94
   int have_fake_front;
95
   int swap_interval;
96
 
97
   uint64_t previous_time;
98
   unsigned frames;
99
};
100
 
101
static const struct glx_context_vtable dri2_context_vtable;
102
 
103
/* For XCB's handling of ust/msc/sbc counters, we have to hand it the high and
104
 * low halves separately.  This helps you split them.
105
 */
106
static void
107
split_counter(uint64_t counter, uint32_t *hi, uint32_t *lo)
108
{
109
   *hi = (counter >> 32);
110
   *lo = counter & 0xffffffff;
111
}
112
 
113
static uint64_t
114
merge_counter(uint32_t hi, uint32_t lo)
115
{
116
   return ((uint64_t)hi << 32) | lo;
117
}
118
 
119
static void
120
dri2_destroy_context(struct glx_context *context)
121
{
122
   struct dri2_context *pcp = (struct dri2_context *) context;
123
   struct dri2_screen *psc = (struct dri2_screen *) context->psc;
124
 
125
   driReleaseDrawables(&pcp->base);
126
 
127
   free((char *) context->extensions);
128
 
129
   (*psc->core->destroyContext) (pcp->driContext);
130
 
131
   free(pcp);
132
}
133
 
134
static Bool
135
dri2_bind_context(struct glx_context *context, struct glx_context *old,
136
		  GLXDrawable draw, GLXDrawable read)
137
{
138
   struct dri2_context *pcp = (struct dri2_context *) context;
139
   struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
140
   struct dri2_drawable *pdraw, *pread;
141
   __DRIdrawable *dri_draw = NULL, *dri_read = NULL;
142
   struct glx_display *dpyPriv = psc->base.display;
143
   struct dri2_display *pdp;
144
 
145
   pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw);
146
   pread = (struct dri2_drawable *) driFetchDrawable(context, read);
147
 
148
   driReleaseDrawables(&pcp->base);
149
 
150
   if (pdraw)
151
      dri_draw = pdraw->driDrawable;
152
   else if (draw != None)
153
      return GLXBadDrawable;
154
 
155
   if (pread)
156
      dri_read = pread->driDrawable;
157
   else if (read != None)
158
      return GLXBadDrawable;
159
 
160
   if (!(*psc->core->bindContext) (pcp->driContext, dri_draw, dri_read))
161
      return GLXBadContext;
162
 
163
   /* If the server doesn't send invalidate events, we may miss a
164
    * resize before the rendering starts.  Invalidate the buffers now
165
    * so the driver will recheck before rendering starts. */
166
   pdp = (struct dri2_display *) dpyPriv->dri2Display;
167
   if (!pdp->invalidateAvailable && pdraw) {
168
      dri2InvalidateBuffers(psc->base.dpy, pdraw->base.xDrawable);
169
      if (pread != pdraw && pread)
170
	 dri2InvalidateBuffers(psc->base.dpy, pread->base.xDrawable);
171
   }
172
 
173
   return Success;
174
}
175
 
176
static void
177
dri2_unbind_context(struct glx_context *context, struct glx_context *new)
178
{
179
   struct dri2_context *pcp = (struct dri2_context *) context;
180
   struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
181
 
182
   (*psc->core->unbindContext) (pcp->driContext);
183
}
184
 
185
static struct glx_context *
186
dri2_create_context(struct glx_screen *base,
187
		    struct glx_config *config_base,
188
		    struct glx_context *shareList, int renderType)
189
{
190
   struct dri2_context *pcp, *pcp_shared;
191
   struct dri2_screen *psc = (struct dri2_screen *) base;
192
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
193
   __DRIcontext *shared = NULL;
194
 
195
   /* Check the renderType value */
196
   if (!validate_renderType_against_config(config_base, renderType))
197
       return NULL;
198
 
199
   if (shareList) {
200
      /* If the shareList context is not a DRI2 context, we cannot possibly
201
       * create a DRI2 context that shares it.
202
       */
203
      if (shareList->vtable->destroy != dri2_destroy_context) {
204
	 return NULL;
205
      }
206
 
207
      pcp_shared = (struct dri2_context *) shareList;
208
      shared = pcp_shared->driContext;
209
   }
210
 
211
   pcp = calloc(1, sizeof *pcp);
212
   if (pcp == NULL)
213
      return NULL;
214
 
215
   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
216
      free(pcp);
217
      return NULL;
218
   }
219
 
220
   pcp->base.renderType = renderType;
221
 
222
   pcp->driContext =
223
      (*psc->dri2->createNewContext) (psc->driScreen,
224
                                      config->driConfig, shared, pcp);
225
 
226
   if (pcp->driContext == NULL) {
227
      free(pcp);
228
      return NULL;
229
   }
230
 
231
   pcp->base.vtable = &dri2_context_vtable;
232
 
233
   return &pcp->base;
234
}
235
 
236
static struct glx_context *
237
dri2_create_context_attribs(struct glx_screen *base,
238
			    struct glx_config *config_base,
239
			    struct glx_context *shareList,
240
			    unsigned num_attribs,
241
			    const uint32_t *attribs,
242
			    unsigned *error)
243
{
244
   struct dri2_context *pcp = NULL;
245
   struct dri2_context *pcp_shared = NULL;
246
   struct dri2_screen *psc = (struct dri2_screen *) base;
247
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
248
   __DRIcontext *shared = NULL;
249
 
250
   uint32_t minor_ver;
251
   uint32_t major_ver;
252
   uint32_t renderType;
253
   uint32_t flags;
254
   unsigned api;
255
   int reset;
256
   uint32_t ctx_attribs[2 * 5];
257
   unsigned num_ctx_attribs = 0;
258
 
259
   if (psc->dri2->base.version < 3) {
260
      *error = __DRI_CTX_ERROR_NO_MEMORY;
261
      goto error_exit;
262
   }
263
 
264
   /* Remap the GLX tokens to DRI2 tokens.
265
    */
266
   if (!dri2_convert_glx_attribs(num_attribs, attribs,
267
                                 &major_ver, &minor_ver, &renderType, &flags,
268
                                 &api, &reset, error))
269
      goto error_exit;
270
 
271
   /* Check the renderType value */
272
   if (!validate_renderType_against_config(config_base, renderType))
273
       goto error_exit;
274
 
275
   if (shareList) {
276
      pcp_shared = (struct dri2_context *) shareList;
277
      shared = pcp_shared->driContext;
278
   }
279
 
280
   pcp = calloc(1, sizeof *pcp);
281
   if (pcp == NULL) {
282
      *error = __DRI_CTX_ERROR_NO_MEMORY;
283
      goto error_exit;
284
   }
285
 
286
   if (!glx_context_init(&pcp->base, &psc->base, &config->base))
287
      goto error_exit;
288
 
289
   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
290
   ctx_attribs[num_ctx_attribs++] = major_ver;
291
   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
292
   ctx_attribs[num_ctx_attribs++] = minor_ver;
293
 
294
   /* Only send a value when the non-default value is requested.  By doing
295
    * this we don't have to check the driver's DRI2 version before sending the
296
    * default value.
297
    */
298
   if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
299
      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
300
      ctx_attribs[num_ctx_attribs++] = reset;
301
   }
302
 
303
   if (flags != 0) {
304
      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
305
 
306
      /* The current __DRI_CTX_FLAG_* values are identical to the
307
       * GLX_CONTEXT_*_BIT values.
308
       */
309
      ctx_attribs[num_ctx_attribs++] = flags;
310
   }
311
 
312
   /* The renderType is retrieved from attribs, or set to default
313
    *  of GLX_RGBA_TYPE.
314
    */
315
   pcp->base.renderType = renderType;
316
 
317
   pcp->driContext =
318
      (*psc->dri2->createContextAttribs) (psc->driScreen,
319
					  api,
320
					  config->driConfig,
321
					  shared,
322
					  num_ctx_attribs / 2,
323
					  ctx_attribs,
324
					  error,
325
					  pcp);
326
 
327
   if (pcp->driContext == NULL)
328
      goto error_exit;
329
 
330
   pcp->base.vtable = &dri2_context_vtable;
331
 
332
   return &pcp->base;
333
 
334
error_exit:
335
   free(pcp);
336
 
337
   return NULL;
338
}
339
 
340
static void
341
dri2DestroyDrawable(__GLXDRIdrawable *base)
342
{
343
   struct dri2_screen *psc = (struct dri2_screen *) base->psc;
344
   struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
345
   struct glx_display *dpyPriv = psc->base.display;
346
   struct dri2_display *pdp = (struct dri2_display *)dpyPriv->dri2Display;
347
 
348
   __glxHashDelete(pdp->dri2Hash, pdraw->base.xDrawable);
349
   (*psc->core->destroyDrawable) (pdraw->driDrawable);
350
 
351
   /* If it's a GLX 1.3 drawables, we can destroy the DRI2 drawable
352
    * now, as the application explicitly asked to destroy the GLX
353
    * drawable.  Otherwise, for legacy drawables, we let the DRI2
354
    * drawable linger on the server, since there's no good way of
355
    * knowing when the application is done with it.  The server will
356
    * destroy the DRI2 drawable when it destroys the X drawable or the
357
    * client exits anyway. */
358
   if (pdraw->base.xDrawable != pdraw->base.drawable)
359
      DRI2DestroyDrawable(psc->base.dpy, pdraw->base.xDrawable);
360
 
361
   free(pdraw);
362
}
363
 
364
static __GLXDRIdrawable *
365
dri2CreateDrawable(struct glx_screen *base, XID xDrawable,
366
		   GLXDrawable drawable, struct glx_config *config_base)
367
{
368
   struct dri2_drawable *pdraw;
369
   struct dri2_screen *psc = (struct dri2_screen *) base;
370
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
371
   struct glx_display *dpyPriv;
372
   struct dri2_display *pdp;
373
   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
374
 
375
   dpyPriv = __glXInitialize(psc->base.dpy);
376
   if (dpyPriv == NULL)
377
      return NULL;
378
 
379
   pdraw = calloc(1, sizeof(*pdraw));
380
   if (!pdraw)
381
      return NULL;
382
 
383
   pdraw->base.destroyDrawable = dri2DestroyDrawable;
384
   pdraw->base.xDrawable = xDrawable;
385
   pdraw->base.drawable = drawable;
386
   pdraw->base.psc = &psc->base;
387
   pdraw->bufferCount = 0;
388
   pdraw->swap_interval = 1; /* default may be overridden below */
389
   pdraw->have_back = 0;
390
 
391
   if (psc->config)
392
      psc->config->configQueryi(psc->driScreen,
393
				"vblank_mode", &vblank_mode);
394
 
395
   switch (vblank_mode) {
396
   case DRI_CONF_VBLANK_NEVER:
397
   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
398
      pdraw->swap_interval = 0;
399
      break;
400
   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
401
   case DRI_CONF_VBLANK_ALWAYS_SYNC:
402
   default:
403
      pdraw->swap_interval = 1;
404
      break;
405
   }
406
 
407
   DRI2CreateDrawable(psc->base.dpy, xDrawable);
408
   pdp = (struct dri2_display *)dpyPriv->dri2Display;;
409
   /* Create a new drawable */
410
   pdraw->driDrawable =
411
      (*psc->dri2->createNewDrawable) (psc->driScreen,
412
                                       config->driConfig, pdraw);
413
 
414
   if (!pdraw->driDrawable) {
415
      DRI2DestroyDrawable(psc->base.dpy, xDrawable);
416
      free(pdraw);
417
      return NULL;
418
   }
419
 
420
   if (__glxHashInsert(pdp->dri2Hash, xDrawable, pdraw)) {
421
      (*psc->core->destroyDrawable) (pdraw->driDrawable);
422
      DRI2DestroyDrawable(psc->base.dpy, xDrawable);
423
      free(pdraw);
424
      return None;
425
   }
426
 
427
   /*
428
    * Make sure server has the same swap interval we do for the new
429
    * drawable.
430
    */
431
   if (psc->vtable.setSwapInterval)
432
      psc->vtable.setSwapInterval(&pdraw->base, pdraw->swap_interval);
433
 
434
   return &pdraw->base;
435
}
436
 
437
static int
438
dri2DrawableGetMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
439
		   int64_t *ust, int64_t *msc, int64_t *sbc)
440
{
441
   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
442
   xcb_dri2_get_msc_cookie_t get_msc_cookie;
443
   xcb_dri2_get_msc_reply_t *get_msc_reply;
444
 
445
   get_msc_cookie = xcb_dri2_get_msc_unchecked(c, pdraw->xDrawable);
446
   get_msc_reply = xcb_dri2_get_msc_reply(c, get_msc_cookie, NULL);
447
 
448
   if (!get_msc_reply)
449
      return 0;
450
 
451
   *ust = merge_counter(get_msc_reply->ust_hi, get_msc_reply->ust_lo);
452
   *msc = merge_counter(get_msc_reply->msc_hi, get_msc_reply->msc_lo);
453
   *sbc = merge_counter(get_msc_reply->sbc_hi, get_msc_reply->sbc_lo);
454
   free(get_msc_reply);
455
 
456
   return 1;
457
}
458
 
459
static int
460
dri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
461
	       int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
462
{
463
   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
464
   xcb_dri2_wait_msc_cookie_t wait_msc_cookie;
465
   xcb_dri2_wait_msc_reply_t *wait_msc_reply;
466
   uint32_t target_msc_hi, target_msc_lo;
467
   uint32_t divisor_hi, divisor_lo;
468
   uint32_t remainder_hi, remainder_lo;
469
 
470
   split_counter(target_msc, &target_msc_hi, &target_msc_lo);
471
   split_counter(divisor, &divisor_hi, &divisor_lo);
472
   split_counter(remainder, &remainder_hi, &remainder_lo);
473
 
474
   wait_msc_cookie = xcb_dri2_wait_msc_unchecked(c, pdraw->xDrawable,
475
                                                 target_msc_hi, target_msc_lo,
476
                                                 divisor_hi, divisor_lo,
477
                                                 remainder_hi, remainder_lo);
478
   wait_msc_reply = xcb_dri2_wait_msc_reply(c, wait_msc_cookie, NULL);
479
 
480
   if (!wait_msc_reply)
481
      return 0;
482
 
483
   *ust = merge_counter(wait_msc_reply->ust_hi, wait_msc_reply->ust_lo);
484
   *msc = merge_counter(wait_msc_reply->msc_hi, wait_msc_reply->msc_lo);
485
   *sbc = merge_counter(wait_msc_reply->sbc_hi, wait_msc_reply->sbc_lo);
486
   free(wait_msc_reply);
487
 
488
   return 1;
489
}
490
 
491
static int
492
dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
493
	       int64_t *msc, int64_t *sbc)
494
{
495
   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
496
   xcb_dri2_wait_sbc_cookie_t wait_sbc_cookie;
497
   xcb_dri2_wait_sbc_reply_t *wait_sbc_reply;
498
   uint32_t target_sbc_hi, target_sbc_lo;
499
 
500
   split_counter(target_sbc, &target_sbc_hi, &target_sbc_lo);
501
 
502
   wait_sbc_cookie = xcb_dri2_wait_sbc_unchecked(c, pdraw->xDrawable,
503
                                                 target_sbc_hi, target_sbc_lo);
504
   wait_sbc_reply = xcb_dri2_wait_sbc_reply(c, wait_sbc_cookie, NULL);
505
 
506
   if (!wait_sbc_reply)
507
      return 0;
508
 
509
   *ust = merge_counter(wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo);
510
   *msc = merge_counter(wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo);
511
   *sbc = merge_counter(wait_sbc_reply->sbc_hi, wait_sbc_reply->sbc_lo);
512
   free(wait_sbc_reply);
513
 
514
   return 1;
515
}
516
 
517
static __DRIcontext *
518
dri2GetCurrentContext()
519
{
520
   struct glx_context *gc = __glXGetCurrentContext();
521
   struct dri2_context *dri2Ctx = (struct dri2_context *)gc;
522
 
523
   return dri2Ctx ? dri2Ctx->driContext : NULL;
524
}
525
 
526
/**
527
 * dri2Throttle - Request driver throttling
528
 *
529
 * This function uses the DRI2 throttle extension to give the
530
 * driver the opportunity to throttle on flush front, copysubbuffer
531
 * and swapbuffers.
532
 */
533
static void
534
dri2Throttle(struct dri2_screen *psc,
535
	     struct dri2_drawable *draw,
536
	     enum __DRI2throttleReason reason)
537
{
538
   if (psc->throttle) {
539
      __DRIcontext *ctx = dri2GetCurrentContext();
540
 
541
      psc->throttle->throttle(ctx, draw->driDrawable, reason);
542
   }
543
}
544
 
545
/**
546
 * Asks the driver to flush any queued work necessary for serializing with the
547
 * X command stream, and optionally the slightly more strict requirement of
548
 * glFlush() equivalence (which would require flushing even if nothing had
549
 * been drawn to a window system framebuffer, for example).
550
 */
551
static void
552
dri2Flush(struct dri2_screen *psc,
553
          __DRIcontext *ctx,
554
          struct dri2_drawable *draw,
555
          unsigned flags,
556
          enum __DRI2throttleReason throttle_reason)
557
{
558
   if (ctx && psc->f && psc->f->base.version >= 4) {
559
      psc->f->flush_with_flags(ctx, draw->driDrawable, flags, throttle_reason);
560
   } else {
561
      if (flags & __DRI2_FLUSH_CONTEXT)
562
         glFlush();
563
 
564
      if (psc->f)
565
         psc->f->flush(draw->driDrawable);
566
 
567
      dri2Throttle(psc, draw, throttle_reason);
568
   }
569
}
570
 
571
static void
572
__dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
573
		    int width, int height,
574
		    enum __DRI2throttleReason reason, Bool flush)
575
{
576
   struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
577
   struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc;
578
   XRectangle xrect;
579
   XserverRegion region;
580
   __DRIcontext *ctx = dri2GetCurrentContext();
581
   unsigned flags;
582
 
583
   /* Check we have the right attachments */
584
   if (!priv->have_back)
585
      return;
586
 
587
   xrect.x = x;
588
   xrect.y = priv->height - y - height;
589
   xrect.width = width;
590
   xrect.height = height;
591
 
592
   flags = __DRI2_FLUSH_DRAWABLE;
593
   if (flush)
594
      flags |= __DRI2_FLUSH_CONTEXT;
595
   dri2Flush(psc, ctx, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
596
 
597
   region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
598
   DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
599
                  DRI2BufferFrontLeft, DRI2BufferBackLeft);
600
 
601
   /* Refresh the fake front (if present) after we just damaged the real
602
    * front.
603
    */
604
   if (priv->have_fake_front)
605
      DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
606
		     DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
607
 
608
   XFixesDestroyRegion(psc->base.dpy, region);
609
}
610
 
611
static void
612
dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y,
613
		  int width, int height, Bool flush)
614
{
615
   __dri2CopySubBuffer(pdraw, x, y, width, height,
616
		       __DRI2_THROTTLE_COPYSUBBUFFER, flush);
617
}
618
 
619
 
620
static void
621
dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src)
622
{
623
   XRectangle xrect;
624
   XserverRegion region;
625
   struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
626
 
627
   xrect.x = 0;
628
   xrect.y = 0;
629
   xrect.width = priv->width;
630
   xrect.height = priv->height;
631
 
632
   if (psc->f)
633
      (*psc->f->flush) (priv->driDrawable);
634
 
635
   region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
636
   DRI2CopyRegion(psc->base.dpy, priv->base.xDrawable, region, dest, src);
637
   XFixesDestroyRegion(psc->base.dpy, region);
638
 
639
}
640
 
641
static void
642
dri2_wait_x(struct glx_context *gc)
643
{
644
   struct dri2_drawable *priv = (struct dri2_drawable *)
645
      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
646
 
647
   if (priv == NULL || !priv->have_fake_front)
648
      return;
649
 
650
   dri2_copy_drawable(priv, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
651
}
652
 
653
static void
654
dri2_wait_gl(struct glx_context *gc)
655
{
656
   struct dri2_drawable *priv = (struct dri2_drawable *)
657
      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
658
 
659
   if (priv == NULL || !priv->have_fake_front)
660
      return;
661
 
662
   dri2_copy_drawable(priv, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
663
}
664
 
665
/**
666
 * Called by the driver when it needs to update the real front buffer with the
667
 * contents of its fake front buffer.
668
 */
669
static void
670
dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
671
{
672
   struct glx_display *priv;
673
   struct dri2_display *pdp;
674
   struct glx_context *gc;
675
   struct dri2_drawable *pdraw = loaderPrivate;
676
   struct dri2_screen *psc;
677
 
678
   if (!pdraw)
679
      return;
680
 
681
   if (!pdraw->base.psc)
682
      return;
683
 
684
   psc = (struct dri2_screen *) pdraw->base.psc;
685
 
686
   priv = __glXInitialize(psc->base.dpy);
687
 
688
   if (priv == NULL)
689
       return;
690
 
691
   pdp = (struct dri2_display *) priv->dri2Display;
692
   gc = __glXGetCurrentContext();
693
 
694
   dri2Throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT);
695
 
696
   /* Old servers don't send invalidate events */
697
   if (!pdp->invalidateAvailable)
698
       dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable);
699
 
700
   dri2_wait_gl(gc);
701
}
702
 
703
 
704
static void
705
dri2DestroyScreen(struct glx_screen *base)
706
{
707
   struct dri2_screen *psc = (struct dri2_screen *) base;
708
 
709
   /* Free the direct rendering per screen data */
710
   (*psc->core->destroyScreen) (psc->driScreen);
711
   driDestroyConfigs(psc->driver_configs);
712
   close(psc->fd);
713
   free(psc);
714
}
715
 
716
/**
717
 * Process list of buffer received from the server
718
 *
719
 * Processes the list of buffers received in a reply from the server to either
720
 * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
721
 */
722
static void
723
process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
724
                unsigned count)
725
{
726
   int i;
727
 
728
   pdraw->bufferCount = count;
729
   pdraw->have_fake_front = 0;
730
   pdraw->have_back = 0;
731
 
732
   /* This assumes the DRI2 buffer attachment tokens matches the
733
    * __DRIbuffer tokens. */
734
   for (i = 0; i < count; i++) {
735
      pdraw->buffers[i].attachment = buffers[i].attachment;
736
      pdraw->buffers[i].name = buffers[i].name;
737
      pdraw->buffers[i].pitch = buffers[i].pitch;
738
      pdraw->buffers[i].cpp = buffers[i].cpp;
739
      pdraw->buffers[i].flags = buffers[i].flags;
740
      if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
741
         pdraw->have_fake_front = 1;
742
      if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
743
         pdraw->have_back = 1;
744
   }
745
 
746
}
747
 
748
unsigned dri2GetSwapEventType(Display* dpy, XID drawable)
749
{
750
      struct glx_display *glx_dpy = __glXInitialize(dpy);
751
      __GLXDRIdrawable *pdraw;
752
      pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
753
      if (!pdraw || !(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
754
         return 0;
755
      return glx_dpy->codes->first_event + GLX_BufferSwapComplete;
756
}
757
 
758
static void show_fps(struct dri2_drawable *draw)
759
{
760
   const int interval =
761
      ((struct dri2_screen *) draw->base.psc)->show_fps_interval;
762
   struct timeval tv;
763
   uint64_t current_time;
764
 
765
   gettimeofday(&tv, 0);
766
   current_time = (uint64_t)tv.tv_sec*1000000 + (uint64_t)tv.tv_usec;
767
 
768
   draw->frames++;
769
 
770
   if (draw->previous_time + interval * 1000000 <= current_time) {
771
      if (draw->previous_time) {
772
         fprintf(stderr, "libGL: FPS = %.1f\n",
773
                 ((uint64_t)draw->frames * 1000000) /
774
                 (double)(current_time - draw->previous_time));
775
      }
776
      draw->frames = 0;
777
      draw->previous_time = current_time;
778
   }
779
}
780
 
781
static int64_t
782
dri2XcbSwapBuffers(Display *dpy,
783
                  __GLXDRIdrawable *pdraw,
784
                  int64_t target_msc,
785
                  int64_t divisor,
786
                  int64_t remainder)
787
{
788
   xcb_dri2_swap_buffers_cookie_t swap_buffers_cookie;
789
   xcb_dri2_swap_buffers_reply_t *swap_buffers_reply;
790
   uint32_t target_msc_hi, target_msc_lo;
791
   uint32_t divisor_hi, divisor_lo;
792
   uint32_t remainder_hi, remainder_lo;
793
   int64_t ret = 0;
794
   xcb_connection_t *c = XGetXCBConnection(dpy);
795
 
796
   split_counter(target_msc, &target_msc_hi, &target_msc_lo);
797
   split_counter(divisor, &divisor_hi, &divisor_lo);
798
   split_counter(remainder, &remainder_hi, &remainder_lo);
799
 
800
   swap_buffers_cookie =
801
      xcb_dri2_swap_buffers_unchecked(c, pdraw->xDrawable,
802
                                      target_msc_hi, target_msc_lo,
803
                                      divisor_hi, divisor_lo,
804
                                      remainder_hi, remainder_lo);
805
 
806
   /* Immediately wait on the swapbuffers reply.  If we didn't, we'd have
807
    * to do so some time before reusing a (non-pageflipped) backbuffer.
808
    * Otherwise, the new rendering could get ahead of the X Server's
809
    * dispatch of the swapbuffer and you'd display garbage.
810
    *
811
    * We use XSync() first to reap the invalidate events through the event
812
    * filter, to ensure that the next drawing doesn't use an invalidated
813
    * buffer.
814
    */
815
   XSync(dpy, False);
816
 
817
   swap_buffers_reply =
818
      xcb_dri2_swap_buffers_reply(c, swap_buffers_cookie, NULL);
819
   if (swap_buffers_reply) {
820
      ret = merge_counter(swap_buffers_reply->swap_hi,
821
                          swap_buffers_reply->swap_lo);
822
      free(swap_buffers_reply);
823
   }
824
   return ret;
825
}
826
 
827
static int64_t
828
dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
829
		int64_t remainder, Bool flush)
830
{
831
    struct dri2_drawable *priv = (struct dri2_drawable *) pdraw;
832
    struct glx_display *dpyPriv = __glXInitialize(priv->base.psc->dpy);
833
    struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
834
    struct dri2_display *pdp =
835
	(struct dri2_display *)dpyPriv->dri2Display;
836
    int64_t ret = 0;
837
 
838
    /* Check we have the right attachments */
839
    if (!priv->have_back)
840
	return ret;
841
 
842
    /* Old servers can't handle swapbuffers */
843
    if (!pdp->swapAvailable) {
844
       __dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height,
845
			   __DRI2_THROTTLE_SWAPBUFFER, flush);
846
    } else {
847
       __DRIcontext *ctx = dri2GetCurrentContext();
848
       unsigned flags = __DRI2_FLUSH_DRAWABLE;
849
       if (flush)
850
          flags |= __DRI2_FLUSH_CONTEXT;
851
       dri2Flush(psc, ctx, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
852
 
853
       ret = dri2XcbSwapBuffers(pdraw->psc->dpy, pdraw,
854
                                target_msc, divisor, remainder);
855
    }
856
 
857
    if (psc->show_fps_interval) {
858
       show_fps(priv);
859
    }
860
 
861
    /* Old servers don't send invalidate events */
862
    if (!pdp->invalidateAvailable)
863
       dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
864
 
865
    return ret;
866
}
867
 
868
static __DRIbuffer *
869
dri2GetBuffers(__DRIdrawable * driDrawable,
870
               int *width, int *height,
871
               unsigned int *attachments, int count,
872
               int *out_count, void *loaderPrivate)
873
{
874
   struct dri2_drawable *pdraw = loaderPrivate;
875
   DRI2Buffer *buffers;
876
 
877
   buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
878
                            width, height, attachments, count, out_count);
879
   if (buffers == NULL)
880
      return NULL;
881
 
882
   pdraw->width = *width;
883
   pdraw->height = *height;
884
   process_buffers(pdraw, buffers, *out_count);
885
 
886
   free(buffers);
887
 
888
   return pdraw->buffers;
889
}
890
 
891
static __DRIbuffer *
892
dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
893
                         int *width, int *height,
894
                         unsigned int *attachments, int count,
895
                         int *out_count, void *loaderPrivate)
896
{
897
   struct dri2_drawable *pdraw = loaderPrivate;
898
   DRI2Buffer *buffers;
899
 
900
   buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
901
                                      pdraw->base.xDrawable,
902
                                      width, height, attachments,
903
                                      count, out_count);
904
   if (buffers == NULL)
905
      return NULL;
906
 
907
   pdraw->width = *width;
908
   pdraw->height = *height;
909
   process_buffers(pdraw, buffers, *out_count);
910
 
911
   free(buffers);
912
 
913
   return pdraw->buffers;
914
}
915
 
916
static int
917
dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
918
{
919
   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
920
   struct dri2_drawable *priv =  (struct dri2_drawable *) pdraw;
921
   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
922
   struct dri2_screen *psc = (struct dri2_screen *) priv->base.psc;
923
 
924
   if (psc->config)
925
      psc->config->configQueryi(psc->driScreen,
926
				"vblank_mode", &vblank_mode);
927
 
928
   switch (vblank_mode) {
929
   case DRI_CONF_VBLANK_NEVER:
930
      if (interval != 0)
931
         return GLX_BAD_VALUE;
932
      break;
933
   case DRI_CONF_VBLANK_ALWAYS_SYNC:
934
      if (interval <= 0)
935
	 return GLX_BAD_VALUE;
936
      break;
937
   default:
938
      break;
939
   }
940
 
941
   xcb_dri2_swap_interval(c, priv->base.xDrawable, interval);
942
   priv->swap_interval = interval;
943
 
944
   return 0;
945
}
946
 
947
static int
948
dri2GetSwapInterval(__GLXDRIdrawable *pdraw)
949
{
950
   struct dri2_drawable *priv =  (struct dri2_drawable *) pdraw;
951
 
952
  return priv->swap_interval;
953
}
954
 
955
static const __DRIdri2LoaderExtension dri2LoaderExtension = {
956
   .base = { __DRI_DRI2_LOADER, 3 },
957
 
958
   .getBuffers              = dri2GetBuffers,
959
   .flushFrontBuffer        = dri2FlushFrontBuffer,
960
   .getBuffersWithFormat    = dri2GetBuffersWithFormat,
961
};
962
 
963
static const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
964
   .base = { __DRI_DRI2_LOADER, 3 },
965
 
966
   .getBuffers              = dri2GetBuffers,
967
   .flushFrontBuffer        = dri2FlushFrontBuffer,
968
   .getBuffersWithFormat    = NULL,
969
};
970
 
971
static const __DRIuseInvalidateExtension dri2UseInvalidate = {
972
   .base = { __DRI_USE_INVALIDATE, 1 }
973
};
974
 
975
_X_HIDDEN void
976
dri2InvalidateBuffers(Display *dpy, XID drawable)
977
{
978
   __GLXDRIdrawable *pdraw =
979
      dri2GetGlxDrawableFromXDrawableId(dpy, drawable);
980
   struct dri2_screen *psc;
981
   struct dri2_drawable *pdp = (struct dri2_drawable *) pdraw;
982
 
983
   if (!pdraw)
984
      return;
985
 
986
   psc = (struct dri2_screen *) pdraw->psc;
987
 
988
   if (pdraw && psc->f && psc->f->base.version >= 3 && psc->f->invalidate)
989
       psc->f->invalidate(pdp->driDrawable);
990
}
991
 
992
static void
993
dri2_bind_tex_image(Display * dpy,
994
		    GLXDrawable drawable,
995
		    int buffer, const int *attrib_list)
996
{
997
   struct glx_context *gc = __glXGetCurrentContext();
998
   struct dri2_context *pcp = (struct dri2_context *) gc;
999
   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1000
   struct glx_display *dpyPriv = __glXInitialize(dpy);
1001
   struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
1002
   struct dri2_display *pdp;
1003
   struct dri2_screen *psc;
1004
 
1005
   if (dpyPriv == NULL)
1006
       return;
1007
 
1008
   pdp = (struct dri2_display *) dpyPriv->dri2Display;
1009
 
1010
   if (pdraw != NULL) {
1011
      psc = (struct dri2_screen *) base->psc;
1012
 
1013
      if (!pdp->invalidateAvailable && psc->f &&
1014
           psc->f->base.version >= 3 && psc->f->invalidate)
1015
	 psc->f->invalidate(pdraw->driDrawable);
1016
 
1017
      if (psc->texBuffer->base.version >= 2 &&
1018
	  psc->texBuffer->setTexBuffer2 != NULL) {
1019
	 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
1020
					   pdraw->base.textureTarget,
1021
					   pdraw->base.textureFormat,
1022
					   pdraw->driDrawable);
1023
      }
1024
      else {
1025
	 (*psc->texBuffer->setTexBuffer) (pcp->driContext,
1026
					  pdraw->base.textureTarget,
1027
					  pdraw->driDrawable);
1028
      }
1029
   }
1030
}
1031
 
1032
static void
1033
dri2_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
1034
{
1035
   struct glx_context *gc = __glXGetCurrentContext();
1036
   struct dri2_context *pcp = (struct dri2_context *) gc;
1037
   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
1038
   struct glx_display *dpyPriv = __glXInitialize(dpy);
1039
   struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
1040
   struct dri2_screen *psc;
1041
 
1042
   if (dpyPriv != NULL && pdraw != NULL) {
1043
      psc = (struct dri2_screen *) base->psc;
1044
 
1045
      if (psc->texBuffer->base.version >= 3 &&
1046
          psc->texBuffer->releaseTexBuffer != NULL) {
1047
         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
1048
                                           pdraw->base.textureTarget,
1049
                                           pdraw->driDrawable);
1050
      }
1051
   }
1052
}
1053
 
1054
static const struct glx_context_vtable dri2_context_vtable = {
1055
   .destroy             = dri2_destroy_context,
1056
   .bind                = dri2_bind_context,
1057
   .unbind              = dri2_unbind_context,
1058
   .wait_gl             = dri2_wait_gl,
1059
   .wait_x              = dri2_wait_x,
1060
   .use_x_font          = DRI_glXUseXFont,
1061
   .bind_tex_image      = dri2_bind_tex_image,
1062
   .release_tex_image   = dri2_release_tex_image,
1063
   .get_proc_address    = NULL,
1064
};
1065
 
1066
static void
1067
dri2BindExtensions(struct dri2_screen *psc, struct glx_display * priv,
1068
                   const char *driverName)
1069
{
1070
   const struct dri2_display *const pdp = (struct dri2_display *)
1071
      priv->dri2Display;
1072
   const __DRIextension **extensions;
1073
   int i;
1074
 
1075
   extensions = psc->core->getExtensions(psc->driScreen);
1076
 
1077
   __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
1078
   __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
1079
   __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
1080
   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
1081
 
1082
   /*
1083
    * GLX_INTEL_swap_event is broken on the server side, where it's
1084
    * currently unconditionally enabled. This completely breaks
1085
    * systems running on drivers which don't support that extension.
1086
    * There's no way to test for its presence on this side, so instead
1087
    * of disabling it unconditionally, just disable it for drivers
1088
    * which are known to not support it, or for DDX drivers supporting
1089
    * only an older (pre-ScheduleSwap) version of DRI2.
1090
    *
1091
    * This is a hack which is required until:
1092
    * http://lists.x.org/archives/xorg-devel/2013-February/035449.html
1093
    * is merged and updated xserver makes it's way into distros:
1094
    */
1095
   if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) {
1096
      __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
1097
   }
1098
 
1099
   if (psc->dri2->base.version >= 3) {
1100
      const unsigned mask = psc->dri2->getAPIMask(psc->driScreen);
1101
 
1102
      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
1103
      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
1104
 
1105
      if ((mask & (1 << __DRI_API_GLES2)) != 0)
1106
	 __glXEnableDirectExtension(&psc->base,
1107
				    "GLX_EXT_create_context_es2_profile");
1108
   }
1109
 
1110
   for (i = 0; extensions[i]; i++) {
1111
      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
1112
	 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
1113
	 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
1114
      }
1115
 
1116
      if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
1117
	 psc->f = (__DRI2flushExtension *) extensions[i];
1118
	 /* internal driver extension, no GL extension exposed */
1119
      }
1120
 
1121
      if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
1122
	 psc->config = (__DRI2configQueryExtension *) extensions[i];
1123
 
1124
      if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0)))
1125
	 psc->throttle = (__DRI2throttleExtension *) extensions[i];
1126
 
1127
      /* DRI2 version 3 is also required because
1128
       * GLX_ARB_create_context_robustness requires GLX_ARB_create_context.
1129
       */
1130
      if (psc->dri2->base.version >= 3
1131
          && strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
1132
         __glXEnableDirectExtension(&psc->base,
1133
                                    "GLX_ARB_create_context_robustness");
1134
 
1135
      /* DRI2 version 3 is also required because GLX_MESA_query_renderer
1136
       * requires GLX_ARB_create_context_profile.
1137
       */
1138
      if (psc->dri2->base.version >= 3
1139
          && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
1140
         psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
1141
         __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
1142
      }
1143
   }
1144
}
1145
 
1146
static const struct glx_screen_vtable dri2_screen_vtable = {
1147
   .create_context         = dri2_create_context,
1148
   .create_context_attribs = dri2_create_context_attribs,
1149
   .query_renderer_integer = dri2_query_renderer_integer,
1150
   .query_renderer_string  = dri2_query_renderer_string,
1151
};
1152
 
1153
static struct glx_screen *
1154
dri2CreateScreen(int screen, struct glx_display * priv)
1155
{
1156
   const __DRIconfig **driver_configs;
1157
   const __DRIextension **extensions;
1158
   const struct dri2_display *const pdp = (struct dri2_display *)
1159
      priv->dri2Display;
1160
   struct dri2_screen *psc;
1161
   __GLXDRIscreen *psp;
1162
   struct glx_config *configs = NULL, *visuals = NULL;
1163
   char *driverName = NULL, *loader_driverName, *deviceName, *tmp;
1164
   drm_magic_t magic;
1165
   int i;
1166
 
1167
   psc = calloc(1, sizeof *psc);
1168
   if (psc == NULL)
1169
      return NULL;
1170
 
1171
   psc->fd = -1;
1172
 
1173
   if (!glx_screen_init(&psc->base, screen, priv)) {
1174
      free(psc);
1175
      return NULL;
1176
   }
1177
 
1178
   if (!DRI2Connect(priv->dpy, RootWindow(priv->dpy, screen),
1179
		    &driverName, &deviceName)) {
1180
      glx_screen_cleanup(&psc->base);
1181
      free(psc);
1182
      InfoMessageF("screen %d does not appear to be DRI2 capable\n", screen);
1183
      return NULL;
1184
   }
1185
 
1186
#ifdef O_CLOEXEC
1187
   psc->fd = open(deviceName, O_RDWR | O_CLOEXEC);
1188
   if (psc->fd == -1 && errno == EINVAL)
1189
#endif
1190
   {
1191
      psc->fd = open(deviceName, O_RDWR);
1192
      if (psc->fd != -1)
1193
         fcntl(psc->fd, F_SETFD, fcntl(psc->fd, F_GETFD) | FD_CLOEXEC);
1194
   }
1195
   if (psc->fd < 0) {
1196
      ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
1197
      goto handle_error;
1198
   }
1199
 
1200
   if (drmGetMagic(psc->fd, &magic)) {
1201
      ErrorMessageF("failed to get magic\n");
1202
      goto handle_error;
1203
   }
1204
 
1205
   if (!DRI2Authenticate(priv->dpy, RootWindow(priv->dpy, screen), magic)) {
1206
      ErrorMessageF("failed to authenticate magic %d\n", magic);
1207
      goto handle_error;
1208
   }
1209
 
1210
   /* If Mesa knows about the appropriate driver for this fd, then trust it.
1211
    * Otherwise, default to the server's value.
1212
    */
1213
   loader_driverName = loader_get_driver_for_fd(psc->fd, 0);
1214
   if (loader_driverName) {
1215
      free(driverName);
1216
      driverName = loader_driverName;
1217
   }
1218
 
1219
   psc->driver = driOpenDriver(driverName);
1220
   if (psc->driver == NULL) {
1221
      ErrorMessageF("driver pointer missing\n");
1222
      goto handle_error;
1223
   }
1224
 
1225
   extensions = driGetDriverExtensions(psc->driver, driverName);
1226
   if (extensions == NULL)
1227
      goto handle_error;
1228
 
1229
   for (i = 0; extensions[i]; i++) {
1230
      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
1231
	 psc->core = (__DRIcoreExtension *) extensions[i];
1232
      if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
1233
	 psc->dri2 = (__DRIdri2Extension *) extensions[i];
1234
   }
1235
 
1236
   if (psc->core == NULL || psc->dri2 == NULL) {
1237
      ErrorMessageF("core dri or dri2 extension not found\n");
1238
      goto handle_error;
1239
   }
1240
 
1241
   if (psc->dri2->base.version >= 4) {
1242
      psc->driScreen =
1243
         psc->dri2->createNewScreen2(screen, psc->fd,
1244
                                     (const __DRIextension **)
1245
                                     &pdp->loader_extensions[0],
1246
                                     extensions,
1247
                                     &driver_configs, psc);
1248
   } else {
1249
      psc->driScreen =
1250
         psc->dri2->createNewScreen(screen, psc->fd,
1251
                                    (const __DRIextension **)
1252
                                    &pdp->loader_extensions[0],
1253
                                    &driver_configs, psc);
1254
   }
1255
 
1256
   if (psc->driScreen == NULL) {
1257
      ErrorMessageF("failed to create dri screen\n");
1258
      goto handle_error;
1259
   }
1260
 
1261
   dri2BindExtensions(psc, priv, driverName);
1262
 
1263
   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
1264
   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
1265
 
1266
   if (!configs || !visuals) {
1267
       ErrorMessageF("No matching fbConfigs or visuals found\n");
1268
       goto handle_error;
1269
   }
1270
 
1271
   glx_config_destroy_list(psc->base.configs);
1272
   psc->base.configs = configs;
1273
   glx_config_destroy_list(psc->base.visuals);
1274
   psc->base.visuals = visuals;
1275
 
1276
   psc->driver_configs = driver_configs;
1277
 
1278
   psc->base.vtable = &dri2_screen_vtable;
1279
   psp = &psc->vtable;
1280
   psc->base.driScreen = psp;
1281
   psp->destroyScreen = dri2DestroyScreen;
1282
   psp->createDrawable = dri2CreateDrawable;
1283
   psp->swapBuffers = dri2SwapBuffers;
1284
   psp->getDrawableMSC = NULL;
1285
   psp->waitForMSC = NULL;
1286
   psp->waitForSBC = NULL;
1287
   psp->setSwapInterval = NULL;
1288
   psp->getSwapInterval = NULL;
1289
   psp->getBufferAge = NULL;
1290
 
1291
   if (pdp->driMinor >= 2) {
1292
      psp->getDrawableMSC = dri2DrawableGetMSC;
1293
      psp->waitForMSC = dri2WaitForMSC;
1294
      psp->waitForSBC = dri2WaitForSBC;
1295
      psp->setSwapInterval = dri2SetSwapInterval;
1296
      psp->getSwapInterval = dri2GetSwapInterval;
1297
      __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
1298
   }
1299
 
1300
   /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
1301
    * available.*/
1302
   psp->copySubBuffer = dri2CopySubBuffer;
1303
   __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
1304
 
1305
   free(driverName);
1306
   free(deviceName);
1307
 
1308
   tmp = getenv("LIBGL_SHOW_FPS");
1309
   psc->show_fps_interval = (tmp) ? atoi(tmp) : 0;
1310
   if (psc->show_fps_interval < 0)
1311
      psc->show_fps_interval = 0;
1312
 
1313
   InfoMessageF("Using DRI2 for screen %d\n", screen);
1314
 
1315
   return &psc->base;
1316
 
1317
handle_error:
1318
   CriticalErrorMessageF("failed to load driver: %s\n", driverName);
1319
 
1320
   if (configs)
1321
       glx_config_destroy_list(configs);
1322
   if (visuals)
1323
       glx_config_destroy_list(visuals);
1324
   if (psc->driScreen)
1325
       psc->core->destroyScreen(psc->driScreen);
1326
   psc->driScreen = NULL;
1327
   if (psc->fd >= 0)
1328
      close(psc->fd);
1329
   if (psc->driver)
1330
      dlclose(psc->driver);
1331
 
1332
   free(driverName);
1333
   free(deviceName);
1334
   glx_screen_cleanup(&psc->base);
1335
   free(psc);
1336
 
1337
   return NULL;
1338
}
1339
 
1340
/* Called from __glXFreeDisplayPrivate.
1341
 */
1342
static void
1343
dri2DestroyDisplay(__GLXDRIdisplay * dpy)
1344
{
1345
   struct dri2_display *pdp = (struct dri2_display *) dpy;
1346
 
1347
   __glxHashDestroy(pdp->dri2Hash);
1348
   free(dpy);
1349
}
1350
 
1351
_X_HIDDEN __GLXDRIdrawable *
1352
dri2GetGlxDrawableFromXDrawableId(Display *dpy, XID id)
1353
{
1354
   struct glx_display *d = __glXInitialize(dpy);
1355
   struct dri2_display *pdp = (struct dri2_display *) d->dri2Display;
1356
   __GLXDRIdrawable *pdraw;
1357
 
1358
   if (__glxHashLookup(pdp->dri2Hash, id, (void *) &pdraw) == 0)
1359
      return pdraw;
1360
 
1361
   return NULL;
1362
}
1363
 
1364
/*
1365
 * Allocate, initialize and return a __DRIdisplayPrivate object.
1366
 * This is called from __glXInitialize() when we are given a new
1367
 * display pointer.
1368
 */
1369
_X_HIDDEN __GLXDRIdisplay *
1370
dri2CreateDisplay(Display * dpy)
1371
{
1372
   struct dri2_display *pdp;
1373
   int eventBase, errorBase, i;
1374
 
1375
   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
1376
      return NULL;
1377
 
1378
   pdp = malloc(sizeof *pdp);
1379
   if (pdp == NULL)
1380
      return NULL;
1381
 
1382
   if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
1383
      free(pdp);
1384
      return NULL;
1385
   }
1386
 
1387
   pdp->driPatch = 0;
1388
   pdp->swapAvailable = (pdp->driMinor >= 2);
1389
   pdp->invalidateAvailable = (pdp->driMinor >= 3);
1390
 
1391
   pdp->base.destroyDisplay = dri2DestroyDisplay;
1392
   pdp->base.createScreen = dri2CreateScreen;
1393
 
1394
   i = 0;
1395
   if (pdp->driMinor < 1)
1396
      pdp->loader_extensions[i++] = &dri2LoaderExtension_old.base;
1397
   else
1398
      pdp->loader_extensions[i++] = &dri2LoaderExtension.base;
1399
 
1400
   pdp->loader_extensions[i++] = &systemTimeExtension.base;
1401
 
1402
   pdp->loader_extensions[i++] = &dri2UseInvalidate.base;
1403
 
1404
   pdp->loader_extensions[i++] = NULL;
1405
 
1406
   pdp->dri2Hash = __glxHashCreate();
1407
   if (pdp->dri2Hash == NULL) {
1408
      free(pdp);
1409
      return NULL;
1410
   }
1411
 
1412
   return &pdp->base;
1413
}
1414
 
1415
#endif /* GLX_DIRECT_RENDERING */