~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/glx/drisw_glx.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2008 George Sapountzis
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, EXPRESS OR
16
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 
 * SOFTWARE.
22
 
 */
23
 
 
24
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
25
 
 
26
 
#include <xcb/xproto.h>
27
 
#include <xcb/shm.h>
28
 
#include <X11/Xlib.h>
29
 
#include <X11/Xlib-xcb.h>
30
 
#include "glxclient.h"
31
 
#include <dlfcn.h>
32
 
#include "dri_common.h"
33
 
#include "drisw_priv.h"
34
 
#include <X11/extensions/shmproto.h>
35
 
#include <assert.h>
36
 
#include "util/debug.h"
37
 
#include "kopper_interface.h"
38
 
 
39
 
static int xshm_error = 0;
40
 
static int xshm_opcode = -1;
41
 
 
42
 
/**
43
 
 * Catches potential Xlib errors.
44
 
 */
45
 
static int
46
 
handle_xerror(Display *dpy, XErrorEvent *event)
47
 
{
48
 
   (void) dpy;
49
 
 
50
 
   assert(xshm_opcode != -1);
51
 
   if (event->request_code != xshm_opcode)
52
 
      return 0;
53
 
 
54
 
   xshm_error = event->error_code;
55
 
   return 0;
56
 
}
57
 
 
58
 
static Bool
59
 
XCreateDrawable(struct drisw_drawable * pdp, int shmid, Display * dpy)
60
 
{
61
 
   if (pdp->ximage) {
62
 
      XDestroyImage(pdp->ximage);
63
 
      pdp->ximage = NULL;
64
 
      if ((pdp->shminfo.shmid > 0) && (shmid != pdp->shminfo.shmid))
65
 
         XShmDetach(dpy, &pdp->shminfo);
66
 
   }
67
 
 
68
 
   if (!xshm_error && shmid >= 0) {
69
 
      pdp->shminfo.shmid = shmid;
70
 
      pdp->ximage = XShmCreateImage(dpy,
71
 
                                    NULL,
72
 
                                    pdp->xDepth,
73
 
                                    ZPixmap,              /* format */
74
 
                                    NULL,                 /* data */
75
 
                                    &pdp->shminfo,        /* shminfo */
76
 
                                    0, 0);                /* width, height */
77
 
      if (pdp->ximage != NULL) {
78
 
         int (*old_handler)(Display *, XErrorEvent *);
79
 
 
80
 
         /* dispatch pending errors */
81
 
         XSync(dpy, False);
82
 
 
83
 
         old_handler = XSetErrorHandler(handle_xerror);
84
 
         /* This may trigger the X protocol error we're ready to catch: */
85
 
         XShmAttach(dpy, &pdp->shminfo);
86
 
         XSync(dpy, False);
87
 
 
88
 
         if (xshm_error) {
89
 
         /* we are on a remote display, this error is normal, don't print it */
90
 
            XDestroyImage(pdp->ximage);
91
 
            pdp->ximage = NULL;
92
 
         }
93
 
 
94
 
         (void) XSetErrorHandler(old_handler);
95
 
      }
96
 
   }
97
 
 
98
 
   if (pdp->ximage == NULL) {
99
 
      pdp->shminfo.shmid = -1;
100
 
      pdp->ximage = XCreateImage(dpy,
101
 
                                 NULL,
102
 
                                 pdp->xDepth,
103
 
                                 ZPixmap, 0,             /* format, offset */
104
 
                                 NULL,                   /* data */
105
 
                                 0, 0,                   /* width, height */
106
 
                                 32,                     /* bitmap_pad */
107
 
                                 0);                     /* bytes_per_line */
108
 
   }
109
 
 
110
 
  /**
111
 
   * swrast does not handle 24-bit depth with 24 bpp, so let X do the
112
 
   * the conversion for us.
113
 
   */
114
 
  if (pdp->ximage->bits_per_pixel == 24)
115
 
     pdp->ximage->bits_per_pixel = 32;
116
 
 
117
 
   return True;
118
 
}
119
 
 
120
 
static void
121
 
XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
122
 
{
123
 
   if (pdp->ximage)
124
 
      XDestroyImage(pdp->ximage);
125
 
 
126
 
   if (pdp->shminfo.shmid > 0)
127
 
      XShmDetach(dpy, &pdp->shminfo);
128
 
 
129
 
   XFreeGC(dpy, pdp->gc);
130
 
}
131
 
 
132
 
/**
133
 
 * swrast loader functions
134
 
 */
135
 
 
136
 
static void
137
 
swrastGetDrawableInfo(__DRIdrawable * draw,
138
 
                      int *x, int *y, int *w, int *h,
139
 
                      void *loaderPrivate)
140
 
{
141
 
   struct drisw_drawable *pdp = loaderPrivate;
142
 
   __GLXDRIdrawable *pdraw = &(pdp->base);
143
 
   Display *dpy = pdraw->psc->dpy;
144
 
   Drawable drawable;
145
 
 
146
 
   Window root;
147
 
   unsigned uw, uh, bw, depth;
148
 
 
149
 
   drawable = pdraw->xDrawable;
150
 
 
151
 
   XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
152
 
   *w = uw;
153
 
   *h = uh;
154
 
}
155
 
 
156
 
