TinyGL 0.4.1 for MinGW
glx.c
Go to the documentation of this file.
1/* simple glx driver for TinyGL */
2#include <GL/glx.h>
3#include <sys/ipc.h>
4#include <sys/shm.h>
5#include <X11/extensions/XShm.h>
6#include "zgl.h"
7
8typedef struct {
10 Display *display;
11 XVisualInfo visual_info;
12 int xsize,ysize;
13 XImage *ximage;
14 GC gc;
15 Colormap cmap;
16 Drawable drawable;
17 int do_convert; /* true if must do convertion to X11 format */
18 /* shared memory */
20 XShmSegmentInfo *shm_info;
23
24Bool glXQueryExtension( Display *dpy, int *errorb, int *event )
25{
26 return True;
27}
28
29
30XVisualInfo* glXChooseVisual( Display *dpy, int screen,
31 int *attribList )
32{
33 XVisualInfo vinfo;
34 int n;
35
36 /* the attribList is ignored : we consider only RGBA rendering (no
37 direct color) */
38
39 if (XMatchVisualInfo (dpy, screen, 16, TrueColor, &vinfo)) {
40 /* 16 bit visual (fastest with TinyGL) */
41 } else if (XMatchVisualInfo (dpy, screen, 24, TrueColor, &vinfo)) {
42 /* 24 bit visual */
43 } else if (XMatchVisualInfo (dpy, screen, 32, TrueColor, &vinfo)) {
44 /* 32 bit visual */
45 } else if (XMatchVisualInfo (dpy, screen, 8, PseudoColor, &vinfo)) {
46 /* 8 bit visual */
47 } else {
48 /* no suitable visual */
49 return NULL;
50 }
51
52 return XGetVisualInfo(dpy,VisualAllMask,&vinfo,&n);
53}
54
55
56
57GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis,
58 GLXContext shareList, Bool direct )
59{
60 TinyGLXContext *ctx;
61
62 if (shareList != NULL) {
63 gl_fatal_error("No sharing available in TinyGL");
64 }
65 ctx=gl_malloc(sizeof(TinyGLXContext));
66 ctx->gl_context=NULL;
67 ctx->visual_info=*vis;
68 return (GLXContext) ctx;
69}
70
71
72void glXDestroyContext( Display *dpy, GLXContext ctx1 )
73{
74 TinyGLXContext *ctx = (TinyGLXContext *) ctx1;
75 if (ctx->gl_context != NULL) {
76 glClose();
77 }
78 gl_free(ctx);
79}
80
81
82static int glxXErrorFlag=0;
83
84static int glxHandleXError(Display *dpy,XErrorEvent *event)
85{
86 glxXErrorFlag=1;
87 return 0;
88}
89
90static int bits_per_pixel(Display *dpy, XVisualInfo *visinfo)
91{
92 XImage *img;
93 int bpp;
94 char *data;
95
96 data = gl_malloc(8);
97 if (data == NULL)
98 return visinfo->depth;
99
100 img = XCreateImage(dpy, visinfo->visual, visinfo->depth,
101 ZPixmap, 0, data, 1, 1, 32, 0);
102 if (img == NULL) {
103 gl_free(data);
104 return visinfo->depth;
105 }
106 bpp = img->bits_per_pixel;
107 gl_free(data);
108 img->data = NULL;
109 XDestroyImage(img);
110 return bpp;
111}
112
113static int create_ximage(TinyGLXContext *ctx,
114 int xsize,int ysize,int depth)
115{
116 int major,minor;
117 Bool pixmaps;
118 unsigned char *framebuffer;
119 int (*old_handler)(Display *,XErrorEvent *);
120
121 if (XShmQueryVersion(ctx->display,&major,&minor,&pixmaps))
122 ctx->shm_use=1;
123 else
124 ctx->shm_use=0;
125
126 if (!ctx->shm_use) goto no_shm;
127
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");
133 ctx->shm_use=0;
134 gl_free(ctx->shm_info);
135 goto no_shm;
136 }
137 ctx->shm_info->shmid=shmget(IPC_PRIVATE,
138 ctx->ysize*ctx->ximage->bytes_per_line,
139 IPC_CREAT | 0777);
140 if (ctx->shm_info->shmid < 0) {
141 fprintf(stderr,"XShm: error: shmget\n");
142 no_shm1:
143 ctx->shm_use=0;
144 XDestroyImage(ctx->ximage);
145 goto no_shm;
146 }
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");
150 no_shm2:
151 shmctl(ctx->shm_info->shmid,IPC_RMID,0);
152 goto no_shm1;
153 }
154 ctx->shm_info->shmaddr=ctx->ximage->data;
155
156 ctx->shm_info->readOnly=False;
157
158 /* attach & test X errors */
159
160 glxXErrorFlag=0;
161 old_handler=XSetErrorHandler(glxHandleXError);
162 XShmAttach(ctx->display,ctx->shm_info);
163 XSync(ctx->display, False);
164
165 if (glxXErrorFlag) {
166 XFlush(ctx->display);
167 shmdt(ctx->shm_info->shmaddr);
168 XSetErrorHandler(old_handler);
169 goto no_shm2;
170 }
171
172 /* the shared memory will be automatically deleted */
173 shmctl(ctx->shm_info->shmid,IPC_RMID,0);
174
175 /* test with a dummy XShmPutImage */
176 XShmPutImage(ctx->display,ctx->drawable,ctx->gc,
177 ctx->ximage,0,0,0,0,1,1,
178 False);
179
180 XSync(ctx->display, False);
181 XSetErrorHandler(old_handler);
182
183 if (glxXErrorFlag) {
184 fprintf(stderr,"XShm: error: XShmPutImage\n");
185 XFlush(ctx->display);
186 shmdt(ctx->shm_info->shmaddr);
187 goto no_shm2;
188 }
189
190 ctx->CompletionType=XShmGetEventBase(ctx->display) + ShmCompletion;
191 /* shared memory is OK !! */
192
193 return 0;
194
195 no_shm:
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 = (char *)framebuffer;
200 return 0;
201}
202
203static void free_ximage(TinyGLXContext *ctx)
204{
205 if (ctx->shm_use)
206 {
207 XShmDetach(ctx->display, ctx->shm_info);
208 XDestroyImage(ctx->ximage);
209 shmdt(ctx->shm_info->shmaddr);
210 gl_free(ctx->shm_info);
211 } else {
212 gl_free(ctx->ximage->data);
213 XDestroyImage(ctx->ximage);
214 }
215}
216
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 */
219
220int glX_resize_viewport(GLContext *c,int *xsize_ptr,int *ysize_ptr)
221{
222 TinyGLXContext *ctx;
223 int xsize,ysize;
224
225 ctx=(TinyGLXContext *)c->opaque;
226
227 xsize=*xsize_ptr;
228 ysize=*ysize_ptr;
229
230 /* we ensure that xsize and ysize are multiples of 2 for the zbuffer.
231 TODO: find a better solution */
232 xsize&=~3;
233 ysize&=~3;
234
235 if (xsize == 0 || ysize == 0) return -1;
236
237 *xsize_ptr=xsize;
238 *ysize_ptr=ysize;
239
240 if (ctx->ximage != NULL) free_ximage(ctx);
241
242 ctx->xsize=xsize;
243 ctx->ysize=ysize;
244
245 if (create_ximage(ctx,ctx->xsize,ctx->ysize,ctx->visual_info.depth) != 0)
246 return -1;
247
248 /* resize the Z buffer */
249 if (ctx->do_convert) {
250 ZB_resize(c->zb,NULL,xsize,ysize);
251 } else {
252 ZB_resize(c->zb,ctx->ximage->data,xsize,ysize);
253 }
254 return 0;
255}
256
257/* we assume here that drawable is a window */
258Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable,
259 GLXContext ctx1)
260{
261 TinyGLXContext *ctx = (TinyGLXContext *) ctx1;
262 XWindowAttributes attr;
263 int i,xsize,ysize;
264 int palette[ZB_NB_COLORS];
265 unsigned char color_indexes[ZB_NB_COLORS];
266 ZBuffer *zb;
267 XColor xcolor;
268 unsigned long pixel[ZB_NB_COLORS],tmp_plane;
269
270 if (ctx->gl_context == NULL) {
271 /* create the TinyGL context */
272
273 ctx->display=dpy;
274 ctx->drawable=drawable;
275
276 XGetWindowAttributes(ctx->display,drawable,&attr);
277
278 xsize=attr.width;
279 ysize=attr.height;
280
281 if (attr.depth != ctx->visual_info.depth) return False;
282
283 /* ximage structure */
284 ctx->ximage=NULL;
285 ctx->shm_use=1; /* use shm */
286
287 if (attr.depth == 8) {
288 /* get the colormap from the window */
289 ctx->cmap = attr.colormap;
290
291 if ( XAllocColorCells(ctx->display,ctx->cmap,True,&tmp_plane,0,
292 pixel,ZB_NB_COLORS) == 0) {
293 /* private cmap */
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;
298 }
299
300 for(i=0;i<ZB_NB_COLORS;i++) color_indexes[i]=pixel[i];
301
302 /* Open the Z Buffer - 256 colors */
303 zb=ZB_open(xsize,ysize,ZB_MODE_INDEX,ZB_NB_COLORS,
304 color_indexes,palette,NULL);
305 if (zb == NULL) {
306 fprintf(stderr, "Error while initializing Z buffer\n");
307 exit(1);
308 }
309
310 for (i=0; i<ZB_NB_COLORS; i++) {
311 xcolor.flags = DoRed | DoGreen | DoBlue;
312
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);
318 }
319 ctx->do_convert = 1;
320 } else {
321 int mode,bpp;
322 /* RGB 16/24/32 */
323 bpp = bits_per_pixel(ctx->display,&ctx->visual_info);
324 switch(bpp) {
325 case 24:
326 mode = ZB_MODE_RGB24;
327 ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 24);
328 break;
329 case 32:
330 mode = ZB_MODE_RGBA;
331 ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 32);
332 break;
333 default:
334 mode = ZB_MODE_5R6G5B;
335 ctx->do_convert = (TGL_FEATURE_RENDER_BITS != 16);
336 break;
337 }
338 zb=ZB_open(xsize,ysize,mode,0,NULL,NULL,NULL);
339 if (zb == NULL) {
340 fprintf(stderr, "Error while initializing Z buffer\n");
341 exit(1);
342 }
343 }
344
345 /* create a gc */
346 ctx->gc = XCreateGC(ctx->display, drawable, 0, 0);
347
348 /* initialisation of the TinyGL interpreter */
349 glInit(zb);
351 ctx->gl_context->opaque=(void *) ctx;
353
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;
357
358 glViewport(0, 0, xsize, ysize);
359 }
360
361 return True;
362}
363
364static Bool WaitForShmCompletion(Display *dpy, XEvent *event, char *arg)
365{
366 TinyGLXContext *ctx=(TinyGLXContext *) arg;
367
368 return (event->type == ctx->CompletionType) &&
369 ( ((XShmCompletionEvent *)event)->drawable == (Window)ctx->drawable);
370}
371
372void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
373{
374 GLContext *gl_context;
375 TinyGLXContext *ctx;
376
377 /* retrieve the current GLXContext */
378 gl_context=gl_get_context();
379 ctx=(TinyGLXContext *)gl_context->opaque;
380
381 /* for non 16 bits visuals, a conversion is required */
382
383
384 if (ctx->do_convert) {
386 ctx->ximage->data,
387 ctx->ximage->bytes_per_line);
388
389 }
390
391 /* draw the ximage */
392 if (ctx->shm_use) {
393 XEvent event;
394
395 XShmPutImage(dpy,drawable,ctx->gc,
396 ctx->ximage,0,0,0,0,ctx->ximage->width, ctx->ximage->height,
397 True);
398 XIfEvent(dpy, &event, WaitForShmCompletion, (char*)ctx);
399 } else {
400 XPutImage(dpy, drawable, ctx->gc,
401 ctx->ximage, 0, 0, 0, 0, ctx->ximage->width, ctx->ximage->height);
402 }
403 XFlush(dpy);
404}
405
406
407void glXWaitGL( void )
408{
409}
410
411void glXWaitX( void )
412{
413}
void gl_fatal_error(char *format,...)
Definition: error.c:4
void glClose(void)
Definition: init.c:184
void glViewport(int x, int y, int width, int height)
Definition: api.c:341
void glInit(void *zbuffer)
Definition: init.c:30
int glX_resize_viewport(GLContext *c, int *xsize_ptr, int *ysize_ptr)
Definition: glx.c:220
GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
Definition: glx.c:57
Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx1)
Definition: glx.c:258
void glXDestroyContext(Display *dpy, GLXContext ctx1)
Definition: glx.c:72
void glXWaitGL(void)
Definition: glx.c:407
XVisualInfo * glXChooseVisual(Display *dpy, int screen, int *attribList)
Definition: glx.c:30
Bool glXQueryExtension(Display *dpy, int *errorb, int *event)
Definition: glx.c:24
void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
Definition: glx.c:372
void glXWaitX(void)
Definition: glx.c:411
Drawable GLXDrawable
Definition: glx.h:88
void * GLXContext
Definition: glx.h:86
GLContext * gl_get_context(void)
Definition: list.c:25
void gl_free(void *p)
Definition: memory.c:8
void * gl_malloc(int size)
Definition: memory.c:13
Definition: zgl.h:159
ZBuffer * zb
Definition: zgl.h:161
void * opaque
Definition: zgl.h:272
GLViewport viewport
Definition: zgl.h:203
int(* gl_resize_viewport)(struct GLContext *c, int *xsize, int *ysize)
Definition: zgl.h:274
int ysize
Definition: zgl.h:91
int xsize
Definition: zgl.h:91
Drawable drawable
Definition: glx.c:16
GLContext * gl_context
Definition: glx.c:9
XVisualInfo visual_info
Definition: glx.c:11
XImage * ximage
Definition: glx.c:13
XShmSegmentInfo * shm_info
Definition: glx.c:20
Display * display
Definition: glx.c:10
int CompletionType
Definition: glx.c:21
int do_convert
Definition: glx.c:17
int ysize
Definition: glx.c:12
int xsize
Definition: glx.c:12
int shm_use
Definition: glx.c:19
Colormap cmap
Definition: glx.c:15
Display * dpy
Definition: x11.c:26
void ZB_copyFrameBuffer(ZBuffer *zb, void *buf, int linesize)
Definition: zbuffer.c:274
void ZB_resize(ZBuffer *zb, void *frame_buffer, int xsize, int ysize)
Definition: zbuffer.c:89
ZBuffer * ZB_open(int xsize, int ysize, int mode, int nb_colors, unsigned char *color_indexes, int *color_table, void *frame_buffer)
Definition: zbuffer.c:12
#define ZB_MODE_5R6G5B
Definition: zbuffer.h:27
#define ZB_MODE_RGB24
Definition: zbuffer.h:30
#define ZB_NB_COLORS
Definition: zbuffer.h:31
#define ZB_MODE_RGBA
Definition: zbuffer.h:29
#define ZB_MODE_INDEX
Definition: zbuffer.h:28
#define TGL_FEATURE_RENDER_BITS
Definition: zfeatures.h:39
if(p1->y > p2->y||(p1->y==p2->y &&p1->x > p2->x))
Definition: zline.h:17