~ubuntu-branches/ubuntu/jaunty/mesa/jaunty

« back to all changes in this revision

Viewing changes to src/glx/mini/miniglx.c

  • Committer: Bazaar Package Importer
  • Author(s): Timo Aaltonen
  • Date: 2009-01-31 12:38:44 UTC
  • mfrom: (1.2.15 upstream) (3.1.4 experimental)
  • Revision ID: james.westby@ubuntu.com-20090131123844-ncib2eu1l01b1et0
Tags: 7.3-1ubuntu1
* Merge with Debian experimental.
* Drop 102_remove_flip.diff, included in 7.3..

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * \file miniglx.c
3
 
 * \brief Mini GLX interface functions.
4
 
 * \author Brian Paul
5
 
 *
6
 
 * The Mini GLX interface is a subset of the GLX interface, plus a
7
 
 * minimal set of Xlib functions.
8
 
 */
9
 
 
10
 
/*
11
 
 * Mesa 3-D graphics library
12
 
 * Version:  6.0.1
13
 
 *
14
 
 * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
15
 
 *
16
 
 * Permission is hereby granted, free of charge, to any person obtaining a
17
 
 * copy of this software and associated documentation files (the "Software"),
18
 
 * to deal in the Software without restriction, including without limitation
19
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20
 
 * and/or sell copies of the Software, and to permit persons to whom the
21
 
 * Software is furnished to do so, subject to the following conditions:
22
 
 *
23
 
 * The above copyright notice and this permission notice shall be included
24
 
 * in all copies or substantial portions of the Software.
25
 
 *
26
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27
 
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
29
 
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
30
 
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31
 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
 
 */
33
 
 
34
 
 
35
 
/**
36
 
 * \mainpage Mini GLX
37
 
 *
38
 
 * \section miniglxIntro Introduction
39
 
 *
40
 
 * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The
41
 
 * interface is a subset of the GLX interface, plus a minimal set of Xlib-like
42
 
 * functions.
43
 
 *
44
 
 * Programs written to the Mini GLX specification should run unchanged
45
 
 * on systems with the X Window System and the GLX extension (after
46
 
 * recompilation). The intention is to allow flexibility for
47
 
 * prototyping and testing.
48
 
 *
49
 
 * The files in the src/miniglx/ directory are compiled to build the
50
 
 * libGL.so library.  This is the library which applications link with.
51
 
 * libGL.so in turn, loads the hardware-specific device driver.
52
 
 *
53
 
 *
54
 
 * \section miniglxDoxygen About Doxygen
55
 
 *
56
 
 * For a list of all files, select <b>File List</b>.  Choose a file from
57
 
 * the list for a list of all functions in the file.
58
 
 *
59
 
 * For a list of all functions, types, constants, etc.
60
 
 * select <b>File Members</b>.
61
 
 *
62
 
 *
63
 
 * \section miniglxReferences References
64
 
 *
65
 
 * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>,
66
 
 *   Tungsten Graphics, Inc.
67
 
 * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc.,
68
 
 *   ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps
69
 
 * - Xlib - C Language X Interface, X Consortium Standard, X Version 11,
70
 
 *   Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz
71
 
 * - XFree86 Man pages, The XFree86 Project, Inc.,
72
 
 *   http://www.xfree86.org/current/manindex3.html
73
 
 *   
74
 
 */
75
 
 
76
 
/**
77
 
 * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
78
 
 * 
79
 
 * -# X (unfortunately) has two (or three) data types which
80
 
 *    describe visuals.  Ideally, there would just be one.
81
 
 * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual
82
 
 *    because we need to describe the GLX-specific attributes of visuals.
83
 
 * -# In this interface there is a one-to-one-to-one correspondence between
84
 
 *    the three types and they're all interconnected.
85
 
 * -# The #XVisualInfo type has a pointer to a #Visual.  The #Visual structure
86
 
 *    (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig.  The
87
 
 *    #Visual structure also has a pointer pointing back to the #XVisualInfo.
88
 
 * -# The #XVisualInfo structure is the only one who's contents are public.
89
 
 * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that
90
 
 *    return #XVisualInfo structures.  They can be freed with XFree(), though
91
 
 *    there is a small memory leak.
92
 
 */
93
 
 
94
 
 
95
 
#include <assert.h>
96
 
#include <errno.h>
97
 
#include <signal.h>
98
 
#include <stdio.h>
99
 
#include <stdlib.h>
100
 
#include <string.h>
101
 
#include <dlfcn.h>
102
 
#include <fcntl.h>
103
 
#include <unistd.h>
104
 
#include <sys/ioctl.h>
105
 
#include <sys/mman.h>
106
 
#include <sys/types.h>
107
 
#include <sys/time.h>    /* for gettimeofday */
108
 
#include <linux/kd.h>
109
 
#include <linux/vt.h>
110
 
 
111
 
#include "miniglxP.h"
112
 
#include "dri_util.h"
113
 
 
114
 
#include "imports.h"
115
 
#include "glcontextmodes.h"
116
 
#include "glapi.h"
117
 
 
118
 
#include "pciaccess.h"
119
 
 
120
 
static GLboolean __glXCreateContextWithConfig(__DRInativeDisplay *dpy,
121
 
        int screen, int fbconfigID, void *contextID,
122
 
        drm_context_t *hHWContext);
123
 
 
124
 
static GLboolean __glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn,
125
 
        __DRIid draw, unsigned int * index, unsigned int * stamp,
126
 
        int * x, int * y, int * width, int * height,
127
 
        int * numClipRects, drm_clip_rect_t ** pClipRects,
128
 
        int * backX, int * backY,
129
 
        int * numBackClipRects, drm_clip_rect_t ** pBackClipRects);
130
 
 
131
 
static __DRIscreen * __glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn);
132
 
 
133
 
static GLboolean __glXWindowExists(__DRInativeDisplay *dpy, __DRIid draw);
134
 
 
135
 
static int __glXGetUST( int64_t * ust );
136
 
 
137
 
static GLboolean __glXGetMscRate(__DRInativeDisplay * dpy, __DRIid drawable,
138
 
    int32_t * numerator, int32_t * denominator);
139
 
 
140
 
static GLboolean xf86DRI_DestroyContext(__DRInativeDisplay *dpy, int screen,
141
 
    __DRIid context_id );
142
 
 
143
 
static GLboolean xf86DRI_CreateDrawable(__DRInativeDisplay *dpy, int screen,
144
 
    __DRIid drawable, drm_drawable_t *hHWDrawable );
145
 
 
146
 
static GLboolean xf86DRI_DestroyDrawable(__DRInativeDisplay *dpy, int screen,
147
 
    __DRIid drawable);
148
 
 
149
 
 
150
 
/** Wrapper around either malloc() */
151
 
void *
152
 
_mesa_malloc(size_t bytes)
153
 
{
154
 
   return malloc(bytes);
155
 
}
156
 
 
157
 
/** Wrapper around either calloc() */
158
 
void *
159
 
_mesa_calloc(size_t bytes)
160
 
{
161
 
   return calloc(1, bytes);
162
 
}
163
 
 
164
 
/** Wrapper around either free() */
165
 
void
166
 
_mesa_free(void *ptr)
167
 
{
168
 
   free(ptr);
169
 
}
170
 
 
171
 
 
172
 
/**
173
 
 * \brief Current GLX context.
174
 
 *
175
 
 * \sa glXGetCurrentContext().
176
 
 */
177
 
static GLXContext CurrentContext = NULL;
178
 
 
179
 
 
180
 
 
181
 
static Display *SignalDisplay = 0;
182
 
 
183
 
static void SwitchVT(int sig)
184
 
{
185
 
   fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay);
186
 
 
187
 
   if (SignalDisplay) {
188
 
      SignalDisplay->vtSignalFlag = 1;
189
 
      switch( sig )
190
 
      {
191
 
      case SIGUSR1:                                /* vt has been released */
192
 
         SignalDisplay->haveVT = 0;
193
 
         break;
194
 
      case SIGUSR2:                                /* vt has been acquired */
195
 
         SignalDisplay->haveVT = 1;
196
 
         break;
197
 
      }
198
 
   }
199
 
}
200
 
 
201
 
/**********************************************************************/
202
 
/** \name Framebuffer device functions                                */
203
 
/**********************************************************************/
204
 
/*@{*/
205
 
 
206
 
/**
207
 
 * \brief Do the first part of setting up the framebuffer device.
208
 
 *
209
 
 * \param dpy the display handle.
210
 
 * \param use_vt use a VT for display or not
211
 
 *
212
 
 * \return GL_TRUE on success, or GL_FALSE on failure.
213
 
 * 
214
 
 * \sa This is called during XOpenDisplay().
215
 
 *
216
 
 * \internal
217
 
 * Gets the VT number, opens the respective console TTY device. Saves its state
218
 
 * to restore when exiting and goes into graphics mode.
219
 
 *
220
 
 * Opens the framebuffer device and make a copy of the original variable screen
221
 
 * information and gets the fixed screen information.  Maps the framebuffer and
222
 
 * MMIO region into the process address space.
223
 
 */
224
 
static GLboolean
225
 
OpenFBDev( Display *dpy, int use_vt )
226
 
{
227
 
   char ttystr[1000];
228
 
   int fd, vtnumber, ttyfd;
229
 
 
230
 
   assert(dpy);
231
 
 
232
 
   if (geteuid()) {
233
 
      fprintf(stderr, "error: you need to be root\n");
234
 
      return GL_FALSE;
235
 
   }
236
 
   
237
 
   if (use_vt) {
238
 
       
239
 
       /* open /dev/tty0 and get the VT number */
240
 
       if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
241
 
           fprintf(stderr, "error opening /dev/tty0\n");
242
 
           return GL_FALSE;
243
 
       }
244
 
       if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
245
 
           fprintf(stderr, "error: couldn't get a free vt\n");
246
 
           return GL_FALSE;
247
 
       }
248
 
       
249
 
       fprintf(stderr, "*** got vt nr: %d\n", vtnumber);
250
 
       close(fd);
251
 
       
252
 
       /* open the console tty */
253
 
       sprintf(ttystr, "/dev/tty%d", vtnumber);  /* /dev/tty1-64 */
254
 
       dpy->ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
255
 
       if (dpy->ConsoleFD < 0) {
256
 
           fprintf(stderr, "error couldn't open console fd\n");
257
 
           return GL_FALSE;
258
 
       }
259
 
       
260
 
       /* save current vt number */
261
 
       {
262
 
           struct vt_stat vts;
263
 
           if (ioctl(dpy->ConsoleFD, VT_GETSTATE, &vts) == 0)
264
 
               dpy->OriginalVT = vts.v_active;
265
 
       }
266
 
       
267
 
       /* disconnect from controlling tty */
268
 
       ttyfd = open("/dev/tty", O_RDWR);
269
 
       if (ttyfd >= 0) {
270
 
           ioctl(ttyfd, TIOCNOTTY, 0);
271
 
           close(ttyfd);
272
 
       }
273
 
       
274
 
       /* some magic to restore the vt when we exit */
275
 
       {
276
 
           struct vt_mode vt;
277
 
           struct sigaction sig_tty;
278
 
           
279
 
           /* Set-up tty signal handler to catch the signal we request below */
280
 
           SignalDisplay = dpy;
281
 
           memset( &sig_tty, 0, sizeof( sig_tty ) );
282
 
           sig_tty.sa_handler = SwitchVT;
283
 
           sigemptyset( &sig_tty.sa_mask );
284
 
           if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) ||
285
 
               sigaction( SIGUSR2, &sig_tty, &dpy->OrigSigUsr2 ) )
286
 
           {
287
 
               fprintf(stderr, "error: can't set up signal handler (%s)",
288
 
                       strerror(errno) );
289
 
               return GL_FALSE;
290
 
           }
291
 
           
292
 
           
293
 
           
294
 
           vt.mode = VT_PROCESS;
295
 
           vt.waitv = 0;
296
 
           vt.relsig = SIGUSR1;
297
 
           vt.acqsig = SIGUSR2;
298
 
           if (ioctl(dpy->ConsoleFD, VT_SETMODE, &vt) < 0) {
299
 
               fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
300
 
                       strerror(errno));
301
 
               return GL_FALSE;
302
 
           }
303
 
           
304
 
           
305
 
           if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
306
 
               printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
307
 
           if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
308
 
               printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
309
 
           
310
 
           if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) {
311
 
               fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
312
 
               return GL_FALSE;
313
 
           }
314
 
           
315
 
           
316
 
           
317
 
       }
318
 
       
319
 
       /* go into graphics mode */
320
 
       if (ioctl(dpy->ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
321
 
           fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
322
 
                   strerror(errno));
323
 
           return GL_FALSE;
324
 
       }
325
 
   }
326
 
 
327
 
   /* open the framebuffer device */
328
 
   dpy->FrameBufferFD = open(dpy->fbdevDevice, O_RDWR);
329
 
   if (dpy->FrameBufferFD < 0) {
330
 
      fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
331
 
      return GL_FALSE;
332
 
   }
333
 
 
334
 
  /* get the original variable screen info */
335
 
   if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->OrigVarInfo)) {
336
 
      fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
337
 
              strerror(errno));
338
 
      return GL_FALSE;
339
 
   }
340
 
 
341
 
   /* make copy */
342
 
   dpy->VarInfo = dpy->OrigVarInfo;  /* structure copy */