/**
157
 
 * Align renderbuffer pitch.
158
 
 *
159
 
 * This should be chosen by the driver and the loader (libGL, xserver/glx)
160
 
 * should use the driver provided pitch.
161
 
 *
162
 
 * It seems that the xorg loader (that is the xserver loading swrast_dri for
163
 
 * indirect rendering, not client-side libGL) requires that the pitch is
164
 
 * exactly the image width padded to 32 bits. XXX
165
 
 *
166
 
 * The above restriction can probably be overcome by using ScratchPixmap and
167
 
 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
168
 
 * the scratch pixmap to 'pitch / cpp'.
169
 
 */
170
 
static inline int
171
 
bytes_per_line(unsigned pitch_bits, unsigned mul)
172
 
{
173
 
   unsigned mask = mul - 1;
174
 
 
175
 
   return ((pitch_bits + mask) & ~mask) / 8;
176
 
}
177
 
 
178
 
static void
179
 
swrastXPutImage(__DRIdrawable * draw, int op,
180
 
                int srcx, int srcy, int x, int y,
181
 
                int w, int h, int stride,
182
 
                int shmid, char *data, void *loaderPrivate)
183
 
{
184
 
   struct drisw_drawable *pdp = loaderPrivate;
185
 
   __GLXDRIdrawable *pdraw = &(pdp->base);
186
 
   Display *dpy = pdraw->psc->dpy;
187
 
   Drawable drawable;
188
 
   XImage *ximage;
189
 
   GC gc = pdp->gc;
190
 
 
191
 
   if (!pdp->ximage || shmid != pdp->shminfo.shmid) {
192
 
      if (!XCreateDrawable(pdp, shmid, dpy))
193
 
         return;
194
 
   }
195
 
 
196
 
   drawable = pdraw->xDrawable;
197
 
   ximage = pdp->ximage;
198
 
   ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
199
 
   ximage->data = data;
200
 
 
201
 
   ximage->width = ximage->bytes_per_line / ((ximage->bits_per_pixel + 7)/ 8);
202
 
   ximage->height = h;
203
 
 
204
 
   if (pdp->shminfo.shmid >= 0) {
205
 
      XShmPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h, False);
206
 
      XSync(dpy, False);
207
 
   } else {
208
 
      XPutImage(dpy, drawable, gc, ximage, srcx, srcy, x, y, w, h);
209
 
   }
210
 
   ximage->data = NULL;
211
 
}
212
 
 
213
 
static void
214
 
swrastPutImageShm(__DRIdrawable * draw, int op,
215
 
                  int x, int y, int w, int h, int stride,
216
 
                  int shmid, char *shmaddr, unsigned offset,
217
 
                  void *loaderPrivate)
218
 
{
219
 
   struct drisw_drawable *pdp = loaderPrivate;
220
 
 
221
 
   if (!pdp)
222
 
      return;
223
 
 
224
 
   pdp->shminfo.shmaddr = shmaddr;
225
 
   swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, shmid,
226
 
                   shmaddr + offset, loaderPrivate);
227
 
}
228
 
 
229
 
static void
230
 
swrastPutImageShm2(__DRIdrawable * draw, int op,
231
 
                   int x, int y,
232
 
                   int w, int h, int stride,
233
 
                   int shmid, char *shmaddr, unsigned offset,
234
 
                   void *loaderPrivate)
235
 
{
236
 
   struct drisw_drawable *pdp = loaderPrivate;
237
 
 
238
 
   if (!pdp)
239
 
      return;
240
 
 
241
 
   pdp->shminfo.shmaddr = shmaddr;
242
 
   swrastXPutImage(draw, op, x, 0, x, y, w, h, stride, shmid,
243
 
                   shmaddr + offset, loaderPrivate);
244
 
}
245
 
 
246
 
static void
247
 
swrastPutImage2(__DRIdrawable * draw, int op,
248
 
                int x, int y, int w, int h, int stride,
249
 
                char *data, void *loaderPrivate)
250
 
{
251
 
   if (!loaderPrivate)
252
 
      return;
253
 
 
254
 
   swrastXPutImage(draw, op, 0, 0, x, y, w, h, stride, -1,
255
 
                   data, loaderPrivate);
256
 
}
257
 
 
258
 
static void
259
 
swrastPutImage(__DRIdrawable * draw, int op,
260
 
               int x, int y, int w, int h,
261
 
               char *data, void *loaderPrivate)
262
 
{
263
 
   if (!loaderPrivate)
264
 
      return;
265
 
 
266
 
   swrastXPutImage(draw, op, 0, 0, x, y, w, h, 0, -1,
267
 
                   data, loaderPrivate);
268
 
}
269
 
 
270
 
static void
271
 
swrastGetImage2(__DRIdrawable * read,
272
 
                int x, int y, int w, int h, int stride,
273
 
                char *data, void *loaderPrivate)
274
 
