~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/glx/glxext.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
 
 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3
 
 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4
 
 *
5
 
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 
 * copy of this software and associated documentation files (the "Software"),
7
 
 * to deal in the Software without restriction, including without limitation
8
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 
 * and/or sell copies of the Software, and to permit persons to whom the
10
 
 * Software is furnished to do so, subject to the following conditions:
11
 
 *
12
 
 * The above copyright notice including the dates of first publication and
13
 
 * either this permission notice or a reference to
14
 
 * http://oss.sgi.com/projects/FreeB/
15
 
 * shall be included in all copies or substantial portions of the Software.
16
 
 *
17
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 
 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22
 
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 
 * SOFTWARE.
24
 
 *
25
 
 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26
 
 * shall not be used in advertising or otherwise to promote the sale, use or
27
 
 * other dealings in this Software without prior written authorization from
28
 
 * Silicon Graphics, Inc.
29
 
 */
30
 
 
31
 
/**
32
 
 * \file glxext.c
33
 
 * GLX protocol interface boot-strap code.
34
 
 *
35
 
 * Direct rendering support added by Precision Insight, Inc.
36
 
 *
37
 
 * \author Kevin E. Martin <kevin@precisioninsight.com>
38
 
 */
39
 
 
40
 
#include <assert.h>
41
 
#include <stdbool.h>
42
 
#include <stdarg.h>
43
 
 
44
 
#include "glxclient.h"
45
 
#include <X11/extensions/Xext.h>
46
 
#include <X11/extensions/extutil.h>
47
 
#ifdef GLX_USE_APPLEGL
48
 
#include "apple/apple_glx.h"
49
 
#include "apple/apple_visual.h"
50
 
#endif
51
 
#include "glxextensions.h"
52
 
 
53
 
#include "util/debug.h"
54
 
#ifndef GLX_USE_APPLEGL
55
 
#include "dri_common.h"
56
 
#endif
57
 
 
58
 
#include <X11/Xlib-xcb.h>
59
 
#include <xcb/xcb.h>
60
 
#include <xcb/glx.h>
61
 
 
62
 
#define __GLX_MIN_CONFIG_PROPS  18
63
 
#define __GLX_EXT_CONFIG_PROPS  32
64
 
 
65
 
/*
66
 
** Since we send all non-core visual properties as token, value pairs,
67
 
** we require 2 words across the wire. In order to maintain backwards
68
 
** compatibility, we need to send the total number of words that the
69
 
** VisualConfigs are sent back in so old libraries can simply "ignore"
70
 
** the new properties.
71
 
*/
72
 
#define __GLX_TOTAL_CONFIG \
73
 
   (__GLX_MIN_CONFIG_PROPS + 2 * __GLX_EXT_CONFIG_PROPS)
74
 
 
75
 
_X_HIDDEN void
76
 
glx_message(int level, const char *f, ...)
77
 
{
78
 
   va_list args;
79
 
   int threshold = _LOADER_WARNING;
80
 
   const char *libgl_debug;
81
 
 
82
 
   libgl_debug = getenv("LIBGL_DEBUG");
83
 
   if (libgl_debug) {
84
 
      if (strstr(libgl_debug, "quiet"))
85
 
         threshold = _LOADER_FATAL;
86
 
      else if (strstr(libgl_debug, "verbose"))
87
 
         threshold = _LOADER_DEBUG;
88
 
   }
89
 
 
90
 
   /* Note that the _LOADER_* levels are lower numbers for more severe. */
91
 
   if (level <= threshold) {
92
 
      fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : "");
93
 
      va_start(args, f);
94
 
      vfprintf(stderr, f, args);
95
 
      va_end(args);
96
 
   }
97
 
}
98
 
 
99
 
/*
100
 
** You can set this cell to 1 to force the gl drawing stuff to be
101
 
** one command per packet
102
 
*/
103
 
_X_HIDDEN int __glXDebug = 0;
104
 
 
105
 
/* Extension required boiler plate */
106
 
 
107
 
static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
108
 
static struct glx_display *glx_displays;
109
 
 
110
 
static /* const */ char *error_list[] = {
111
 
   "GLXBadContext",
112
 
   "GLXBadContextState",
113
 
   "GLXBadDrawable",
114
 
   "GLXBadPixmap",
115
 
   "GLXBadContextTag",
116
 
   "GLXBadCurrentWindow",
117
 
   "GLXBadRenderRequest",
118
 
   "GLXBadLargeRequest",
119
 
   "GLXUnsupportedPrivateRequest",
120
 
   "GLXBadFBConfig",
121
 
   "GLXBadPbuffer",
122
 
   "GLXBadCurrentDrawable",
123
 
   "GLXBadWindow",
124
 
   "GLXBadProfileARB",
125
 
};
126
 
 
127
 
#ifdef GLX_USE_APPLEGL
128
 
static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, 
129
 
                              char *buf, int n);
130
 
#endif
131
 
 
132
 
static
133
 
XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
134
 
                           __GLX_NUMBER_ERRORS, error_list)
135
 
 
136
 
/*
137
 
 * GLX events are a bit funky.  We don't stuff the X event code into
138
 
 * our user exposed (via XNextEvent) structure.  Instead we use the GLX
139
 
 * private event code namespace (and hope it doesn't conflict).  Clients
140
 
 * have to know that bit 15 in the event type field means they're getting
141
 
 * a GLX event, and then handle the various sub-event types there, rather
142
 
 * than simply checking the event code and handling it directly.
143
 
 */
144
 
 
145
 
static Bool
146
 
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
147
 