343
 
 
344
 
   /* Turn off hw accels (otherwise mmap of mmio region will be
345
 
    * refused)
346
 
    */
347
 
   dpy->VarInfo.accel_flags = 0; 
348
 
   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
349
 
      fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
350
 
              strerror(errno));
351
 
      return GL_FALSE;
352
 
   }
353
 
 
354
 
 
355
 
 
356
 
   /* Get the fixed screen info */
357
 
   if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
358
 
      fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
359
 
              strerror(errno));
360
 
      return GL_FALSE;
361
 
   }
362
 
 
363
 
 
364
 
 
365
 
   /* mmap the framebuffer into our address space */
366
 
   dpy->driverContext.FBStart = dpy->FixedInfo.smem_start;
367
 
   dpy->driverContext.FBSize = dpy->FixedInfo.smem_len;
368
 
   dpy->driverContext.shared.fbSize = dpy->FixedInfo.smem_len;
369
 
   dpy->driverContext.FBAddress = (caddr_t) mmap(0, /* start */
370
 
                                     dpy->driverContext.shared.fbSize, /* bytes */
371
 
                                     PROT_READ | PROT_WRITE, /* prot */
372
 
                                     MAP_SHARED, /* flags */
373
 
                                     dpy->FrameBufferFD, /* fd */
374
 
                                     0 /* offset */);
375
 
   if (dpy->driverContext.FBAddress == (caddr_t) - 1) {
376
 
      fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
377
 
              strerror(errno));
378
 
      return GL_FALSE;
379
 
   }
380
 
            
381
 
   /* mmap the MMIO region into our address space */
382
 
   dpy->driverContext.MMIOStart = dpy->FixedInfo.mmio_start;
383
 
   dpy->driverContext.MMIOSize = dpy->FixedInfo.mmio_len;
384
 
   dpy->driverContext.MMIOAddress = (caddr_t) mmap(0, /* start */
385
 
                                     dpy->driverContext.MMIOSize, /* bytes */
386
 
                                     PROT_READ | PROT_WRITE, /* prot */
387
 
                                     MAP_SHARED, /* flags */
388
 
                                     dpy->FrameBufferFD, /* fd */
389
 
                                     dpy->FixedInfo.smem_len /* offset */);
390
 
   if (dpy->driverContext.MMIOAddress == (caddr_t) - 1) {
391
 
      fprintf(stderr, "error: unable to mmap mmio region: %s\n",
392
 
              strerror(errno));
393
 
      return GL_FALSE;
394
 
   }
395
 
 
396
 
   fprintf(stderr, "got MMIOAddress %p offset %d\n",
397
 
           dpy->driverContext.MMIOAddress,
398
 
           dpy->FixedInfo.smem_len);
399
 
 
400
 
   return GL_TRUE;
401
 
}
402
 
 
403
 
 
404
 
 
405
 
 
406
 
/**
407
 
 * \brief Setup up the desired framebuffer device mode.  
408
 
 *
409
 
 * \param dpy the display handle.
410
 
 * 
411
 
 * \return GL_TRUE on success, or GL_FALSE on failure.
412
 
 * 
413
 
 * \sa This is called during __miniglx_StartServer().
414
 
 *
415
 
 * \internal
416
 
 *
417
 
 * Bumps the size of the window the the next supported mode. Sets the
418
 
 * variable screen information according to the desired mode and asks
419
 
 * the driver to validate the mode. Certifies that a DirectColor or
420
 
 * TrueColor visual is used from the updated fixed screen information.
421
 
 * In the case of DirectColor visuals, sets up an 'identity' colormap to
422
 
 * mimic a TrueColor visual.
423
 
 *
424
 
 * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
425
 
 * allow the driver to make modifications to the chosen mode according
426
 
 * to hardware constraints, or to save and restore videocard registers
427
 
 * that may be clobbered by the fbdev driver.
428
 
 *
429
 
 * \todo Timings are hard-coded in the source for a set of supported modes.
430
 
 */
431
 
static GLboolean
432
 
SetupFBDev( Display *dpy )
433
 
{
434
 
   int width, height;
435
 
 
436
 
   assert(dpy);
437
 
 
438
 
   width = dpy->driverContext.shared.virtualWidth;
439
 
   height = dpy->driverContext.shared.virtualHeight;
440
 
   
441
 
   if (width==832)
442
 
        width=800;
443
 
#if 0
444
 
   /* Bump size up to next supported mode.
445
 
    */
446
 
   if (width <= 720 && height <= 480) { 
447
 
      width = 720; height = 480; 
448
 
   } 
449
 
   else if (width <= 960 && height <= 540) {
450
 
      width = 960; height = 540; 
451
 
   }  
452
 
   else if (width <= 800 && height <= 600) {
453
 
      width = 800; height = 600; 
454
 
   }  
455
 
   else if (width <= 1024 && height <= 768) { 
456
 
      width = 1024; height = 768; 
457
 
   } 
458
 
   else if (width <= 768 && height <= 1024) {
459
 
      width = 768; height = 1024; 
460
 
   }  
461
 
   else if (width <= 1280 && height <= 1024) { 
462
 
      width = 1280; height = 1024; 
463
 
   } 
464
 
#endif
465
 
 
466
 
   dpy->driverContext.shared.fbStride = width * (dpy->driverContext.bpp / 8);
467
 
   
468
 
   /* set the depth, resolution, etc */
469
 
   dpy->VarInfo = dpy->OrigVarInfo;
470
 
   dpy->VarInfo.bits_per_pixel = dpy->driverContext.bpp;
471
 
   dpy->VarInfo.xres_virtual = dpy->driverContext.shared.virtualWidth;
472
 
   dpy->VarInfo.yres_virtual = dpy->driverContext.shared.virtualHeight;
473
 
   dpy->VarInfo.xres = dpy->driverContext.shared.Width;
474
 
   dpy->VarInfo.yres = height;
475
 
   dpy->VarInfo.xoffset = 0;
476
 
   dpy->VarInfo.yoffset = 0;
477
 
   dpy->VarInfo.nonstd = 0;
478
 
   dpy->VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
479
 
 
480
 
   if (dpy->VarInfo.bits_per_pixel == 32) {
481
 
      dpy->VarInfo.red.offset = 16;
482
 
      dpy->VarInfo.green.offset = 8;
483
 
      dpy->VarInfo.blue.offset = 0;
484
 
      dpy->VarInfo.transp.offset = 24;
485
 
      dpy->VarInfo.red.length = 8;
486
 
      dpy->VarInfo.green.length = 8;
487
 
      dpy->VarInfo.blue.length = 8;
488
 
      dpy->VarInfo.transp.length = 8;
489
 
   }
490
 
   else if (dpy->VarInfo.bits_per_pixel == 16) {
491
 
      dpy->VarInfo.red.offset = 11;
492
 
      dpy->VarInfo.green.offset = 5;
493
 
      dpy->VarInfo.blue.offset = 0;
494
 
      dpy->VarInfo.red.length = 5;
495
 
      dpy->VarInfo.green.length = 6;
496
 
      dpy->VarInfo.blue.length = 5;
497
 
      dpy->VarInfo.transp.offset = 0;
498
 
      dpy->VarInfo.transp.length = 0;
499
 
   }
500
 
   else {
501
 
      fprintf(stderr, "Only 32bpp and 16bpp modes supported at the moment\n");
502
 
      return 0;
503
 
   }
504
 
 
505
 
   if (!dpy->driver->validateMode( &dpy->driverContext )) {
506
 
      fprintf(stderr, "Driver validateMode() failed\n");
507
 
      return 0;
508
 
   }
509
 
 
510
 
   /* These should be calculated with the gtf.c program, and then we could
511
 
      remove all this... AlanH. */
512
 
   if (dpy->VarInfo.xres == 1280 && 
513
 
       dpy->VarInfo.yres == 1024) {
514
 
      /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
515
 
      dpy->VarInfo.pixclock = 7408;
516
 
      dpy->VarInfo.left_margin = 248;
517
 
      dpy->VarInfo.right_margin = 16;
518
 
      dpy->VarInfo.upper_margin = 38;
519
 
      dpy->VarInfo.lower_margin = 1;
520
 
      dpy->VarInfo.hsync_len = 144;
521
 
      dpy->VarInfo.vsync_len = 3;
522
 
   }
523
 
   else if (dpy->VarInfo.xres == 1024 && 
524
 
            dpy->VarInfo.yres == 768) {
525
 
      /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
526
 
      dpy->VarInfo.pixclock = 12699;
527
 
      dpy->VarInfo.left_margin = 176;
528
 
      dpy->VarInfo.right_margin = 16;
529
 
      dpy->VarInfo.upper_margin = 28;
530
 
      dpy->VarInfo.lower_margin = 1;
531
 
      dpy->VarInfo.hsync_len = 96;
532
 
      dpy->VarInfo.vsync_len = 3;
533
 
   }
534
 
   else if (dpy->VarInfo.xres == 800 &&
535
 
            dpy->VarInfo.yres == 600) {
536
 
      /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
537
 
      dpy->VarInfo.pixclock = 27778;
538
 
      dpy->VarInfo.left_margin = 128;
539
 
      dpy->VarInfo.right_margin = 24;
540
 
      dpy->VarInfo.upper_margin = 22;
541
 
      dpy->VarInfo.lower_margin = 1;
542
 
      dpy->VarInfo.hsync_len = 72;
543
 
      dpy->VarInfo.vsync_len = 2;
544
 
   }
545
 
   else if (dpy->VarInfo.xres == 720 &&
546
 
            dpy->VarInfo.yres == 480) {
547
 
      dpy->VarInfo.pixclock = 37202;
548
 
      dpy->VarInfo.left_margin = 88;
549
 
      dpy->VarInfo.right_margin = 16;
550
 
      dpy->VarInfo.upper_margin = 14;
551
 
      dpy->VarInfo.lower_margin = 1;
552
 
      dpy->VarInfo.hsync_len = 72;
553
 
      dpy->VarInfo.vsync_len = 3;
554
 
   }
555
 
   else if (dpy->VarInfo.xres == 960 &&
556
 
            dpy->VarInfo.yres == 540) {
557
 
      dpy->VarInfo.pixclock = 24273;
558
 
      dpy->VarInfo.left_margin = 128;
559
 
      dpy->VarInfo.right_margin = 32;
560
 
      dpy->VarInfo.upper_margin = 16;
561
 
      dpy->VarInfo.lower_margin = 1;
562
 
      dpy->VarInfo.hsync_len = 96;
563
 
      dpy->VarInfo.vsync_len = 3;
564
 
   }
565
 
   else if (dpy->VarInfo.xres == 768 &&
566
 
            dpy->VarInfo.yres == 1024) {
567
 
      /* timing values for 768x1024 @ 75Hz */
568
 
      dpy->VarInfo.pixclock = 11993;
569
 
      dpy->VarInfo.left_margin = 136;
570
 
      dpy->VarInfo.right_margin = 32;
571
 
      dpy->VarInfo.upper_margin = 41;
572
 
      dpy->VarInfo.lower_margin = 1;
573
 
      dpy->VarInfo.hsync_len = 80;
574
 
      dpy->VarInfo.vsync_len = 3;
575
 
   }
576
 
   else {
577
 
      /* XXX need timings for other screen sizes */
578
 
      fprintf(stderr, "XXXX screen size %d x %d not supported at this time!\n",
579
 
              dpy->VarInfo.xres, dpy->VarInfo.yres);
580
 
      return GL_FALSE;
581
 
   }
582
 
 
583
 
   fprintf(stderr, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
584
 
           dpy->VarInfo.xres, dpy->VarInfo.yres,
585
 
           dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
586
 
           dpy->VarInfo.bits_per_pixel);
587
 
 
588
 
   /* set variable screen info */
589
 
   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
590
 
      fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
591
 
              strerror(errno));
592
 
      return GL_FALSE;
593
 
   }
594
 
 
595
 
   /* get the variable screen info, in case it has been modified */
596
 
   if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->VarInfo)) {
597
 
      fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
598
 
              strerror(errno));
599
 
      return GL_FALSE;
600
 
   }
601
 
 
602
 
 
603
 
   fprintf(stderr, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
604
 
           dpy->VarInfo.xres, dpy->VarInfo.yres,
605
 
           dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
606
 
           dpy->VarInfo.bits_per_pixel);
607
 
 
608
 
   /* Get the fixed screen info */
609
 
   if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
610
 
      fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
611
 
              strerror(errno));
612
 
      return GL_FALSE;
613
 
   }
614
 
 
615
 
   if (dpy->FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
616
 
       dpy->FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
617
 
      fprintf(stderr, "non-TRUECOLOR visuals not supported.\n");
618
 
      return GL_FALSE;
619
 
   }