{
275
 
   struct drisw_drawable *prp = loaderPrivate;
276
 
   __GLXDRIdrawable *pread = &(prp->base);
277
 
   Display *dpy = pread->psc->dpy;
278
 
   Drawable readable;
279
 
   XImage *ximage;
280
 
 
281
 
   if (!prp->ximage || prp->shminfo.shmid >= 0) {
282
 
      if (!XCreateDrawable(prp, -1, dpy))
283
 
         return;
284
 
   }
285
 
 
286
 
   readable = pread->xDrawable;
287
 
 
288
 
   ximage = prp->ximage;
289
 
   ximage->data = data;
290
 
   ximage->width = w;
291
 
   ximage->height = h;
292
 
   ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
293
 
 
294
 
   XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
295
 
 
296
 
   ximage->data = NULL;
297
 
}
298
 
 
299
 
static void
300
 
swrastGetImage(__DRIdrawable * read,
301
 
               int x, int y, int w, int h,
302
 
               char *data, void *loaderPrivate)
303
 
{
304
 
   swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
305
 
}
306
 
 
307
 
static GLboolean
308
 
swrastGetImageShm2(__DRIdrawable * read,
309
 
                   int x, int y, int w, int h,
310
 
                   int shmid, void *loaderPrivate)
311
 
{
312
 
   struct drisw_drawable *prp = loaderPrivate;
313
 
   __GLXDRIdrawable *pread = &(prp->base);
314
 
   Display *dpy = pread->psc->dpy;
315
 
   Drawable readable;
316
 
   XImage *ximage;
317
 
 
318
 
   if (!prp->ximage || shmid != prp->shminfo.shmid) {
319
 
      if (!XCreateDrawable(prp, shmid, dpy))
320
 
         return GL_FALSE;
321
 
   }
322
 
 
323
 
   if (prp->shminfo.shmid == -1)
324
 
      return GL_FALSE;
325
 
   readable = pread->xDrawable;
326
 
 
327
 
   ximage = prp->ximage;
328
 
   ximage->data = prp->shminfo.shmaddr; /* no offset */
329
 
   ximage->width = w;
330
 
   ximage->height = h;
331
 
   ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
332
 
 
333
 
   XShmGetImage(dpy, readable, ximage, x, y, ~0L);
334
 
   return GL_TRUE;
335
 
}
336
 
 
337
 
static void
338
 
swrastGetImageShm(__DRIdrawable * read,
339
 
                  int x, int y, int w, int h,
340
 
                  int shmid, void *loaderPrivate)
341
 
{
342
 
   swrastGetImageShm2(read, x, y, w, h, shmid, loaderPrivate);
343
 
}
344
 
 
345
 
static const __DRIswrastLoaderExtension swrastLoaderExtension_shm = {
346
 
   .base = {__DRI_SWRAST_LOADER, 6 },
347
 
 
348
 
   .getDrawableInfo     = swrastGetDrawableInfo,
349
 
   .putImage            = swrastPutImage,
350
 
   .getImage            = swrastGetImage,
351
 
   .putImage2           = swrastPutImage2,
352
 
   .getImage2           = swrastGetImage2,
353
 
   .putImageShm         = swrastPutImageShm,
354
 
   .getImageShm         = swrastGetImageShm,
355
 
   .putImageShm2        = swrastPutImageShm2,
356
 
   .getImageShm2        = swrastGetImageShm2,
357
 
};
358
 
 
359
 
static const __DRIswrastLoaderExtension swrastLoaderExtension = {
360
 
   .base = {__DRI_SWRAST_LOADER, 3 },
361
 
 
362
 
   .getDrawableInfo     = swrastGetDrawableInfo,
363
 
   .putImage            = swrastPutImage,
364
 
   .getImage            = swrastGetImage,
365
 
   .putImage2           = swrastPutImage2,
366
 
   .getImage2           = swrastGetImage2,
367
 
};
368
 
 
369
 
static void
370
 
kopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out)
371
 
{
372
 
    __GLXDRIdrawable *draw = _draw;
373
 
 
374
 
    out->xcb.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
375
 
    out->xcb.pNext = NULL;
376
 
    out->xcb.flags = 0;
377
 
    out->xcb.connection = XGetXCBConnection(draw->psc->dpy);
378
 
    out->xcb.window = draw->xDrawable;
379
 
}
380
 
 
381
 
static const __DRIkopperLoaderExtension kopperLoaderExtension = {
382
 
    .base = { __DRI_KOPPER_LOADER, 1 },
383
 
 
384
 
    .SetSurfaceCreateInfo   = kopperSetSurfaceCreateInfo,
385
 
};
386
 
 
387
 
static const __DRIextension *loader_extensions_shm[] = {
388
 
   &swrastLoaderExtension_shm.base,
389
 
   &kopperLoaderExtension.base,
390
 
   NULL
391
 
};
392
 
 
393
 
static const __DRIextension *loader_extensions_noshm[] = {
394
 
   &swrastLoaderExtension.base,
395
 
   &kopperLoaderExtension.base,
396
 
   NULL
397
 
};
398
 
 
399
 
extern const __DRIuseInvalidateExtension dri2UseInvalidate;
400
 
extern const __DRIbackgroundCallableExtension driBackgroundCallable;
401
 
 
402
 
static const __DRIextension *kopper_extensions_noshm[] = {
403
 
   &swrastLoaderExtension.base,
404
 
   &kopperLoaderExtension.base,
405
 
   &dri2UseInvalidate.base,
406
 
   &driBackgroundCallable.base,
407
 
   NULL
408
 
};
409
 
 
410
 