{
148
 
     struct glx_display *glx_dpy = __glXInitialize(dpy);
149
 
 
150
 
   if (glx_dpy == NULL)
151
 
      return False;
152
 
 
153
 
   switch ((wire->u.u.type & 0x7f) - glx_dpy->codes.first_event) {
154
 
   case GLX_PbufferClobber:
155
 
   {
156
 
      GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
157
 
      xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
158
 
      aevent->event_type = awire->type;
159
 
      aevent->serial = awire->sequenceNumber;
160
 
      aevent->event_type = awire->event_type;
161
 
      aevent->draw_type = awire->draw_type;
162
 
      aevent->drawable = awire->drawable;
163
 
      aevent->buffer_mask = awire->buffer_mask;
164
 
      aevent->aux_buffer = awire->aux_buffer;
165
 
      aevent->x = awire->x;
166
 
      aevent->y = awire->y;
167
 
      aevent->width = awire->width;
168
 
      aevent->height = awire->height;
169
 
      aevent->count = awire->count;
170
 
      return True;
171
 
   }
172
 
   case GLX_BufferSwapComplete:
173
 
   {
174
 
      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
175
 
      xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
176
 
      struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
177
 
 
178
 
      if (!glxDraw)
179
 
         return False;
180
 
 
181
 
      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
182
 
      aevent->send_event = (awire->type & 0x80) != 0;
183
 
      aevent->display = dpy;
184
 
      aevent->event_type = awire->event_type;
185
 
      aevent->drawable = glxDraw->xDrawable;
186
 
      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
187
 
      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
188
 
 
189
 
      /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
190
 
       * of sequence 64-Bit sbc's
191
 
       */
192
 
      if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
193
 
         glxDraw->eventSbcWrap += 0x100000000;
194
 
      if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
195
 
         glxDraw->eventSbcWrap -= 0x100000000;
196
 
      glxDraw->lastEventSbc = awire->sbc;
197
 
      aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
198
 
      return True;
199
 
   }
200
 
   default:
201
 
      /* client doesn't support server event */
202
 
      break;
203
 
   }
204
 
 
205
 
   return False;
206
 
}
207
 
 
208
 
/* We don't actually support this.  It doesn't make sense for clients to
209
 
 * send each other GLX events.
210
 
 */
211
 
static Status
212
 
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
213
 
{
214
 
     struct glx_display *glx_dpy = __glXInitialize(dpy);
215
 
 
216
 
   if (glx_dpy == NULL)
217
 
      return False;
218
 
 
219
 
   switch (event->type) {
220
 
   case GLX_DAMAGED:
221
 
      break;
222
 
   case GLX_SAVED:
223
 
      break;
224
 
   case GLX_EXCHANGE_COMPLETE_INTEL:
225
 
      break;
226
 
   case GLX_COPY_COMPLETE_INTEL:
227
 
      break;
228
 
   case GLX_FLIP_COMPLETE_INTEL:
229
 
      break;
230
 
   default:
231
 
      /* client doesn't support server event */
232
 
      break;
233
 
   }
234
 
 
235
 
   return Success;
236
 
}
237
 
 
238
 
/************************************************************************/
239
 
/*
240
 
** Free the per screen configs data as well as the array of
241
 
** __glXScreenConfigs.
242
 
*/
243
 
static void
244
 
FreeScreenConfigs(struct glx_display * priv)
245
 
{
246
 
   struct glx_screen *psc;
247
 
   GLint i, screens;
248
 
 
249
 
   /* Free screen configuration information */
250
 
   screens = ScreenCount(priv->dpy);
251
 
   for (i = 0; i < screens; i++) {
252
 
      psc = priv->screens[i];
253
 
      if (!psc)
254
 
         continue;
255
 
      glx_screen_cleanup(psc);
256
 
 
257
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
258
 
      if (psc->driScreen) {
259
 
         psc->driScreen->destroyScreen(psc);
260
 
      } else {
261
 
         free(psc);
262
 
      }
263
 
#else
264
 
      free(psc);
265
 
#endif
266
 
   }
267
 
   free((char *) priv->screens);
268
 
   priv->screens = NULL;
269
 
}
270
 
 
271
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
272
 
static void
273
 
free_zombie_glx_drawable(struct set_entry *entry)
274
 
{
275
 
   __GLXDRIdrawable *pdraw = (__GLXDRIdrawable *)entry->key;
276
 
 
277
 
   pdraw->destroyDrawable(pdraw);
278
 
}
279
 
#endif
280
 
 
281
 
static void
282
 
glx_display_free(struct glx_display *priv)
283
 