620
 
 
621
 
   if (dpy->FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
622
 
      struct fb_cmap cmap;
623
 
      unsigned short red[256], green[256], blue[256];
624
 
      int rcols = 1 << dpy->VarInfo.red.length;
625
 
      int gcols = 1 << dpy->VarInfo.green.length;
626
 
      int bcols = 1 << dpy->VarInfo.blue.length;
627
 
      int i;
628
 
 
629
 
      cmap.start = 0;      
630
 
      cmap.len = gcols;
631
 
      cmap.red   = red;
632
 
      cmap.green = green;
633
 
      cmap.blue  = blue;
634
 
      cmap.transp = NULL;
635
 
 
636
 
      for (i = 0; i < rcols ; i++) 
637
 
         red[i] = (65536/(rcols-1)) * i;
638
 
 
639
 
      for (i = 0; i < gcols ; i++) 
640
 
         green[i] = (65536/(gcols-1)) * i;
641
 
 
642
 
      for (i = 0; i < bcols ; i++) 
643
 
         blue[i] = (65536/(bcols-1)) * i;
644
 
      
645
 
      if (ioctl(dpy->FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
646
 
         fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
647
 
         exit(1);
648
 
      }
649
 
   }
650
 
 
651
 
   /* May need to restore regs fbdev has clobbered:
652
 
    */
653
 
   if (!dpy->driver->postValidateMode( &dpy->driverContext )) {
654
 
      fprintf(stderr, "Driver postValidateMode() failed\n");
655
 
      return 0;
656
 
   }
657
 
 
658
 
   return GL_TRUE;
659
 
}
660
 
 
661
 
 
662
 
/**
663
 
 * \brief Restore the framebuffer device to state it was in before we started
664
 
 *
665
 
 * Undoes the work done by SetupFBDev().
666
 
 * 
667
 
 * \param dpy the display handle.
668
 
 *
669
 
 * \return GL_TRUE on success, or GL_FALSE on failure.
670
 
 * 
671
 
 * \sa Called from XDestroyWindow().
672
 
 *
673
 
 * \internal
674
 
 * Restores the original variable screen info.
675
 
 */
676
 
static GLboolean
677
 
RestoreFBDev( Display *dpy )
678
 
{
679
 
   /* restore original variable screen info */
680
 
   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->OrigVarInfo)) {
681
 
      fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
682
 
              strerror(errno));
683
 
      return GL_FALSE;
684
 
   }
685
 
   dpy->VarInfo = dpy->OrigVarInfo;
686
 
 
687
 
   return GL_TRUE;
688
 
}
689
 
 
690
 
 
691
 
/**
692
 
 * \brief Close the framebuffer device.  
693
 
 *
694
 
 * \param dpy the display handle.
695
 
 * 
696
 
 * \sa Called from XCloseDisplay().
697
 
 *
698
 
 * \internal
699
 
 * Unmaps the framebuffer and MMIO region.  Restores the text mode and the
700
 
 * original virtual terminal. Closes the console and framebuffer devices.
701
 
 */
702
 
static void
703
 
CloseFBDev( Display *dpy )
704
 
{
705
 
   struct vt_mode VT;
706
 
 
707
 
   munmap(dpy->driverContext.FBAddress, dpy->driverContext.FBSize);
708
 
   munmap(dpy->driverContext.MMIOAddress, dpy->driverContext.MMIOSize);
709
 
 
710
 
   if (dpy->ConsoleFD) {
711
 
       /* restore text mode */
712
 
       ioctl(dpy->ConsoleFD, KDSETMODE, KD_TEXT);
713
 
       
714
 
       /* set vt */
715
 
       if (ioctl(dpy->ConsoleFD, VT_GETMODE, &VT) != -1) {
716
 
           VT.mode = VT_AUTO;
717
 
           ioctl(dpy->ConsoleFD, VT_SETMODE, &VT);
718
 
       }
719
 
       
720
 
       /* restore original vt */
721
 
       if (dpy->OriginalVT >= 0) {
722
 
           ioctl(dpy->ConsoleFD, VT_ACTIVATE, dpy->OriginalVT);
723
 
           dpy->OriginalVT = -1;
724
 
       }
725
 
       
726
 
       close(dpy->ConsoleFD);
727
 
   }
728
 
   close(dpy->FrameBufferFD);
729
 
}
730
 
 
731
 
/*@}*/
732
 
 
733
 
 
734
 
/**********************************************************************/
735
 
/** \name Misc functions needed for DRI drivers                       */
736
 
/**********************************************************************/
737
 
/*@{*/
738
 
 
739
 
/**
740
 
 * \brief Find the DRI screen dependent methods associated with the display.
741
 
 *
742
 
 * \param dpy a display handle, as returned by XOpenDisplay().
743
 
 * \param scrn the screen number. Not referenced.
744
 
 * 
745
 
 * \returns a pointer to a __DRIscreenRec structure.
746
 
 * 
747
 
 * \internal
748
 
 * Returns the MiniGLXDisplayRec::driScreen attribute.
749
 
 */
750
 
static __DRIscreen *
751
 
__glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn)
752
 
{
753
 
   (void) scrn;
754
 
   return &((Display*)dpy)->driScreen;
755
 
}
756
 
 
757
 
/**
758
 
 * \brief Validate a drawable.
759
 
 *
760
 
 * \param dpy a display handle, as returned by XOpenDisplay().
761
 
 * \param draw drawable to validate.
762
 
 * 
763
 
 * \internal
764
 
 * Since Mini GLX only supports one window, compares the specified drawable with
765
 
 * the MiniGLXDisplayRec::TheWindow attribute.
766
 
 */
767
 
static GLboolean
768
 
__glXWindowExists(__DRInativeDisplay *dpy, __DRIid draw)
769
 
{
770
 
   const Display * const display = (Display*)dpy;
771
 
   if (display->TheWindow == (Window) draw)
772
 
      return True;
773
 
   else
774
 
      return False;
775
 
}
776
 
 
777
 
/**
778
 
 * \brief Get current thread ID.
779
 
 *
780
 
 * \return thread ID.
781
 
 *
782
 
 * \internal
783
 
 * Always returns 0. 
784
 
 */
785
 
/*unsigned long
786
 
_glthread_GetID(void)
787
 
{
788
 
   return 0;
789
 
}*/
790
 
 
791
 
/*@}*/
792
 
 
793
 
 
794
 
/**
795
 
 * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
796
 
 * chipset based on supplied bus ID.
797
 
 * 
798
 
 * \return probed chipset (non-zero) on success, zero otherwise.
799
 
 * 
800
 
 * \internal 
801
 
 */
802
 
static int get_chipset_from_busid( Display *dpy )
803
 
{
804
 
   char buf[0x200];
805
 
   FILE *file;
806
 
   const char *fname = "/proc/bus/pci/devices";
807
 
   int retval = 0;
808
 
 
809
 
   if (!(file = fopen(fname,"r"))) {
810
 
      fprintf(stderr, "couldn't open %s: %s\n", fname, strerror(errno));
811
 
      return 0;
812
 
   }
813
 
 
814
 
   while (fgets(buf, sizeof(buf)-1, file)) {
815
 
      unsigned int nr, bus, dev, fn, vendor, device, encode;
816
 
      nr = sscanf(buf, "%04x\t%04x%04x", &encode, 
817
 
                  &vendor, &device);
818
 
      
819
 
      bus = encode >> 8;
820
 
      dev = (encode & 0xFF) >> 3;
821
 
      fn = encode & 0x7;
822
 
 
823
 
      if (nr != 3)
824
 
         break;
825
 
 
826
 
      if (bus == dpy->driverContext.pciBus &&
827
 
          dev == dpy->driverContext.pciDevice &&
828
 
          fn  == dpy->driverContext.pciFunc) {
829
 
         retval = device;
830
 
         break;
831
 
      }
832
 
   }
833
 
 
834
 
   fclose(file);
835
 
 
836
 
   if (retval)
837
 
      fprintf(stderr, "[miniglx] probed chipset 0x%x\n", retval);
838
 
   else
839
 
      fprintf(stderr, "[miniglx] failed to probe chipset\n");
840
 
 
841
 
   return retval;
842
 
}
843
 
 
844
 
 
845
 
/**
846
 
 * \brief Read settings from a configuration file.
847
 
 * 
848
 
 * The configuration file is usually "/etc/miniglx.conf", but can be overridden
849
 
 * with the MINIGLX_CONF environment variable. 
850
 
 *
851
 
 * The format consists in \code option = value \endcode lines. The option names 
852
 
 * corresponds to the fields in MiniGLXDisplayRec.
853
 
 * 
854
 
 * \param dpy the display handle as.
855
 
 *
856
 
 * \return non-zero on success, zero otherwise.
857
 
 * 
858
 
 * \internal 
859
 
 * Sets some defaults. Opens and parses the the Mini GLX configuration file and
860
 
 * fills in the MiniGLXDisplayRec field that corresponds for each option.
861
 
 */
862
 
static int __read_config_file( Display *dpy )
863
 
{
864
 
   FILE *file;
865
 
   const char *fname;
866
 
 
867
 
   /* Fallback/defaults
868
 
    */
869
 
   dpy->fbdevDevice = "/dev/fb0";
870
 
   dpy->clientDriverName = "fb_dri.so";
871
 
   dpy->driverContext.pciBus = 0;
872
 
   dpy->driverContext.pciDevice = 0;
873
 
   dpy->driverContext.pciFunc = 0;
874
 
   dpy->driverContext.chipset = 0;   
875
 
   dpy->driverContext.pciBusID = 0;
876
 
   dpy->driverContext.shared.virtualWidth = 1280;
877
 
   dpy->driverContext.shared.virtualHeight = 1024;
878
 
   dpy->driverContext.bpp = 32;
879
 
   dpy->driverContext.cpp = 4;
880
 
   dpy->rotateMode = 0;
881
 
   dpy->driverContext.agpmode = 1;
882
 
   dpy->driverContext.isPCI = 0;
883
 
   dpy->driverContext.colorTiling = 0;
884
 
 
885
 
   fname = getenv("MINIGLX_CONF");
886
 
   if (!fname) fname = "/etc/miniglx.conf";
887
 
 
888
 
   file = fopen(fname, "r");
889
 
   if (!file) {
890
 
      fprintf(stderr, "couldn't open config file %s: %s\n", fname, strerror(errno));
891
 
      return 0;
892
 
   }
893
 
 
894
 
 
895
 
   while (!feof(file)) {
896
 
      char buf[81], *opt = buf, *val, *tmp1, *tmp2;
897
 
      fgets(buf, sizeof(buf), file); 
898
 
 
899
 
      /* Parse 'opt = val' -- must be easier ways to do this.
900
 
       */
901
 
      while (isspace(*opt)) opt++;
902
 
      val = opt;
903
 
      if (*val == '#') continue; /* comment */
904
 
      while (!isspace(*val) && *val != '=' && *val) val++;
905
 
      tmp1 = val;
906
 
      while (isspace(*val)) val++;
907
 
      if (*val != '=') continue;
908
 
      *tmp1 = 0; 
909
 
      val++;
910
 
      while (isspace(*val)) val++;
911
 
      tmp2 = val;
912
 
      while (!isspace(*tmp2) && *tmp2 != '\n' && *tmp2) tmp2++;
913
 
      *tmp2 = 0;
914
 
 
915
 
 
916
 
      if (strcmp(opt, "fbdevDevice") == 0) 
917
 
         dpy->fbdevDevice = strdup(val);
918
 
      else if (strcmp(opt, "clientDriverName") == 0)
919
 
         dpy->clientDriverName = strdup(val);
920
 
      else if (strcmp(opt, "rotateMode") == 0)
921
 
         dpy->rotateMode = atoi(val) ? 1 : 0;
922
 
      else if (strcmp(opt, "pciBusID") == 0) {
923
 
         if (sscanf(val, "PCI:%d:%d:%d",
924
 
                    &dpy->driverContext.pciBus,
925
 
                    &dpy->driverContext.pciDevice,
926
 
                    &dpy->driverContext.pciFunc) != 3) {
927
 
            fprintf(stderr, "malformed bus id: %s\n", val);
928
 
            continue;
929
 
         }
930
 
         dpy->driverContext.pciBusID = strdup(val);
931
 
      }
932
 
      else if (strcmp(opt, "chipset") == 0) {
933
 
         if (sscanf(val, "0x%x", &dpy->driverContext.chipset) != 1)
934
 
            fprintf(stderr, "malformed chipset: %s\n", opt);
935
 
      }
936
 
      else if (strcmp(opt, "virtualWidth") == 0) {
937
 
         if (sscanf(val, "%d", &dpy->driverContext.shared.virtualWidth) != 1)
938
 
            fprintf(stderr, "malformed virtualWidth: %s\n", opt);
939
 
      }
940
 
      else if (strcmp(opt, "virtualHeight") == 0) {
941
 
         if (sscanf(val, "%d", &dpy->driverContext.shared.virtualHeight) != 1)
942
 
            fprintf(stderr, "malformed virutalHeight: %s\n", opt);
943
 
      }
944
 
      else if (strcmp(opt, "bpp") == 0) {
945
 
         if (sscanf(val, "%d", &dpy->driverContext.bpp) != 1)
946
 
            fprintf(stderr, "malformed bpp: %s\n", opt);
947
 
         dpy->driverContext.cpp = dpy->driverContext.bpp / 8;
948
 
      }
949
 
      else if (strcmp(opt, "agpmode") == 0) {
950
 
         if (sscanf(val, "%d", &dpy->driverContext.agpmode) != 1)
951
 
            fprintf(stderr, "malformed agpmode: %s\n", opt);
952
 
      }
953
 
      else if (strcmp(opt, "isPCI") == 0) {
954
 
         dpy->driverContext.isPCI = atoi(val) ? 1 : 0;
955
 
      }
956
 
      else if (strcmp(opt, "colorTiling") == 0) {
957
 
         dpy->driverContext.colorTiling = atoi(val) ? 1 : 0;
958
 
      }
959
 
   }
960
 
 
961
 
   fclose(file);
962
 
 
963
 
   if (dpy->driverContext.chipset == 0 && dpy->driverContext.pciBusID != 0) 
964
 
      dpy->driverContext.chipset = get_chipset_from_busid( dpy );
965
 
 
966
 
   return 1;
967
 
}
968
 
 
969
 