/**
411
 
 * GLXDRI functions
412
 
 */
413
 
 
414
 
static void
415
 
drisw_destroy_context(struct glx_context *context)
416
 
{
417
 
   struct drisw_context *pcp = (struct drisw_context *) context;
418
 
   struct drisw_screen *psc = (struct drisw_screen *) context->psc;
419
 
 
420
 
   driReleaseDrawables(&pcp->base);
421
 
 
422
 
   free((char *) context->extensions);
423
 
 
424
 
   (*psc->core->destroyContext) (pcp->driContext);
425
 
 
426
 
   free(pcp);
427
 
}
428
 
 
429
 
static int
430
 
drisw_bind_context(struct glx_context *context, struct glx_context *old,
431
 
                   GLXDrawable draw, GLXDrawable read)
432
 
{
433
 
   struct drisw_context *pcp = (struct drisw_context *) context;
434
 
   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
435
 
   struct drisw_drawable *pdraw, *pread;
436
 
 
437
 
   pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
438
 
   pread = (struct drisw_drawable *) driFetchDrawable(context, read);
439
 
 
440
 
   driReleaseDrawables(&pcp->base);
441
 
 
442
 
   if (!(*psc->core->bindContext) (pcp->driContext,
443
 
                                  pdraw ? pdraw->driDrawable : NULL,
444
 
                                  pread ? pread->driDrawable : NULL))
445
 
      return GLXBadContext;
446
 
   if (psc->f) {
447
 
      if (pdraw)
448
 
         psc->f->invalidate(pdraw->driDrawable);
449
 
      if (pread && (!pdraw || pread->driDrawable != pdraw->driDrawable))
450
 
         psc->f->invalidate(pread->driDrawable);
451
 
   }
452
 
 
453
 
   return Success;
454
 
}
455
 
 
456
 
static void
457
 
drisw_unbind_context(struct glx_context *context, struct glx_context *new)
458
 
{
459
 
   struct drisw_context *pcp = (struct drisw_context *) context;
460
 
   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
461
 
 
462
 
   (*psc->core->unbindContext) (pcp->driContext);
463
 
}
464
 
 
465
 
static void
466
 
drisw_wait_gl(struct glx_context *context)
467
 
{
468
 
   glFinish();
469
 
}
470
 
 
471
 
static void
472
 
drisw_wait_x(struct glx_context *context)
473
 
{
474
 
   XSync(context->currentDpy, False);
475
 
}
476
 
 
477
 
static void
478
 
drisw_bind_tex_image(__GLXDRIdrawable *base,
479
 
                     int buffer, const int *attrib_list)
480
 
{
481
 
   struct glx_context *gc = __glXGetCurrentContext();
482
 
   struct drisw_context *pcp = (struct drisw_context *) gc;
483
 
   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
484
 
   struct drisw_screen *psc;
485
 
 
486
 
   if (pdraw != NULL) {
487
 
      psc = (struct drisw_screen *) base->psc;
488
 
 
489
 
      if (!psc->texBuffer)
490
 
         return;
491
 
 
492
 
      if (psc->texBuffer->base.version >= 2 &&
493
 
        psc->texBuffer->setTexBuffer2 != NULL) {
494
 
              (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
495
 
                                           pdraw->base.textureTarget,
496
 
                                           pdraw->base.textureFormat,
497
 
                                           pdraw->driDrawable);
498
 
      }
499
 
      else {
500
 
              (*psc->texBuffer->setTexBuffer) (pcp->driContext,
501
 
                                          pdraw->base.textureTarget,
502
 
                                          pdraw->driDrawable);
503
 
      }
504
 
   }
505
 
}
506
 
 
507
 
static void
508
 
drisw_release_tex_image(__GLXDRIdrawable *base, int buffer)
509
 
{
510
 
   struct glx_context *gc = __glXGetCurrentContext();
511
 
   struct drisw_context *pcp = (struct drisw_context *) gc;
512
 
   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
513
 
   struct drisw_screen *psc;
514
 
 
515
 
   if (pdraw != NULL) {
516
 
      psc = (struct drisw_screen *) base->psc;
517
 
 
518
 
      if (!psc->texBuffer)
519
 
         return;
520
 
 
521
 
      if (psc->texBuffer->base.version >= 3 &&
522
 
          psc->texBuffer->releaseTexBuffer != NULL) {
523
 
         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
524
 
                                           pdraw->base.textureTarget,
525
 
                                           pdraw->driDrawable);
526
 
      }
527
 
   }
528
 
}
529
 
 
530
 
static const struct glx_context_vtable drisw_context_vtable = {
531
 
   .destroy             = drisw_destroy_context,
532
 
   .bind                = drisw_bind_context,
533
 
   .unbind              = drisw_unbind_context,
534
 
   .wait_gl             = drisw_wait_gl,
535
 
   .wait_x              = drisw_wait_x,
536
 
};
537
 
 
538
 
static struct glx_context *
539
 
drisw_create_context_attribs(struct glx_screen *base,
540
 
                             struct glx_config *config_base,
541
 
                             struct glx_context *shareList,
542
 
                             unsigned num_attribs,
543
 
                             const uint32_t *attribs,
544
 
                             unsigned *error)