{
284
 
   struct glx_context *gc;
285
 
 
286
 
   gc = __glXGetCurrentContext();
287
 
   if (priv->dpy == gc->currentDpy) {
288
 
      gc->vtable->destroy(gc);
289
 
      __glXSetCurrentContextNull();
290
 
   }
291
 
 
292
 
   /* Needs to be done before free screen. */
293
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
294
 
   _mesa_set_destroy(priv->zombieGLXDrawable, free_zombie_glx_drawable);
295
 
#endif
296
 
 
297
 
   FreeScreenConfigs(priv);
298
 
 
299
 
   __glxHashDestroy(priv->glXDrawHash);
300
 
 
301
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
302
 
   __glxHashDestroy(priv->drawHash);
303
 
 
304
 
   /* Free the direct rendering per display data */
305
 
   if (priv->driswDisplay)
306
 
      (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
307
 
   priv->driswDisplay = NULL;
308
 
 
309
 
#if defined (GLX_USE_DRM)
310
 
   if (priv->dri2Display)
311
 
      (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
312
 
   priv->dri2Display = NULL;
313
 
 
314
 
   if (priv->dri3Display)
315
 
      (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
316
 
   priv->dri3Display = NULL;
317
 
#endif /* GLX_USE_DRM */
318
 
 
319
 
#if defined(GLX_USE_WINDOWSGL)
320
 
   if (priv->windowsdriDisplay)
321
 
      (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
322
 
   priv->windowsdriDisplay = NULL;
323
 
#endif /* GLX_USE_WINDOWSGL */
324
 
 
325
 
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
326
 
 
327
 
   free((char *) priv);
328
 
}
329
 
 
330
 
static int
331
 
__glXCloseDisplay(Display * dpy, XExtCodes * codes)
332
 
{
333
 
   struct glx_display *priv, **prev;
334
 
 
335
 
   _XLockMutex(_Xglobal_lock);
336
 
   prev = &glx_displays;
337
 
   for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
338
 
      if (priv->dpy == dpy) {
339
 
         *prev = priv->next;
340
 
         break;
341
 
      }
342
 
   }
343
 
   _XUnlockMutex(_Xglobal_lock);
344
 
 
345
 
   if (priv != NULL)
346
 
      glx_display_free(priv);
347
 
 
348
 
   return 1;
349
 
}
350
 
 
351
 
/*
352
 
** Query the version of the GLX extension.  This procedure works even if
353
 
** the client extension is not completely set up.
354
 
*/
355
 
static Bool
356
 
QueryVersion(Display * dpy, int opcode, int *major, int *minor)
357
 
{
358
 
   xcb_connection_t *c = XGetXCBConnection(dpy);
359
 
   xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
360
 
                                                                      xcb_glx_query_version
361
 
                                                                      (c,
362
 
                                                                       GLX_MAJOR_VERSION,
363
 
                                                                       GLX_MINOR_VERSION),
364
 
                                                                      NULL);
365
 
 
366
 
   if (!reply)
367
 
     return GL_FALSE;
368
 
 
369
 
   if (reply->major_version != GLX_MAJOR_VERSION) {
370
 
      free(reply);
371
 
      return GL_FALSE;
372
 
   }
373
 
   *major = reply->major_version;
374
 
   *minor = min(reply->minor_version, GLX_MINOR_VERSION);
375
 
   free(reply);
376
 
   return GL_TRUE;
377
 
}
378
 
 
379
 
/* 
380
 
 * We don't want to enable this GLX_OML_swap_method in glxext.h, 
381
 
 * because we can't support it.  The X server writes it out though,
382
 
 * so we should handle it somehow, to avoid false warnings.
383
 
 */
384
 
enum {
385
 
    IGNORE_GLX_SWAP_METHOD_OML = 0x8060
386
 
};
387
 
 
388
 
 
389
 
static GLint
390
 
convert_from_x_visual_type(int visualType)
391
 
{
392
 
   static const int glx_visual_types[] = {
393
 
      [StaticGray]  = GLX_STATIC_GRAY,
394
 
      [GrayScale]   = GLX_GRAY_SCALE,
395
 
      [StaticColor] = GLX_STATIC_COLOR,
396
 
      [PseudoColor] = GLX_PSEUDO_COLOR,
397
 
      [TrueColor]   = GLX_TRUE_COLOR,
398
 
      [DirectColor] = GLX_DIRECT_COLOR,
399
 
   };
400
 
 
401
 
   if (visualType < ARRAY_SIZE(glx_visual_types))
402
 
      return glx_visual_types[visualType];
403
 
 
404
 
   return GLX_NONE;
405
 
}
406
 
 
407
 
/*
408
 
 * getVisualConfigs uses the !tagged_only path.
409
 
 * getFBConfigs uses the tagged_only path.
410
 
 */
411
 
_X_HIDDEN void
412
 
__glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
413
 
                                    const INT32 * bp, Bool tagged_only,
414
 
                                    Bool fbconfig_style_tags)
415
 
{
416
 
   int i;
417
 
 
418
 
   if (!tagged_only) {
419
 
      /* Copy in the first set of properties */
420
 
      config->visualID = *bp++;
421
 
 
422
 
      config->visualType = convert_from_x_visual_type(*bp++);
423
 
 
424
 
      config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
425
 
 
426
 
      config->redBits = *bp++;
427
 
      config->greenBits = *bp++;
428
 
      config->blueBits = *bp++;
429
 
      config->alphaBits = *bp++;
430
 
      config->accumRedBits = *bp++;
431
 
      config->accumGreenBits = *bp++;
432
 
      config->accumBlueBits = *bp++;
433
 
      config->accumAlphaBits = *bp++;
434
 
 
435
 
      config->doubleBufferMode = *bp++;
436
 
      config->stereoMode = *bp++;
437
 
 
438
 
      config->rgbBits = *bp++;
439
 
      config->depthBits = *bp++;
440
 
      config->stencilBits = *bp++;
441
 
      config->numAuxBuffers = *bp++;
442
 
      config->level = *bp++;
443
 
 
444
 
#ifdef GLX_USE_APPLEGL
445
 
       /* AppleSGLX supports pixmap and pbuffers with all config. */
446
 
       config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
447
 
       /* Unfortunately this can create an ABI compatibility problem. */
448
 
       count -= 18;
449
 
#else
450
 
      count -= __GLX_MIN_CONFIG_PROPS;
451
 
#endif
452
 
   }
453
 
 
454
 
   /*
455
 
    ** Additional properties may be in a list at the end
456
 
    ** of the reply.  They are in pairs of property type
457
 
    ** and property value.
458
 
    */
459
 
 
460
 
#define FETCH_OR_SET(tag) \
461
 
    config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
462
 
 
463
 
   for (i = 0; i < count; i += 2) {
464
 
      long int tag = *bp++;
465
 
      
466
 
      switch (tag) {
467
 
      case GLX_RGBA:
468
 
         if (fbconfig_style_tags)
469
 
            config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
470
 
         else
471
 
            config->renderType = GLX_RGBA_BIT;
472
 
         break;
473
 
      case GLX_BUFFER_SIZE:
474
 
         config->rgbBits = *bp++;
475
 
         break;
476
 
      case GLX_LEVEL:
477
 
         config->level = *bp++;
478
 
         break;
479
 
      case GLX_DOUBLEBUFFER:
480
 
         FETCH_OR_SET(doubleBufferMode);
481
 
         break;
482
 
      case GLX_STEREO:
483
 
         FETCH_OR_SET(stereoMode);
484
 
         break;
485
 
      case GLX_AUX_BUFFERS:
486
 
         config->numAuxBuffers = *bp++;
487
 
         break;
488
 
      case GLX_RED_SIZE:
489
 
         config->redBits = *bp++;
490
 
         break;
491
 
      case GLX_GREEN_SIZE:
492
 
         config->greenBits = *bp++;
493
 
         break;
494
 
      case GLX_BLUE_SIZE:
495
 
         config->blueBits = *bp++;
496
 
         break;
497
 
      case GLX_ALPHA_SIZE:
498
 
         config->alphaBits = *bp++;
499
 
         break;
500
 
      case GLX_DEPTH_SIZE:
501
 
         config->depthBits = *bp++;
502
 
         break;
503
 
      case GLX_STENCIL_SIZE:
504
 
         config->stencilBits = *bp++;
505
 
         break;
506
 
      case GLX_ACCUM_RED_SIZE:
507
 
         config->accumRedBits = *bp++;
508
 
         break;
509
 
      case GLX_ACCUM_GREEN_SIZE:
510
 
         config->accumGreenBits = *bp++;
511
 
         break;
512
 
      case GLX_ACCUM_BLUE_SIZE:
513
 
         config->accumBlueBits = *bp++;
514
 
         break;
515
 
      case GLX_ACCUM_ALPHA_SIZE:
516
 
         config->accumAlphaBits = *bp++;
517
 
         break;
518
 
      case GLX_VISUAL_CAVEAT_EXT:
519
 
         config->visualRating = *bp++;
520
 
         break;
521
 
      case GLX_X_VISUAL_TYPE:
522
 
         config->visualType = *bp++;
523
 
         break;
524
 
      case GLX_TRANSPARENT_TYPE:
525
 
         config->transparentPixel = *bp++;
526
 
         break;
527
 
      case GLX_TRANSPARENT_INDEX_VALUE:
528
 
         config->transparentIndex = *bp++;
529
 
         break;
530
 
      case GLX_TRANSPARENT_RED_VALUE:
531
 
         config->transparentRed = *bp++;
532
 
         break;
533
 
      case GLX_TRANSPARENT_GREEN_VALUE:
534
 
         config->transparentGreen = *bp++;
535
 
         break;
536
 
      case GLX_TRANSPARENT_BLUE_VALUE:
537
 
         config->transparentBlue = *bp++;
538
 
         break;
539
 
      case GLX_TRANSPARENT_ALPHA_VALUE:
540
 
         config->transparentAlpha = *bp++;
541
 
         break;
542
 
      case GLX_VISUAL_ID:
543
 
         config->visualID = *bp++;
544
 
         break;
545
 
      case GLX_DRAWABLE_TYPE:
546
 
         config->drawableType = *bp++;
547
 
#ifdef GLX_USE_APPLEGL
548
 
         /* AppleSGLX supports pixmap and pbuffers with all config. */
549
 
         config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;              
550
 
#endif
551
 
         break;
552
 
      case GLX_RENDER_TYPE: /* fbconfig render type bits */
553
 
         config->renderType = *bp++;
554
 
         break;
555
 
      case GLX_X_RENDERABLE:
556
 
         config->xRenderable = *bp++;
557
 
         break;
558
 
      case GLX_FBCONFIG_ID:
559
 
         config->fbconfigID = *bp++;
560
 
         break;
561
 
      case GLX_MAX_PBUFFER_WIDTH:
562
 
         config->maxPbufferWidth = *bp++;
563
 
         break;
564
 
      case GLX_MAX_PBUFFER_HEIGHT:
565
 
         config->maxPbufferHeight = *bp++;
566
 
         break;
567
 
      case GLX_MAX_PBUFFER_PIXELS:
568
 
         config->maxPbufferPixels = *bp++;
569
 
         break;
570
 
#ifndef GLX_USE_APPLEGL
571
 
      case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
572
 
         config->optimalPbufferWidth = *bp++;
573
 
         break;
574
 
      case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
575
 
         config->optimalPbufferHeight = *bp++;
576
 
         break;
577
 
      case GLX_VISUAL_SELECT_GROUP_SGIX:
578
 
         config->visualSelectGroup = *bp++;
579
 
         break;
580
 
      case GLX_SWAP_METHOD_OML:
581
 
         if (*bp == GLX_SWAP_UNDEFINED_OML ||
582
 
             *bp == GLX_SWAP_COPY_OML ||
583
 
             *bp == GLX_SWAP_EXCHANGE_OML) {
584
 
            config->swapMethod = *bp++;
585
 
         } else {
586
 
            /* X servers with old HW drivers may return any value here, so
587
 
             * assume GLX_SWAP_METHOD_UNDEFINED.
588
 
             */
589
 
            config->swapMethod = GLX_SWAP_UNDEFINED_OML;
590
 
            bp++;
591
 
         }
592
 
         break;
593
 
#endif
594
 
      case GLX_SAMPLE_BUFFERS_SGIS:
595
 
         config->sampleBuffers = *bp++;
596
 
         break;
597
 
      case GLX_SAMPLES_SGIS:
598
 
         config->samples = *bp++;
599
 
         break;
600
 
#ifdef GLX_USE_APPLEGL
601
 
      case IGNORE_GLX_SWAP_METHOD_OML:
602
 
         /* We ignore this tag.  See the comment above this function. */
603
 
         ++bp;
604
 
         break;
605
 
#else
606
 
      case GLX_BIND_TO_TEXTURE_RGB_EXT:
607
 
         config->bindToTextureRgb = *bp++;
608
 
         break;
609
 
      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
610
 
         config->bindToTextureRgba = *bp++;
611
 
         break;
612
 
      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
613
 
         config->bindToMipmapTexture = *bp++;
614
 
         break;
615
 
      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
616
 
         config->bindToTextureTargets = *bp++;
617
 
         break;
618
 
      case GLX_Y_INVERTED_EXT:
619
 
         config->yInverted = *bp++;
620
 
         break;
621
 
#endif
622
 
      case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
623
 
         config->sRGBCapable = *bp++;
624
 
         break;
625
 
 
626
 
      case GLX_USE_GL:
627
 
         if (fbconfig_style_tags)
628
 
            bp++;
629
 
         break;
630
 
      case GLX_FLOAT_COMPONENTS_NV:
631
 
         config->floatComponentsNV = *bp++;
632
 
         break;
633
 
      case None:
634
 
         i = count;
635
 
         break;
636
 
      default: {
637
 
            long int tagvalue = *bp++;
638
 
            DebugMessageF("WARNING: unknown fbconfig attribute from server: "
639
 
                          "tag 0x%lx value 0x%lx\n", tag, tagvalue);
640
 
            break;
641
 
         }
642
 
      }
643
 
   }
644
 
}
645
 
 
646
 
static struct glx_config *
647
 
createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
648
 
                            int screen, GLboolean tagged_only)
