1 /* simple glx driver for TinyGL */
5 #include <X11/extensions/XShm.h>
11 XVisualInfo visual_info
;
17 int do_convert
; /* true if must do convertion to X11 format */
20 XShmSegmentInfo
*shm_info
;
24 Bool
glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
30 XVisualInfo
* glXChooseVisual( Display
*dpy
, int screen
,
36 /* the attribList is ignored : we consider only RGBA rendering (no
39 if (XMatchVisualInfo (dpy
, screen
, 16, TrueColor
, &vinfo
)) {
40 /* 16 bit visual (fastest with TinyGL) */
41 } else if (XMatchVisualInfo (dpy
, screen
, 24, TrueColor
, &vinfo
)) {
43 } else if (XMatchVisualInfo (dpy
, screen
, 32, TrueColor
, &vinfo
)) {
45 } else if (XMatchVisualInfo (dpy
, screen
, 8, PseudoColor
, &vinfo
)) {
48 /* no suitable visual */
52 return XGetVisualInfo(dpy
,VisualAllMask
,&vinfo
,&n
);
57 GLXContext
glXCreateContext( Display
*dpy
, XVisualInfo
*vis
,
58 GLXContext shareList
, Bool direct
)
62 if (shareList
!= NULL
) {
63 gl_fatal_error("No sharing available in TinyGL");
65 ctx
=gl_malloc(sizeof(TinyGLXContext
));
67 ctx
->visual_info
=*vis
;
68 return (GLXContext
) ctx
;
72 void glXDestroyContext( Display
*dpy
, GLXContext ctx1
)
74 TinyGLXContext
*ctx
= (TinyGLXContext
*) ctx1
;
75 if (ctx
->gl_context
!= NULL
) {
82 static int glxXErrorFlag
=0;
84 static int glxHandleXError(Display
*dpy
,XErrorEvent
*event
)
90 static int bits_per_pixel(Display
*dpy
, XVisualInfo
*visinfo
)
98 return visinfo
->depth
;
100 img
= XCreateImage(dpy
, visinfo
->visual
, visinfo
->depth
,
101 ZPixmap
, 0, data
, 1, 1, 32, 0);
104 return visinfo
->depth
;
106 bpp
= img
->bits_per_pixel
;
113 static int create_ximage(TinyGLXContext
*ctx
,
114 int xsize
,int ysize
,int depth
)
118 unsigned char *framebuffer
;
119 int (*old_handler
)(Display
*,XErrorEvent
*);
121 if (XShmQueryVersion(ctx
->display
,&major
,&minor
,&pixmaps
))
126 if (!ctx
->shm_use
) goto no_shm
;
128 ctx
->shm_info
=gl_malloc(sizeof(XShmSegmentInfo
));
129 ctx
->ximage
=XShmCreateImage(ctx
->display
,None
,depth
,ZPixmap
,NULL
,
130 ctx
->shm_info
,xsize
,ysize
);
131 if (ctx
->ximage
== NULL
) {
132 fprintf(stderr
,"XShm: error: XShmCreateImage\n");
134 gl_free(ctx
->shm_info
);
137 ctx
->shm_info
->shmid
=shmget(IPC_PRIVATE
,
138 ctx
->ysize
*ctx
->ximage
->bytes_per_line
,
140 if (ctx
->shm_info
->shmid
< 0) {
141 fprintf(stderr
,"XShm: error: shmget\n");
144 XDestroyImage(ctx
->ximage
);
147 ctx
->ximage
->data
=shmat(ctx
->shm_info
->shmid
,0,0);
148 if (ctx
->ximage
->data
== (char *) -1) {
149 fprintf(stderr
,"XShm: error: shmat\n");
151 shmctl(ctx
->shm_info
->shmid
,IPC_RMID
,0);
154 ctx
->shm_info
->shmaddr
=ctx
->ximage
->data
;
156 ctx
->shm_info
->readOnly
=False
;
158 /* attach & test X errors */
161 old_handler
=XSetErrorHandler(glxHandleXError
);
162 XShmAttach(ctx
->display
,ctx
->shm_info
);
163 XSync(ctx
->display
, False
);
166 XFlush(ctx
->display
);
167 shmdt(ctx
->shm_info
->shmaddr
);
168 XSetErrorHandler(old_handler
);
172 /* the shared memory will be automatically deleted */
173 shmctl(ctx
->shm_info
->shmid
,IPC_RMID
,0);
175 /* test with a dummy XShmPutImage */
176 XShmPutImage(ctx
->display
,ctx
->drawable
,ctx
->gc
,
177 ctx
->ximage
,0,0,0,0,1,1,
180 XSync(ctx
->display
, False
);
181 XSetErrorHandler(old_handler
);
184 fprintf(stderr
,"XShm: error: XShmPutImage\n");
185 XFlush(ctx
->display
);
186 shmdt(ctx
->shm_info
->shmaddr
);
190 ctx
->CompletionType
=XShmGetEventBase(ctx
->display
) + ShmCompletion
;
191 /* shared memory is OK !! */
196 ctx
->ximage
=XCreateImage(ctx
->display
, None
, depth
, ZPixmap
, 0,
197 NULL
,xsize
,ysize
, 8, 0);
198 framebuffer
=gl_malloc(ysize
* ctx
->ximage
->bytes_per_line
);
199 ctx
->ximage
->data
= framebuffer
;
203 static void free_ximage(TinyGLXContext
*ctx
)
207 XShmDetach(ctx
->display
, ctx
->shm_info
);
208 XDestroyImage(ctx
->ximage
);
209 shmdt(ctx
->shm_info
->shmaddr
);
210 gl_free(ctx
->shm_info
);
212 gl_free(ctx
->ximage
->data
);
213 XDestroyImage(ctx
->ximage
);
217 /* resize the glx viewport : we try to use the xsize and ysize
218 given. We return the effective size which is guaranted to be smaller */
220 int glX_resize_viewport(GLContext
*c
,int *xsize_ptr
,int *ysize_ptr
)
225 ctx
=(TinyGLXContext
*)c
->opaque
;
230 /* we ensure that xsize and ysize are multiples of 2 for the zbuffer.
231 TODO: find a better solution */
235 if (xsize
== 0 || ysize
== 0) return -1;
240 if (ctx
->ximage
!= NULL
) free_ximage(ctx
);
245 if (create_ximage(ctx
,ctx
->xsize
,ctx
->ysize
,ctx
->visual_info
.depth
) != 0)
248 /* resize the Z buffer */
249 if (ctx
->do_convert
) {
250 ZB_resize(c
->zb
,NULL
,xsize
,ysize
);
252 ZB_resize(c
->zb
,ctx
->ximage
->data
,xsize
,ysize
);
257 /* we assume here that drawable is a window */
258 Bool
glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
,
261 TinyGLXContext
*ctx
= (TinyGLXContext
*) ctx1
;
262 XWindowAttributes attr
;
264 unsigned int palette
[ZB_NB_COLORS
];
265 unsigned char color_indexes
[ZB_NB_COLORS
];
268 unsigned long pixel
[ZB_NB_COLORS
],tmp_plane
;
270 if (ctx
->gl_context
== NULL
) {
271 /* create the TinyGL context */
274 ctx
->drawable
=drawable
;
276 XGetWindowAttributes(ctx
->display
,drawable
,&attr
);
281 if (attr
.depth
!= ctx
->visual_info
.depth
) return False
;
283 /* ximage structure */
285 ctx
->shm_use
=1; /* use shm */
287 if (attr
.depth
== 8) {
288 /* get the colormap from the window */
289 ctx
->cmap
= attr
.colormap
;
291 if ( XAllocColorCells(ctx
->display
,ctx
->cmap
,True
,&tmp_plane
,0,
292 pixel
,ZB_NB_COLORS
) == 0) {
294 ctx
->cmap
= XCreateColormap(ctx
->display
, drawable
,
295 ctx
->visual_info
.visual
, AllocAll
);
296 XSetWindowColormap(ctx
->display
, drawable
, ctx
->cmap
);
297 for(i
=0;i
<ZB_NB_COLORS
;i
++) pixel
[i
]=i
;
300 for(i
=0;i
<ZB_NB_COLORS
;i
++) color_indexes
[i
]=pixel
[i
];
302 /* Open the Z Buffer - 256 colors */
303 zb
=ZB_open(xsize
,ysize
,ZB_MODE_INDEX
,ZB_NB_COLORS
,
304 color_indexes
,palette
,NULL
);
306 fprintf(stderr
, "Error while initializing Z buffer\n");
310 for (i
=0; i
<ZB_NB_COLORS
; i
++) {
311 xcolor
.flags
= DoRed
| DoGreen
| DoBlue
;
313 xcolor
.red
= (palette
[i
]>>8) & 0xFF00;
314 xcolor
.green
= (palette
[i
] & 0xFF00);
315 xcolor
.blue
= (palette
[i
] << 8) & 0xFF00;
316 xcolor
.pixel
= pixel
[i
];
317 XStoreColor(ctx
->display
,ctx
->cmap
,&xcolor
);
323 bpp
= bits_per_pixel(ctx
->display
,&ctx
->visual_info
);
326 mode
= ZB_MODE_RGB24
;
327 ctx
->do_convert
= (TGL_FEATURE_RENDER_BITS
!= 16);
331 ctx
->do_convert
= (TGL_FEATURE_RENDER_BITS
!= 16);
334 mode
= ZB_MODE_5R6G5B
;
335 ctx
->do_convert
= (TGL_FEATURE_RENDER_BITS
!= 16);
338 zb
=ZB_open(xsize
,ysize
,mode
,0,NULL
,NULL
,NULL
);
340 fprintf(stderr
, "Error while initializing Z buffer\n");
346 ctx
->gc
= XCreateGC(ctx
->display
, drawable
, 0, 0);
348 /* initialisation of the TinyGL interpreter */
350 ctx
->gl_context
=gl_get_context();
351 ctx
->gl_context
->opaque
=(void *) ctx
;
352 ctx
->gl_context
->gl_resize_viewport
=glX_resize_viewport
;
354 /* set the viewport : we force a call to glX_resize_viewport */
355 ctx
->gl_context
->viewport
.xsize
=-1;
356 ctx
->gl_context
->viewport
.ysize
=-1;
358 glViewport(0, 0, xsize
, ysize
);
364 static Bool
WaitForShmCompletion(Display
*dpy
, XEvent
*event
, char *arg
)
366 TinyGLXContext
*ctx
=(TinyGLXContext
*) arg
;
368 return (event
->type
== ctx
->CompletionType
) &&
369 ( ((XShmCompletionEvent
*)event
)->drawable
== (Window
)ctx
->drawable
);
372 void glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
374 GLContext
*gl_context
;
377 /* retrieve the current GLXContext */
378 gl_context
=gl_get_context();
379 ctx
=(TinyGLXContext
*)gl_context
->opaque
;
381 /* for non 16 bits visuals, a conversion is required */
384 if (ctx
->do_convert
) {
385 ZB_copyFrameBuffer(ctx
->gl_context
->zb
,
387 ctx
->ximage
->bytes_per_line
);
391 /* draw the ximage */
395 XShmPutImage(dpy
,drawable
,ctx
->gc
,
396 ctx
->ximage
,0,0,0,0,ctx
->ximage
->width
, ctx
->ximage
->height
,
398 XIfEvent(dpy
, &event
, WaitForShmCompletion
, (char*)ctx
);
400 XPutImage(dpy
, drawable
, ctx
->gc
,
401 ctx
->ximage
, 0, 0, 0, 0, ctx
->ximage
->width
, ctx
->ximage
->height
);
407 void glXWaitGL( void )
411 void glXWaitX( void )