545
 
{
546
 
   struct drisw_context *pcp, *pcp_shared;
547
 
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
548
 
   struct drisw_screen *psc = (struct drisw_screen *) base;
549
 
   __DRIcontext *shared = NULL;
550
 
 
551
 
   struct dri_ctx_attribs dca;
552
 
   uint32_t ctx_attribs[2 * 5];
553
 
   unsigned num_ctx_attribs = 0;
554
 
 
555
 
   if (!psc->base.driScreen)
556
 
      return NULL;
557
 
 
558
 
   if (psc->swrast->base.version < 3)
559
 
      return NULL;
560
 
 
561
 
   *error = dri_convert_glx_attribs(num_attribs, attribs, &dca);
562
 
   if (*error != __DRI_CTX_ERROR_SUCCESS)
563
 
      return NULL;
564
 
 
565
 
   /* Check the renderType value */
566
 
   if (!validate_renderType_against_config(config_base, dca.render_type)) {
567
 
       return NULL;
568
 
   }
569
 
 
570
 
   if (shareList) {
571
 
      /* We can't share with an indirect context */
572
 
      if (!shareList->isDirect)
573
 
         return NULL;
574
 
 
575
 
      /* The GLX_ARB_create_context_no_error specs say:
576
 
       *
577
 
       *    BadMatch is generated if the value of GLX_CONTEXT_OPENGL_NO_ERROR_ARB
578
 
       *    used to create <share_context> does not match the value of
579
 
       *    GLX_CONTEXT_OPENGL_NO_ERROR_ARB for the context being created.
580
 
       */
581
 
      if (!!shareList->noError != !!dca.no_error) {
582
 
         *error = __DRI_CTX_ERROR_BAD_FLAG;
583
 
         return NULL;
584
 
      }
585
 
 
586
 
      pcp_shared = (struct drisw_context *) shareList;
587
 
      shared = pcp_shared->driContext;
588
 
   }
589
 
 
590
 
   pcp = calloc(1, sizeof *pcp);
591
 
   if (pcp == NULL)
592
 
      return NULL;
593
 
 
594
 
   if (!glx_context_init(&pcp->base, &psc->base, config_base)) {
595
 
      free(pcp);
596
 
      return NULL;
597
 
   }
598
 
 
599
 
   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
600
 
   ctx_attribs[num_ctx_attribs++] = dca.major_ver;
601
 
   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
602
 
   ctx_attribs[num_ctx_attribs++] = dca.minor_ver;
603
 
   if (dca.reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
604
 
      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
605
 
      ctx_attribs[num_ctx_attribs++] = dca.reset;
606
 
   }
607
 
 
608
 
   if (dca.release != __DRI_CTX_RELEASE_BEHAVIOR_FLUSH) {
609
 
       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR;
610
 
       ctx_attribs[num_ctx_attribs++] = dca.release;
611
 
   }
612
 
   if (dca.no_error) {
613
 
       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_NO_ERROR;
614
 
       ctx_attribs[num_ctx_attribs++] = GL_TRUE;
615
 
       pcp->base.noError = GL_TRUE;
616
 
   }
617
 
 
618
 
   if (dca.flags != 0) {
619
 
      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
620
 
      ctx_attribs[num_ctx_attribs++] = dca.flags;
621
 
   }
622
 
 
623
 
   pcp->base.renderType = dca.render_type;
624
 
 
625
 
   pcp->driContext =
626
 
      (*psc->swrast->createContextAttribs) (psc->driScreen,
627
 
                                            dca.api,
628
 
                                            config ? config->driConfig : NULL,
629
 
                                            shared,
630
 
                                            num_ctx_attribs / 2,
631
 
                                            ctx_attribs,
632
 
                                            error,
633
 
                                            pcp);
634
 
   if (pcp->driContext == NULL) {
635
 
      free(pcp);
636
 
      return NULL;
637
 
   }
638
 
 
639
 
   pcp->base.vtable = base->context_vtable;
640
 
 
641
 
   return &pcp->base;
642
 
}
643
 
 
644
 
static void
645
 
driswDestroyDrawable(__GLXDRIdrawable * pdraw)
646
 
{
647
 
   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
648
 
   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
649
 
 
650
 
   (*psc->core->destroyDrawable) (pdp->driDrawable);
651
 
 
652
 
   XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
653
 
   free(pdp);
654
 
}
655
 
 
656
 
static __GLXDRIdrawable *
657
 
driswCreateDrawable(struct glx_screen *base, XID xDrawable,
658
 
                    GLXDrawable drawable, int type,
659
 
                    struct glx_config *modes)
660
 