649
 
{
650
 
   INT32 buf[__GLX_TOTAL_CONFIG], *props;
651
 
   unsigned prop_size;
652
 
   struct glx_config *modes, *m;
653
 
   int i;
654
 
 
655
 
   if (nprops == 0)
656
 
      return NULL;
657
 
 
658
 
   /* Check number of properties */
659
 
   if (nprops < __GLX_MIN_CONFIG_PROPS)
660
 
      return NULL;
661
 
 
662
 
   /* Allocate memory for our config structure */
663
 
   modes = glx_config_create_list(nvisuals);
664
 
   if (!modes)
665
 
      return NULL;
666
 
 
667
 
   prop_size = nprops * __GLX_SIZE_INT32;
668
 
   if (prop_size <= sizeof(buf))
669
 
      props = buf;
670
 
   else
671
 
      props = malloc(prop_size);
672
 
 
673
 
   /* Read each config structure and convert it into our format */
674
 
   m = modes;
675
 
   for (i = 0; i < nvisuals; i++) {
676
 
      _XRead(dpy, (char *) props, prop_size);
677
 
#ifdef GLX_USE_APPLEGL
678
 
       /* Older X servers don't send this so we default it here. */
679
 
      m->drawableType = GLX_WINDOW_BIT;
680
 
#else
681
 
      /* 
682
 
       * The XQuartz 2.3.2.1 X server doesn't set this properly, so
683
 
       * set the proper bits here.
684
 
       * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
685
 
       */
686
 
      m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
687
 
#endif
688
 
       __glXInitializeVisualConfigFromTags(m, nprops, props,
689
 
                                          tagged_only, GL_TRUE);
690
 
      m->screen = screen;
691
 
      m = m->next;
692
 
   }
693
 
 
694
 
   if (props != buf)
695
 
      free(props);
696
 
 
697
 
   return modes;
698
 
}
699
 
 
700
 