/**
970
 
 * Versioned name of the expected \c __driCreateNewScreen function.
971
 
 * 
972
 
 * The version of the last incompatible loader/driver inteface change is
973
 
 * appended to the name of the \c __driCreateNewScreen function.  This
974
 
 * prevents loaders from trying to load drivers that are too old.
975
 
 * 
976
 
 * \todo
977
 
 * Create a macro or something so that this is automatically updated.
978
 
 */
979
 
static const char createNewScreenName[] = "__driCreateNewScreen_20050727";
980
 
 
981
 
 
982
 
static int InitDriver( Display *dpy )
983
 
{
984
 
   /*
985
 
    * Begin DRI setup.
986
 
    * We're kind of combining the per-display and per-screen information
987
 
    * which was kept separate in XFree86/DRI's libGL.
988
 
    */
989
 
   dpy->dlHandle = dlopen(dpy->clientDriverName, RTLD_NOW | RTLD_GLOBAL);
990
 
   if (!dpy->dlHandle) {
991
 
      fprintf(stderr, "Unable to open %s: %s\n", dpy->clientDriverName,
992
 
              dlerror());
993
 
      goto failed;
994
 
   }
995
 
 
996
 
   /* Pull in Mini GLX specific hooks:
997
 
    */
998
 
   dpy->driver = (struct DRIDriverRec *) dlsym(dpy->dlHandle,
999
 
                                               "__driDriver");
1000
 
   if (!dpy->driver) {
1001
 
      fprintf(stderr, "Couldn't find __driDriver in %s\n",
1002
 
              dpy->clientDriverName);
1003
 
      goto failed;
1004
 
   }
1005
 
 
1006
 
   /* Pull in standard DRI client-side driver hooks:
1007
 
    */
1008
 
   dpy->createNewScreen = (PFNCREATENEWSCREENFUNC)
1009
 
           dlsym(dpy->dlHandle, createNewScreenName);
1010
 
   if (!dpy->createNewScreen) {
1011
 
      fprintf(stderr, "Couldn't find %s in %s\n", createNewScreenName,
1012
 
              dpy->clientDriverName);
1013
 
      goto failed;
1014
 
   }
1015
 
 
1016
 
   return GL_TRUE;
1017
 
 
1018
 
failed:
1019
 
   if (dpy->dlHandle) {
1020
 
       dlclose(dpy->dlHandle);
1021
 
       dpy->dlHandle = 0;
1022
 
   }
1023
 
   return GL_FALSE;
1024
 
}
1025
 
 
1026
 
 
1027
 
/**********************************************************************/
1028
 
/** \name Public API functions (Xlib and GLX)                         */
1029
 
/**********************************************************************/
1030
 
/*@{*/
1031
 
 
1032
 
 
1033
 
/**
1034
 
 * \brief Initialize the graphics system.
1035
 
 * 
1036
 
 * \param display_name currently ignored. It is recommended to pass it as NULL.
1037
 
 * \return a pointer to a #Display if the function is able to initialize
1038
 
 * the graphics system, NULL otherwise.
1039
 
 * 
1040
 
 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1041
 
 * configuration file. 
1042
 
 *
1043
 
 * Calls OpenFBDev() to open the framebuffer device and calls
1044
 
 * DRIDriverRec::initFBDev to do the client-side initialization on it.
1045
 
 *
1046
 
 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1047
 
 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1048
 
 * Asks the driver for a list of supported visuals.  Performs the per-screen
1049
 
 * client-side initialization.  Also setups the callbacks in the screen private
1050
 
 * information.
1051
 
 *
1052
 
 * Does the framebuffer device setup. Calls __miniglx_open_connections() to
1053
 
 * serve clients.
1054
 
 */
1055
 
Display *
1056
 
__miniglx_StartServer( const char *display_name )
1057
 
{
1058
 
   Display *dpy;
1059
 
   int use_vt = 0;
1060
 
 
1061
 
   pci_system_init();
1062
 
 
1063
 
   dpy = (Display *)calloc(1, sizeof(Display));
1064
 
   if (!dpy)
1065
 
      return NULL;
1066
 
 
1067
 
   dpy->IsClient = False;
1068
 
 
1069
 
   if (!__read_config_file( dpy )) {
1070
 
      fprintf(stderr, "Couldn't get configuration details\n");
1071
 
      free(dpy);
1072
 
      return NULL;
1073
 
   }
1074
 
 
1075
 
   /* Open the fbdev device
1076
 
    */
1077
 
   if (!OpenFBDev(dpy, use_vt)) {
1078
 
      fprintf(stderr, "OpenFBDev failed\n");
1079
 
      free(dpy);
1080
 
      return NULL;
1081
 
   }
1082
 
 
1083
 
   if (!InitDriver(dpy)) {
1084
 
      fprintf(stderr, "InitDriver failed\n");
1085
 
      free(dpy);
1086
 
      return NULL;
1087
 
   }
1088
 
 
1089
 
   /* Perform the initialization normally done in the X server 
1090
 
    */
1091
 
   if (!dpy->driver->initFBDev( &dpy->driverContext )) {
1092
 
      fprintf(stderr, "%s: __driInitFBDev failed\n", __FUNCTION__);
1093
 
      dlclose(dpy->dlHandle);
1094
 
      return GL_FALSE;
1095
 
   }
1096
 
 
1097
 
   /* do fbdev setup
1098
 
    */
1099
 
   if (!SetupFBDev(dpy)) {
1100
 
      fprintf(stderr, "SetupFBDev failed\n");
1101
 
      free(dpy);
1102
 
      return NULL;
1103
 
   }
1104
 
 
1105
 
   /* unlock here if not using VT -- JDS */
1106
 
   if (!use_vt) {
1107
 
       if (dpy->driver->restoreHardware)
1108
 
           dpy->driver->restoreHardware( &dpy->driverContext ); 
1109
 
       DRM_UNLOCK( dpy->driverContext.drmFD,
1110
 
                   dpy->driverContext.pSAREA,
1111
 
                   dpy->driverContext.serverContext );
1112
 
       dpy->hwActive = 1;
1113
 
   }
1114
 
 
1115
 
   /* Ready for clients:
1116
 
    */
1117
 
   if (!__miniglx_open_connections(dpy)) {
1118
 
      free(dpy);
1119
 
      return NULL;
1120
 
   }
1121
 
      
1122
 
   return dpy;
1123
 
}
1124
 
 
1125
 
 
1126
 
/**
1127
 
 * Implement \c __DRIinterfaceMethods::getProcAddress.
1128
 
 */
1129
 
static __DRIfuncPtr get_proc_address( const char * proc_name )
1130
 
{
1131
 
    (void) proc_name;
1132
 
    return NULL;
1133
 
}
1134
 
 
1135
 
 
1136
 
/**
1137
 
 * Table of functions exported by the loader to the driver.
1138
 
 */
1139
 
static const __DRIinterfaceMethods interface_methods = {
1140
 
    get_proc_address,
1141
 
 
1142
 
    _gl_context_modes_create,
1143
 
    _gl_context_modes_destroy,
1144
 
      
1145
 
    __glXFindDRIScreen,
1146
 
    __glXWindowExists,
1147
 
      
1148
 
    __glXCreateContextWithConfig,
1149
 
    xf86DRI_DestroyContext,
1150
 
 
1151
 
    xf86DRI_CreateDrawable,
1152
 
    xf86DRI_DestroyDrawable,
1153
 
    __glXGetDrawableInfo,
1154
 
 
1155
 
    __glXGetUST,
1156
 
    __glXGetMscRate,
1157
 
};
1158
 
 
1159
 
 
1160
 
static void *
1161
 
CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc)
1162
 
{
1163
 
    void *psp = NULL;
1164
 
    drm_handle_t hSAREA;
1165
 
    drmAddress pSAREA;
1166
 
    const char *BusID;
1167
 
    int   i;
1168
 
    __DRIversion   ddx_version;
1169
 
    __DRIversion   dri_version;
1170
 
    __DRIversion   drm_version;
1171
 
    __DRIframebuffer  framebuffer;
1172
 
    int   fd = -1;
1173
 
    int   status;
1174
 
    const char * err_msg;
1175
 
    const char * err_extra;
1176
 
    drmVersionPtr version;
1177
 
    drm_handle_t  hFB;
1178
 
    drm_magic_t magic;
1179
 
 
1180
 
 
1181
 
    hSAREA = dpy->driverContext.shared.hSAREA;
1182
 
    BusID = dpy->driverContext.pciBusID;
1183
 
 
1184
 
    fd = drmOpen(NULL, BusID);
1185
 
 
1186
 
    err_msg = "open DRM";
1187
 
    err_extra = strerror( -fd );
1188
 
 
1189
 
    if (fd < 0) goto done;
1190
 
 
1191
 
    err_msg = "drmGetMagic";
1192
 
    err_extra = NULL;
1193
 
 
1194
 
    if (drmGetMagic(fd, &magic)) goto done;
1195
 
    
1196
 
    dpy->authorized = False;
1197
 
    send_char_msg( dpy, 0, _Authorize );
1198
 
    send_msg( dpy, 0, &magic, sizeof(magic));
1199
 
    
1200
 
    /* force net buffer flush */
1201
 
    while (!dpy->authorized)
1202
 
      handle_fd_events( dpy, 0 );
1203
 
 
1204
 
    version = drmGetVersion(fd);
1205
 
    if (version) {
1206
 
        drm_version.major = version->version_major;
1207
 
        drm_version.minor = version->version_minor;
1208
 
        drm_version.patch = version->version_patchlevel;
1209
 
        drmFreeVersion(version);
1210
 
    }
1211
 
    else {
1212
 
        drm_version.major = -1;
1213
 
        drm_version.minor = -1;
1214
 
        drm_version.patch = -1;
1215
 
    }
1216
 
 
1217
 
    /*
1218
 
     * Get device name (like "tdfx") and the ddx version numbers.
1219
 
     * We'll check the version in each DRI driver's "createScreen"
1220
 
     * function.
1221
 
     */
1222
 
    ddx_version.major = -1;
1223
 
    ddx_version.minor = 0;
1224
 
    ddx_version.patch = 0;
1225
 
 
1226
 
    /*
1227
 
     * Get the DRI X extension version.
1228
 
     */
1229
 
    dri_version.major = 4;
1230
 
    dri_version.minor = 0;
1231
 
    dri_version.patch = 0;
1232
 
 
1233
 
    /*
1234
 
     * Get device-specific info.  pDevPriv will point to a struct
1235
 
     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1236
 
     * that has information about the screen size, depth, pitch,
1237
 
     * ancilliary buffers, DRM mmap handles, etc.
1238
 
     */
1239
 
    hFB = dpy->driverContext.shared.hFrameBuffer;
1240
 
    framebuffer.size = dpy->driverContext.shared.fbSize;
1241
 
    framebuffer.stride = dpy->driverContext.shared.fbStride;
1242
 
    framebuffer.dev_priv_size = dpy->driverContext.driverClientMsgSize;
1243
 
    framebuffer.dev_priv = dpy->driverContext.driverClientMsg;
1244
 
    framebuffer.width = dpy->driverContext.shared.virtualWidth;
1245
 
    framebuffer.height = dpy->driverContext.shared.virtualHeight;
1246
 
 
1247
 
    /*
1248
 
     * Map the framebuffer region.
1249
 
     */
1250
 
    status = drmMap(fd, hFB, framebuffer.size, 
1251
 
            (drmAddressPtr)&framebuffer.base);
1252
 
 
1253
 
    err_msg = "drmMap of framebuffer";
1254
 
    err_extra = strerror( -status );
1255
 
 
1256
 
    if ( status != 0 ) goto done;
1257
 
 
1258
 
    /*
1259
 
     * Map the SAREA region.  Further mmap regions may be setup in
1260
 
     * each DRI driver's "createScreen" function.
1261
 
     */
1262
 
    status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
1263
 
 
1264
 
    err_msg = "drmMap of sarea";
1265
 
    err_extra = strerror( -status );
1266
 
 
1267
 
    if ( status == 0 ) {
1268
 
        err_msg = "InitDriver";
1269
 
        err_extra = NULL;
1270
 
        psp = dpy->createNewScreen(dpy, scrn, psc, NULL,
1271
 
                & ddx_version,
1272
 
                & dri_version,
1273
 
                & drm_version,
1274
 
                & framebuffer,
1275
 
                pSAREA,
1276
 
                fd,
1277
 
                20050727,
1278
 
                & interface_methods,
1279
 
                (__GLcontextModes **) &dpy->driver_modes);
1280
 
 
1281
 
        /* fill in dummy visual ids */
1282
 
        {
1283
 
          __GLcontextModes *temp;
1284
 
          temp = (__GLcontextModes *)dpy->driver_modes;
1285
 
          i = 1;
1286
 
          while (temp)
1287
 
          {
1288
 
            temp->visualID = i++;
1289
 
            temp=temp->next;
1290
 
          }
1291
 
        }
1292
 
    }
1293
 
    
1294
 
done:
1295
 
    if ( psp == NULL ) {
1296
 
        if ( pSAREA != MAP_FAILED ) {
1297
 
            (void)drmUnmap(pSAREA, SAREA_MAX);
1298
 
        }
1299
 
 
1300
 
        if ( framebuffer.base != MAP_FAILED ) {
1301
 
            (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
1302
 
        }
1303
 
 
1304
 
        if ( framebuffer.dev_priv != NULL ) {
1305
 
            free(framebuffer.dev_priv);
1306
 
        }
1307
 
 
1308
 
        if ( fd >= 0 ) {
1309
 
            (void)drmClose(fd);
1310
 
        }
1311
 
 
1312
 
        if ( err_extra != NULL ) {
1313
 
            fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
1314
 
                    err_extra);
1315
 
        }
1316
 
        else {
1317
 
            fprintf(stderr, "libGL error: %s failed\n", err_msg );
1318
 
        }
1319
 
 
1320
 
        fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
1321
 
    }
1322
 
 
1323
 
    return psp;
1324
 
}
1325
 
 
1326
 