{
661
 
   struct drisw_drawable *pdp;
662
 
   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
663
 
   struct drisw_screen *psc = (struct drisw_screen *) base;
664
 
   const __DRIswrastExtension *swrast = psc->swrast;
665
 
   const __DRIkopperExtension *kopper = psc->kopper;
666
 
   Display *dpy = psc->base.dpy;
667
 
 
668
 
   pdp = calloc(1, sizeof(*pdp));
669
 
   if (!pdp)
670
 
      return NULL;
671
 
 
672
 
   pdp->base.xDrawable = xDrawable;
673
 
   pdp->base.drawable = drawable;
674
 
   pdp->base.psc = &psc->base;
675
 
   pdp->config = modes;
676
 
   pdp->gc = XCreateGC(dpy, xDrawable, 0, NULL);
677
 
   pdp->xDepth = 0;
678
 
 
679
 
   /* Use the visual depth, if this fbconfig corresponds to a visual */
680
 
   if (pdp->config->visualID != 0) {
681
 
      int matches = 0;
682
 
      XVisualInfo *visinfo, template;
683
 
 
684
 
      template.visualid = pdp->config->visualID;
685
 
      template.screen = pdp->config->screen;
686
 
      visinfo = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask,
687
 
                               &template, &matches);
688
 
 
689
 
      if (visinfo && matches) {
690
 
         pdp->xDepth = visinfo->depth;
691
 
         XFree(visinfo);
692
 
      }
693
 
   }
694
 
 
695
 
   /* Otherwise, or if XGetVisualInfo failed, ask the server */
696
 
   if (pdp->xDepth == 0) {
697
 
      Window root;
698
 
      int x, y;
699
 
      unsigned uw, uh, bw, depth;
700
 
 
701
 
      XGetGeometry(dpy, xDrawable, &root, &x, &y, &uw, &uh, &bw, &depth);
702
 
      pdp->xDepth = depth;
703
 
   }
704
 
 
705
 
   /* Create a new drawable */
706
 
   if (kopper) {
707
 
      pdp->driDrawable =
708
 
         (*kopper->createNewDrawable) (psc->driScreen, config->driConfig, pdp, !(type & GLX_WINDOW_BIT));
709
 
      pdp->swapInterval = 1;
710
 
   }
711
 
   else
712
 
      pdp->driDrawable =
713
 
         (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp);
714
 
 
715
 
   if (!pdp->driDrawable) {
716
 
      XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
717
 
      free(pdp);
718
 
      return NULL;
719
 
   }
720
 
 
721
 
   pdp->base.destroyDrawable = driswDestroyDrawable;
722
 
 
723
 
   return &pdp->base;
724
 
}
725
 
 
726
 
static int64_t
727
 
driswSwapBuffers(__GLXDRIdrawable * pdraw,
728
 
                 int64_t target_msc, int64_t divisor, int64_t remainder,
729
 
                 Bool flush)
730
 
{
731
 
   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
732
 
   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
733
 
 
734
 
   (void) target_msc;
735
 
   (void) divisor;
736
 
   (void) remainder;
737
 
 
738
 
   if (flush) {
739
 
      glFlush();
740
 
   }
741
 
 
742
 
   if (psc->kopper)
743
 
       return psc->kopper->swapBuffers (pdp->driDrawable);
744
 
 
745
 
   (*psc->core->swapBuffers) (pdp->driDrawable);
746
 
 
747
 
   return 0;
748
 
}
749
 
 
750
 
static void
751
 
driswCopySubBuffer(__GLXDRIdrawable * pdraw,
752
 
                   int x, int y, int width, int height, Bool flush)
753
 
{
754
 
   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
755
 
   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
756
 
 
757
 
   if (flush) {
758
 
      glFlush();
759
 
   }
760
 
 
761
 
   (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable,
762
 
                                            x, y, width, height);
763
 
}
764
 
 
765
 
static void
766
 
driswDestroyScreen(struct glx_screen *base)
767
 
{
768
 
   struct drisw_screen *psc = (struct drisw_screen *) base;
769
 
 
770
 
   /* Free the direct rendering per screen data */
771
 
   (*psc->core->destroyScreen) (psc->driScreen);
772
 
   driDestroyConfigs(psc->driver_configs);
773
 
   psc->driScreen = NULL;
774
 
   if (psc->driver)
775
 
      dlclose(psc->driver);
776
 
   free(psc);
777
 
}
778
 
 
779
 
static char *
780
 
drisw_get_driver_name(struct glx_screen *glx_screen)
781
 
{
782
 
   struct drisw_screen *psc = (struct drisw_screen *) glx_screen;
783
 
   return strdup(psc->name);
784
 
}
785
 
 
786
 
static const struct glx_screen_vtable drisw_screen_vtable = {
787
 
   .create_context         = dri_common_create_context,
788
 
   .create_context_attribs = drisw_create_context_attribs,
789
 
   .query_renderer_integer = drisw_query_renderer_integer,
790
 
   .query_renderer_string  = drisw_query_renderer_string,
791
 
   .get_driver_name        = drisw_get_driver_name,
792
 
};
793
 
 
794
 
static void
795
 
driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
796
 