static GLboolean
701
 
getVisualConfigs(struct glx_screen *psc,
702
 
                  struct glx_display *priv, int screen)
703
 
{
704
 
   xGLXGetVisualConfigsReq *req;
705
 
   xGLXGetVisualConfigsReply reply;
706
 
   Display *dpy = priv->dpy;
707
 
 
708
 
   LockDisplay(dpy);
709
 
 
710
 
   psc->visuals = NULL;
711
 
   GetReq(GLXGetVisualConfigs, req);
712
 
   req->reqType = priv->codes.major_opcode;
713
 
   req->glxCode = X_GLXGetVisualConfigs;
714
 
   req->screen = screen;
715
 
 
716
 
   if (!_XReply(dpy, (xReply *) & reply, 0, False))
717
 
      goto out;
718
 
 
719
 
   psc->visuals = createConfigsFromProperties(dpy,
720
 
                                              reply.numVisuals,
721
 
                                              reply.numProps,
722
 
                                              screen, GL_FALSE);
723
 
 
724
 
 out:
725
 
   UnlockDisplay(dpy);
726
 
   return psc->visuals != NULL;
727
 
}
728
 
 
729
 
static GLboolean
730
 
getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
731
 
{
732
 
   xGLXGetFBConfigsReq *fb_req;
733
 
   xGLXGetFBConfigsSGIXReq *sgi_req;
734
 
   xGLXVendorPrivateWithReplyReq *vpreq;
735
 
   xGLXGetFBConfigsReply reply;
736
 
   Display *dpy = priv->dpy;
737
 
 
738
 
   psc->serverGLXexts = __glXQueryServerString(dpy, screen, GLX_EXTENSIONS);
739
 
 
740
 
   if (psc->serverGLXexts == NULL) {
741
 
      return GL_FALSE;
742
 
   }
743
 
 
744
 
   LockDisplay(dpy);
745
 
 
746
 
   psc->configs = NULL;
747
 
   if (priv->minorVersion >= 3) {
748
 
      GetReq(GLXGetFBConfigs, fb_req);
749
 
      fb_req->reqType = priv->codes.major_opcode;
750
 
      fb_req->glxCode = X_GLXGetFBConfigs;
751
 
      fb_req->screen = screen;
752
 
   }
753
 
   else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
754
 
      GetReqExtra(GLXVendorPrivateWithReply,
755
 
                  sz_xGLXGetFBConfigsSGIXReq -
756
 
                  sz_xGLXVendorPrivateWithReplyReq, vpreq);
757
 
      sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
758
 
      sgi_req->reqType = priv->codes.major_opcode;
759
 
      sgi_req->glxCode = X_GLXVendorPrivateWithReply;
760
 
      sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
761
 
      sgi_req->screen = screen;
762
 
   }