/**
1327
 
 * \brief Initialize the graphics system.
1328
 
 * 
1329
 
 * \param display_name currently ignored. It is recommended to pass it as NULL.
1330
 
 * \return a pointer to a #Display if the function is able to initialize
1331
 
 * the graphics system, NULL otherwise.
1332
 
 * 
1333
 
 * Allocates a MiniGLXDisplayRec structure and fills in with information from a
1334
 
 * configuration file. 
1335
 
 *
1336
 
 * Calls __miniglx_open_connections() to connect to the server.
1337
 
 * 
1338
 
 * Loads the DRI driver and pulls in Mini GLX specific hooks into a
1339
 
 * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
1340
 
 * Asks the driver for a list of supported visuals.  Performs the per-screen
1341
 
 * client-side initialization.  Also setups the callbacks in the screen private
1342
 
 * information.
1343
 
 *
1344
 
 * \todo
1345
 
 *   - read config file
1346
 
 *      - what about virtualWidth, etc?
1347
 
 *   - determine dpy->driverClientMsgSize,
1348
 
 *   - allocate dpy->driverClientMsg
1349
 
 */
1350
 
Display *
1351
 
XOpenDisplay( const char *display_name )
1352
 
{
1353
 
   Display *dpy;
1354
 
 
1355
 
   dpy = (Display *)calloc(1, sizeof(Display));
1356
 
   if (!dpy)
1357
 
      return NULL;
1358
 
 
1359
 
   dpy->IsClient = True;
1360
 
 
1361
 
   /* read config file 
1362
 
    */
1363
 
   if (!__read_config_file( dpy )) {
1364
 
      fprintf(stderr, "Couldn't get configuration details\n");
1365
 
      free(dpy);
1366
 
      return NULL;
1367
 
   }
1368
 
 
1369
 
   /* Connect to the server and receive driverClientMsg
1370
 
    */
1371
 
   if (!__miniglx_open_connections(dpy)) {
1372
 
      free(dpy);
1373
 
      return NULL;
1374
 
   }
1375
 
 
1376
 
   /* dlopen the driver .so file
1377
 
    */
1378
 
   if (!InitDriver(dpy)) {
1379
 
      fprintf(stderr, "InitDriver failed\n");
1380
 
      free(dpy);
1381
 
      return NULL;
1382
 
   }
1383
 
 
1384
 
   /* Perform the client-side initialization.  
1385
 
    *
1386
 
    * Clearly there is a limit of one on the number of windows in
1387
 
    * existence at any time.
1388
 
    *
1389
 
    * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
1390
 
    */
1391
 
   dpy->driScreen.private = CallCreateNewScreen(dpy, 0, &dpy->driScreen);
1392
 
   if (!dpy->driScreen.private) {
1393
 
      fprintf(stderr, "%s: __driCreateScreen failed\n", __FUNCTION__);
1394
 
      dlclose(dpy->dlHandle);
1395
 
      free(dpy);
1396
 
      return NULL;
1397
 
   }
1398
 
   
1399
 
   /* Anything more to do?
1400
 
    */
1401
 
   return dpy;
1402
 
}
1403
 
 
1404
 
 
1405
 
/**
1406
 
 * \brief Release display resources.
1407
 
 * 
1408
 
 * When the application is about to exit, the resources associated with the
1409
 
 * graphics system can be released by calling this function.
1410
 
 * 
1411
 
 * \param dpy display handle. It becomes invalid at this point.
1412
 
 * 
1413
 
 * Destroys the window if any, and destroys the per-screen
1414
 
 * driver private information.
1415
 
 * Calls __miniglx_close_connections().
1416
 
 * 
1417
 
 * If a server, puts the the framebuffer back into the initial state.
1418
 
 *
1419
 
 * Finally frees the display structure.
1420
 
 */
1421
 
void
1422
 
XCloseDisplay( Display *dpy )
1423
 
{
1424
 
   glXMakeCurrent( dpy, NULL, NULL);
1425
 
 
1426
 
   if (dpy->NumWindows) 
1427
 
      XDestroyWindow( dpy, dpy->TheWindow );
1428
 
 
1429
 
   /* As this is done in XOpenDisplay, need to undo it here:
1430
 
    */
1431
 
   dpy->driScreen.destroyScreen(dpy, 0, dpy->driScreen.private);
1432
 
 
1433
 
   __miniglx_close_connections( dpy );
1434
 
 
1435
 
   if (!dpy->IsClient) {
1436
 
      /* put framebuffer back to initial state 
1437
 
       */
1438
 
      (*dpy->driver->haltFBDev)( &dpy->driverContext );
1439
 
      RestoreFBDev(dpy);
1440
 
      CloseFBDev(dpy);
1441
 
   }
1442
 
 
1443
 
   dlclose(dpy->dlHandle);
1444
 
   free(dpy);
1445
 
}
1446
 
 
1447
 
 
1448
 
/**
1449
 
 * \brief Window creation.
1450
 
 *
1451
 
 * \param display a display handle, as returned by XOpenDisplay().
1452
 
 * \param parent the parent window for the new window. For Mini GLX this should
1453
 
 * be 
1454
 
 * \code RootWindow(display, 0) \endcode
1455
 
 * \param x the window abscissa. For Mini GLX, it should be zero.
1456
 
 * \param y the window ordinate. For Mini GLX, it should be zero.
1457
 
 * \param width the window width. For Mini GLX, this specifies the desired
1458
 
 * screen width such as 1024 or 1280. 
1459
 
 * \param height the window height. For Mini GLX, this specifies the desired
1460
 
 * screen height such as 768 or 1024.
1461
 
 * \param border_width the border width. For Mini GLX, it should be zero.
1462
 
 * \param depth the window pixel depth. For Mini GLX, this should be the depth
1463
 
 * found in the #XVisualInfo object returned by glXChooseVisual() 
1464
 
 * \param winclass the window class. For Mini GLX this value should be
1465
 
 * #InputOutput.
1466
 
 * \param visual the visual type. It should be the visual field of the
1467
 
 * #XVisualInfo object returned by glXChooseVisual().
1468
 
 * \param valuemask which fields of the XSetWindowAttributes() are to be used.
1469
 
 * For Mini GLX this is typically the bitmask 
1470
 
 * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
1471
 
 * \param attributes initial window attributes. The
1472
 
 * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
1473
 
 * and XSetWindowAttributes::colormap fields should be set.
1474
 
 *
1475
 
 * \return a window handle if it succeeds or zero if it fails.
1476
 
 * 
1477
 
 * \note For Mini GLX, windows are full-screen; they cover the entire frame
1478
 
 * buffer.  Also, Mini GLX imposes a limit of one window. A second window
1479
 
 * cannot be created until the first one is destroyed.
1480
 
 *
1481
 
 * This function creates and initializes a ::MiniGLXWindowRec structure after
1482
 
 * ensuring that there is no other window created.  Performs the per-drawable
1483
 
 * client-side initialization calling the __DRIscreenRec::createDrawable
1484
 
 * method.
1485
 
 * 
1486
 
 */
1487
 
Window
1488
 
XCreateWindow( Display *dpy, Window parent, int x, int y,
1489
 
               unsigned int width, unsigned int height,
1490
 
               unsigned int border_width, int depth, unsigned int winclass,
1491
 
               Visual *visual, unsigned long valuemask,
1492
 
               XSetWindowAttributes *attributes )
1493
 
{
1494
 
   const int empty_attribute_list[1] = { None };
1495
 
 
1496
 
   Window win;
1497
 
 
1498
 
   /* ignored */
1499
 
   (void) x;
1500
 
   (void) y;
1501
 
   (void) border_width;
1502
 
   (void) depth;
1503
 
   (void) winclass;
1504
 
   (void) valuemask;
1505
 
   (void) attributes;
1506
 
 
1507
 
   if (!dpy->IsClient) {
1508
 
      fprintf(stderr, "Server process may not create windows (currently)\n");
1509
 
      return NULL;
1510
 
   }
1511
 
 
1512
 
   if (dpy->NumWindows > 0)
1513
 
      return NULL;  /* only allow one window */
1514
 
 
1515
 
   assert(dpy->TheWindow == NULL);
1516
 
 
1517
 
   win = malloc(sizeof(struct MiniGLXWindowRec));
1518
 
   if (!win)
1519
 
      return NULL;
1520
 
 
1521
 
   /* In rotated mode, translate incoming x,y,width,height into
1522
 
    * 'normal' coordinates.
1523
 
    */
1524
 
   if (dpy->rotateMode) {
1525
 
      int tmp;
1526
 
      tmp = width; width = height; height = tmp;
1527
 
      tmp = x; x = y; y = tmp;
1528
 
   }
1529
 
 
1530
 
   /* init other per-window fields */
1531
 
   win->x = x;
1532
 
   win->y = y;
1533
 
   win->w = width;
1534
 
   win->h = height;
1535
 
   win->visual = visual;  /* ptr assignment */
1536
 
 
1537
 
   win->bytesPerPixel = dpy->driverContext.cpp;
1538
 
   win->rowStride = dpy->driverContext.shared.virtualWidth * win->bytesPerPixel;
1539
 
   win->size = win->rowStride * height; 
1540
 
   win->frontStart = dpy->driverContext.FBAddress + (win->rowStride * win->x) + (win->y * win->bytesPerPixel);
1541
 
   win->frontBottom = (GLubyte *) win->frontStart + (height-1) * win->rowStride;
1542
 
 
1543
 
   /* This is incorrect: the hardware driver could put the backbuffer
1544
 
    * just about anywhere.  These fields, including the above are
1545
 
    * hardware dependent & don't really belong here.
1546
 
    */
1547
 
   if (visual->mode->doubleBufferMode) {
1548
 
      win->backStart = (GLubyte *) win->frontStart +
1549
 
         win->rowStride * dpy->driverContext.shared.virtualHeight;
1550
 
      win->backBottom = (GLubyte *) win->backStart
1551
 
         + (height - 1) * win->rowStride;
1552
 
      win->curBottom = win->backBottom;
1553
 
   }
1554
 
   else {
1555
 
      /* single buffered */
1556
 
      win->backStart = NULL;
1557
 
      win->backBottom = NULL;
1558
 
      win->curBottom = win->frontBottom;
1559
 
   }
1560
 
 
1561
 
   dpy->driScreen.createNewDrawable(dpy, visual->mode, (int) win,
1562
 
           &win->driDrawable, GLX_WINDOW_BIT, empty_attribute_list);
1563
 
 
1564
 
   if (!win->driDrawable.private) {
1565
 
      fprintf(stderr, "%s: dri.createDrawable failed\n", __FUNCTION__);
1566
 
      free(win);
1567
 
      return NULL;
1568
 
   }
1569
 
 
1570
 
   dpy->NumWindows++;
1571
 
   dpy->TheWindow = win;
1572
 
 
1573
 
   return win; 
1574
 
}
1575
 
 
1576
 
 
1577
 
/**
1578
 
 * \brief Destroy window.
1579
 
 *
1580
 
 * \param display display handle.
1581
 
 * \param w window handle.
1582
 
 *
1583
 
 * This function calls XUnmapWindow() and frees window \p w.
1584
 
 * 
1585
 
 * In case of destroying the current buffer first unbinds the GLX context
1586
 
 * by calling glXMakeCurrent() with no drawable.
1587
 
 */
1588
 
void
1589
 
XDestroyWindow( Display *display, Window win )
1590
 
{
1591
 
   if (display && display->IsClient && win) {
1592
 
      /* check if destroying the current buffer */
1593
 
      Window curDraw = glXGetCurrentDrawable();
1594
 
      if (win == curDraw) {
1595
 
         glXMakeCurrent( display, NULL, NULL);
1596
 
      }
1597
 
 
1598
 
      XUnmapWindow( display, win );
1599
 
 
1600
 
      /* Destroy the drawable. */
1601
 
      win->driDrawable.destroyDrawable(display, win->driDrawable.private);
1602
 
      free(win);
1603
 
      
1604
 
      /* unlink window from display */
1605
 
      display->NumWindows--;
1606
 
      assert(display->NumWindows == 0);
1607
 
      display->TheWindow = NULL;
1608
 
   }
1609
 
}
1610
 
 
1611
 
 
1612
 
 
1613
 
 
1614
 