{
797
 
   int i;
798
 
 
799
 
   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
800
 
 
801
 
   if (psc->swrast->base.version >= 3) {
802
 
      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
803
 
      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
804
 
      __glXEnableDirectExtension(&psc->base, "GLX_EXT_no_config_context");
805
 
 
806
 
      /* DRISW version >= 2 implies support for OpenGL ES.
807
 
       */
808
 
      __glXEnableDirectExtension(&psc->base,
809
 
                                 "GLX_EXT_create_context_es_profile");
810
 
      __glXEnableDirectExtension(&psc->base,
811
 
                                 "GLX_EXT_create_context_es2_profile");
812
 
   }
813
 
 
814
 
   if (psc->copySubBuffer)
815
 
      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");      
816
 
 
817
 
   /* FIXME: Figure out what other extensions can be ported here from dri2. */
818
 
   for (i = 0; extensions[i]; i++) {
819
 
      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
820
 
         psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
821
 
         __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
822
 
      }
823
 
      /* DRISW version 3 is also required because GLX_MESA_query_renderer
824
 
       * requires GLX_ARB_create_context_profile.
825
 
       */
826
 
      if (psc->swrast->base.version >= 3
827
 
          && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
828
 
         psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
829
 
         __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
830
 
         unsigned int no_error = 0;
831
 
         if (psc->rendererQuery->queryInteger(psc->driScreen,
832
 
                                              __DRI2_RENDERER_HAS_NO_ERROR_CONTEXT,
833
 
                                              &no_error) == 0 && no_error)
834
 
             __glXEnableDirectExtension(&psc->base,
835
 
                                        "GLX_ARB_create_context_no_error");
836
 
      }
837
 
 
838
 
      if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
839
 
         __glXEnableDirectExtension(&psc->base,
840
 
                                    "GLX_ARB_create_context_robustness");
841
 
 
842
 
      if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) {
843
 
          __glXEnableDirectExtension(&psc->base,
844
 
                                     "GLX_ARB_context_flush_control");
845
 
      }
846
 
      if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)
847
 
         psc->f = (__DRI2flushExtension *) extensions[i];
848
 
   }
849
 
 
850
 
   if (psc->kopper) {
851
 
       __glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control");
852
 
       __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
853
 
       __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
854
 
       // This needs to check whether RELAXED is available
855
 
       // __glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control_tear");
856
 
   }
857
 
}
858
 
 
859
 
static int
860
 
check_xshm(Display *dpy)
861
 
{
862
 
   xcb_connection_t *c = XGetXCBConnection(dpy);
863
 
   xcb_void_cookie_t cookie;
864
 
   xcb_generic_error_t *error;
865
 
   int ret = True;
866
 
   int ignore;
867
 
 
868
 
   if (!XQueryExtension(dpy, "MIT-SHM", &xshm_opcode, &ignore, &ignore))
869
 
      return False;
870
 
 
871
 
   cookie = xcb_shm_detach_checked(c, 0);
872
 
   if ((error = xcb_request_check(c, cookie))) {
873
 
      /* BadRequest means we're a remote client. If we were local we'd
874
 
       * expect BadValue since 'info' has an invalid segment name.
875
 
       */
876
 
      if (error->error_code == BadRequest)
877
 
         ret = False;
878
 
      free(error);
879
 
   }
880
 
 
881
 
   return ret;
882
 
}
883
 
 
884
 
static int
885
 
kopperSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
886
 
{
887
 
   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
888
 
   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
889
 
 
890
 
   psc->kopper->setSwapInterval(pdp->driDrawable, interval);
891
 
   pdp->swapInterval = interval;
892
 
 
893
 
   return 1;
894
 
}
895
 
 
896
 
static int
897
 
kopperGetSwapInterval(__GLXDRIdrawable *pdraw)
898
 
{
899
 
   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
900
 
 
901
 
   return pdp->swapInterval;
902
 
}
903
 
 
904
 
static struct glx_screen *
905
 
driswCreateScreenDriver(int screen, struct glx_display *priv,
906
 
                        const char *driver)
907
 
{
908
 
   __GLXDRIscreen *psp;
909
 
   const __DRIconfig **driver_configs;
910
 
   const __DRIextension **extensions;
911
 
   struct drisw_screen *psc;
912
 
   struct glx_config *configs = NULL, *visuals = NULL;
913
 
   int i;
914
 
   const __DRIextension **loader_extensions_local;
915
 
   const struct drisw_display *pdpyp = (struct drisw_display *)priv->driswDisplay;
916
 
 
917
 
   psc = calloc(1, sizeof *psc);
918
 
   if (psc == NULL)
919
 
      return NULL;
920
 
 
921
 
   if (!glx_screen_init(&psc->base, screen, priv)) {
922
 
      free(psc);
923
 
      return NULL;
924
 
   }
925
 
 
926
 
   extensions = driOpenDriver(driver, &psc->driver);
927
 
   if (extensions == NULL)
928
 
      goto handle_error;
929
 
   psc->name = driver;
930
 
 
931
 
   if (pdpyp->zink)
932
 
      loader_extensions_local = kopper_extensions_noshm;
933
 
   else if (!check_xshm(psc->base.dpy))
934
 
      loader_extensions_local = loader_extensions_noshm;
935
 
   else
936
 
      loader_extensions_local = loader_extensions_shm;
937
 
 
938
 
   for (i = 0; extensions[i]; i++) {
939
 
      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
940
 
         psc->core = (__DRIcoreExtension *) extensions[i];
941
 
      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
942
 
         psc->swrast = (__DRIswrastExtension *) extensions[i];
943
 
      if (strcmp(extensions[i]->name, __DRI_KOPPER) == 0)
944
 
         psc->kopper = (__DRIkopperExtension *) extensions[i];
945
 
      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0)
946
 
         psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
947
 
   }