763
 
   else
764
 
      goto out;
765
 
 
766
 
   if (!_XReply(dpy, (xReply *) & reply, 0, False))
767
 
      goto out;
768
 
 
769
 
   psc->configs = createConfigsFromProperties(dpy,
770
 
                                              reply.numFBConfigs,
771
 
                                              reply.numAttribs * 2,
772
 
                                              screen, GL_TRUE);
773
 
 
774
 
 out:
775
 
   UnlockDisplay(dpy);
776
 
   return psc->configs != NULL;
777
 
}
778
 
 
779
 
_X_HIDDEN Bool
780
 
glx_screen_init(struct glx_screen *psc,
781
 
                 int screen, struct glx_display * priv)
782
 
{
783
 
   /* Initialize per screen dynamic client GLX extensions */
784
 
   psc->ext_list_first_time = GL_TRUE;
785
 
   psc->scr = screen;
786
 
   psc->dpy = priv->dpy;
787
 
   psc->display = priv;
788
 
 
789
 
   if (!getVisualConfigs(psc, priv, screen))
790
 
      return GL_FALSE;
791
 
 
792
 
   if (!getFBConfigs(psc, priv, screen))
793
 
      return GL_FALSE;
794
 
 
795
 
   return GL_TRUE;
796
 
}
797
 
 
798
 
_X_HIDDEN void
799
 
glx_screen_cleanup(struct glx_screen *psc)
800
 
{
801
 
   if (psc->configs) {
802
 
      glx_config_destroy_list(psc->configs);
803
 
      free(psc->effectiveGLXexts);
804
 
      psc->configs = NULL;   /* NOTE: just for paranoia */
805
 
   }
806
 
   if (psc->visuals) {
807
 
      glx_config_destroy_list(psc->visuals);
808
 
      psc->visuals = NULL;   /* NOTE: just for paranoia */
809
 
   }
810
 
   free((char *) psc->serverGLXexts);
811
 
   free((char *) psc->serverGLXvendor);
812
 
   free((char *) psc->serverGLXversion);
813
 
}
814
 
 
815
 
/*
816
 
** Allocate the memory for the per screen configs for each screen.
817
 
** If that works then fetch the per screen configs data.
818
 
*/
819
 
static Bool
820
 
AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
821
 
{
822
 
   struct glx_screen *psc;
823
 
   GLint i, screens;
824
 
 
825
 
   /*
826
 
    ** First allocate memory for the array of per screen configs.
827
 
    */
828
 
   screens = ScreenCount(dpy);
829
 
   priv->screens = calloc(screens, sizeof *priv->screens);
830
 
   if (!priv->screens)
831
 
      return GL_FALSE;
832
 
 
833
 
   for (i = 0; i < screens; i++, psc++) {
834
 
      psc = NULL;
835
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
836
 
#if defined(GLX_USE_DRM)
837
 
#if defined(HAVE_DRI3)
838
 
      if (priv->dri3Display)
839
 
         psc = (*priv->dri3Display->createScreen) (i, priv);
840
 
#endif /* HAVE_DRI3 */
841
 
      if (psc == NULL && priv->dri2Display)
842
 
         psc = (*priv->dri2Display->createScreen) (i, priv);
843
 
#endif /* GLX_USE_DRM */
844
 
 
845
 
#ifdef GLX_USE_WINDOWSGL
846
 
      if (psc == NULL && priv->windowsdriDisplay)
847
 
         psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
848
 
#endif
849
 
 
850
 
      if (psc == NULL && priv->driswDisplay)
851
 
         psc = (*priv->driswDisplay->createScreen) (i, priv);
852
 
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
853
 
 
854
 
#if defined(GLX_USE_APPLEGL)
855
 
      if (psc == NULL)
856
 
         psc = applegl_create_screen(i, priv);
857
 
#else
858
 
      if (psc == NULL)
859
 
         psc = indirect_create_screen(i, priv);
860
 
#endif
861
 
      priv->screens[i] = psc;
862
 
   }
863
 
   SyncHandle();
864
 
   return GL_TRUE;
865
 
}
866
 
 
867
 
/*
868
 
** Initialize the client side extension code.
869
 
*/
870
 
 _X_HIDDEN struct glx_display *
871
 
__glXInitialize(Display * dpy)
872
 