/**
1615
 
 * \brief Create color map structure.
1616
 
 *
1617
 
 * \param dpy the display handle as returned by XOpenDisplay().
1618
 
 * \param w the window on whose screen you want to create a color map. This
1619
 
 * parameter is ignored by Mini GLX but should be the value returned by the
1620
 
 * \code RootWindow(display, 0) \endcode macro.
1621
 
 * \param visual a visual type supported on the screen. This parameter is
1622
 
 * ignored by Mini GLX but should be the XVisualInfo::visual returned by
1623
 
 * glXChooseVisual().
1624
 
 * \param alloc the color map entries to be allocated. This parameter is ignored
1625
 
 * by Mini GLX but should be set to #AllocNone.
1626
 
 *
1627
 
 * \return the color map.
1628
 
 * 
1629
 
 * This function is only provided to ease porting.  Practically a no-op -
1630
 
 * returns a pointer to a dynamically allocated chunk of memory (one byte).
1631
 
 */
1632
 
Colormap
1633
 
XCreateColormap( Display *dpy, Window w, Visual *visual, int alloc )
1634
 
{
1635
 
   (void) dpy;
1636
 
   (void) w;
1637
 
   (void) visual;
1638
 
   (void) alloc;
1639
 
   return (Colormap) malloc(1);
1640
 
}
1641
 
 
1642
 
 
1643
 
/**
1644
 
 * \brief Destroy color map structure.
1645
 
 *
1646
 
 * \param display The display handle as returned by XOpenDisplay().
1647
 
 * \param colormap the color map to destroy.
1648
 
 *
1649
 
 * This function is only provided to ease porting.  Practically a no-op. 
1650
 
 *
1651
 
 * Frees the memory pointed by \p colormap.
1652
 
 */
1653
 
void
1654
 
XFreeColormap( Display *display, Colormap colormap )
1655
 
{
1656
 
   (void) display;
1657
 
   (void) colormap;
1658
 
   free(colormap);
1659
 
}
1660
 
 
1661
 
 
1662
 
/**
1663
 
 * \brief Free client data.
1664
 
 *
1665
 
 * \param data the data that is to be freed.
1666
 
 *
1667
 
 * Frees the memory pointed by \p data.
1668
 
 */
1669
 
void
1670
 
XFree( void *data )
1671
 
{
1672
 
   free(data);
1673
 
}
1674
 
 
1675
 
 
1676
 
/**
1677
 
 * \brief Query available visuals.
1678
 
 *
1679
 
 * \param dpy the display handle, as returned by XOpenDisplay().
1680
 
 * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
1681
 
 * are to be matched.  The value must be \c VisualScreenMask.
1682
 
 * \param vinfo_template a template whose fields indicate which visual
1683
 
 * attributes must be matched by the results.  The XVisualInfo::screen field of
1684
 
 * this structure must be zero.
1685
 
 * \param nitens_return will hold the number of visuals returned.
1686
 
 *
1687
 
 * \return the address of an array of all available visuals.
1688
 
 * 
1689
 
 * An example of using XGetVisualInfo() to get all available visuals follows:
1690
 
 * 
1691
 
 * \code
1692
 
 * XVisualInfo vinfo_template, *results;
1693
 
 * int nitens_return;
1694
 
 * Display *dpy = XOpenDisplay(NULL);
1695
 
 * vinfo_template.screen = 0;
1696
 
 * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
1697
 
 * \endcode
1698
 
 * 
1699
 
 * Returns the list of all ::XVisualInfo available, one per
1700
 
 * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
1701
 
 */
1702
 
XVisualInfo *
1703
 
XGetVisualInfo( Display *dpy, long vinfo_mask, XVisualInfo *vinfo_template, int *nitens_return )
1704
 
{
1705
 
   const __GLcontextModes *mode;
1706
 
   XVisualInfo *results;
1707
 
   Visual *visResults;
1708
 
   int i, n=0;
1709
 
 
1710
 
   //   ASSERT(vinfo_mask == VisualScreenMask);
1711
 
   ASSERT(vinfo_template.screen == 0);
1712
 
 
1713
 
   if (vinfo_mask == VisualIDMask)
1714
 
   {
1715
 
     for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next )
1716
 
       if (mode->visualID == vinfo_template->visualid)
1717
 
         n=1;
1718
 
 
1719
 
     if (n==0)
1720
 
       return NULL;
1721
 
     
1722
 
     results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo));
1723
 
     if (!results) {
1724
 
       *nitens_return = 0;
1725
 
       return NULL;
1726
 
     }
1727
 
     
1728
 
     visResults = (Visual *)calloc(1, n * sizeof(Visual));
1729
 
     if (!results) {
1730
 
       free(results);
1731
 
       *nitens_return = 0;
1732
 
       return NULL;
1733
 
     }
1734
 
 
1735
 
     for ( mode = dpy->driver_modes ; mode != NULL ; mode= mode->next )
1736
 
       if (mode->visualID == vinfo_template->visualid)
1737
 
       {
1738
 
         visResults[0].mode=mode;
1739
 
         visResults[0].visInfo = results;
1740
 
         visResults[0].dpy = dpy;
1741
 
         if (dpy->driverContext.bpp == 32)
1742
 
           visResults[0].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */
1743
 
         else
1744
 
           visResults[0].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */
1745
 
       
1746
 
         results[0].visual = visResults;
1747
 
         results[0].visualid = mode->visualID;
1748
 
#if defined(__cplusplus) || defined(c_plusplus)
1749
 
         results[0].c_class = TrueColor;
1750
 
#else
1751
 
         results[0].class = TrueColor;
1752
 
#endif
1753
 
         results[0].depth = mode->redBits +
1754
 
           mode->redBits +
1755
 
           mode->redBits +
1756
 
           mode->redBits;
1757
 
         results[0].bits_per_rgb = dpy->driverContext.bpp;
1758
 
         
1759
 
       }
1760
 
     
1761
 
   }
1762
 
   else // if (vinfo_mask == VisualScreenMask)
1763
 
   {
1764
 
     n = 0;
1765
 
     for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next )
1766
 
       n++;
1767
 
     
1768
 
     results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo));
1769
 
     if (!results) {
1770
 
       *nitens_return = 0;
1771
 
       return NULL;
1772
 
     }
1773
 
     
1774
 
     visResults = (Visual *)calloc(1, n * sizeof(Visual));
1775
 
     if (!results) {
1776
 
       free(results);
1777
 
       *nitens_return = 0;
1778
 
       return NULL;
1779
 
     }
1780
 
     
1781
 
     for ( mode = dpy->driver_modes, i = 0 ; mode != NULL ; mode = mode->next, i++ ) {
1782
 
       visResults[i].mode = mode;
1783
 
       visResults[i].visInfo = results + i;
1784
 
       visResults[i].dpy = dpy;
1785
 
       
1786
 
       if (dpy->driverContext.bpp == 32)
1787
 
         visResults[i].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */
1788
 
       else
1789
 
         visResults[i].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */
1790
 
       
1791
 
       results[i].visual = visResults + i;
1792
 
       results[i].visualid = mode->visualID;
1793
 
#if defined(__cplusplus) || defined(c_plusplus)
1794
 
       results[i].c_class = TrueColor;
1795
 
#else
1796
 
       results[i].class = TrueColor;
1797
 
#endif
1798
 
       results[i].depth = mode->redBits +
1799
 
         mode->redBits +
1800
 
         mode->redBits +
1801
 
         mode->redBits;
1802
 
       results[i].bits_per_rgb = dpy->driverContext.bpp;
1803
 
     }
1804
 
   }
1805
 
   *nitens_return = n;
1806
 
   return results;
1807
 
}
1808
 
 
1809
 
 
1810
 
/**
1811
 
 * \brief Return a visual that matches specified attributes.
1812
 
 *
1813
 
 * \param dpy the display handle, as returned by XOpenDisplay().
1814
 
 * \param screen the screen number. It is currently ignored by Mini GLX and
1815
 
 * should be zero.
1816
 
 * \param attribList a list of GLX attributes which describe the desired pixel
1817
 
 * format. It is terminated by the token \c None. 
1818
 
 *
1819
 
 * The attributes are as follows:
1820
 
 * \arg GLX_USE_GL:
1821
 
 * This attribute should always be present in order to maintain compatibility
1822
 
 * with GLX.
1823
 
 * \arg GLX_RGBA:
1824
 
 * If present, only RGBA pixel formats will be considered. Otherwise, only
1825
 
 * color index formats are considered.
1826
 
 * \arg GLX_DOUBLEBUFFER:
1827
 
 * if present, only double-buffered pixel formats will be chosen.
1828
 
 * \arg GLX_RED_SIZE \e n:
1829
 
 * Must be followed by a non-negative integer indicating the minimum number of
1830
 
 * bits per red pixel component that is acceptable.
1831
 
 * \arg GLX_GREEN_SIZE \e n:
1832
 
 * Must be followed by a non-negative integer indicating the minimum number of
1833
 
 * bits per green pixel component that is acceptable.
1834
 
 * \arg GLX_BLUE_SIZE \e n:
1835
 
 * Must be followed by a non-negative integer indicating the minimum number of
1836
 
 * bits per blue pixel component that is acceptable.
1837
 
 * \arg GLX_ALPHA_SIZE \e n:
1838
 
 * Must be followed by a non-negative integer indicating the minimum number of
1839
 
 * bits per alpha pixel component that is acceptable.
1840
 
 * \arg GLX_STENCIL_SIZE \e n:
1841
 
 * Must be followed by a non-negative integer indicating the minimum number of
1842
 
 * bits per stencil value that is acceptable.
1843
 
 * \arg GLX_DEPTH_SIZE \e n:
1844
 
 * Must be followed by a non-negative integer indicating the minimum number of
1845
 
 * bits per depth component that is acceptable.
1846
 
 * \arg None:
1847
 
 * This token is used to terminate the attribute list.
1848
 
 *
1849
 
 * \return a pointer to an #XVisualInfo object which most closely matches the
1850
 
 * requirements of the attribute list. If there is no visual which matches the
1851
 
 * request, \c NULL will be returned.
1852
 
 *
1853
 
 * \note Visuals with accumulation buffers are not available.
1854
 
 *
1855
 
 * This function searches the list of available visual configurations in
1856
 
 * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
1857
 
 * attribute list parameter.  A new ::XVisualInfo object is created which
1858
 
 * describes the visual configuration.  The match criteria is described in the
1859
 
 * specification.
1860
 
 */
1861
 
XVisualInfo*
1862
 
glXChooseVisual( Display *dpy, int screen, int *attribList )
1863
 
{
1864
 
   const __GLcontextModes *mode;
1865
 
   Visual *vis;
1866
 
   XVisualInfo *visInfo;
1867
 
   const int *attrib;
1868
 
   GLboolean rgbFlag = GL_FALSE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
1869
 
   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
1870
 
   GLint indexBits = 0, depthBits = 0, stencilBits = 0;
1871
 
   GLint numSamples = 0;
1872
 
   int i=0;
1873
 
 
1874
 
   /*
1875
 
    * XXX in the future, <screen> might be interpreted as a VT
1876
 
    */
1877
 
   ASSERT(dpy);
1878
 
   ASSERT(screen == 0);
1879
 
 
1880
 
   vis = (Visual *)calloc(1, sizeof(Visual));
1881
 
   if (!vis)
1882
 
      return NULL;
1883
 
 
1884
 
   visInfo = (XVisualInfo *)malloc(sizeof(XVisualInfo));
1885
 
   if (!visInfo) {
1886
 
      free(vis);
1887
 
      return NULL;
1888
 
   }
1889
 
 
1890
 
   visInfo->visual = vis;
1891
 
   vis->visInfo = visInfo;
1892
 
   vis->dpy = dpy;
1893
 
 
1894
 
   /* parse the attribute list */
1895
 
   for (attrib = attribList; attrib && *attrib != None; attrib++) {
1896
 
      switch (attrib[0]) {
1897
 
      case GLX_DOUBLEBUFFER:
1898
 
         dbFlag = GL_TRUE;
1899
 
         break;
1900
 
      case GLX_RGBA:
1901
 
         rgbFlag = GL_TRUE;
1902
 
         break;
1903
 
      case GLX_RED_SIZE:
1904
 
         redBits = attrib[1];
1905
 
         attrib++;
1906
 
         break;
1907
 
      case GLX_GREEN_SIZE:
1908
 
         greenBits = attrib[1];
1909
 
         attrib++;
1910
 
         break;
1911
 
      case GLX_BLUE_SIZE:
1912
 
         blueBits = attrib[1];
1913
 
         attrib++;
1914
 
         break;
1915
 
      case GLX_ALPHA_SIZE:
1916
 
         alphaBits = attrib[1];
1917
 
         attrib++;
1918
 
         break;
1919
 
      case GLX_STENCIL_SIZE:
1920
 
         stencilBits = attrib[1];
1921
 
         attrib++;
1922
 
         break;
1923
 
      case GLX_DEPTH_SIZE:
1924
 
         depthBits = attrib[1];
1925
 
         attrib++;
1926
 
         break;
1927
 
#if 0
1928
 
      case GLX_ACCUM_RED_SIZE:
1929
 
         accumRedBits = attrib[1];
1930
 
         attrib++;
1931
 
         break;
1932
 
      case GLX_ACCUM_GREEN_SIZE:
1933
 
         accumGreenBits = attrib[1];
1934
 
         attrib++;
1935
 
         break;
1936
 
      case GLX_ACCUM_BLUE_SIZE:
1937
 
         accumBlueBits = attrib[1];
1938
 
         attrib++;
1939
 
         break;
1940
 
      case GLX_ACCUM_ALPHA_SIZE:
1941
 
         accumAlphaBits = attrib[1];
1942
 
         attrib++;
1943
 
         break;
1944
 
      case GLX_LEVEL:
1945
 
         /* ignored for now */
1946
 
         break;
1947
 
#endif
1948
 
      default:
1949
 
         /* unexpected token */
1950
 
         fprintf(stderr, "unexpected token in glXChooseVisual attrib list\n");
1951
 
         free(vis);
1952
 
         free(visInfo);
1953
 
         return NULL;
1954
 
      }
1955
 
   }
1956
 
 
1957
 
   /* search screen configs for suitable visual */
1958
 
   (void) numSamples;
1959
 
   (void) indexBits;
1960
 
   (void) redBits;
1961
 
   (void) greenBits;
1962
 
   (void) blueBits;
1963
 
   (void) alphaBits;
1964
 
   (void) stereoFlag;
1965
 
   for ( mode = dpy->driver_modes ; mode != NULL ; mode = mode->next ) {
1966
 
     i++;
1967
 
      if (mode->rgbMode == rgbFlag &&
1968
 
          mode->doubleBufferMode == dbFlag &&
1969
 
          mode->redBits >= redBits &&
1970
 
          mode->greenBits >= greenBits &&
1971
 
          mode->blueBits >= blueBits &&
1972
 
          mode->alphaBits >= alphaBits &&
1973
 
          mode->depthBits >= depthBits &&
1974
 
          mode->stencilBits >= stencilBits) {
1975
 
         /* found it */
1976
 
         visInfo->visualid = i;
1977
 
         vis->mode = mode;
1978
 
         break;
1979
 
      }          
1980
 
   }
1981
 
   if (!vis->mode)
1982
 
       return NULL;
1983
 
 
1984
 
   /* compute depth and bpp */
1985
 
   if (rgbFlag) {
1986
 
      /* XXX maybe support depth 16 someday */
1987
 
#if defined(__cplusplus) || defined(c_plusplus)
1988
 
      visInfo->c_class = TrueColor;
1989
 
#else
1990
 
      visInfo->class = TrueColor;
1991
 
#endif
1992
 
      visInfo->depth = dpy->driverContext.bpp;
1993
 
      visInfo->bits_per_rgb = dpy->driverContext.bpp;
1994
 
      if (dpy->driverContext.bpp == 32)
1995
 
         vis->pixelFormat = PF_B8G8R8A8;
1996
 
      else
1997
 
         vis->pixelFormat = PF_B5G6R5;
1998
 
   }
1999
 
   else {
2000
 
      /* color index mode */
2001
 
#if defined(__cplusplus) || defined(c_plusplus)
2002
 
      visInfo->c_class = PseudoColor;
2003
 
#else
2004
 
      visInfo->class = PseudoColor;
2005
 
#endif
2006
 
      visInfo->depth = 8;
2007
 
      visInfo->bits_per_rgb = 8;  /* bits/pixel */
2008
 
      vis->pixelFormat = PF_CI8;
2009
 
   }
2010
 
 
2011
 
   return visInfo;
2012
 
}
2013
 
 
2014
 
 
2015
 