948
 
 
949
 
   if (psc->core == NULL || psc->swrast == NULL) {
950
 
      ErrorMessageF("core dri extension not found\n");
951
 
      goto handle_error;
952
 
   }
953
 
 
954
 
   if (psc->swrast->base.version >= 4) {
955
 
      psc->driScreen =
956
 
         psc->swrast->createNewScreen2(screen, loader_extensions_local,
957
 
                                       extensions,
958
 
                                       &driver_configs, psc);
959
 
   } else {
960
 
      psc->driScreen =
961
 
         psc->swrast->createNewScreen(screen, loader_extensions_local,
962
 
                                      &driver_configs, psc);
963
 
   }
964
 
   if (psc->driScreen == NULL) {
965
 
      ErrorMessageF("glx: failed to create drisw screen\n");
966
 
      goto handle_error;
967
 
   }
968
 
 
969
 
   extensions = psc->core->getExtensions(psc->driScreen);
970
 
   driswBindExtensions(psc, extensions);
971
 
 
972
 
   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
973
 
   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
974
 
 
975
 
   if (!configs || !visuals) {
976
 
       ErrorMessageF("No matching fbConfigs or visuals found\n");
977
 
       goto handle_error;
978
 
   }
979
 
 
980
 
   glx_config_destroy_list(psc->base.configs);
981
 
   psc->base.configs = configs;
982
 
   glx_config_destroy_list(psc->base.visuals);
983
 
   psc->base.visuals = visuals;
984
 
 
985
 
   psc->driver_configs = driver_configs;
986
 
 
987
 
   psc->base.vtable = &drisw_screen_vtable;
988
 
   psc->base.context_vtable = &drisw_context_vtable;
989
 
   psp = &psc->vtable;
990
 
   psc->base.driScreen = psp;
991
 
   psp->destroyScreen = driswDestroyScreen;
992
 
   psp->createDrawable = driswCreateDrawable;
993
 
   psp->swapBuffers = driswSwapBuffers;
994
 
   psp->bindTexImage = drisw_bind_tex_image;
995
 
   psp->releaseTexImage = drisw_release_tex_image;
996
 
 
997
 
   if (psc->copySubBuffer)
998
 
      psp->copySubBuffer = driswCopySubBuffer;
999
 
 
1000
 
   if (psc->kopper) {
1001
 
      psp->setSwapInterval = kopperSetSwapInterval;
1002
 
      psp->getSwapInterval = kopperGetSwapInterval;
1003
 
      psp->maxSwapInterval = 1;
1004
 
   }
1005
 
 
1006
 
   return &psc->base;
1007
 
 
1008
 
 handle_error:
1009
 
   if (configs)
1010
 
       glx_config_destroy_list(configs);
1011
 
   if (visuals)
1012
 
       glx_config_destroy_list(visuals);
1013
 
   if (psc->driScreen)
1014
 
       psc->core->destroyScreen(psc->driScreen);
1015
 
   psc->driScreen = NULL;
1016
 
 
1017
 
   if (psc->driver)
1018
 
      dlclose(psc->driver);
1019
 
   glx_screen_cleanup(&psc->base);
1020
 
   free(psc);
1021
 
 
1022
 
   CriticalErrorMessageF("failed to load driver: %s\n", driver);
1023
 
 
1024
 
   return NULL;
1025
 
}
1026
 
 
1027
 
static struct glx_screen *
1028
 
driswCreateScreen(int screen, struct glx_display *priv)
1029
 
{
1030
 
   const struct drisw_display *pdpyp = (struct drisw_display *)priv->driswDisplay;
1031
 
   if (pdpyp->zink && !env_var_as_boolean("LIBGL_KOPPER_DISABLE", false)) {
1032
 
      return driswCreateScreenDriver(screen, priv, "zink");
1033
 
   }
1034
 
 
1035
 
    return driswCreateScreenDriver(screen, priv, "swrast");
1036
 
}
1037
 
 
1038
 
/* Called from __glXFreeDisplayPrivate.
1039
 
 */
1040
 
static void
1041
 
driswDestroyDisplay(__GLXDRIdisplay * dpy)
1042
 
{
1043
 
   free(dpy);
1044
 
}
1045
 
 
1046
 
/*
1047
 
 * Allocate, initialize and return a __DRIdisplayPrivate object.
1048
 
 * This is called from __glXInitialize() when we are given a new
1049
 
 * display pointer.
1050
 
 */
1051
 
_X_HIDDEN __GLXDRIdisplay *
1052
 
driswCreateDisplay(Display * dpy, bool zink)
1053
 
{
1054
 
   struct drisw_display *pdpyp;
1055
 
 
1056
 
   pdpyp = malloc(sizeof *pdpyp);
1057
 
   if (pdpyp == NULL)
1058
 
      return NULL;
1059
 
 
1060
 
   pdpyp->base.destroyDisplay = driswDestroyDisplay;
1061
 
   pdpyp->base.createScreen = driswCreateScreen;
1062
 
   pdpyp->zink = zink;
1063
 
 
1064
 
   return &pdpyp->base;
1065
 
}
1066
 
 
1067
 
#endif /* GLX_DIRECT_RENDERING */