{
873
 
   XExtCodes *codes;
874
 
   struct glx_display *dpyPriv, *d;
875
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
876
 
   Bool glx_direct, glx_accel;
877
 
#endif
878
 
   int i, majorVersion = 0;
879
 
 
880
 
   _XLockMutex(_Xglobal_lock);
881
 
 
882
 
   for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
883
 
      if (dpyPriv->dpy == dpy) {
884
 
         _XUnlockMutex(_Xglobal_lock);
885
 
         return dpyPriv;
886
 
      }
887
 
   }
888
 
 
889
 
   /* Drop the lock while we create the display private. */
890
 
   _XUnlockMutex(_Xglobal_lock);
891
 
 
892
 
   dpyPriv = calloc(1, sizeof *dpyPriv);
893
 
   if (!dpyPriv)
894
 
      return NULL;
895
 
 
896
 
   codes = XInitExtension(dpy, __glXExtensionName);
897
 
   if (!codes) {
898
 
      free(dpyPriv);
899
 
      return NULL;
900
 
   }
901
 
 
902
 
   dpyPriv->codes = *codes;
903
 
   dpyPriv->dpy = dpy;
904
 
 
905
 
   /* This GLX implementation requires X_GLXQueryExtensionsString
906
 
    * and X_GLXQueryServerString, which are new in GLX 1.1.
907
 
    */
908
 
   if (!QueryVersion(dpy, dpyPriv->codes.major_opcode,
909
 
                     &majorVersion, &dpyPriv->minorVersion)
910
 
       || (majorVersion != 1)
911
 
       || (majorVersion == 1 && dpyPriv->minorVersion < 1)) {
912
 
      free(dpyPriv);
913
 
      return NULL;
914
 
   }
915
 
 
916
 
   for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
917
 
      XESetWireToEvent(dpy, dpyPriv->codes.first_event + i, __glXWireToEvent);
918
 
      XESetEventToWire(dpy, dpyPriv->codes.first_event + i, __glXEventToWire);
919
 
   }
920
 
 
921
 
   XESetCloseDisplay(dpy, dpyPriv->codes.extension, __glXCloseDisplay);
922
 
   XESetErrorString (dpy, dpyPriv->codes.extension, __glXErrorString);
923
 
 
924
 
   dpyPriv->glXDrawHash = __glxHashCreate();
925
 
 
926
 
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
927
 
   glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
928
 
   glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
929
 
   Bool zink;
930
 
   const char *env = getenv("MESA_LOADER_DRIVER_OVERRIDE");
931
 
   zink = env && !strcmp(env, "zink");
932
 
 
933
 
   dpyPriv->drawHash = __glxHashCreate();
934
 
 
935
 
   dpyPriv->zombieGLXDrawable = _mesa_pointer_set_create(NULL);
936
 
 
937
 
#ifndef GLX_USE_APPLEGL
938
 
   /* Set the logger before the *CreateDisplay functions. */
939
 
   loader_set_logger(glx_message);
940
 
#endif
941
 
 
942
 
   /*
943
 
    ** Initialize the direct rendering per display data and functions.
944
 
    ** Note: This _must_ be done before calling any other DRI routines
945
 
    ** (e.g., those called in AllocAndFetchScreenConfigs).
946
 
    */
947
 
#if defined(GLX_USE_DRM)
948
 
   if (glx_direct && glx_accel && !zink) {
949
 
#if defined(HAVE_DRI3)
950
 
      if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
951
 
         dpyPriv->dri3Display = dri3_create_display(dpy);
952
 
#endif /* HAVE_DRI3 */
953
 
      if (!env_var_as_boolean("LIBGL_DRI2_DISABLE", false))
954
 
         dpyPriv->dri2Display = dri2CreateDisplay(dpy);
955
 
   }
956
 
#endif /* GLX_USE_DRM */
957
 
   if (glx_direct)
958
 
      dpyPriv->driswDisplay = driswCreateDisplay(dpy, zink);
959
 
#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
960
 
 
961
 
#ifdef GLX_USE_APPLEGL
962
 
   if (!applegl_create_display(dpyPriv)) {
963
 
      free(dpyPriv);
964
 
      return NULL;
965
 
   }
966
 
#endif
967
 
 
968
 
#ifdef GLX_USE_WINDOWSGL
969
 
   if (glx_direct && glx_accel)
970
 
      dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
971
 
#endif
972
 
 
973
 
   if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
974
 
      free(dpyPriv);
975
 
      return NULL;
976
 
   }
977
 
 
978
 
   __glX_send_client_info(dpyPriv);
979
 
 
980
 
   /* Grab the lock again and add the dispay private, unless somebody
981
 
    * beat us to initializing on this display in the meantime. */
982
 
   _XLockMutex(_Xglobal_lock);
983
 
 
984
 
   for (d = glx_displays; d; d = d->next) {
985
 
      if (d->dpy == dpy) {
986
 
         _XUnlockMutex(_Xglobal_lock);
987
 
         glx_display_free(dpyPriv);
988
 
         return d;
989
 
      }
990
 
   }
991
 
 
992
 
   dpyPriv->next = glx_displays;
993
 
   glx_displays = dpyPriv;
994
 
 
995
 
   _XUnlockMutex(_Xglobal_lock);
996
 
 
997
 
   return dpyPriv;
998
 
}
999
 
 
1000
 
/*
1001
 
** Setup for sending a GLX command on dpy.  Make sure the extension is
1002
 
** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
1003
 
*/
1004
 
_X_HIDDEN CARD8
1005
 
__glXSetupForCommand(Display * dpy)
1006
 