/**
2016
 
 * \brief Return information about GLX visuals.
2017
 
 *
2018
 
 * \param dpy the display handle, as returned by XOpenDisplay().
2019
 
 * \param vis the visual to be queried, as returned by glXChooseVisual().
2020
 
 * \param attrib the visual attribute to be returned.
2021
 
 * \param value pointer to an integer in which the result of the query will be
2022
 
 * stored.
2023
 
 * 
2024
 
 * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
2025
 
 * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
2026
 
 * invalid.
2027
 
 *
2028
 
 * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
2029
 
 * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
2030
 
 *
2031
 
 * \sa data types.
2032
 
 */
2033
 
int
2034
 
glXGetConfig( Display *dpy, XVisualInfo *vis, int attrib, int *value )
2035
 
{
2036
 
   const __GLcontextModes *mode = vis->visual->mode;
2037
 
   if (!mode) {
2038
 
      *value = 0;
2039
 
      return GLX_BAD_VISUAL;
2040
 
   }
2041
 
 
2042
 
   switch (attrib) {
2043
 
   case GLX_USE_GL:
2044
 
      *value = True;
2045
 
      return 0;
2046
 
   case GLX_RGBA:
2047
 
      *value = mode->rgbMode;
2048
 
      return 0;
2049
 
   case GLX_DOUBLEBUFFER:
2050
 
      *value = mode->doubleBufferMode;
2051
 
      return 0;
2052
 
   case GLX_RED_SIZE:
2053
 
      *value = mode->redBits;
2054
 
      return 0;
2055
 
   case GLX_GREEN_SIZE:
2056
 
      *value = mode->greenBits;
2057
 
      return 0;
2058
 
   case GLX_BLUE_SIZE:
2059
 
      *value = mode->blueBits;
2060
 
      return 0;
2061
 
   case GLX_ALPHA_SIZE:
2062
 
      *value = mode->alphaBits;
2063
 
      return 0;
2064
 
   case GLX_DEPTH_SIZE:
2065
 
      *value = mode->depthBits;
2066
 
      return 0;
2067
 
   case GLX_STENCIL_SIZE:
2068
 
      *value = mode->stencilBits;
2069
 
      return 0;
2070
 
   default:
2071
 
      *value = 0;
2072
 
      return GLX_BAD_ATTRIBUTE;
2073
 
   }
2074
 
   return 0;
2075
 
}
2076
 
 
2077
 
 
2078
 
/**
2079
 
 * \brief Create a new GLX rendering context.
2080
 
 *
2081
 
 * \param dpy the display handle, as returned by XOpenDisplay().
2082
 
 * \param vis the visual that defines the frame buffer resources available to
2083
 
 * the rendering context, as returned by glXChooseVisual().
2084
 
 * \param shareList If non-zero, texture objects and display lists are shared
2085
 
 * with the named rendering context. If zero, texture objects and display lists
2086
 
 * will (initially) be private to this context. They may be shared when a
2087
 
 * subsequent context is created.
2088
 
 * \param direct whether direct or indirect rendering is desired. For Mini GLX
2089
 
 * this value is ignored but it should be set to \c True.
2090
 
 *
2091
 
 * \return a ::GLXContext handle if it succeeds or zero if it fails due to
2092
 
 * invalid parameter or insufficient resources.
2093
 
 *
2094
 
 * This function creates and initializes a ::MiniGLXContextRec structure and
2095
 
 * calls the __DRIscreenRec::createContext method to initialize the client
2096
 
 * private data.
2097
 
 */ 
2098
 
GLXContext
2099
 
glXCreateContext( Display *dpy, XVisualInfo *vis,
2100
 
                        GLXContext shareList, Bool direct )
2101
 
{
2102
 
   GLXContext ctx;
2103
 
   void *sharePriv;
2104
 
 
2105
 
   ASSERT(vis);
2106
 
 
2107
 
   ctx = (struct MiniGLXContextRec *)calloc(1, sizeof(struct MiniGLXContextRec));
2108
 
   if (!ctx)
2109
 
      return NULL;
2110
 
 
2111
 
   ctx->vid = vis->visualid;
2112
 
 
2113
 
   if (shareList)
2114
 
      sharePriv = shareList->driContext.private;
2115
 
   else
2116
 
      sharePriv = NULL;
2117
 
  
2118
 
   ctx->driContext.mode = vis->visual->mode;
2119
 
   ctx->driContext.private = dpy->driScreen.createNewContext(dpy, vis->visual->mode,
2120
 
           GLX_WINDOW_BIT, sharePriv, &ctx->driContext);
2121
 
 
2122
 
   if (!ctx->driContext.private) {
2123
 
      free(ctx);
2124
 
      return NULL;
2125
 
   }
2126
 
 
2127
 
   return ctx;
2128
 
}
2129
 
 
2130
 
 
2131
 
/**
2132
 
 * \brief Destroy a GLX context.
2133
 
 *
2134
 
 * \param dpy the display handle, as returned by XOpenDisplay().
2135
 
 * \param ctx the GLX context to be destroyed.
2136
 
 * 
2137
 
 * This function frees the \p ctx parameter after unbinding the current context
2138
 
 * by calling the __DRIcontextRec::bindContext method with zeros and calling
2139
 
 * the __DRIcontextRec::destroyContext method.
2140
 
 */
2141
 
void
2142
 
glXDestroyContext( Display *dpy, GLXContext ctx )
2143
 
{
2144
 
   GLXContext glxctx = glXGetCurrentContext();
2145
 
 
2146
 
   if (ctx) {
2147
 
      if (glxctx == ctx) {
2148
 
         /* destroying current context */
2149
 
         ctx->driContext.bindContext(dpy, 0, 0, 0, 0);
2150
 
         CurrentContext = 0;
2151
 
      }
2152
 
      ctx->driContext.destroyContext(dpy, 0, ctx->driContext.private);
2153
 
      free(ctx);
2154
 
   }
2155
 
}
2156
 
 
2157
 
 
2158
 
/**
2159
 
 * \brief Bind a GLX context to a window or a pixmap.
2160
 
 *
2161
 
 * \param dpy the display handle, as returned by XOpenDisplay().
2162
 
 * \param drawable the window or drawable to bind to the rendering context.
2163
 
 * This should be the value returned by XCreateWindow().
2164
 
 * \param ctx the GLX context to be destroyed.
2165
 
 *
2166
 
 * \return \c True if it succeeds, \c False otherwise to indicate an invalid
2167
 
 * display, window or context parameter.
2168
 
 *
2169
 
 * The current rendering context may be unbound by calling glXMakeCurrent()
2170
 
 * with the window and context parameters set to zero.
2171
 
 * 
2172
 
 * An application may create any number of rendering contexts and bind them as
2173
 
 * needed. Note that binding a rendering context is generally not a
2174
 
 * light-weight operation.  Most simple OpenGL applications create only one
2175
 
 * rendering context.
2176
 
 *
2177
 
 * This function first unbinds any old context via
2178
 
 * __DRIcontextRec::unbindContext and binds the new one via
2179
 
 * __DRIcontextRec::bindContext.
2180
 
 *
2181
 
 * If \p drawable is zero it unbinds the GLX context by calling
2182
 
 * __DRIcontextRec::bindContext with zeros.
2183
 
 */
2184
 
Bool
2185
 
glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx)
2186
 
{
2187
 
   if (dpy && drawable && ctx) {
2188
 
      GLXContext oldContext = glXGetCurrentContext();
2189
 
      GLXDrawable oldDrawable = glXGetCurrentDrawable();
2190
 
      /* unbind old */
2191
 
      if (oldContext) {
2192
 
         oldContext->driContext.unbindContext(dpy, 0,
2193
 
                 (__DRIid) oldDrawable, (__DRIid) oldDrawable,
2194
 
                 &oldContext->driContext);
2195
 
      }
2196
 
      /* bind new */
2197
 
      CurrentContext = ctx;
2198
 
      ctx->driContext.bindContext(dpy, 0, (__DRIid) drawable,
2199
 
              (__DRIid) drawable, &ctx->driContext);
2200
 
      ctx->drawBuffer = drawable;
2201
 
      ctx->curBuffer = drawable;
2202
 
   }
2203
 
   else if (ctx && dpy) {
2204
 
      /* unbind */
2205
 
      ctx->driContext.bindContext(dpy, 0, 0, 0, 0);
2206
 
   }
2207
 
   else if (dpy) {
2208
 
      CurrentContext = 0;       /* kw:  this seems to be intended??? */
2209
 
   }
2210
 
 
2211
 
   return True;
2212
 
}
2213
 
 
2214
 
 
2215
 
/**
2216
 
 * \brief Exchange front and back buffers.
2217
 
 * 
2218
 
 * \param dpy the display handle, as returned by XOpenDisplay().
2219
 
 * \param drawable the drawable whose buffers are to be swapped.
2220
 
 * 
2221
 
 * Any pending rendering commands will be completed before the buffer swap
2222
 
 * takes place.
2223
 
 * 
2224
 
 * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
2225
 
 *
2226
 
 * This function just calls the __DRIdrawableRec::swapBuffers method to do the
2227
 
 * work.
2228
 
 */
2229
 
void
2230
 
glXSwapBuffers( Display *dpy, GLXDrawable drawable )
2231
 
{
2232
 
   if (!dpy || !drawable)
2233
 
      return;
2234
 
 
2235
 
   drawable->driDrawable.swapBuffers(dpy, drawable->driDrawable.private);
2236
 
}
2237
 
 
2238
 
 
2239
 
/**
2240
 
 * \brief Return the current context
2241
 
 *
2242
 
 * \return the current context, as specified by glXMakeCurrent(), or zero if no
2243
 
 * context is currently bound.
2244
 
 *
2245
 
 * \sa glXCreateContext(), glXMakeCurrent()
2246
 
 *
2247
 
 * Returns the value of the ::CurrentContext global variable.
2248
 
 */
2249
 
GLXContext
2250
 
glXGetCurrentContext( void )
2251
 
{
2252
 
   return CurrentContext;
2253
 
}
2254
 
 
2255
 
 
2256
 
/**
2257
 
 * \brief Return the current drawable.
2258
 
 *
2259
 
 * \return the current drawable, as specified by glXMakeCurrent(), or zero if
2260
 
 * no drawable is currently bound.
2261
 
 *
2262
 
 * This function gets the current context via glXGetCurrentContext() and
2263
 
 * returns the MiniGLXContextRec::drawBuffer attribute.
2264
 
 */
2265
 
GLXDrawable
2266
 
glXGetCurrentDrawable( void )
2267
 
{
2268
 
   GLXContext glxctx = glXGetCurrentContext();
2269
 
   if (glxctx)
2270
 
      return glxctx->drawBuffer;
2271
 
   else
2272
 
      return NULL;
2273
 
}
2274
 
 
2275
 
 
2276
 
static GLboolean
2277
 
__glXCreateContextWithConfig(__DRInativeDisplay *dpy, int screen,
2278
 
        int fbconfigID, void *contextID, drm_context_t *hHWContext)
2279
 
{
2280
 
    __DRIscreen *pDRIScreen;
2281
 
    __DRIscreenPrivate *psp;
2282
 
 
2283
 
    pDRIScreen = __glXFindDRIScreen(dpy, screen);
2284
 
    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
2285
 
        return GL_FALSE;
2286
 
    }
2287
 
 
2288
 
    psp = (__DRIscreenPrivate *) pDRIScreen->private;
2289
 
 
2290
 
    if (psp->fd) {
2291
 
        if (drmCreateContext(psp->fd, hHWContext)) {
2292
 
            fprintf(stderr, ">>> drmCreateContext failed\n");
2293
 
            return GL_FALSE;
2294
 
        }
2295
 
        *(void**)contextID = (void*) *hHWContext;
2296
 
    }
2297
 
 
2298
 
    return GL_TRUE;
2299
 
}
2300
 
 
2301
 
 
2302
 
static GLboolean
2303
 
__glXGetDrawableInfo(__DRInativeDisplay *dpy, int scrn,
2304
 
        __DRIid draw, unsigned int * index, unsigned int * stamp,
2305
 
        int * x, int * y, int * width, int * height,
2306
 
        int * numClipRects, drm_clip_rect_t ** pClipRects,
2307
 
        int * backX, int * backY,
2308
 
        int * numBackClipRects, drm_clip_rect_t ** pBackClipRects)
2309
 
{
2310
 
    GLXDrawable drawable = (GLXDrawable) draw;
2311
 
    drm_clip_rect_t * cliprect;
2312
 
    Display* display = (Display*)dpy;
2313
 
    __DRIscreenPrivate *psp = display->driScreen.private;
2314
 
    __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)CurrentContext->driContext.private;
2315
 
    __DRIdrawablePrivate *pdp = pcp->driDrawablePriv;
2316
 
    if (drawable == 0) {
2317
 
        return GL_FALSE;
2318
 
    }
2319
 
 
2320
 
    cliprect = (drm_clip_rect_t*) _mesa_malloc(sizeof(drm_clip_rect_t));
2321
 
    cliprect->x1 = drawable->x;
2322
 
    cliprect->y1 = drawable->y;
2323
 
    cliprect->x2 = drawable->x + drawable->w;
2324
 
    cliprect->y2 = drawable->y + drawable->h;
2325
 
    
2326
 
    /* the drawable index is by client id */
2327
 
    *index = display->clientID;
2328
 
 
2329
 
    *stamp = pcp->driScreenPriv->pSAREA->drawableTable[display->clientID].stamp;
2330
 
    drmUpdateDrawableInfo(psp->fd, pdp->hHWDrawable, DRM_DRAWABLE_CLIPRECTS, 1, cliprect);
2331
 
    *x = drawable->x;
2332
 
    *y = drawable->y;
2333
 
    *width = drawable->w;
2334
 
    *height = drawable->h;
2335
 
    *numClipRects = 1;
2336
 
    *pClipRects = cliprect;
2337
 
    
2338
 
    *backX = drawable->x;
2339
 
    *backY = drawable->y;
2340
 
    *numBackClipRects = 0;
2341
 
    *pBackClipRects = 0;
2342
 
 
2343
 
    return GL_TRUE;
2344
 
}
2345
 
 
2346
 
 
2347
 
static GLboolean
2348
 
xf86DRI_DestroyContext(__DRInativeDisplay *dpy, int screen, __DRIid context_id )
2349
 
{
2350
 
    return GL_TRUE;
2351
 
}
2352
 
 
2353
 
 
2354
 
static GLboolean
2355
 
xf86DRI_CreateDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable,
2356
 
        drm_drawable_t *hHWDrawable )
2357
 
{
2358
 
 
2359
 
  Display *display = (Display *)dpy;
2360
 
  __DRIscreenPrivate *psp = display->driScreen.private;
2361
 
  int ret;
2362
 
  ret = drmCreateDrawable(psp->fd, hHWDrawable);
2363
 
  
2364
 
  fprintf(stderr, "drawable is %d %08X ret is %d\n", *hHWDrawable, drawable, -ret);
2365
 
  if (ret != 0)
2366
 
    return GL_FALSE;
2367
 
  return GL_TRUE;
2368
 
}
2369
 
 
2370
 
 
2371
 
static GLboolean
2372
 
xf86DRI_DestroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable)
2373
 
{
2374
 
  return GL_TRUE;
2375
 
}
2376
 
 
2377
 
 
2378
 
/**
2379
 
 * \brief Query function address.
2380
 
 *
2381
 
 * The glXGetProcAddress() function will return the address of any available
2382
 
 * OpenGL or Mini GLX function.
2383
 
 * 
2384
 
 * \param procName name of the function to be returned.
2385
 
 *
2386
 
 * \return If \p procName is a valid function name, a pointer to that function
2387
 
 * will be returned.  Otherwise, \c NULL will be returned.
2388
 
 *
2389
 
 * The purpose of glXGetProcAddress() is to facilitate using future extensions
2390
 
 * to OpenGL or Mini GLX. If a future version of the library adds new extension
2391
 
 * functions they'll be accessible via glXGetProcAddress(). The alternative is
2392
 
 * to hard-code calls to the new functions in the application but doing so will
2393
 
 * prevent linking the application with older versions of the library.
2394
 
 * 
2395
 
 * Returns the function address by looking up its name in a static (name,
2396
 
 * address) pair list.
2397
 
 */
2398
 
void (*glXGetProcAddress(const GLubyte *procname))( void ) 
2399
 
{
2400
 
   struct name_address {
2401
 
      const char *name;
2402
 
      const void *func;
2403
 
   };
2404
 
   static const struct name_address functions[] = {
2405
 
      { "glXChooseVisual", (void *) glXChooseVisual },
2406
 
      { "glXCreateContext", (void *) glXCreateContext },
2407
 
      { "glXDestroyContext", (void *) glXDestroyContext },
2408
 
      { "glXMakeCurrent", (void *) glXMakeCurrent },
2409
 
      { "glXSwapBuffers", (void *) glXSwapBuffers },
2410
 
      { "glXGetCurrentContext", (void *) glXGetCurrentContext },
2411
 
      { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable },
2412
 
      { "glXGetProcAddress", (void *) glXGetProcAddress },
2413
 
      { "XOpenDisplay", (void *) XOpenDisplay },
2414
 
      { "XCloseDisplay", (void *) XCloseDisplay },
2415
 
      { "XCreateWindow", (void *) XCreateWindow },
2416
 
      { "XDestroyWindow", (void *) XDestroyWindow },
2417
 
      { "XMapWindow", (void *) XMapWindow },
2418
 
      { "XCreateColormap", (void *) XCreateColormap },
2419
 
      { "XFreeColormap", (void *) XFreeColormap },
2420
 
      { "XFree", (void *) XFree },
2421
 
      { "XGetVisualinfo", (void *) XGetVisualInfo },
2422
 
      { "glXCreatePbuffer", (void *) glXCreatePbuffer },
2423
 
      { "glXDestroyPbuffer", (void *) glXDestroyPbuffer },
2424
 
      { "glXChooseFBConfig", (void *) glXChooseFBConfig },
2425
 
      { "glXGetVisualFromFBConfig", (void *) glXGetVisualFromFBConfig },
2426
 
      { NULL, NULL }
2427
 
   };
2428
 
   const struct name_address *entry;
2429
 
   for (entry = functions; entry->name; entry++) {
2430
 
      if (strcmp(entry->name, (const char *) procname) == 0) {
2431
 
         return entry->func;
2432
 
      }
2433
 
   }
2434
 
   return _glapi_get_proc_address((const char *) procname);
2435
 
}
2436
 
 
2437
 
void (*glXGetProcAddressARB(const GLubyte *procName))( void ) __attribute__ ((alias ("glXGetProcAddress")));
2438
 
 
2439
 
/**
2440
 
 * \brief Query the Mini GLX version.
2441
 
 *
2442
 
 * \param dpy the display handle. It is currently ignored, but should be the
2443
 
 * value returned by XOpenDisplay().
2444
 
 * \param major receives the major version number of Mini GLX.
2445
 
 * \param minor receives the minor version number of Mini GLX.
2446
 
 *
2447
 
 * \return \c True if the function succeeds, \c False if the function fails due
2448
 
 * to invalid parameters.
2449
 
 *
2450
 
 * \sa #MINI_GLX_VERSION_1_0.
2451
 
 * 
2452
 
 * Returns the hard-coded Mini GLX version.
2453
 
 */
2454
 
Bool
2455
 
glXQueryVersion( Display *dpy, int *major, int *minor )
2456
 
{
2457
 
   (void) dpy;
2458
 
   *major = 1;
2459
 
   *minor = 0;
2460
 
   return True;
2461
 
}
2462
 
 
2463
 
 
2464
 
/**
2465
 
 * \brief Create a new pbuffer.
2466
 
 */
2467
 
GLXPbuffer
2468
 
glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList )
2469
 
{
2470
 
   return NULL;
2471
 
}
2472
 
 
2473
 
 
2474
 
void
2475
 
glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2476
 
{
2477
 
   free(pbuf);
2478
 
}
2479
 
 
2480
 
 
2481
 
GLXFBConfig *
2482
 
glXChooseFBConfig( Display *dpy, int screen, const int *attribList,
2483
 
                   int *nitems )
2484
 
{
2485
 
   GLXFBConfig *f = (GLXFBConfig *) malloc(sizeof(GLXFBConfig));
2486
 
   f->visInfo = glXChooseVisual( dpy, screen, (int *) attribList );
2487
 
   if (f->visInfo) { 
2488
 
      *nitems = 1;
2489
 
      return f;
2490
 
   }
2491
 
   else {
2492
 
      *nitems = 0;
2493
 
      free(f);
2494
 
      return NULL;
2495
 
   }
2496
 
}
2497
 
 
2498
 
 
2499
 
XVisualInfo *
2500
 
glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
2501
 
{
2502
 
   /* XVisualInfo and GLXFBConfig are the same structure */
2503
 
   (void) dpy;
2504
 
   return config.visInfo;
2505
 
}
2506
 
 
2507
 
void *glXAllocateMemoryMESA(Display *dpy, int scrn,
2508
 
                            size_t size, float readFreq,
2509
 
                            float writeFreq, float priority)
2510
 
{
2511
 
    if (dpy->driScreen.private && dpy->driScreen.allocateMemory) {
2512
 
        return (*dpy->driScreen.allocateMemory)( dpy, scrn, size,
2513
 
                                                 readFreq, writeFreq,
2514
 
                                                 priority );
2515
 
    }
2516
 
 
2517
 
    return NULL;
2518
 
}
2519
 
 
2520
 
void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer)
2521
 
{
2522
 
    if (dpy->driScreen.private && dpy->driScreen.freeMemory) {
2523
 
        (*dpy->driScreen.freeMemory)( dpy, scrn, pointer );
2524
 
    }
2525
 
}
2526
 
 
2527
 
GLuint glXGetMemoryOffsetMESA( Display *dpy, int scrn,
2528
 
                               const void *pointer )
2529
 
{
2530
 
    if (dpy->driScreen.private && dpy->driScreen.memoryOffset) {
2531
 
        return (*dpy->driScreen.memoryOffset)( dpy, scrn, pointer );
2532
 
    }
2533
 
 
2534
 
    return 0;
2535
 
}
2536
 
 
2537
 
 
2538
 
/**
2539
 
 * Get the unadjusted system time (UST).  Currently, the UST is measured in
2540
 
 * microseconds since Epoc.  The actual resolution of the UST may vary from
2541
 
 * system to system, and the units may vary from release to release.
2542
 
 * Drivers should not call this function directly.  They should instead use
2543
 
 * \c glXGetProcAddress to obtain a pointer to the function.
2544
 
 *
2545
 
 * \param ust Location to store the 64-bit UST
2546
 
 * \returns Zero on success or a negative errno value on failure.
2547
 
 *
2548
 
 * \note
2549
 
 * This function was copied directly from src/glx/x11/glxcmds.c.
2550
 
 */
2551
 
static int __glXGetUST( int64_t * ust )
2552
 
{
2553
 
    struct timeval  tv;
2554
 
    
2555
 
    if ( ust == NULL ) {
2556
 
        return -EFAULT;
2557
 
    }
2558
 
 
2559
 
    if ( gettimeofday( & tv, NULL ) == 0 ) {
2560
 
        ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
2561
 
        return 0;
2562
 
    } else {
2563
 
        return -errno;
2564
 
    }
2565
 
}
2566
 
 
2567
 
 
2568
 
/**
2569
 
 * 
2570
 
 * \bug
2571
 
 * This needs to be implemented for miniGlx.
2572
 
 */
2573
 
static GLboolean __glXGetMscRate(__DRInativeDisplay * dpy, __DRIid drawable,
2574
 
                                 int32_t * numerator, int32_t * denominator)
2575
 
{
2576
 
    *numerator = 0;
2577
 
    *denominator = 0;
2578
 
    return False;
2579
 
}
2580
 
/*@}*/