{
1007
 
    struct glx_context *gc;
1008
 
    struct glx_display *priv;
1009
 
 
1010
 
   /* If this thread has a current context, flush its rendering commands */
1011
 
   gc = __glXGetCurrentContext();
1012
 
   if (gc->currentDpy) {
1013
 
      /* Flush rendering buffer of the current context, if any */
1014
 
      (void) __glXFlushRenderBuffer(gc, gc->pc);
1015
 
 
1016
 
      if (gc->currentDpy == dpy) {
1017
 
         /* Use opcode from gc because its right */
1018
 
         return gc->majorOpcode;
1019
 
      }
1020
 
      else {
1021
 
         /*
1022
 
          ** Have to get info about argument dpy because it might be to
1023
 
          ** a different server
1024
 
          */
1025
 
      }
1026
 
   }
1027
 
 
1028
 
   /* Forced to lookup extension via the slow initialize route */
1029
 
   priv = __glXInitialize(dpy);
1030
 
   if (!priv) {
1031
 
      return 0;
1032
 
   }
1033
 
   return priv->codes.major_opcode;
1034
 
}
1035
 
 
1036
 
/**
1037
 
 * Flush the drawing command transport buffer.
1038
 
 *
1039
 
 * \param ctx  Context whose transport buffer is to be flushed.
1040
 
 * \param pc   Pointer to first unused buffer location.
1041
 
 *
1042
 
 * \todo
1043
 
 * Modify this function to use \c ctx->pc instead of the explicit
1044
 
 * \c pc parameter.
1045
 
 */
1046
 
_X_HIDDEN GLubyte *
1047
 
__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
1048
 
{
1049
 
   Display *const dpy = ctx->currentDpy;
1050
 
   xcb_connection_t *c = XGetXCBConnection(dpy);
1051
 
   const GLint size = pc - ctx->buf;
1052
 
 
1053
 
   if ((dpy != NULL) && (size > 0)) {
1054
 
      xcb_glx_render(c, ctx->currentContextTag, size,
1055
 
                     (const uint8_t *) ctx->buf);
1056
 
   }
1057
 
 
1058
 
   /* Reset pointer and return it */
1059
 
   ctx->pc = ctx->buf;
1060
 
   return ctx->pc;
1061
 
}
1062
 
 
1063
 
 
1064
 
/**
1065
 
 * Send a portion of a GLXRenderLarge command to the server.  The advantage of
1066
 
 * this function over \c __glXSendLargeCommand is that callers can use the
1067
 
 * data buffer in the GLX context and may be able to avoid allocating an
1068
 
 * extra buffer.  The disadvantage is the clients will have to do more
1069
 
 * GLX protocol work (i.e., calculating \c totalRequests, etc.).
1070
 
 *
1071
 
 * \sa __glXSendLargeCommand
1072
 
 *
1073
 
 * \param gc             GLX context
1074
 
 * \param requestNumber  Which part of the whole command is this?  The first
1075
 
 *                       request is 1.
1076
 
 * \param totalRequests  How many requests will there be?
1077
 
 * \param data           Command data.
1078
 
 * \param dataLen        Size, in bytes, of the command data.
1079
 
 */
1080
 
_X_HIDDEN void
1081
 
__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
1082
 
                    GLint totalRequests, const GLvoid * data, GLint dataLen)
1083
 
{
1084
 
   Display *dpy = gc->currentDpy;
1085
 
   xcb_connection_t *c = XGetXCBConnection(dpy);
1086
 
   xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
1087
 
                        totalRequests, dataLen, data);
1088
 
}
1089
 
 
1090
 
 
1091
 
/**
1092
 
 * Send a command that is too large for the GLXRender protocol request.
1093
 
 *
1094
 
 * Send a large command, one that is too large for some reason to
1095
 
 * send using the GLXRender protocol request.  One reason to send
1096
 
 * a large command is to avoid copying the data.
1097
 
 *
1098
 
 * \param ctx        GLX context
1099
 
 * \param header     Header data.
1100
 
 * \param headerLen  Size, in bytes, of the header data.  It is assumed that
1101
 
 *                   the header data will always be small enough to fit in
1102
 
 *                   a single X protocol packet.
1103
 
 * \param data       Command data.
1104
 
 * \param dataLen    Size, in bytes, of the command data.
1105
 
 */
1106
 
_X_HIDDEN void
1107
 
__glXSendLargeCommand(struct glx_context * ctx,
1108
 
                      const GLvoid * header, GLint headerLen,
1109
 
                      const GLvoid * data, GLint dataLen)
1110
 
{
1111
 
   GLint maxSize;
1112
 
   GLint totalRequests, requestNumber;
1113
 
 
1114
 
   /*
1115
 
    ** Calculate the maximum amount of data can be stuffed into a single
1116
 
    ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
1117
 
    ** packet size minus sz_xGLXRenderReq.
1118
 
    */
1119
 
   maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
1120
 
   totalRequests = 1 + (dataLen / maxSize);
1121
 
   if (dataLen % maxSize)
1122
 
      totalRequests++;
1123
 
 
1124
 
   /*
1125
 
    ** Send all of the command, except the large array, as one request.
1126
 
    */
1127
 
   assert(headerLen <= maxSize);
1128
 
   __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
1129
 
 
1130
 
   /*
1131
 
    ** Send enough requests until the whole array is sent.
1132
 
    */
1133
 
   for (requestNumber = 2; requestNumber <= (totalRequests - 1);
1134
 
        requestNumber++) {
1135
 
      __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
1136
 
      data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
1137
 
      dataLen -= maxSize;
1138
 
      assert(dataLen > 0);
1139
 
   }
1140
 
 
1141
 
   assert(dataLen <= maxSize);
1142
 
   __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
1143
 
}