qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Experimental initial patch providing accelerated OpenGL for Linux i386 (2nd attempt to post)
@ 2006-11-16 20:34 Even Rouault
  2006-11-16 21:13 ` Even Rouault
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Even Rouault @ 2006-11-16 20:34 UTC (permalink / raw)
  To: qemu-devel

Here's an attempt of providing accelerated OpenGL for QEMU.
I must underline first that it should really really be considered as 
experimental or a proof-of-concept. There's
still a lot of work to do to make it reliable and releasable.
So what is it exactly ?
- a patch for QEMU itself that intercepts any call to 'int $0x99' which is the 
interface I have chosen to dedicate to
  communication between guest user programs and QEMU. The modification of QEMU 
existing code is very slight.
  The essential of code on the guest side is in new files.
- a replacement libGL.so library that must be used inside the Linux guest. The 
library redirects guest OpenGL and GLX calls
  to host side, where your host libGL.so will do the real job.

It works currently only with Linux x86 as guest and host OS.

Now, the good news : which programs do currently work with this patch ?
- glxinfo
- glxgears. I get ~330 FPS with QEMU/GL (direct GLX), ~210 FPS through a SSH 
console on the guest OS (indirect GLX)
- some mesa demos programs.
    * tunnel     : ~26 FPS with QEMU/GL,  ~3 FPS through a SSH console on the 
guest OS
    * teapot     : ~50 FPS with QEMU/GL,  ~7 FPS through a SSH console on the 
guest OS
    * fire       : ~14 FPS with QEMU/GL,  ~2 FPS through a SSH console on the 
guest OS
    * arbfplight : ~100 FPS with QEMU/GL,  not possible through a SSH console 
on the guest OS (GL_ARB_vertex_program not available)
- ... and ppracer ! (some crash from time to time. Starting at ~20 FPS at the 
beginning of the race, and finishing at ~10 FPS... strange...)

How fast is it ? Enough fast to have 15 FPS in ppracer with KQEMU disabled.
When KQEMU is enabled, paradoxically, the performance is really poor :-(

Successfully tested on the following platforms :
- Ubuntu Edgy x86 as host with ATI FGLRX driver / FC5 x86 as guest
- Ubuntu Dapper x86 as host with NVIDIA Proprietary driver / Ubuntu Dapper x86 
as guest

Which programs do not work : probably most for the moment ;-)
I'd like to make it work with XGL (I've downloaded the latest Mandriva 2007 
Live CD and I'm quite
impatient to enable the 3D in it) and GoogleEarth.

How to use it ? (ONLY on Linux i386 and with only i386-softmmu as target-list)
* Apply the patch and recompile QEMU 
* Lauch QEMU with -enable-gl option
* Get the compiled libGL.so from ./i386-softmmu and copy it to the guest OS
* In the guest OS : LD_LIBRARY_PATH=/path/to/replacement/libGL.so glxgears

TODO list :
- implement correctly full OpenGL API
- improve vertex arrays support
- maybe fix how the end of the guest process is detected
- make replacement libGL work when compiled with optimization flags
- integrate in a better way the window that popups on the guest side with the 
main qemu window
- integrate it properly into QEMU build system (helper_opengl.c can't compile 
with -O2 : 'unable to find a register to spill in class `DIREG'')
- understand why it's slower when KQEMU enabled and try to fix that if 
possible
- enable several guest OS processes to use OpenGL at the same time
- make it run on x86_64, and allowing any combination guest x86/x86_64 and 
host x86/x86_64, other archs
- port it to other UNIX-like OS with X
- improve security if possible (preventing malicious guest code from crashing 
host qemu)
- clean the code !
- much testing and debugging
- port it to Windows platform (first OpenGL / WGL, then D3D through Wine 
libs ?)
- make a patch to Valgrind to make it happy with 'int $0x99' when running on 
guest side
- ...

The new files :
- opengl_client.c  : the OpenGL guest library
- helper_opengl.c : main guest-side code
- gl_func.h, server_stub.c, client_stub.c : generated files by parse_gl_h.c 
from gl.h parsing
- glgetv_cst.h  : generated file from parsing of a man page
- gl_func_perso.h, opengl_func.h : hand-written "prototypes"

In the mean time, enjoy !

PS :
I posted a similar message thursday, but it didn't get to the list apparently, 
maybe because of the two big attached patch (500 kB). I have reduced the size 
of the patch to 160 KB by not including generated source files. I will send 
it just after, so this message has a chance of coming. If you don't see a 
following message with the patch attached, I'll have to figure out where to 
store the patch...

^ permalink raw reply	[flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH] Experimental initial patch providing accelerated OpenGL for Linux i386 (2nd attempt to post)
@ 2006-11-16 20:36 Even Rouault
  0 siblings, 0 replies; 11+ messages in thread
From: Even Rouault @ 2006-11-16 20:36 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3927 bytes --]

Here's an attempt of providing accelerated OpenGL for QEMU.
I must underline first that it should really really be considered as 
experimental or a proof-of-concept. There's
still a lot of work to do to make it reliable and releasable.
So what is it exactly ?
- a patch for QEMU itself that intercepts any call to 'int $0x99' which is the 
interface I have chosen to dedicate to
  communication between guest user programs and QEMU. The modification of QEMU 
existing code is very slight.
  The essential of code on the guest side is in new files.
- a replacement libGL.so library that must be used inside the Linux guest. The 
library redirects guest OpenGL and GLX calls
  to host side, where your host libGL.so will do the real job.

It works currently only with Linux x86 as guest and host OS.

Now, the good news : which programs do currently work with this patch ?
- glxinfo
- glxgears. I get ~330 FPS with QEMU/GL (direct GLX), ~210 FPS through a SSH 
console on the guest OS (indirect GLX)
- some mesa demos programs.
    * tunnel     : ~26 FPS with QEMU/GL,  ~3 FPS through a SSH console on the 
guest OS
    * teapot     : ~50 FPS with QEMU/GL,  ~7 FPS through a SSH console on the 
guest OS
    * fire       : ~14 FPS with QEMU/GL,  ~2 FPS through a SSH console on the 
guest OS
    * arbfplight : ~100 FPS with QEMU/GL,  not possible through a SSH console 
on the guest OS (GL_ARB_vertex_program not available)
- ... and ppracer ! (some crash from time to time. Starting at ~20 FPS at the 
beginning of the race, and finishing at ~10 FPS... strange...)

How fast is it ? Enough fast to have 15 FPS in ppracer with KQEMU disabled.
When KQEMU is enabled, paradoxically, the performance is really poor :-(

Successfully tested on the following platforms :
- Ubuntu Edgy x86 as host with ATI FGLRX driver / FC5 x86 as guest
- Ubuntu Dapper x86 as host with NVIDIA Proprietary driver / Ubuntu Dapper x86 
as guest

Which programs do not work : probably most for the moment ;-)
I'd like to make it work with XGL (I've downloaded the latest Mandriva 2007 
Live CD and I'm quite
impatient to enable the 3D in it) and GoogleEarth.

How to use it ? (ONLY on Linux i386 and with only i386-softmmu as target-list)
* Apply the patch and recompile QEMU 
* Lauch QEMU with -enable-gl option
* Get the compiled libGL.so from ./i386-softmmu and copy it to the guest OS
* In the guest OS : LD_LIBRARY_PATH=/path/to/replacement/libGL.so glxgears

TODO list :
- implement correctly full OpenGL API
- improve vertex arrays support
- maybe fix how the end of the guest process is detected
- make replacement libGL work when compiled with optimization flags
- integrate in a better way the window that popups on the guest side with the 
main qemu window
- integrate it properly into QEMU build system (helper_opengl.c can't compile 
with -O2 : 'unable to find a register to spill in class `DIREG'')
- understand why it's slower when KQEMU enabled and try to fix that if 
possible
- enable several guest OS processes to use OpenGL at the same time
- make it run on x86_64, and allowing any combination guest x86/x86_64 and 
host x86/x86_64, other archs
- port it to other UNIX-like OS with X
- improve security if possible (preventing malicious guest code from crashing 
host qemu)
- clean the code !
- much testing and debugging
- port it to Windows platform (first OpenGL / WGL, then D3D through Wine 
libs ?)
- make a patch to Valgrind to make it happy with 'int $0x99' when running on 
guest side
- ...

The new files :
- opengl_client.c  : the OpenGL guest library
- helper_opengl.c : main guest-side code
- gl_func.h, server_stub.c, client_stub.c : generated files by parse_gl_h.c 
from gl.h parsing
- glgetv_cst.h  : generated file from parsing of a man page
- gl_func_perso.h, opengl_func.h : hand-written "prototypes"

In the mean time, enjoy !

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: qemu_opengl.patch --]
[-- Type: text/x-diff; charset="us-ascii"; name="qemu_opengl.patch", Size: 172416 bytes --]

diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/dyngen-exec.h qemu/dyngen-exec.h
--- qemu.ori/dyngen-exec.h	2006-11-14 00:18:09.000000000 +0100
+++ qemu/dyngen-exec.h	2006-11-14 21:46:24.000000000 +0100
@@ -75,12 +75,16 @@ typedef signed long long int64_t;
 #define UINT32_MAX		(4294967295U)
 #define UINT64_MAX		((uint64_t)(18446744073709551615))
 
+#ifndef _STDIO_H
+
 typedef struct FILE FILE;
 extern int fprintf(FILE *, const char *, ...);
 extern int printf(const char *, ...);
 #undef NULL
 #define NULL 0
 
+#endif
+
 #ifdef __i386__
 #define AREG0 "ebp"
 #define AREG1 "ebx"
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/kqemu.c qemu/kqemu.c
--- qemu.ori/kqemu.c	2006-11-14 00:18:09.000000000 +0100
+++ qemu/kqemu.c	2006-11-14 21:46:24.000000000 +0100
@@ -87,6 +87,7 @@ unsigned long *modified_ram_pages;
 unsigned int nb_modified_ram_pages;
 uint8_t *modified_ram_pages_table;
 extern uint32_t **l1_phys_map;
+extern int enable_gl;
 
 #define cpuid(index, eax, ebx, ecx, edx) \
   asm volatile ("cpuid" \
@@ -721,6 +722,7 @@ int kqemu_cpu_exec(CPUState *env)
     ret = ioctl(kqemu_fd, KQEMU_EXEC, kenv);
 #endif
 #endif
+
     if (env->cpuid_features & CPUID_FXSR)
         save_native_fp_fxsave(env);
     else
@@ -749,7 +751,6 @@ int kqemu_cpu_exec(CPUState *env)
     env->kernelgsbase = kenv->kernelgsbase;
 #endif
 #endif
-
     /* flush pages as indicated by kqemu */
     if (kenv->nb_pages_to_flush >= KQEMU_FLUSH_ALL) {
         tlb_flush(env, 1);
@@ -825,13 +826,40 @@ int kqemu_cpu_exec(CPUState *env)
     else
         env->hflags &= ~HF_OSFXSR_MASK;
         
+    /* OPENGL Stuff */
+    if (enable_gl && ((env->hflags & HF_CPL_MASK) == 3))
+    {
+      int index = (env->eip >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+      if (env->segs[R_CS].base != 0)
+      {
+        fprintf(stderr, "env->segs[R_CS].base != 0 !\n");
+      }
+      else if (__builtin_expect(env->tlb_table[1][index].addr_code != 
+                           (env->eip & TARGET_PAGE_MASK), 0))
+      {
+        ldub_code(env->eip);
+      }
+      if (env->tlb_table[1][index].addend)
+      {
+        unsigned char* ptr = env->eip + env->tlb_table[1][index].addend;
+        if (ptr[0] == 0xCD && ptr[1] == 0x99)
+        {
+          helper_opengl(env);
+        }
+        /*else if (ptr[0] == 0xCD && ptr[1] == 0x80)
+        {
+          fprintf(stderr, "system call %d\n", env->regs[R_EAX]);
+        }*/
+      }
+    }
+    
 #ifdef DEBUG
     if (loglevel & CPU_LOG_INT) {
         fprintf(logfile, "kqemu: kqemu_cpu_exec: ret=0x%x\n", ret);
     }
 #endif
     if (ret == KQEMU_RET_SYSCALL) {
-        /* syscall instruction */
+  /* syscall instruction */
         return do_syscall(env, kenv);
     } else 
     if ((ret & 0xff00) == KQEMU_RET_INT) {
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/Makefile.target qemu/Makefile.target
--- qemu.ori/Makefile.target	2006-11-14 00:18:09.000000000 +0100
+++ qemu/Makefile.target	2006-11-16 20:59:49.000000000 +0100
@@ -285,8 +285,6 @@ ifdef CONFIG_GDBSTUB
 OBJS+=gdbstub.o
 endif
 
-all: $(PROGS)
-
 $(QEMU_USER): $(OBJS)
 	$(CC) $(LDFLAGS) -o $@ $^  $(LIBS)
 ifeq ($(ARCH),alpha)
@@ -435,8 +433,28 @@ ifdef CONFIG_WIN32
 SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
 endif
 
+ifeq ($(TARGET_BASE_ARCH), i386)
+parse_gl_h: parse_gl_h.c
+	$(CC) -o $@ $<
+server_stub.c: parse_gl_h
+	./parse_gl_h
+client_stub.c: parse_gl_h
+	./parse_gl_h
+gl_func.h: parse_gl_h
+	./parse_gl_h
+# -O2 doesn't work --> 'unable to find a register to spill in class `DIREG''
+GL_CFLAGS := -Wall -g -fno-strict-aliasing
+helper_opengl.o: helper_opengl.c server_stub.c gl_func.h
+	$(CC) $(GL_CFLAGS) $(DEFINES) -c -o $@ $<
+LIBOBJS+=helper_opengl.o
+libGL.so: client_stub.c gl_func.h
+	$(CC) $(GL_CFLAGS) $(SRC_PATH)/target-i386/opengl_client.c -shared -o libGL.so -I. -I$(SRC_PATH)/target-i386
+PROGS+=libGL.so
+GL_GENERATED_FILES=libGL.so parse_gl_h server_stub.c client_stub.c gl_func.h
+endif
+
 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
-	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) -lGL
 
 cocoa.o: cocoa.m
 	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
@@ -545,7 +563,7 @@ $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h 
 	$(CC) $(DEFINES) -c -o $@ $<
 
 clean:
-	rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
+	rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o $(GL_GENERATED_FILES)
 
 install: all 
 ifneq ($(PROGS),)
@@ -561,3 +579,5 @@ audio.o sdlaudio.o dsoundaudio.o ossaudi
 fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
 CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
 endif
+
+all: $(PROGS)
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/gl_func_perso.h qemu/target-i386/gl_func_perso.h
--- qemu.ori/target-i386/gl_func_perso.h	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/gl_func_perso.h	2006-11-14 21:46:24.000000000 +0100
@@ -0,0 +1,93 @@
+/*
+ *  Hand-implemented GL/GLX API
+ * 
+ *  Copyright (c) 2006 Even Rouault
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+MAGIC_MACRO(_exit_process),
+MAGIC_MACRO(_moveResizeWindow),
+MAGIC_MACRO(_changeWindowState),
+MAGIC_MACRO(_needSync),
+
+MAGIC_MACRO(glXChooseVisual),
+MAGIC_MACRO(glXQueryExtensionsString),
+MAGIC_MACRO(glXQueryServerString),
+MAGIC_MACRO(glXCreateContext),
+MAGIC_MACRO(glXGetCurrentContext),
+MAGIC_MACRO(glXGetCurrentDrawable),
+MAGIC_MACRO(glXDestroyContext),
+MAGIC_MACRO(glXGetClientString),
+MAGIC_MACRO(glXQueryVersion),
+MAGIC_MACRO(glXMakeCurrent),
+MAGIC_MACRO(glXGetConfig),
+MAGIC_MACRO(glXChooseFBConfig),
+MAGIC_MACRO(glXCreatePbuffer),
+MAGIC_MACRO(glXGetVisualFromFBConfig),
+MAGIC_MACRO(glXUseXFont),
+MAGIC_MACRO(glXIsDirect),
+MAGIC_MACRO(glXGetProcAddress_fake),
+
+MAGIC_MACRO(glGetString),
+MAGIC_MACRO(glGetIntegerv),
+MAGIC_MACRO(glGetFloatv),
+MAGIC_MACRO(glGetConvolutionParameteriv),
+MAGIC_MACRO(glLightfv),
+MAGIC_MACRO(glMaterialfv),
+MAGIC_MACRO(glXSwapBuffers),
+MAGIC_MACRO(glXQueryExtension),
+MAGIC_MACRO(glLightModelfv),
+MAGIC_MACRO(glMap1f),
+MAGIC_MACRO(glMap1d),
+MAGIC_MACRO(glMap2f),
+MAGIC_MACRO(glMap2d),
+MAGIC_MACRO(glGenTextures),
+MAGIC_MACRO(glDeleteTextures),
+MAGIC_MACRO(glTexImage1D),
+MAGIC_MACRO(glTexImage2D),
+MAGIC_MACRO(glCompressedTexImage2DARB),
+MAGIC_MACRO(glTexSubImage2D),
+MAGIC_MACRO(glCompressedTexSubImage2DARB),
+MAGIC_MACRO(glTexImage3D),
+MAGIC_MACRO(glGetTexLevelParameteriv),
+MAGIC_MACRO(glFogfv),
+MAGIC_MACRO(glBitmap),
+MAGIC_MACRO(glTexGenfv),
+MAGIC_MACRO(glTexEnvfv),
+MAGIC_MACRO(glTexParameterfv),
+MAGIC_MACRO(glTexParameteriv),
+MAGIC_MACRO(glPointParameterfvARB),
+MAGIC_MACRO(glCallLists),
+MAGIC_MACRO(glGenProgramsARB),
+MAGIC_MACRO(glProgramStringARB),
+MAGIC_MACRO(glDeleteProgramsARB),
+MAGIC_MACRO(glShaderSourceARB),
+MAGIC_MACRO(glGetUniformLocationARB),
+MAGIC_MACRO(glGetVertexAttribfvARB),
+MAGIC_MACRO(glGetVertexAttribivARB),
+MAGIC_MACRO(glGetVertexAttribdvARB),
+MAGIC_MACRO(glGetProgramLocalParameterfvARB),
+MAGIC_MACRO(glGetProgramLocalParameterdvARB),
+MAGIC_MACRO(glGetProgramEnvParameterfvARB),
+MAGIC_MACRO(glGetProgramEnvParameterdvARB),
+MAGIC_MACRO(glGetProgramivARB),
+MAGIC_MACRO(glGetProgramStringARB),
+MAGIC_MACRO(glVertexPointer),
+MAGIC_MACRO(glNormalPointer),
+MAGIC_MACRO(glColorPointer),
+MAGIC_MACRO(glTexCoordPointer),
+MAGIC_MACRO(glDrawArrays),
+MAGIC_MACRO(glDrawElements),
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/glgetv_cst.h qemu/target-i386/glgetv_cst.h
--- qemu.ori/target-i386/glgetv_cst.h	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/glgetv_cst.h	2006-11-14 21:46:24.000000000 +0100
@@ -0,0 +1,250 @@
+struct token_name {
+  GLuint count;
+  GLenum token;
+  const char *name;
+};
+#define MAKE_TOKEN_NAME(x)   x, #x
+static const struct token_name limits[] = {
+  { 1, MAKE_TOKEN_NAME(GL_ACCUM_ALPHA_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_ACCUM_BLUE_BITS) },
+  { 4, MAKE_TOKEN_NAME(GL_ACCUM_CLEAR_VALUE) },
+  { 1, MAKE_TOKEN_NAME(GL_ACCUM_GREEN_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_ACCUM_RED_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_ACTIVE_TEXTURE_ARB) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_SCALE) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_TEST) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_TEST_FUNC) },
+  { 1, MAKE_TOKEN_NAME(GL_ALPHA_TEST_REF) },
+  { 1, MAKE_TOKEN_NAME(GL_ATTRIB_STACK_DEPTH) },
+  { 1, MAKE_TOKEN_NAME(GL_AUTO_NORMAL) },
+  { 1, MAKE_TOKEN_NAME(GL_AUX_BUFFERS) },
+  { 1, MAKE_TOKEN_NAME(GL_BLEND) },
+  { 4, MAKE_TOKEN_NAME(GL_BLEND_COLOR) },
+  { 1, MAKE_TOKEN_NAME(GL_BLEND_DST) },
+  { 1, MAKE_TOKEN_NAME(GL_BLEND_EQUATION) },
+  { 1, MAKE_TOKEN_NAME(GL_BLEND_SRC) },
+  { 1, MAKE_TOKEN_NAME(GL_BLUE_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_BLUE_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_BLUE_SCALE) },
+  { 1, MAKE_TOKEN_NAME(GL_CLIP_PLANE0) },
+  { 1, MAKE_TOKEN_NAME(GL_CLIP_PLANE1) },
+  { 1, MAKE_TOKEN_NAME(GL_CLIP_PLANE2) },
+  { 1, MAKE_TOKEN_NAME(GL_CLIP_PLANE3) },
+  { 1, MAKE_TOKEN_NAME(GL_CLIP_PLANE4) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_ARRAY_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_ARRAY_STRIDE) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_ARRAY_TYPE) },
+  { 4, MAKE_TOKEN_NAME(GL_COLOR_CLEAR_VALUE) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_LOGIC_OP) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_MATERIAL) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_MATERIAL_FACE) },
+  { 16, MAKE_TOKEN_NAME(GL_COLOR_MATRIX) },
+  { 1, MAKE_TOKEN_NAME(GL_COLOR_TABLE) },
+  { 4, MAKE_TOKEN_NAME(GL_COLOR_WRITEMASK) },
+  { 1, MAKE_TOKEN_NAME(GL_CONVOLUTION_1D) },
+  { 1, MAKE_TOKEN_NAME(GL_CONVOLUTION_2D) },
+  { 1, MAKE_TOKEN_NAME(GL_CULL_FACE) },
+  { 1, MAKE_TOKEN_NAME(GL_CULL_FACE_MODE) },
+  { 4, MAKE_TOKEN_NAME(GL_CURRENT_COLOR) },
+  { 1, MAKE_TOKEN_NAME(GL_CURRENT_INDEX) },
+  { 3, MAKE_TOKEN_NAME(GL_CURRENT_NORMAL) },
+  { 4, MAKE_TOKEN_NAME(GL_CURRENT_RASTER_COLOR) },
+  { 1, MAKE_TOKEN_NAME(GL_CURRENT_RASTER_INDEX) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_CLEAR_VALUE) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_FUNC) },
+  { 2, MAKE_TOKEN_NAME(GL_DEPTH_RANGE) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_SCALE) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_TEST) },
+  { 1, MAKE_TOKEN_NAME(GL_DEPTH_WRITEMASK) },
+  { 1, MAKE_TOKEN_NAME(GL_DITHER) },
+  { 1, MAKE_TOKEN_NAME(GL_DOUBLEBUFFER) },
+  { 1, MAKE_TOKEN_NAME(GL_DRAW_BUFFER) },
+  { 1, MAKE_TOKEN_NAME(GL_EDGE_FLAG) },
+  { 1, MAKE_TOKEN_NAME(GL_EDGE_FLAG_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_FEEDBACK_BUFFER_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_FEEDBACK_BUFFER_TYPE) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG) },
+  { 4, MAKE_TOKEN_NAME(GL_FOG_COLOR) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_DENSITY) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_END) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_HINT) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_INDEX) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_FOG_START) },
+  { 1, MAKE_TOKEN_NAME(GL_FRONT_FACE) },
+  { 1, MAKE_TOKEN_NAME(GL_GREEN_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_GREEN_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_GREEN_SCALE) },
+  { 1, MAKE_TOKEN_NAME(GL_HISTOGRAM) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_ARRAY_STRIDE) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_ARRAY_TYPE) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_CLEAR_VALUE) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_LOGIC_OP) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_OFFSET) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_SHIFT) },
+  { 1, MAKE_TOKEN_NAME(GL_INDEX_WRITEMASK) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT0) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT1) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT2) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT3) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT4) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT5) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT6) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHTING) },
+  { 4, MAKE_TOKEN_NAME(GL_LIGHT_MODEL_AMBIENT) },
+  { 1, MAKE_TOKEN_NAME(GL_LIGHT_MODEL_TWO_SIDE) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_SMOOTH) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_SMOOTH_HINT) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_STIPPLE) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_STIPPLE_PATTERN) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_STIPPLE_REPEAT) },
+  { 1, MAKE_TOKEN_NAME(GL_LINE_WIDTH) },
+  { 2, MAKE_TOKEN_NAME(GL_LINE_WIDTH_RANGE) },
+  { 1, MAKE_TOKEN_NAME(GL_LIST_BASE) },
+  { 1, MAKE_TOKEN_NAME(GL_LIST_INDEX) },
+  { 1, MAKE_TOKEN_NAME(GL_LIST_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_LOGIC_OP_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_COLOR_4) },
+  { 2, MAKE_TOKEN_NAME(GL_MAP1_GRID_DOMAIN) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_GRID_SEGMENTS) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_INDEX) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_NORMAL) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_TEXTURE_COORD_1) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_TEXTURE_COORD_2) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_TEXTURE_COORD_3) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_TEXTURE_COORD_4) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_VERTEX_3) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP1_VERTEX_4) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_COLOR_4) },
+  { 4, MAKE_TOKEN_NAME(GL_MAP2_GRID_DOMAIN) },
+  { 2, MAKE_TOKEN_NAME(GL_MAP2_GRID_SEGMENTS) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_INDEX) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_NORMAL) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_TEXTURE_COORD_1) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_TEXTURE_COORD_2) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_TEXTURE_COORD_3) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_TEXTURE_COORD_4) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_VERTEX_3) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP2_VERTEX_4) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP_COLOR) },
+  { 1, MAKE_TOKEN_NAME(GL_MAP_STENCIL) },
+  { 1, MAKE_TOKEN_NAME(GL_MATRIX_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_3D_TEXTURE_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_CLIP_PLANES) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_ELEMENTS_INDICES) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_ELEMENTS_VERTICES) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_EVAL_ORDER) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_LIGHTS) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_LIST_NESTING) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_NAME_STACK_DEPTH) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_PIXEL_MAP_TABLE) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_TEXTURE_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_TEXTURE_UNITS_ARB) },
+  { 2, MAKE_TOKEN_NAME(GL_MAX_VIEWPORT_DIMS) },
+  { 1, MAKE_TOKEN_NAME(GL_MINMAX) },
+  { 16, MAKE_TOKEN_NAME(GL_MODELVIEW_MATRIX) },
+  { 1, MAKE_TOKEN_NAME(GL_MODELVIEW_STACK_DEPTH) },
+  { 1, MAKE_TOKEN_NAME(GL_NAME_STACK_DEPTH) },
+  { 1, MAKE_TOKEN_NAME(GL_NORMAL_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_NORMAL_ARRAY_STRIDE) },
+  { 1, MAKE_TOKEN_NAME(GL_NORMAL_ARRAY_TYPE) },
+  { 1, MAKE_TOKEN_NAME(GL_NORMALIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_ALIGNMENT) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_IMAGE_HEIGHT) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_LSB_FIRST) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_ROW_LENGTH) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_SKIP_IMAGES) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_SKIP_PIXELS) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_SKIP_ROWS) },
+  { 1, MAKE_TOKEN_NAME(GL_PACK_SWAP_BYTES) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_A_TO_A_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_B_TO_B_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_G_TO_G_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_I_TO_A_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_I_TO_B_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_I_TO_G_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_I_TO_I_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_I_TO_R_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_R_TO_R_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_PIXEL_MAP_S_TO_S_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_POINT_SIZE) },
+  { 2, MAKE_TOKEN_NAME(GL_POINT_SIZE_RANGE) },
+  { 1, MAKE_TOKEN_NAME(GL_POINT_SMOOTH) },
+  { 1, MAKE_TOKEN_NAME(GL_POINT_SMOOTH_HINT) },
+  { 2, MAKE_TOKEN_NAME(GL_POLYGON_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_OFFSET_FACTOR) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_OFFSET_UNITS) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_OFFSET_FILL) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_OFFSET_LINE) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_OFFSET_POINT) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_SMOOTH) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_SMOOTH_HINT) },
+  { 1, MAKE_TOKEN_NAME(GL_POLYGON_STIPPLE) },
+  { 16, MAKE_TOKEN_NAME(GL_PROJECTION_MATRIX) },
+  { 1, MAKE_TOKEN_NAME(GL_READ_BUFFER) },
+  { 1, MAKE_TOKEN_NAME(GL_RED_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_RED_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_RED_SCALE) },
+  { 1, MAKE_TOKEN_NAME(GL_RENDER_MODE) },
+  { 1, MAKE_TOKEN_NAME(GL_RESCALE_NORMAL) },
+  { 1, MAKE_TOKEN_NAME(GL_RGBA_MODE) },
+  { 4, MAKE_TOKEN_NAME(GL_SCISSOR_BOX) },
+  { 1, MAKE_TOKEN_NAME(GL_SCISSOR_TEST) },
+  { 1, MAKE_TOKEN_NAME(GL_SEPARABLE_2D) },
+  { 1, MAKE_TOKEN_NAME(GL_SHADE_MODEL) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_CLEAR_VALUE) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_FAIL) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_FUNC) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_REF) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_TEST) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_VALUE_MASK) },
+  { 1, MAKE_TOKEN_NAME(GL_STENCIL_WRITEMASK) },
+  { 1, MAKE_TOKEN_NAME(GL_STEREO) },
+  { 1, MAKE_TOKEN_NAME(GL_SUBPIXEL_BITS) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_1D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_BINDING_1D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_2D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_BINDING_2D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_3D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_BINDING_3D) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_COORD_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_GEN_Q) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_GEN_R) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_GEN_S) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_GEN_T) },
+  { 16, MAKE_TOKEN_NAME(GL_TEXTURE_MATRIX) },
+  { 1, MAKE_TOKEN_NAME(GL_TEXTURE_STACK_DEPTH) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_ALIGNMENT) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_IMAGE_HEIGHT) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_LSB_FIRST) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_ROW_LENGTH) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_SKIP_IMAGES) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_SKIP_PIXELS) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_SKIP_ROWS) },
+  { 1, MAKE_TOKEN_NAME(GL_UNPACK_SWAP_BYTES) },
+  { 1, MAKE_TOKEN_NAME(GL_VERTEX_ARRAY) },
+  { 1, MAKE_TOKEN_NAME(GL_VERTEX_ARRAY_SIZE) },
+  { 1, MAKE_TOKEN_NAME(GL_VERTEX_ARRAY_STRIDE) },
+  { 1, MAKE_TOKEN_NAME(GL_VERTEX_ARRAY_TYPE) },
+  { 4, MAKE_TOKEN_NAME(GL_VIEWPORT) },
+  { 1, MAKE_TOKEN_NAME(GL_ZOOM_X) },
+  { 1, MAKE_TOKEN_NAME(GL_ZOOM_Y) },
+  { 2, MAKE_TOKEN_NAME(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_GENERAL_COMBINERS_NV) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_TEXTURE_LOD_BIAS) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_TEXTURE_LOD_BIAS_EXT) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB) },
+  { 1, MAKE_TOKEN_NAME(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV) },
+  { 1, MAKE_TOKEN_NAME(GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB) },
+  { 1, MAKE_TOKEN_NAME(GL_PROGRAM_ERROR_POSITION_ARB) },
+  { 0, (GLenum) 0, NULL }
+};
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/helper.c qemu/target-i386/helper.c
--- qemu.ori/target-i386/helper.c	2006-11-14 00:18:10.000000000 +0100
+++ qemu/target-i386/helper.c	2006-11-14 21:46:24.000000000 +0100
@@ -3782,6 +3782,16 @@ void update_fp_status(void)
 #endif
 }
 
+void helper_opengl(CPUState *env);
+
+void helper_int99()
+{
+  regs_to_env();
+  helper_opengl(env);
+  env_to_regs();
+}
+
+
 #if !defined(CONFIG_USER_ONLY) 
 
 #define MMUSUFFIX _mmu
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/helper_opengl.c qemu/target-i386/helper_opengl.c
--- qemu.ori/target-i386/helper_opengl.c	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/helper_opengl.c	2006-11-14 21:57:41.000000000 +0100
@@ -0,0 +1,1764 @@
+/*
+ *  Host-side implementation of GL/GLX API
+ * 
+ *  Copyright (c) 2006 Even Rouault
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <stdio.h>
+#include "exec.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#include "opengl_func.h"
+
+#include "glgetv_cst.h"
+
+#define GET_EXT_PTR(type, func_name, args_decl) \
+      static int detect = 0; \
+      static type(*ptr_func)args_decl = NULL; \
+      if (detect == 0) \
+{ \
+        detect = 1; \
+        ptr_func = glXGetProcAddress((const GLubyte*)#func_name); \
+        assert (ptr_func); \
+}
+
+static inline void* get_phys_mem_addr(const CPUState *env, target_ulong addr)
+{
+  int is_user, index;
+  index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+  is_user = ((env->hflags & HF_CPL_MASK) == 3);
+  if (is_user == 0)
+  {
+    fprintf(stderr, "not in userland !!!\n");
+    return NULL;
+  }
+  if (__builtin_expect(env->tlb_table[is_user][index].addr_code != 
+      (addr & TARGET_PAGE_MASK), 0))
+  {
+    target_ulong ret = cpu_get_phys_page_debug(env, addr);
+    if (ret == -1)
+    {
+      fprintf(stderr, "cpu_get_phys_page_debug(env, %p) == %p\n", addr, ret);
+      fprintf(stderr, "not in phys mem %p (%p %p)\n", addr, env->tlb_table[is_user][index].addr_code, addr & TARGET_PAGE_MASK);
+      fprintf(stderr, "cpu_x86_handle_mmu_fault = %d\n",
+              cpu_x86_handle_mmu_fault(env, addr, 0, 1, 1));
+      return NULL;
+    }
+    else
+    {
+      if (ret + TARGET_PAGE_SIZE <= phys_ram_size)
+      {
+        return phys_ram_base + ret + (((target_ulong)addr) & (TARGET_PAGE_SIZE - 1));
+      }
+      else
+      {
+        fprintf(stderr, "cpu_get_phys_page_debug(env, %p) == %p\n", addr, ret);
+        fprintf(stderr, "ret=%p phys_ram_size=%p\n", ret, phys_ram_size);
+        return NULL;
+      }
+    }
+  }
+  else
+  {
+    return (void*)(addr + env->tlb_table[is_user][index].addend);
+  }
+}
+
+#define MIN(a,b) (((a)<(b)) ? (a) : (b))
+
+enum
+{
+  NOT_MAPPED,
+  MAPPED_CONTIGUOUS,
+  MAPPED_NOT_CONTIGUOUS
+};
+
+#define TARGET_ADDR_LOW_ALIGN(x)  ((target_ulong)(x) & ~(TARGET_PAGE_SIZE - 1))
+
+/* Return NOT_MAPPED if a page is not mapped into target physical memory */
+/*        MAPPED_CONTIGUOUS if all pages are mapped into target physical memory and contiguous */
+/*        MAPPED_NOT_CONTIGUOUS if all pages are mapped into target physical memory but not contiguous */
+static int get_target_mem_state(const CPUState *env, const void* target_addr, int len)
+{
+  void* aligned_target_addr = TARGET_ADDR_LOW_ALIGN(target_addr);
+  int to_end_page = (long)aligned_target_addr + TARGET_PAGE_SIZE - (long)target_addr;
+  int ret = MAPPED_CONTIGUOUS;
+  
+  if (aligned_target_addr != target_addr)
+  {
+    void* phys_addr = get_phys_mem_addr(env, aligned_target_addr);
+    void* last_phys_addr = phys_addr;
+    if (phys_addr == 0)
+    {
+      return NOT_MAPPED;
+    }
+    if (len > to_end_page)
+    {
+      len -= to_end_page;
+      aligned_target_addr += TARGET_PAGE_SIZE;
+      int i;
+      for(i=0;i<len;i+=TARGET_PAGE_SIZE)
+      {
+        void* phys_addr = get_phys_mem_addr(env, aligned_target_addr + i);
+        if (phys_addr == 0)
+        {
+          return NOT_MAPPED;
+        }
+        if (phys_addr != last_phys_addr + TARGET_PAGE_SIZE)
+          ret = MAPPED_NOT_CONTIGUOUS;
+        last_phys_addr = phys_addr;
+      }
+    }
+  }
+  else
+  {
+    void* last_phys_addr = NULL;
+    int i;
+    for(i=0;i<len;i+=TARGET_PAGE_SIZE)
+    {
+      void* phys_addr = get_phys_mem_addr(env, target_addr + i);
+      if (phys_addr == 0)
+      {
+        return NOT_MAPPED;
+      }
+      if (i != 0 && phys_addr != last_phys_addr + TARGET_PAGE_SIZE)
+          ret = MAPPED_NOT_CONTIGUOUS;
+      last_phys_addr = phys_addr;
+    }
+  }
+  return ret;
+}
+
+/* copy len bytes from host memory at addr host_addr to target memory at logical addr target_addr */
+/* Returns 1 if successfull, 0 if some target pages are not mapped into target physical memory */
+static int memcpy_host_to_target(const CPUState *env, target_ulong target_addr, const void* host_addr, int len)
+{
+  int i;
+  void* aligned_target_addr = TARGET_ADDR_LOW_ALIGN(target_addr);
+  int to_end_page = (long)aligned_target_addr + TARGET_PAGE_SIZE - (long)target_addr;
+  int ret = get_target_mem_state(env, target_addr, len);
+  if (ret == NOT_MAPPED)
+  {
+    return 0;
+  }
+  
+  if (ret == MAPPED_CONTIGUOUS)
+  {
+    void *phys_addr = get_phys_mem_addr(env, target_addr);
+    memcpy(phys_addr, host_addr, len);
+  }
+  else
+  {
+    if (aligned_target_addr != target_addr)
+    {
+      void* phys_addr = get_phys_mem_addr(env, target_addr);
+      memcpy(phys_addr, host_addr, MIN(len, to_end_page));
+      if (len <= to_end_page)
+      {
+        return 1;
+      }
+      len -= to_end_page;
+      host_addr += to_end_page;
+      target_addr = aligned_target_addr + TARGET_PAGE_SIZE;
+    }
+    for(i=0;i<len;i+=TARGET_PAGE_SIZE)
+    {
+      void *phys_addr = get_phys_mem_addr(env, target_addr + i);
+      memcpy(phys_addr, host_addr + i, (i + TARGET_PAGE_SIZE < len) ? TARGET_PAGE_SIZE : len & (TARGET_PAGE_SIZE - 1));
+    }
+  }
+  
+  return 1;
+}
+
+static int memcpy_target_to_host(const CPUState *env, void* host_addr, target_ulong target_addr, int len)
+{
+  int i;
+  void* aligned_target_addr = TARGET_ADDR_LOW_ALIGN(target_addr);
+  int to_end_page = (long)aligned_target_addr + TARGET_PAGE_SIZE - (long)target_addr;
+  int ret = get_target_mem_state(env, target_addr, len);
+  if (ret == NOT_MAPPED)
+  {
+    return 0;
+  }
+  
+  if (ret == MAPPED_CONTIGUOUS)
+  {
+    void *phys_addr = get_phys_mem_addr(env, target_addr);
+    memcpy(host_addr, phys_addr, len);
+  }
+  else
+  {
+    if (aligned_target_addr != target_addr)
+    {
+      void* phys_addr = get_phys_mem_addr(env, target_addr);
+      memcpy(host_addr, phys_addr, MIN(len, to_end_page));
+      if (len <= to_end_page)
+      {
+        return 1;
+      }
+      len -= to_end_page;
+      host_addr += to_end_page;
+      target_addr = aligned_target_addr + TARGET_PAGE_SIZE;
+    }
+    for(i=0;i<len;i+=TARGET_PAGE_SIZE)
+    {
+      void *phys_addr = get_phys_mem_addr(env, target_addr + i);
+      memcpy(host_addr + i, phys_addr, (i + TARGET_PAGE_SIZE < len) ? TARGET_PAGE_SIZE : len & (TARGET_PAGE_SIZE - 1));
+    }
+  }
+  
+  return 1;
+}
+
+static int host_offset = 0;
+static void reset_host_offset()
+{
+  host_offset = 0;
+}
+
+/* Return a host pointer with the content of [target_addr, target_addr + len bytes[ */
+/* Do not free or modify */
+static const void* get_host_read_pointer(const CPUState *env, const target_ulong target_addr, int len)
+{
+  int ret = get_target_mem_state(env, target_addr, len);
+  if (ret == NOT_MAPPED)
+  {
+    return NULL;
+  }
+  else if (ret == MAPPED_CONTIGUOUS)
+  {
+    return get_phys_mem_addr(env, target_addr);
+  }
+  else
+  {
+    static int host_mem_size = 0;
+    static void* host_mem = NULL;
+    static void* ret;
+    if (host_mem_size < host_offset + len)
+    {
+      host_mem_size = 2 * host_mem_size + host_offset + len;
+      host_mem = realloc(host_mem, host_mem_size);
+    }
+    ret = host_mem + host_offset;
+    assert(memcpy_target_to_host(env, ret, target_addr, len));
+    host_offset += len;
+    return ret;
+  }
+}
+
+
+static Display* dpy = NULL;
+static int display_function_call = 0;
+static char* ret_string = NULL;
+
+static XVisualInfo* get_visual()
+{
+  int attribDouble[] = {
+    GLX_RGBA,
+    GLX_RED_SIZE, 1,
+    GLX_GREEN_SIZE, 1,
+    GLX_BLUE_SIZE, 1,
+    GLX_DOUBLEBUFFER,
+    None
+  };
+  static XVisualInfo* vis = NULL;
+  if (vis == NULL)
+    vis = glXChooseVisual(dpy, 0, attribDouble);  
+  return vis;
+}
+static Window create_window( const char *name, int x, int y, int width, int height)
+{
+  int scrnum;
+  XSetWindowAttributes attr;
+  unsigned long mask;
+  Window root;
+  Window win;
+  XVisualInfo *vis;
+
+  scrnum = DefaultScreen( dpy );
+  root = RootWindow( dpy, scrnum );
+  vis = get_visual();
+  
+  /* window attributes */
+  attr.background_pixel = 0;
+  attr.border_pixel = 0;
+  attr.colormap = XCreateColormap( dpy, root, vis->visual, AllocNone);
+  attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+  attr.override_redirect = 0; //fullscreen;
+  mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
+
+  win = XCreateWindow( dpy, root, 0, 0, width, height,
+                       0, vis->depth, InputOutput,
+                       vis->visual, mask, &attr );
+
+  /* set hints and properties */
+  {
+    XSizeHints sizehints;
+    sizehints.x = x;
+    sizehints.y = y;
+    sizehints.width  = width;
+    sizehints.height = height;
+    sizehints.flags = USSize | USPosition;
+    XSetWMNormalHints(dpy, win, &sizehints);
+    XSetStandardProperties(dpy, win, name, name,
+                           None, (char **)NULL, 0, &sizehints);
+  }
+  
+  /*
+  int loop = 1;
+  while (loop) {
+    while (XPending(dpy) > 0) {
+      XEvent event;
+      XNextEvent(dpy, &event);
+      switch (event.type) {
+        case CreateNotify:
+        {
+          if (((XCreateWindowEvent*)&event)->window == win)
+          {
+            loop = 0;
+          }
+          break;
+        }
+      }
+    }
+}*/
+  
+  return win;
+}
+
+
+typedef struct
+{
+  void* key;
+  void* value;
+} Assoc;
+
+
+#define MAX_HANDLED_PROCESS 100
+#define MAX_ASSOC_SIZE 100
+
+typedef struct
+{
+  int process_id;
+  
+  int next_available_context_number;
+
+  void* vertexPointer;
+  void* normalPointer;
+  void* colorPointer;
+  void* texCoordPointer;
+  int vertexPointerStride;
+
+  int serverActiveTexture;
+  int clientActiveTexture;
+  int pointerArraysEnable[6];
+  int texCoordPointerEnable[16];
+
+  Assoc association_fakecontext_glxcontext[MAX_ASSOC_SIZE];
+  Assoc association_clientdrawable_serverdrawable[MAX_ASSOC_SIZE];
+} ProcessStruct;
+
+ProcessStruct processTab[MAX_HANDLED_PROCESS];
+
+int last_process_id = 0;
+
+target_ulong args[50];
+
+
+#ifdef SYSTEMATIC_ERROR_CHECK
+int last_error = 0;
+#endif
+
+
+#define ARG_TO_CHAR(x)                (char)(x)
+#define ARG_TO_UNSIGNED_CHAR(x)       (unsigned char)(x)
+#define ARG_TO_SHORT(x)               (short)(x)
+#define ARG_TO_UNSIGNED_SHORT(x)      (unsigned short)(x)
+#define ARG_TO_INT(x)                 (int)(x)
+#define ARG_TO_UNSIGNED_INT(x)        (unsigned int)(x)
+#define ARG_TO_FLOAT(x)               (*(float*)&(x))
+#define ARG_TO_DOUBLE(x)              (*(double*)(x))
+#define ARG_TO_FLOAT16_ARRAY(x)       (float*)(x)
+#define ARG_TO_DOUBLE16_ARRAY(x)      (double*)(x)
+
+#include "server_stub.c"
+
+int do_function_call(int func_number, int pid);
+
+
+static const int attribDouble[] = {
+  GLX_RGBA,
+  GLX_RED_SIZE, 1,
+  GLX_GREEN_SIZE, 1,
+  GLX_BLUE_SIZE, 1,
+  GLX_DOUBLEBUFFER,
+  None
+};
+
+void* get_association_fakecontext_glxcontext(ProcessStruct* process, void* fakecontext)
+{
+  int i;
+  for(i=0;i < MAX_ASSOC_SIZE && process->association_fakecontext_glxcontext[i].key != NULL;i++)
+  {
+    if (process->association_fakecontext_glxcontext[i].key == fakecontext)
+      return process->association_fakecontext_glxcontext[i].value;
+  }
+  return NULL;
+}
+void set_association_fakecontext_glxcontext(ProcessStruct* process, void* fakecontext, void* glxcontext)
+{
+  int i;
+  for(i=0;i < MAX_ASSOC_SIZE && process->association_fakecontext_glxcontext[i].key != NULL;i++)
+  {
+    if (process->association_fakecontext_glxcontext[i].key == fakecontext)
+    {
+      break;
+    }
+  }
+  if (i < MAX_ASSOC_SIZE)
+  {
+    process->association_fakecontext_glxcontext[i].key = fakecontext;
+    process->association_fakecontext_glxcontext[i].value = glxcontext;
+  }
+  else
+  {
+    fprintf(stderr, "MAX_ASSOC_SIZE reached\n");
+  }
+}
+void unset_association_fakecontext_glxcontext(ProcessStruct* process, void* fakecontext)
+{
+  int i;
+  for(i=0;i < MAX_ASSOC_SIZE && process->association_fakecontext_glxcontext[i].key != NULL;i++)
+  {
+    if (process->association_fakecontext_glxcontext[i].key == fakecontext)
+    {
+      memmove(&process->association_fakecontext_glxcontext[i],
+               &process->association_fakecontext_glxcontext[i+1],
+              sizeof(Assoc) * (MAX_ASSOC_SIZE - 1 - i));
+      return;
+    }
+  }
+}
+
+void* get_association_clientdrawable_serverdrawable(ProcessStruct* process, void* clientdrawable)
+{
+  int i;
+  for(i=0;i < MAX_ASSOC_SIZE && process->association_clientdrawable_serverdrawable[i].key != NULL;i++)
+  {
+    if (process->association_clientdrawable_serverdrawable[i].key == clientdrawable)
+      return process->association_clientdrawable_serverdrawable[i].value;
+  }
+  return NULL;
+}
+void* get_association_serverdrawable_clientdrawable(ProcessStruct* process, void* serverdrawable)
+{
+  int i;
+  for(i=0;i < MAX_ASSOC_SIZE && process->association_clientdrawable_serverdrawable[i].key != NULL;i++)
+  {
+    if (process->association_clientdrawable_serverdrawable[i].value == serverdrawable)
+      return process->association_clientdrawable_serverdrawable[i].key;
+  }
+  return NULL;
+}
+void set_association_clientdrawable_serverdrawable(ProcessStruct* process, void* clientdrawable, void* serverdrawable)
+{
+  int i;
+  for(i=0;process->association_clientdrawable_serverdrawable[i].key != NULL;i++)
+  {
+    if (process->association_clientdrawable_serverdrawable[i].key == clientdrawable)
+    {
+      break;
+    }
+  }
+  if (i < MAX_ASSOC_SIZE)
+  {
+    process->association_clientdrawable_serverdrawable[i].key = clientdrawable;
+    process->association_clientdrawable_serverdrawable[i].value = serverdrawable;
+  }
+  else
+  {
+    fprintf(stderr, "MAX_ASSOC_SIZE reached\n");
+  }
+}
+
+void display_client_server_state(ProcessStruct* process)
+{
+  int i;
+  printf("serverActiveTexture = %d\n", process->serverActiveTexture);
+  printf("clientActiveTexture = %d\n", process->clientActiveTexture);
+  for(i=0;i<6;i++)
+  {
+    if (i == 5) continue;
+    printf("pointerArraysEnable[%d] = %d\n", i, process->pointerArraysEnable[i]);
+  }
+  for(i=0;i<8;i++)
+  {
+    printf("texCoordPointerEnable[%d] = %d\n", i, process->texCoordPointerEnable[i]);
+  }
+}
+
+int do_function_call(int func_number, int pid)
+{
+  char ret_char = 0;
+  int ret_int = 0;
+  void* ret_ptr = NULL;
+  const char* ret_str = NULL;
+  
+  int iProcess;
+  ProcessStruct* process = NULL;
+  for(iProcess=0;iProcess<MAX_HANDLED_PROCESS;iProcess++)
+  {
+    if (processTab[iProcess].process_id == pid)
+    {
+      process = &processTab[iProcess];
+      break;
+    }
+    else if (processTab[iProcess].process_id == 0)
+    {
+      process = &processTab[iProcess];
+      memset(process, 0, sizeof(ProcessStruct));
+      process->process_id = pid;
+      break;
+    }
+  }
+  if (process == NULL)
+  {
+    fprintf(stderr, "Too many processes !\n");
+    return 0;
+  }
+
+  //fprintf(stderr, "%s\n", tab_opengl_calls_name[func_number]);
+
+  switch (func_number)
+  {
+    case _exit_process_func:
+    {
+      int i;
+      if (display_function_call) fprintf(stderr, "_exit_process\n");
+      
+      for(i=0;i < MAX_ASSOC_SIZE && process->association_fakecontext_glxcontext[i].key != NULL;i++)
+      {
+        GLXContext ctxt = process->association_fakecontext_glxcontext[i].value;
+        fprintf(stderr, "Destroy context corresponding to fake_context = %d\n",
+                process->association_fakecontext_glxcontext[i].key);
+        glXDestroyContext(dpy, ctxt);
+      }
+      
+      for(i=0;i < MAX_ASSOC_SIZE && process->association_clientdrawable_serverdrawable[i].key != NULL;i++)
+      {
+        fprintf(stderr, "Destroy window corresponding to client_drawable = %p\n",
+                process->association_clientdrawable_serverdrawable[i].key);
+        
+        Window win = process->association_clientdrawable_serverdrawable[i].value;
+        XDestroyWindow(dpy, win);
+        
+        int loop = 1;
+        while (loop) {
+          while (XPending(dpy) > 0) {
+            XEvent event;
+            XNextEvent(dpy, &event);
+            switch (event.type) {
+              case DestroyNotify:
+              {
+                if (((XDestroyWindowEvent*)&event)->window == win)
+                {
+                  loop = 0;
+                }
+                break;
+              }
+            }
+          }
+        }
+      }
+      
+      if (process->vertexPointer) free(process->vertexPointer);
+      if (process->normalPointer) free(process->normalPointer);
+      if (process->colorPointer) free(process->colorPointer);
+      if (process->texCoordPointer) free(process->texCoordPointer);
+      
+      memmove(&processTab[iProcess], &processTab[iProcess+1], (MAX_HANDLED_PROCESS - 1 - iProcess) * sizeof(ProcessStruct));
+      
+      last_process_id = 0;
+
+      break;
+    }
+    
+    case _changeWindowState_func:
+    {
+      GLXDrawable client_drawable = args[0];
+      if (display_function_call) fprintf(stderr, "_changeWindowState_func client_drawable=%p\n", (void*)client_drawable);
+      
+      GLXDrawable drawable = get_association_clientdrawable_serverdrawable(process, client_drawable);
+      if (drawable)
+      {
+        if (args[1] == IsViewable)
+        {
+          XMapWindow(dpy, drawable);
+          
+          int loop = 1;
+          while (loop) {
+            while (XPending(dpy) > 0) {
+              XEvent event;
+              XNextEvent(dpy, &event);
+              switch (event.type) {
+                case ConfigureNotify:
+                {
+                  if (((XConfigureEvent*)&event)->window == drawable)
+                  {
+                    loop = 0;
+                  }
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
+      
+      break;
+    }
+    
+    case _moveResizeWindow_func:
+    {
+      GLXDrawable client_drawable = args[0];
+      if (display_function_call) fprintf(stderr, "_moveResizeWindow client_drawable=%p\n", (void*)client_drawable);
+      
+      GLXDrawable drawable = get_association_clientdrawable_serverdrawable(process, client_drawable);
+      if (drawable)
+      {
+        int* params = (int*)args[1];
+        fprintf(stderr, "%d %d %d %d\n", params[0], params[1], params[2], params[3]);
+        XMoveResizeWindow(dpy, drawable, params[0], params[1], params[2], params[3]);
+        
+        int loop = 1;
+        while (loop) {
+          while (XPending(dpy) > 0) {
+            XEvent event;
+            XNextEvent(dpy, &event);
+            switch (event.type) {
+              case ConfigureNotify:
+              {
+                if (((XConfigureEvent*)&event)->window == drawable)
+                {
+                  loop = 0;
+                }
+                break;
+              }
+            }
+          }
+        }
+      }
+      break;
+    }
+
+    case _needSync_func:
+    {
+      if (display_function_call) fprintf(stderr, "_needSync\n");
+      ret_int = 1;
+      break;
+    }
+  
+    case glXChooseVisual_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXChooseVisual\n");
+      ret_ptr = glXChooseVisual(dpy, 0, (void*)args[2]);
+      break;
+    }
+  
+    case glXQueryExtensionsString_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXQueryExtensionsString\n");
+      ret_str = glXQueryExtensionsString(dpy, 0);
+      break;
+    }
+  
+    case glXQueryServerString_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXQueryServerString %d\n", args[2]);
+      ret_str = glXQueryServerString(dpy, 0, args[2]);
+      break;
+    }
+  
+    case glXGetClientString_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXQueryServerString %d\n", args[1]);
+      ret_str = glXGetClientString(dpy, args[1]);
+      break;
+    }
+  
+    case glXCreateContext_func:
+    {
+      void* fake_shareList = args[2];
+      if (1 || display_function_call) fprintf(stderr, "glXCreateContext fake_shareList=%p\n", fake_shareList);
+    
+      process->next_available_context_number ++;
+      void* fake_ctxt = (void*)process->next_available_context_number;
+      
+      GLXContext shareList = get_association_fakecontext_glxcontext(process, fake_shareList);
+      XVisualInfo* vis = get_visual();
+      GLXContext ctxt = glXCreateContext(dpy, vis, shareList, args[3]);
+      set_association_fakecontext_glxcontext(process, fake_ctxt, ctxt);
+    
+      ret_ptr = fake_ctxt;
+      break;
+    }
+  
+    case glXGetCurrentContext_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXGetCurrentContext\n");
+      ret_ptr = get_association_fakecontext_glxcontext(process, glXGetCurrentContext());
+      break;
+    }
+  
+    case glXGetCurrentDrawable_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXGetCurrentDrawable\n");
+      ret_ptr = get_association_serverdrawable_clientdrawable(process, glXGetCurrentDrawable());
+      break;
+    }
+  
+    case glXDestroyContext_func:
+    {
+      GLXContext fake_ctxt = args[1];
+      if (display_function_call) fprintf(stderr, "glXDestroyContext fake_ctxt=%p\n", fake_ctxt);
+      
+      GLXContext ctxt = get_association_fakecontext_glxcontext(process, fake_ctxt);
+      if (ctxt == NULL)
+      {
+        fprintf(stderr, "invalid fake_ctxt (%p) !\n", fake_ctxt);
+      }
+      else
+      {
+        glXDestroyContext(dpy, ctxt);
+        unset_association_fakecontext_glxcontext(process, fake_ctxt);
+      }
+      break;
+    }
+  
+    case glXQueryVersion_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXQueryVersion\n");
+      ret_int = glXQueryVersion(dpy, args[1], args[2]);
+      break;
+    }
+  
+    case glGetString_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetString %d\n", args[0]);
+      ret_str = (char*)glGetString(args[0]);
+      break;
+    }
+  
+    case glXMakeCurrent_func:
+    {
+      GLXDrawable client_drawable = args[1];
+      GLXContext fake_ctxt = args[2];
+      if (display_function_call) fprintf(stderr, "glXMakeCurrent client_drawable=%p fake_ctx=%p\n", (void*)client_drawable, fake_ctxt);
+      
+      if (client_drawable == NULL && fake_ctxt == NULL)
+      {
+        ret_int = glXMakeCurrent(dpy, NULL, NULL);
+      }
+      else
+      {
+        GLXContext ctxt = get_association_fakecontext_glxcontext(process, fake_ctxt);
+        GLXDrawable drawable;
+        if (ctxt == NULL)
+        {
+          fprintf(stderr, "invalid fake_ctxt (%p) !\n", fake_ctxt);
+          ret_int = 0;
+        }
+        else
+        {
+          drawable = get_association_clientdrawable_serverdrawable(process, client_drawable);
+          if (drawable == NULL)
+          {
+            drawable = create_window("", 0, 0, 300, 300);
+            set_association_clientdrawable_serverdrawable(process, client_drawable, drawable);
+          }
+          
+          ret_int = glXMakeCurrent(dpy, drawable, ctxt);
+        }
+      }
+      break;
+    }
+  
+    case glXSwapBuffers_func:
+    {
+      GLXDrawable client_drawable = args[1];
+      if (display_function_call) fprintf(stderr, "glXSwapBuffers client_drawable=%p\n", (void*)client_drawable);
+      
+      GLXDrawable drawable = get_association_clientdrawable_serverdrawable(process, client_drawable);
+      if (drawable == 0)
+      {
+        fprintf(stderr, "unknown client_drawable (%p) !\n", client_drawable);
+      }
+      else
+      {
+        glXSwapBuffers(dpy, drawable);
+      }
+      break;
+    }
+    
+    case glXIsDirect_func:
+    {
+      GLXContext fake_ctxt = args[1];
+      if (display_function_call) fprintf(stderr, "glXIsDirect fake_ctx=%p\n", fake_ctxt);
+      GLXContext ctxt = get_association_fakecontext_glxcontext(process, fake_ctxt);
+      if (ctxt == NULL)
+      {
+        fprintf(stderr, "invalid fake_ctxt (%p) !\n", fake_ctxt);
+        ret_char = False;
+      }
+      else
+      {
+        ret_char = glXIsDirect(dpy, ctxt);
+      }
+      break;
+    }
+  
+    case glXGetConfig_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXGetConfig %d\n", args[2]);
+      ret_int = glXGetConfig(dpy, get_visual(), args[2], args[3]);
+      break;
+    }
+  
+    case glXUseXFont_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXUseXFont\n");
+      fprintf(stderr, "not implemented !\n");
+      break;
+    }
+  
+      
+    case glXQueryExtension_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXQueryExtension\n");
+      ret_int = glXQueryExtension(dpy, args[1], args[2]);
+      break;
+    }
+  
+    case glXChooseFBConfig_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXChooseFBConfig\n");
+      fprintf(stderr, "not implemented !\n");
+      ret_ptr = 0;
+      break;
+    }
+  
+    case glXCreatePbuffer_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXCreatePbuffer\n");
+      fprintf(stderr, "not implemented !\n");
+      ret_ptr = NULL;
+      break;
+    }
+  
+    case glXGetVisualFromFBConfig_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXGetVisualFromFBConfig\n");
+      fprintf(stderr, "not implemented !\n");
+      ret_ptr = NULL;
+      break;
+    }
+  
+    case glXGetProcAddress_fake_func:
+    {
+      if (display_function_call) fprintf(stderr, "glXGetProcAddress %s\n", args[0]);
+      ret_int = glXGetProcAddress(args[0]) != NULL;
+      break;
+    }
+  
+    case glFlush_func:
+    {
+      glFlush();
+      break;
+    }
+  
+    case glGetIntegerv_func:
+    {
+      int param = args[0];
+      if (display_function_call) fprintf(stderr, "glGetIntegerv %d\n", param);
+      glGetIntegerv(param, args[1]);
+      break;
+    }
+  
+    case glGetFloatv_func:
+    {
+      int param = args[0];
+      if (display_function_call) fprintf(stderr, "glGetFloatv %d\n", param);
+      glGetIntegerv(param, args[1]);
+      break;
+    }
+  
+    case glGetConvolutionParameteriv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetConvolutionParameteriv %d %d\n", args[0], args[1]);
+      glGetConvolutionParameteriv(args[0], args[1], args[2]);
+      break;
+    }
+  
+    case glLightfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glLightfv\n");
+      glLightfv(args[0], args[1],(float*)args[2]);
+      break;
+    }
+  
+    case glMaterialfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glMaterialfv\n");
+      glMaterialfv(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glLightModelfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glLightModelfv\n");
+      glLightModelfv(args[0], (float*)args[1]);
+      break;
+    }
+    
+    case glMap1f_func:
+    {
+      if (display_function_call) fprintf(stderr, "glMap1f\n");
+      glMap1f(args[0],
+              ARG_TO_FLOAT(args[1]),
+              ARG_TO_FLOAT(args[2]),
+              args[3],
+              args[4],
+              (float*)args[5]);
+      break;
+    }
+    
+    case glMap1d_func:
+    {
+      if (display_function_call) fprintf(stderr, "glMap1d\n");
+      glMap1f(args[0],
+              ARG_TO_DOUBLE(args[1]),
+              ARG_TO_DOUBLE(args[2]),
+              args[3],
+              args[4],
+              (double*)args[5]);
+      break;
+    }
+
+    case glMap2f_func:
+    {
+      if (display_function_call) fprintf(stderr, "glMap2f\n");
+      glMap2f(args[0],
+              ARG_TO_FLOAT(args[1]),
+              ARG_TO_FLOAT(args[2]),
+              args[3],
+              args[4],
+              ARG_TO_FLOAT(args[5]),
+              ARG_TO_FLOAT(args[6]),
+              args[7],
+              args[8],
+              (float*)args[9]);
+      break;
+    }
+  
+    case glMap2d_func:
+    {
+      if (display_function_call) fprintf(stderr, "glMap2d\n");
+      glMap2d(args[0],
+             ARG_TO_DOUBLE(args[1]),
+             ARG_TO_DOUBLE(args[2]),
+             args[3],
+             args[4],
+             ARG_TO_DOUBLE(args[5]),
+             ARG_TO_DOUBLE(args[6]),
+             args[7],
+             args[8],
+             (double*)args[9]);
+      break;
+    }
+  
+    case glGenTextures_func:
+    {
+      int nTextures = args[0];
+      if (display_function_call) fprintf(stderr, "glGenTextures\n");
+      glGenTextures(nTextures, args[1]);
+      break;
+    }
+  
+    case glDeleteTextures_func:
+    {
+      if (display_function_call) fprintf(stderr, "glDeleteTextures\n");
+      glDeleteTextures(args[0], (int*)args[1]);
+      break;
+    }
+  
+    case glCallLists_func:
+    {
+      if (display_function_call) fprintf(stderr, "glCallLists\n");
+      glCallLists(args[0], args[1], (void*)args[2]);
+      break;
+    }
+    
+    case glTexImage1D_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexImage1D\n");
+      glTexImage1D(args[0],
+                   args[1],
+                   args[2],
+                   args[3],
+                   args[4],
+                   args[5],
+                   args[6],
+                   (void*)args[7]);
+      break;
+    }
+  
+    case glTexImage2D_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexImage2D\n");
+      glTexImage2D(args[0],
+                   args[1],
+                   args[2],
+                   args[3],
+                   args[4],
+                   args[5],
+                   args[6],
+                   args[7],
+                   (void*)args[8]);
+      break;
+    }
+
+    case glTexSubImage2D_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexSubImage2D\n");
+      glTexSubImage2D(args[0],
+                      args[1],
+                      args[2],
+                      args[3],
+                      args[4],
+                      args[5],
+                      args[6],
+                      args[7],
+                      (void*)args[8]);
+      break;
+    }
+
+    case glCompressedTexImage2DARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glCompressedTexImage2DARB\n");
+      GET_EXT_PTR(void, glCompressedTexImage2DARB, (int,int,int,int,int,int,int,void*));
+      ptr_func(args[0],
+                args[1],
+                args[2],
+                args[3],
+                args[4],
+                args[5],
+                args[6],
+                (void*)args[7]);
+      break;
+    }
+  
+    case glCompressedTexSubImage2DARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glCompressedTexSubImage2DARB\n");
+      GET_EXT_PTR(void, glCompressedTexSubImage2DARB, (int,int,int,int,int,int,int,void*));
+      ptr_func (args[0],
+                args[1],
+                args[2],
+                args[3],
+                args[4],
+                args[5],
+                args[6],
+                (void*)args[7]);
+      break;
+    }
+
+    case glGenProgramsARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGenProgramsARB\n");
+      GET_EXT_PTR(void, glGenProgramsARB, (int,int*));
+      ptr_func(args[0], (int*)args[1]);
+      break;
+    }
+  
+    case glProgramStringARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glProgramStringARB\n");
+      GET_EXT_PTR(void, glProgramStringARB, (int,int,int,void*));
+      ptr_func(args[0], args[1], args[2], (void*)args[3]);
+      break;
+    }
+  
+    case glDeleteProgramsARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glDeleteProgramsARB\n");
+      GET_EXT_PTR(void, glDeleteProgramsARB, (int,int*));
+      ptr_func(args[0], (int*)args[1]);
+      break;
+    }
+  
+    case glShaderSourceARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glShaderSourceARB\n");
+      GET_EXT_PTR(void, glShaderSourceARB, (int,int,char**,void*));
+      ptr_func(args[0], 1, (char**)&args[1], NULL);
+      break;
+    }
+  
+    case glGetUniformLocationARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetUniformLocationARB\n");
+      GET_EXT_PTR(int, glGetUniformLocationARB, (int,char*));
+      ret_int = ptr_func(args[0], (char*)args[1]);
+      break;
+    }
+
+    case glPointParameterfvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glPointParameterfvARB\n");
+      GET_EXT_PTR(void, glPointParameterfvARB, (int,float*));
+      ptr_func(args[0], (float*)args[1]);
+      break;
+    }
+  
+    case glGetVertexAttribfvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetVertexAttribfvARB\n");
+      GET_EXT_PTR(void, glGetVertexAttribfvARB, (int,int,float*));
+      ptr_func(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glGetVertexAttribivARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetVertexAttribivARB\n");
+      GET_EXT_PTR(void, glGetVertexAttribfvARB, (int,int,double*));
+      ptr_func(args[0], args[1], (double*)args[2]);
+      break;
+    }
+  
+    case glGetVertexAttribdvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetVertexAttribdvARB\n");
+      GET_EXT_PTR(void, glGetVertexAttribdvARB, (int,int,int*));
+      ptr_func(args[0], args[1], (int*)args[2]);
+      break;
+    }
+  
+    case glGetProgramLocalParameterfvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetProgramLocalParameterfvARB\n");
+      GET_EXT_PTR(void, glGetProgramLocalParameterfvARB, (int,int,float*));
+      ptr_func(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glGetProgramLocalParameterdvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetProgramLocalParameterdvARB\n");
+      GET_EXT_PTR(void, glGetProgramLocalParameterdvARB, (int,int,double*));
+      ptr_func(args[0], args[1], (double*)args[2]);
+      break;
+    }
+  
+    case glGetProgramEnvParameterfvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetProgramEnvParameterfvARB\n");
+      GET_EXT_PTR(void, glGetProgramEnvParameterfvARB, (int,int,float*));
+      ptr_func(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glGetProgramEnvParameterdvARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetProgramEnvParameterdvARB\n");
+      GET_EXT_PTR(void, glGetProgramEnvParameterdvARB, (int,int,double*));
+      ptr_func(args[0], args[1], (double*)args[2]);
+      break;
+    }
+  
+    case glGetProgramivARB_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetProgramivARB\n");
+      GET_EXT_PTR(void, glGetProgramivARB, (int,int,int*));
+      ptr_func(args[0], args[1], (int*)args[2]);
+      break;
+    }
+  
+    case glGetProgramStringARB_func:
+    {
+      assert(0);
+      /*
+      int len;
+      char* string;
+      {
+        GET_EXT_PTR(void, glGetProgramivARB, (int,int,int*));
+        ptr_func(args[0], GL_PROGRAM_LENGTH_ARB, &len);
+        string = g_malloc(len);
+      }
+      if (display_function_call) fprintf(stderr, "glGetProgramStringARB\n");
+      GET_EXT_PTR(void, glGetProgramStringARB, (int,int,void*));
+      ptr_func(args[0], args[1], string);
+      len = strlen(string);
+      write_to_client(client, &len, sizeof(int));
+      write_to_client(client, string, len);
+      g_free(string);*/
+      break;
+    }
+
+    case glTexImage3D_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexImage3D\n");
+      glTexImage3D(args[0],
+                    args[1],
+                    args[2],
+                    args[3],
+                    args[4],
+                    args[5],
+                    args[6],
+                    args[7],
+                    args[8],
+                    (void*)args[9]);
+      break;
+    }
+  
+    case glGetTexLevelParameteriv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glGetTexLevelParameteriv\n");
+      glGetTexLevelParameteriv(args[0], args[1], args[2], (int*)args[3]);
+      break;
+    }
+  
+    case glFogfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glFogfv\n");
+      glFogfv(args[0], (float*)args[1]);
+      break;
+    }
+  
+    case glBitmap_func:
+    {
+      if (display_function_call) fprintf(stderr, "glBitmap\n");
+      glBitmap (args[0],
+                args[1],
+                ARG_TO_FLOAT(args[2]),
+                ARG_TO_FLOAT(args[3]),
+                ARG_TO_FLOAT(args[4]),
+                ARG_TO_FLOAT(args[5]),
+                (void*)args[6]);
+      break;
+    }
+  
+    case glTexGenfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexGenfv\n");
+      glTexGenfv(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glTexEnvfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexEnvfv\n");
+      glTexEnvfv(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glTexParameterfv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexParameterfv\n");
+      glTexParameterfv(args[0], args[1], (float*)args[2]);
+      break;
+    }
+  
+    case glTexParameteriv_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexParameteriv\n");
+      glTexParameteriv(args[0], args[1], (int*)args[2]);
+      break;
+    }
+  
+    case glVertexPointer_func:
+    {
+      if (display_function_call) fprintf(stderr, "glVertexPointer\n");
+      if (process->vertexPointer) free(process->vertexPointer);
+      int size = args[3];
+      process->vertexPointer = malloc(size);
+      memcpy(process->vertexPointer, args[4], size);
+      glVertexPointer(args[0], args[1], args[2], process->vertexPointer);
+      break;
+    }
+  
+    case glNormalPointer_func:
+    {
+      if (display_function_call) fprintf(stderr, "glNormalPointer\n");
+      if (process->normalPointer) free(process->normalPointer);
+      int size = args[2];
+      process->normalPointer = malloc(size);
+      memcpy(process->normalPointer, args[3], size);
+      glNormalPointer(args[0], args[1], process->normalPointer);
+      break;
+    }
+  
+    case glColorPointer_func:
+    {
+      if (display_function_call) fprintf(stderr, "glColorPointer\n");
+      if (process->colorPointer) free(process->colorPointer);
+      int size = args[3];
+      process->colorPointer = malloc(size);
+      memcpy(process->colorPointer, args[4], size);
+      glColorPointer(args[0], args[1], args[2], process->colorPointer);
+
+      break;
+    }
+  
+    case glTexCoordPointer_func:
+    {
+      if (display_function_call) fprintf(stderr, "glTexCoordPointer\n");
+      if (process->texCoordPointer) free(process->texCoordPointer);
+      int size = args[3];
+      process->texCoordPointer = malloc(size);
+      memcpy(process->texCoordPointer, args[4], size);
+      glTexCoordPointer(args[0], args[1], args[2], process->texCoordPointer);
+      break;
+    }
+  
+    case glBegin_func:
+    {
+    //display_client_server_state(client);
+      glBegin(args[0]);
+      break;
+    }
+  
+    case glActiveTexture_func:
+    case glActiveTextureARB_func:
+    {
+      process->serverActiveTexture = args[0] - GL_TEXTURE0_ARB;
+    //printf("set server active texture %d\n", clientActiveTexture);
+      glActiveTexture(args[0]);
+      break;
+    }
+  
+    case glClientActiveTexture_func:
+    case glClientActiveTextureARB_func:
+    {
+      process->clientActiveTexture = args[0] - GL_TEXTURE0_ARB;
+    //printf("set client active texture %d\n", clientActiveTexture);
+      glClientActiveTexture(args[0]);
+      break;
+    }
+  
+    case glEnableClientState_func:
+    {
+      int num = args[0] - GL_VERTEX_ARRAY;
+      if (num == GL_TEXTURE_COORD_ARRAY - GL_VERTEX_ARRAY)
+      {
+      //printf("enable texture %d\n", clientActiveTexture);
+        process->texCoordPointerEnable[process->clientActiveTexture] = 1;
+      }
+      else if (num >= 0 && num < 6)
+      {
+        //printf("enable feature %d\n", num);
+        process->pointerArraysEnable[num] = 1;
+      }
+      glEnableClientState(args[0]);
+      break;
+    }
+  
+    case glDisableClientState_func:
+    {
+      int num = args[0] - GL_VERTEX_ARRAY;
+      if (num == GL_TEXTURE_COORD_ARRAY - GL_VERTEX_ARRAY)
+      {
+      //printf("disable texture %d\n", clientActiveTexture);
+        process->texCoordPointerEnable[process->clientActiveTexture] = 0;
+      }
+      else if (num >= 0 && num < 6)
+      {
+        //printf("disable feature %d\n", num);
+        process->pointerArraysEnable[num] = 0;
+      }
+      glDisableClientState(args[0]);
+      break;
+    }
+  
+    case glArrayElement_func:
+    {
+      if (display_function_call) fprintf(stderr, "glArrayElement\n");
+      glArrayElement(args[0]);
+      break;
+    }
+  
+    case glDrawArrays_func:
+    {
+      if (display_function_call) fprintf(stderr, "glDrawArrays\n");
+    //printf("glDrawArrays %d %d %d\n",args[0], args[1],args[2]);
+      glDrawArrays(args[0], args[1],args[2]);
+      break;
+    }
+  
+    case glDrawElements_func:
+    {
+      if (display_function_call) fprintf(stderr, "glDrawElements\n");
+      glDrawElements(args[0], args[1],args[2],(void*)args[3]);
+      break;
+    }
+    
+    case glGetError_func:
+    {
+#ifdef SYSTEMATIC_ERROR_CHECK
+      ret_int = last_error;
+#else
+      ret_int = glGetError();
+#endif
+      break;
+    }
+  
+    default:
+      execute_func(func_number, &ret_int, &ret_char);
+      break;
+  }
+
+#ifdef SYSTEMATIC_ERROR_CHECK
+  if (funcNumber == glGetError_func)
+  {
+    last_error = 0;
+  }
+  else
+  {
+    last_error = glGetError();
+    if (last_error != 0)
+    {
+      printf("error %s 0x%X\n",  tab_opengl_calls_name[func_number], last_error);
+    }
+  }
+#endif
+
+  Signature* signature = (Signature*)tab_opengl_calls[func_number];
+  int ret_type = signature->ret_type;
+  int nb_args = signature->nb_args;
+  switch(ret_type)
+  {
+    case TYPE_NONE:
+      break;
+    
+    case TYPE_CHAR:
+    case TYPE_UNSIGNED_CHAR:
+      ret_int = ret_char;
+      break;
+    
+    case TYPE_INT:
+    case TYPE_UNSIGNED_INT:
+      break;
+    
+    case TYPE_POINTER:
+      ret_int = ret_ptr;
+      break;
+    
+    case TYPE_VISUAL_INFO:
+      //memcpy(args[nb_args], ret_ptr, sizeof(XVisualInfo));
+      XFree(ret_ptr);
+      break;
+    
+    case TYPE_CONST_CHAR:
+    {
+      strncpy(ret_string, ret_str, 32768);
+      break;
+    }
+    
+    default:
+      fprintf(stderr, "unexpected ret type : %d\n", ret_type);
+      exit(-1);
+      break;
+  }
+
+  return ret_int;
+}
+ 
+int doing_opengl = 0;
+static int last_func_number = -1;
+
+static int decode_call_int(CPUState *env, int func_number, int pid, target_ulong target_ret_string,
+                           target_ulong in_args, target_ulong in_args_size)
+{
+  Signature* signature = (Signature*)tab_opengl_calls[func_number];
+  int ret_type = signature->ret_type;
+  int has_out_parameters = signature->has_out_parameters;
+  int nb_args = signature->nb_args;
+  int* args_type = signature->args_type;
+  int i;
+  int ret;
+  const int* args_size = NULL;
+  target_ulong saved_out_ptr[50];
+  
+  if (last_func_number == _exit_process_func && func_number == _exit_process_func)
+  {
+    last_func_number = -1;
+    return 0;
+  }
+  
+  if (last_process_id == 0)
+  {
+    last_process_id = pid;
+  }
+  else if (last_process_id != pid)
+  {
+    fprintf(stderr, "damnit. I don't support (yet) opengl calls coming from // processes... Sorry !\n");
+    return 0;
+  }
+      
+  if (dpy == NULL)
+  {
+    dpy = XOpenDisplay(NULL);
+    memset(processTab, 0, sizeof(processTab));
+    ret_string = malloc(32768);
+  }
+  
+  reset_host_offset();
+  
+  if (nb_args)
+  {
+    if (memcpy_target_to_host(env, args, in_args, sizeof(target_ulong) * nb_args) == 0)
+    {
+      fprintf(stderr, "call %s pid=%d\n", tab_opengl_calls_name[func_number], pid);
+      fprintf(stderr, "cannot get call parameters\n");
+      return 0;
+    }
+    
+    args_size = (const int*)get_host_read_pointer(env, in_args_size, sizeof(int) * nb_args);
+    if (args_size == NULL)
+    {
+      fprintf(stderr, "call %s pid=%d\n", tab_opengl_calls_name[func_number], pid);
+      fprintf(stderr, "cannot get call parameters size\n");
+      return 0;
+    }
+  }
+  
+  for(i=0;i<nb_args;i++)
+  {
+    switch(args_type[i])
+    {
+      case TYPE_VISUAL_INFO:
+      case TYPE_POINTER:
+      {
+        fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+        fprintf(stderr, "unsupported arg TYPE_POINTER\n");
+        return 0;
+        break;
+      }
+        
+      case TYPE_NONE_TERMINATED_INT_ARRAY:
+      case TYPE_NULL_TERMINATED_STRING:
+      case TYPE_ARRAY_CHAR:
+      case TYPE_ARRAY_INT:
+      case TYPE_ARRAY_FLOAT:
+      case TYPE_ARRAY_DOUBLE:
+        if (args[i] != 0)
+        {
+          if (args_size[i] == 0)
+          {
+            fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+            fprintf(stderr, "args_size[i] == 0 !!\n");
+            return 0;
+          }
+          args[i] = get_host_read_pointer(env, args[i], args_size[i]);
+          if (args[i] == 0)
+          {
+            fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+            fprintf(stderr, "can not get %d bytes\n", args_size[i]);
+            return 0;
+          }
+        }
+        break;
+        
+      case TYPE_OUT_CHAR_ARRAY:
+      case TYPE_OUT_INT_ARRAY:
+      case TYPE_OUT_FLOAT_ARRAY:
+      case TYPE_OUT_DOUBLE_ARRAY:
+      case TYPE_OUT_INT_POINTER:
+      {
+        int mem_state;
+        if (func_number == glXQueryExtension_func && args[i] == 0)
+        {
+          saved_out_ptr[i] = 0;
+          continue;
+        }
+        if (args[i] == 0)
+        {
+          fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+          return 0;
+        }
+        if (args_size[i] == 0)
+        {
+          fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+          fprintf(stderr, "args_size[i] == 0 !!\n");
+          return 0;
+        }
+        mem_state = get_target_mem_state(env, args[i], args_size[i]);
+        if (mem_state == NOT_MAPPED)
+        {
+          fprintf(stderr, "call %s arg %d pid=%d addr=%p size=%d NOT_MAPPED\n", tab_opengl_calls_name[func_number], i, pid, args[i], args_size[i]);
+          return 0;
+        }
+        else if (mem_state == MAPPED_CONTIGUOUS)
+        {
+          saved_out_ptr[i] = 0;
+          args[i] = get_phys_mem_addr(env, args[i]); 
+        }
+        else
+        {
+          saved_out_ptr[i] = args[i];
+          args[i] = malloc(args_size[i]);
+        }
+        break;
+      }
+        
+      case TYPE_DOUBLE:
+      case TYPE_2CHAR:
+      case TYPE_3CHAR:
+      case TYPE_4CHAR:
+      case TYPE_2SHORT:
+      case TYPE_3SHORT:
+      case TYPE_4SHORT:
+      case TYPE_2INT:
+      case TYPE_3INT:
+      case TYPE_4INT:
+      case TYPE_2FLOAT:
+      case TYPE_3FLOAT:
+      case TYPE_4FLOAT:
+      case TYPE_16FLOAT:
+      case TYPE_2DOUBLE:
+      case TYPE_3DOUBLE:
+      case TYPE_4DOUBLE:
+      case TYPE_16DOUBLE:
+        args[i] = get_host_read_pointer(env, args[i], tab_args_type_length[args_type[i]]);
+        if (args[i] == 0)
+        {
+          fprintf(stderr, "call %s arg %d pid=%d\n", tab_opengl_calls_name[func_number], i, pid);
+          fprintf(stderr, "can not get %d bytes\n", tab_args_type_length[args_type[i]]);
+          return 0;
+        }
+        break;
+        
+     case TYPE_IN_IGNORED_POINTER:
+       args[i] = 0;
+       break;
+        
+      default:
+        if (tab_args_type_length[args_type[i]] == 0)
+        {
+          fprintf(stderr, "args %s, type %d\n", i, args_type[i]);
+          return 0;
+        }
+        break;
+    }
+  }
+  
+  if (ret_type == TYPE_CONST_CHAR)
+  {
+    ret_string[0] = 0;
+  }
+  
+  if (func_number == glDrawElements_func)
+  {
+    fprintf(stderr, "glDrawElements_func %d %d %d %X\n", args[0], args[1], args[2], args[3]);
+  }
+
+  ret = do_function_call(func_number, pid);
+  
+  for(i=0;i<nb_args;i++)
+  {
+    switch(args_type[i])
+    {
+      case TYPE_OUT_CHAR_ARRAY:
+      case TYPE_OUT_INT_ARRAY:
+      case TYPE_OUT_FLOAT_ARRAY:
+      case TYPE_OUT_DOUBLE_ARRAY:
+      case TYPE_OUT_INT_POINTER:
+      {
+        if (saved_out_ptr[i])
+        {
+          if (memcpy_host_to_target(env, saved_out_ptr[i], args[i], args_size[i]) == 0)
+          {
+            return 0;
+          }
+          free(args[i]);
+        }
+        break;
+      }
+      
+      default:
+        break;
+    }
+  }
+  
+  if (ret_type == TYPE_CONST_CHAR)
+  {
+    if (target_ret_string)
+    {
+      if (memcpy_host_to_target(env, target_ret_string, ret_string, strlen(ret_string) + 1) == 0)
+      {
+        return 0;
+      }
+    }
+  }
+  return ret;
+}
+
+static int decode_call(CPUState *env, int func_number, int pid, target_ulong target_ret_string,
+                       target_ulong in_args, target_ulong in_args_size)
+{
+  int ret;
+  //fprintf(stderr, "cr3 = %d\n", env->cr[3]);
+  if( ! (func_number >= 0 && func_number < GL_N_CALLS) )
+  {
+    fprintf(stderr, "func_number >= 0 && func_number < GL_N_CALLS failed\n");
+    return 0;
+  }
+  if (func_number == glDrawElements_func)
+  {
+    fprintf(stderr, "entering call %s pid=%d\n", tab_opengl_calls_name[func_number], pid);
+  }
+  ret = decode_call_int(env, func_number, pid, target_ret_string, in_args, in_args_size);
+  if (func_number == glDrawElements_func)
+  {
+    fprintf(stderr, "leaving call %s pid=%d\n", tab_opengl_calls_name[func_number], pid);
+  }
+  return ret;
+}
+
+void helper_opengl(CPUState *env)
+{
+  doing_opengl = 1;
+  env->regs[R_EAX] = decode_call(env,
+                                 env->regs[R_EAX],
+                                 env->regs[R_EBX],
+                                 env->regs[R_ECX],
+                                 env->regs[R_EDX],
+                                 env->regs[R_ESI]);
+  doing_opengl = 0;
+}
Les fichiers binaires qemu.ori/target-i386/libGL.so.1 et qemu/target-i386/libGL.so.1 sont différents.
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/op.c qemu/target-i386/op.c
--- qemu.ori/target-i386/op.c	2006-11-14 00:18:10.000000000 +0100
+++ qemu/target-i386/op.c	2006-11-14 21:46:24.000000000 +0100
@@ -132,6 +132,13 @@ static inline target_long lshift(target_
 
 #endif
 
+void helper_int99(void);
+
+void OPPROTO op_int99(void)
+{
+  helper_int99();
+}
+
 /* operations with flags */
 
 /* update flags with T0 and T1 (add/sub case) */
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/opengl_client.c qemu/target-i386/opengl_client.c
--- qemu.ori/target-i386/opengl_client.c	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/opengl_client.c	2006-11-14 21:46:24.000000000 +0100
@@ -0,0 +1,1956 @@
+/*
+ *  Guest-side implementation of GL/GLX API. Replacement of standard libGL.so
+ * 
+ *  Copyright (c) 2006 Even Rouault
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+/* gcc -Wall -g opengl_client.c -shared -o libGL.so.1 */
+
+#define _GNU_SOURCE
+#define _XOPEN_SOURCE 600
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include <X11/X.h>
+#include <X11/Xutil.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <dlfcn.h>
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+#define EXT_FUNC(x) x
+
+#define CHECK_PROC_WITH_RET(x)  \
+  static int detect = -1; \
+  if (detect < 0) \
+  { \
+    detect = (glXGetProcAddress((const GLubyte *)#x) != NULL); \
+  } \
+  if (detect == 0) \
+  {  \
+    fprintf(stderr, "Symbol " #x " not available in server libGL\n"); \
+    return 0; \
+  } 
+
+#define CHECK_PROC(x)  \
+  static int detect = -1; \
+  if (detect < 0) \
+  { \
+    detect = (glXGetProcAddress((const GLubyte *)#x) != NULL); \
+  } \
+  if (detect == 0) \
+  {  \
+    fprintf(stderr, "Symbol " #x " not available in server libGL\n"); \
+    return; \
+  } 
+
+#include "opengl_func.h"
+
+#include "glgetv_cst.h"
+
+typedef struct
+{
+  int size;
+  int type;
+  int stride;
+  const void* ptr;
+} VertexNormalColorPointerStruct;
+
+static VertexNormalColorPointerStruct vertexPointer = {0};
+static VertexNormalColorPointerStruct normalPointer = {0};
+static VertexNormalColorPointerStruct colorPointer = {0};
+static VertexNormalColorPointerStruct texCoordPointer[16] = {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},};
+static int clientActiveTexture = 0;
+static int pointerArraysEnable[6] = { 0 };
+static int texCoordPointerEnable[16] = { 0 };
+
+
+static struct sigaction old_action;
+void sigsegv_handler(int signum, siginfo_t* info, void* ptr)
+{
+  struct ucontext* context = (struct ucontext*)ptr;
+  unsigned char* eip_ptr = context->uc_mcontext.gregs[REG_EIP];
+  if (eip_ptr[0] == 0xCD && eip_ptr[1] == 0x99)
+  {
+    context->uc_mcontext.gregs[REG_EIP] += 2;
+  }
+  else
+  {
+    fprintf(stderr, "unhandled SIGSEGV\n");
+    exit(-1); // FIXME
+    if (old_action.sa_flags & SA_SIGINFO)
+    {
+      old_action.sa_sigaction(signum, info, ptr);
+    }
+    else
+    {
+      old_action.sa_handler(signum);
+    }
+  }
+}
+
+int call_opengl(int func_number, int pid, void* ret_string, void* args, void* args_size)
+{
+  __asm__ ("push %ebx");
+  __asm__ ("push %ecx");
+  __asm__ ("push %edx");
+  __asm__ ("push %esi");
+  __asm__ ("mov %0, %%eax"::"m"(func_number));
+  __asm__ ("mov %0, %%ebx"::"m"(pid));
+  __asm__ ("mov %0, %%ecx"::"m"(ret_string));
+  __asm__ ("mov %0, %%edx"::"m"(args));
+  __asm__ ("mov %0, %%esi"::"m"(args_size));
+  __asm__ ("int $0x99");
+  __asm__ ("pop %esi");
+  __asm__ ("pop %edx");
+  __asm__ ("pop %ecx");
+  __asm__ ("pop %ebx");
+}
+
+static void do_opengl_call(int func_number, void* ret_ptr, ...);
+
+static int pid_fork = -1;
+static int stop_now = 0;
+
+static void sigint_exit_process_func(int ignored)
+{
+  stop_now = 1;
+  if (pid_fork > 0)
+  {
+    call_opengl(_exit_process_func, pid_fork, NULL, NULL, NULL);
+    pid_fork = 0;
+  }
+  exit(0);
+}
+
+static void real_sigint_exit_process_func(int ignored)
+{
+  call_opengl(_exit_process_func, getpid(), NULL, NULL, NULL);
+  exit(0);
+}
+
+
+static void do_init()
+{
+  static int init_done = 0;
+  if (init_done == 0)
+  {
+    init_done = 1;
+    
+    pid_fork = fork();
+    if (pid_fork > 0)
+    {
+      struct sigaction action;
+      action.sa_sigaction = sigsegv_handler;
+      sigemptyset(&(action.sa_mask));
+      action.sa_flags = SA_SIGINFO;
+      sigaction(SIGSEGV, &action, &old_action);
+
+      signal(SIGINT, sigint_exit_process_func);
+      signal(SIGKILL, sigint_exit_process_func);
+      signal(SIGQUIT, sigint_exit_process_func);
+      int status;
+      wait(&status);
+      if (pid_fork > 0)
+      {
+        call_opengl(_exit_process_func, pid_fork, NULL, NULL, NULL);
+        pid_fork = 0;
+      }
+      if (WIFEXITED(status))
+      {
+        exit(WEXITSTATUS(status));
+      }
+      else
+      {
+        exit(0);
+      }
+    }
+    
+    signal(SIGINT, real_sigint_exit_process_func);
+    
+    struct sigaction action;
+    action.sa_sigaction = sigsegv_handler;
+    sigemptyset(&(action.sa_mask));
+    action.sa_flags = SA_SIGINFO;
+    sigaction(SIGSEGV, &action, &old_action);
+  }
+}
+
+static int try_to_put_into_phys_memory(void* addr, int len)
+{
+  int pagesize = getpagesize();
+  int i;
+  void* aligned_addr = ((long)addr & (~(pagesize - 1)));
+  int to_end_page = (long)aligned_addr + pagesize - (long)addr;
+  char c = 0;
+  if (aligned_addr != addr)
+  {
+    c += ((char*)addr)[0];
+    if (len <= to_end_page)
+    {
+      return c;
+    }
+    len -= to_end_page;
+    addr = aligned_addr + pagesize;
+  }
+  for(i=0;i<len;i+=pagesize)
+  {
+    c += ((char*)addr)[0];
+    addr += pagesize;
+  }
+  return c;
+}
+
+static void do_opengl_call(int func_number, void* ret_ptr, ...)
+{
+  if( ! (func_number >= 0 && func_number < GL_N_CALLS) )
+  {
+    fprintf(stderr, "func_number >= 0 && func_number < GL_N_CALLS failed\n");
+    return;
+  }
+
+  Signature* signature = (Signature*)tab_opengl_calls[func_number];
+  int ret_type = signature->ret_type;
+  int nb_args = signature->nb_args;
+  int* args_type = signature->args_type;
+  static long args[100] = {0};
+  static int args_size[100]={0};
+  static double args_double[100]={0};
+  static char* ret_string = NULL;
+  int ret_int;
+  va_list list;
+  int i;
+  
+  do_init();
+
+  if (ret_string == NULL)
+  {
+    int pagesize = getpagesize();
+    int nbPages = 32768 / pagesize;
+    posix_memalign(&ret_string, pagesize, 32768);
+    memset(ret_string, 0, 32768);
+    int ret = mlock(ret_string, 32768);
+    if (ret == -1)
+    {
+      fprintf(stderr, "errno = %d, ENOMEM=%d, EPERM=%d, EINVAL=%d\n", errno, ENOMEM, EPERM, EINVAL);
+      assert(0);
+    }
+  }
+  
+  //fprintf(stderr, "%s\n", tab_opengl_calls_name[func_number]);
+  
+  va_start(list, ret_ptr);
+  for(i=0;i<nb_args;i++)
+  {
+    void* arg_pointer;
+    char arg_char;
+    short arg_short;
+    int arg_int;
+    float arg_float;
+    double arg_double;
+    switch(args_type[i])
+    {
+      case TYPE_NONE:
+        args[i] = NULL;
+        break;
+        
+      case TYPE_UNSIGNED_INT:
+      case TYPE_INT:
+      {
+        arg_int = va_arg(list, int);
+        args[i] = arg_int;
+        break;
+      }
+      
+      case TYPE_FLOAT:
+      {
+        arg_float = va_arg(list, double);
+        args[i] = *(int*)&arg_float;
+        break;
+      }
+      
+      case TYPE_DOUBLE:
+      {
+        arg_double = va_arg(list, double);
+        args_double[i] = arg_double;
+        args[i] = (long)&args_double[i];
+        break;
+      }
+      
+      case TYPE_UNSIGNED_CHAR:
+      {
+        arg_char = va_arg(list, int);
+        args[i] = arg_char;
+        break;
+      }
+      
+      case TYPE_CHAR:
+      {
+        arg_char = va_arg(list, int);
+        args[i] = arg_char;
+        break;
+      }
+      
+      case TYPE_UNSIGNED_SHORT:
+      {
+        arg_short = va_arg(list, int);
+        args[i] = arg_short;
+        break;
+      }
+      
+      case TYPE_SHORT:
+      {
+        arg_short = va_arg(list, int);
+        args[i] = arg_short;
+        break;
+      }
+
+      case TYPE_POINTER:
+      {
+        arg_pointer = va_arg(list, void*);
+        args[i] = (int)arg_pointer;
+        break;
+      }
+      
+      case TYPE_NONE_TERMINATED_INT_ARRAY:
+      {
+        int* tab = va_arg(list, int*);
+        args[i] = (int)tab;
+        int array_size = 0;
+        while(tab[array_size])
+        {
+          array_size++;
+        }
+        array_size++;
+        args_size[i] = array_size * sizeof(int);
+        break;
+      }
+      
+      case TYPE_ARRAY_CHAR:
+      {
+        int array_size = va_arg(list, int);
+        void* tab = va_arg(list, void*);
+        try_to_put_into_phys_memory(tab, array_size);
+        args[i] = tab;
+        args_size[i] = array_size;
+        break;
+      }
+      
+      case TYPE_ARRAY_INT:
+      {
+        int array_size = va_arg(list, int);
+        array_size *= sizeof(int);
+        int* tab = va_arg(list, int*);
+        try_to_put_into_phys_memory(tab, array_size);
+        args[i] = tab;
+        args_size[i] = array_size;
+        break;
+      }
+      
+      case TYPE_ARRAY_FLOAT:
+      {
+        int array_size = va_arg(list, int);
+        array_size *= sizeof(float);
+        float* tab = va_arg(list, float*);
+        try_to_put_into_phys_memory(tab, array_size);
+        args[i] = tab;
+        args_size[i] = array_size;
+        break;
+      }
+      
+      case TYPE_ARRAY_DOUBLE:
+      {
+        int array_size = va_arg(list, int);
+        array_size *= sizeof(double);
+        double* tab = va_arg(list, double*);
+        try_to_put_into_phys_memory(tab, array_size);
+        args[i] = tab;
+        args_size[i] = array_size;
+        break;
+      }
+      
+      case TYPE_NULL_TERMINATED_STRING:
+      {
+        char* str = va_arg(list, char*);
+        int array_size = strlen(str) + 1;
+        args[i] = str;
+        args_size[i] = array_size;
+        break;
+      }
+      
+      case TYPE_OUT_INT_POINTER:
+      {
+        args[i] = va_arg(list, void*);
+        args_size[i] = sizeof(int);
+        break;
+      }
+      
+      case TYPE_IN_IGNORED_POINTER:
+      case TYPE_OUT_INT_ARRAY:
+      case TYPE_OUT_FLOAT_ARRAY:
+      case TYPE_OUT_DOUBLE_ARRAY:
+      {
+        args[i] = va_arg(list, void*);
+        args_size[i] = 0;
+        break;
+      }
+      
+      case TYPE_2CHAR:
+      case TYPE_3CHAR:
+      case TYPE_4CHAR:
+      case TYPE_2SHORT:
+      case TYPE_3SHORT:
+      case TYPE_4SHORT:
+      case TYPE_2INT:
+      case TYPE_3INT:
+      case TYPE_4INT:
+      case TYPE_2FLOAT:
+      case TYPE_3FLOAT:
+      case TYPE_4FLOAT:
+      case TYPE_16FLOAT:
+      case TYPE_2DOUBLE:
+      case TYPE_3DOUBLE:
+      case TYPE_4DOUBLE:
+      case TYPE_16DOUBLE:
+      {
+        void* tab = va_arg(list, void*);
+        try_to_put_into_phys_memory(tab, tab_args_type_length[args_type[i]]);
+        args[i] = tab;
+        break;
+      }
+      
+      default:
+      {
+        fprintf(stderr, "unexpected arg type %d\n", args_type[i]);
+        exit(-1);
+        break;
+      }
+    }
+  }
+  va_end(list);
+  
+  if (func_number == glActiveTexture_func || func_number == glActiveTextureARB_func)
+  {
+    //printf("server active texture %d\n", (int)args[0] - GL_TEXTURE0_ARB);
+  }
+  else
+  if (func_number == glClientActiveTexture_func || func_number == glClientActiveTextureARB_func)
+  {
+    clientActiveTexture = (int)args[0] - GL_TEXTURE0_ARB;
+    //printf("clientActiveTexture %d\n", clientActiveTexture);
+    assert(clientActiveTexture >= 0 && clientActiveTexture < 16);
+  }
+  else
+  if (func_number == glEnableClientState_func)
+  {
+    int num = (int)args[0] - GL_VERTEX_ARRAY;
+    if (num == GL_TEXTURE_COORD_ARRAY - GL_VERTEX_ARRAY)
+    {
+      //printf("enable texture %d\n", clientActiveTexture);
+      texCoordPointerEnable[clientActiveTexture] = 1;
+    }
+    else
+    if (num >= 0 && num < 6)
+    {
+      //printf("enable feature %d\n", num);
+      pointerArraysEnable[num] = 1;
+    }
+  }
+  else if (func_number == glDisableClientState_func)
+  {
+    int num = (int)args[0] - GL_VERTEX_ARRAY;
+    if (num == GL_TEXTURE_COORD_ARRAY - GL_VERTEX_ARRAY)
+    {
+      //printf("disable texture %d\n", clientActiveTexture);
+      texCoordPointerEnable[clientActiveTexture] = 0;
+    }
+    else
+    if (num >= 0 && num < 6)
+    {
+      //printf("disable feature %d\n", num);
+      pointerArraysEnable[num] = 0;
+    }
+  }
+  else if (func_number == glPushClientAttrib_func)
+  {
+    if ((int)args[0] & GL_CLIENT_VERTEX_ARRAY_BIT)
+    {
+      printf("save vertex array\n");
+    }
+  }
+
+  /* We set fake values into the pointers to avoid make QEMU crash */
+  switch (func_number)
+  {
+    case glXQueryVersion_func:
+    {
+      int* ptr;
+      ptr = (int*)args[1];
+      if (ptr) *ptr = 0;
+      ptr = (int*)args[2];
+      if (ptr) *ptr = 0;
+      break;
+    }
+    
+    case glXGetConfig_func:
+    {
+      *(int*)args[3] = 0;
+      break;
+    }
+    
+    case glGetIntegerv_func:
+    {
+      int* ptr = (int*)args[1];
+      int param = (int)args[0];
+      i = 0;
+      while(limits[i].count)
+      {
+        if (limits[i].token == param)
+        {
+          memset(ptr, 0, limits[i].count * sizeof(int));
+          break;
+        }
+        i++;
+      }
+      if (limits[i].count == 0)
+      {
+        fprintf(stderr, "unknown name for glGetIntegerv : %d\n", param);
+      }
+      args_size[1] = limits[i].count * sizeof(int);
+      break;
+    }
+    
+    case glGetFloatv_func:
+    {
+      float* ptr = (float*)args[1];
+      int param = (int)args[0];
+      i = 0;
+      while(limits[i].count)
+      {
+        if (limits[i].token == param)
+        {
+          memset(ptr, 0, limits[i].count * sizeof(float));
+          break;
+        }
+        i++;
+      }
+      if (limits[i].count == 0)
+      {
+        fprintf(stderr, "unknown name for glGetFloatv : %d\n", param);
+      }
+      args_size[1] = limits[i].count * sizeof(float);
+      break;
+    }
+    
+    case glGetConvolutionParameteriv_func:
+    {
+      int* ptr = (int*)args[2];
+      args_size[2] = (((int)args[1] == GL_CONVOLUTION_BORDER_COLOR) ? 4 : 1) * sizeof(int);
+      memset(ptr, 0, (((int)args[1] == GL_CONVOLUTION_BORDER_COLOR) ? 4 : 1) * sizeof(int));
+      break;
+    }
+    
+    case glXQueryExtension_func:
+    {
+      int* ptr;
+      ptr = (int*)args[1];
+      if (ptr) *ptr = 0;
+      ptr = (int*)args[2];
+      if (ptr) *ptr = 0;
+      break;
+    }
+    
+    case glGenTextures_func:
+    {
+      assert(args[1]);
+      memset(args[1], 0, (int)args[0] * sizeof(int));
+      args_size[1] = (int)args[0] * sizeof(int);
+      break;
+    }
+    
+    case glGetTexLevelParameteriv_func:
+    {
+      int* ptr = (int*)args[3];
+      assert(ptr);
+      *ptr = 0;
+      break;
+    }
+    
+    case glGenProgramsARB_func:
+    {
+      assert(args[1]);
+      *(int*)args[1] = 0;
+      break;
+    }
+    
+    case glXChooseFBConfig_func:
+    {
+      assert(args[3]);
+      *(int*)args[3] = 0;
+      break;
+    }
+    
+    case glGetVertexAttribfvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(float));
+      args_size[2] = (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(float);
+      break;
+    }
+    
+    case glGetVertexAttribivARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(int));
+      args_size[2] = (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(int);
+      break;
+    }
+    
+    case glGetVertexAttribdvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(double));
+      args_size[2] = (((int)args[1] == GL_CURRENT_VERTEX_ATTRIB_ARB) ? 4 : 1) * sizeof(double);
+      break;
+    }
+    
+    case glGetProgramLocalParameterfvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, 4 * sizeof(float));
+      args_size[2] = 4 * sizeof(float);
+      break;
+    }
+    
+    case glGetProgramLocalParameterdvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, 4 * sizeof(double));
+      args_size[2] = 4 * sizeof(double);
+      break;
+    }
+    
+    case glGetProgramEnvParameterfvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, 4 * sizeof(float));
+      args_size[2] = 4 * sizeof(float);
+      break;
+    }
+    
+    case glGetProgramEnvParameterdvARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, 4 * sizeof(double));
+      args_size[2] = 4 * sizeof(double);
+      break;
+    }
+    
+    case glGetProgramivARB_func:
+    {
+      assert(args[2]);
+      memset(args[2], 0, sizeof(int));
+      break;
+    }
+    
+    case glGetProgramStringARB_func:
+    {
+      int len;
+      assert(args[2]);
+      assert(0); // FIXME
+      /*read_from_sock(sock, &len, sizeof(int));
+      read_from_sock(sock, args[2], len);*/
+    }
+    
+    default:
+      break;
+  }
+  
+  if (signature->ret_type == TYPE_CONST_CHAR)
+  {
+    try_to_put_into_phys_memory(ret_string, 32768);
+  }
+  
+  // DO CALL
+  if (stop_now)
+    return;
+  
+  ret_int = call_opengl(func_number, getpid(), (signature->ret_type == TYPE_CONST_CHAR) ? ret_string : NULL, args, args_size);
+  
+  if (signature->ret_type == TYPE_UNSIGNED_INT ||
+      signature->ret_type == TYPE_INT)
+  {
+    *(int*)ret_ptr = ret_int;
+  }
+  else if (signature->ret_type == TYPE_UNSIGNED_CHAR ||
+           signature->ret_type == TYPE_CHAR)
+  {
+    *(char*)ret_ptr = ret_int;
+  }
+  else if (signature->ret_type == TYPE_POINTER)
+  {
+    *(void**)ret_ptr = (void*)ret_int;
+  }
+  else if (signature->ret_type == TYPE_CONST_CHAR)
+  {
+    char* ret_str = NULL;
+    if (func_number == glXQueryExtensionsString_func)
+    {
+      static char* glXQueryExtensionsString_ret = NULL;
+      if (glXQueryExtensionsString_ret) free(glXQueryExtensionsString_ret);
+      glXQueryExtensionsString_ret = ret_str = strdup(ret_string);
+    }
+    else if (func_number == glXQueryServerString_func)
+    {
+      static char* glXQueryServerString_ret[100] = {NULL};
+      int name = (int)args[2];
+      assert(name >= 0 && name < 100);
+      if (glXQueryServerString_ret[name]) free(glXQueryServerString_ret[name]);
+      glXQueryServerString_ret[name] = ret_str = strdup(ret_string);
+    }
+    else if (func_number == glXGetClientString_func)
+    {
+      static char* glXGetClientString_ret[100] = {NULL};
+      int name = (int)args[1];
+      assert(name >= 0 && name < 100);
+      if (glXGetClientString_ret[name]) free(glXGetClientString_ret[name]);
+      glXGetClientString_ret[name] = ret_str = strdup(ret_string);
+    }
+    else if (func_number == glGetString_func)
+    {
+      static char* glGetString_ret[10000] = {NULL};
+      int name = (int)args[0];
+      assert(name >= 0 && name < 10000);
+      if (glGetString_ret[name]) free(glGetString_ret[name]);
+      glGetString_ret[name] = ret_str = strdup(ret_string);
+    }
+    else
+    {
+      exit(-1);
+    }
+    *(char**)(ret_ptr) = ret_str;
+  }
+  
+  /*switch (func_number)
+  {
+    case glXChooseVisual_func:
+    {
+      Display* dpy = args[0];
+      int screen = (int)args[1];
+      
+      XVisualInfo temp, *vis;
+      long mask;
+      int n;
+
+      mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+      temp.screen = screen;
+      temp.depth = DefaultDepth(dpy,screen);
+      temp.class = DefaultVisual(dpy,screen)->class;
+      temp.visualid = DefaultVisual(dpy,screen)->visualid;
+      mask |= VisualIDMask;
+
+      vis = XGetVisualInfo( dpy, mask, &temp, &n );
+      
+      *(void**)(ret_ptr) = vis;
+      break;
+    }
+    
+    default:
+      break;
+}*/
+}
+
+void glGetIntegerv( GLenum pname, GLint *params )
+{
+  do_opengl_call(glGetIntegerv_func, NULL, pname, params);
+}
+
+void glGetFloatv( GLenum pname, GLfloat *params )
+{
+  do_opengl_call(glGetFloatv_func, NULL, pname, params);
+}
+
+const char *glXQueryExtensionsString( Display *dpy, int screen )
+{
+  const char* ret = NULL;
+  do_opengl_call(glXQueryExtensionsString_func, &ret, dpy, screen);
+  return ret;
+}
+
+XVisualInfo* glXChooseVisual( Display *dpy, int screen,
+                              int *attribList )
+{
+  XVisualInfo temp, *vis;
+  long mask;
+  int n;
+  
+  mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+  temp.screen = screen;
+  temp.depth = DefaultDepth(dpy,screen);
+  temp.class = DefaultVisual(dpy,screen)->class;
+  temp.visualid = DefaultVisual(dpy,screen)->visualid;
+  mask |= VisualIDMask;
+
+  vis = XGetVisualInfo( dpy, mask, &temp, &n );
+  
+  //do_opengl_call(glXChooseVisual_func, vis, dpy, screen, attribList);
+  
+  return vis;
+}
+
+const char *glXQueryServerString( Display *dpy, int screen, int name )
+{
+  const char* ret = NULL;
+  do_opengl_call(glXQueryServerString_func, &ret, dpy, screen, name);
+  return ret;
+}
+
+const char *glXGetClientString( Display *dpy, int name )
+{
+  const char* ret = NULL;
+  do_opengl_call(glXGetClientString_func, &ret, dpy, name);
+  return ret;
+}
+
+GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis,
+                             GLXContext shareList, Bool direct )
+{
+  GLXContext ret = NULL;
+  do_opengl_call(glXCreateContext_func, &ret, dpy, vis, shareList, direct);
+  printf("glXCreateContext = %p\n", ret);
+  return ret;
+}
+
+GLXContext glXGetCurrentContext (void)
+{
+  GLXContext ret = NULL;
+  do_opengl_call(glXGetCurrentContext_func, &ret);
+  printf("glXGetCurrentContext = %p\n", ret);
+  return ret;
+}
+
+GLXDrawable glXGetCurrentDrawable (void)
+{
+  GLXDrawable ret = 0;
+  do_opengl_call(glXGetCurrentDrawable_func, &ret);
+  printf("glXGetCurrentDrawable = %p\n", (void*)ret);
+  return ret;
+}
+
+void glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+  printf("glXDestroyContext %p\n", ctx);
+  do_opengl_call(glXDestroyContext_func, NULL, dpy, ctx);
+}
+
+Bool glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+  Bool ret = False;
+  do_opengl_call(glXQueryVersion_func, &ret, dpy, maj, min);
+  return ret;
+}
+
+
+typedef struct
+{
+  int x;
+  int y;
+  int width;
+  int height;
+  int map_state;
+} WindowPosStruct;
+
+static WindowPosStruct oldPos = {0};
+
+static void _get_window_pos(Display *dpy, Window win, WindowPosStruct* pos)
+{
+  XWindowAttributes window_attributes_return;
+  Window child;
+  int x, y;
+  Window root = DefaultRootWindow(dpy);
+  XGetWindowAttributes(dpy, win, &window_attributes_return);
+  XTranslateCoordinates(dpy, win, root, 0, 0, &x, &y, &child);
+  /*printf("%d %d %d %d\n", x, y,
+  window_attributes_return.width, window_attributes_return.height);*/
+  pos->x = x;
+  pos->y = y;
+  pos->width = window_attributes_return.width;
+  pos->height = window_attributes_return.height;
+  pos->map_state = window_attributes_return.map_state;
+}
+
+static GLXPbuffer pbuffer = NULL;
+
+static void _move_win_if_necessary(Display *dpy, Window win)
+{
+  if (pbuffer != NULL && win == pbuffer)
+  {
+    return;
+  }
+  
+  WindowPosStruct pos;
+  _get_window_pos(dpy, win, &pos);
+  if (memcmp(&pos, &oldPos, sizeof(oldPos)) != 0)
+  {
+    if (pos.map_state != oldPos.map_state)
+    {
+      do_opengl_call(_changeWindowState_func, NULL, win, pos.map_state);
+    }
+    memcpy(&oldPos, &pos, sizeof(oldPos));
+    do_opengl_call(_moveResizeWindow_func, NULL, win, &pos);
+  }
+}
+
+Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{
+  Bool ret = False;
+  do_opengl_call(glXMakeCurrent_func, &ret, dpy, drawable, ctx);
+  _move_win_if_necessary(dpy, drawable);
+  return ret;
+}
+
+
+Bool glXIsDirect( Display *dpy, GLXContext ctx )
+{
+  Bool ret = False;
+  do_opengl_call(glXIsDirect_func, &ret, dpy, ctx);
+  return ret;
+}
+
+int glXGetConfig( Display *dpy, XVisualInfo *visual,
+                  int attrib, int *value )
+{
+  int ret = 0;
+  do_opengl_call(glXGetConfig_func, &ret, dpy, visual, attrib, value);
+  return ret;
+}
+
+void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+  _move_win_if_necessary(dpy, drawable);
+  do_opengl_call(glXSwapBuffers_func, NULL, dpy, drawable);
+}
+
+Bool glXQueryExtension( Display *dpy,
+                        int *errorBase,
+                        int *eventBase )
+{
+  Bool ret;
+  do_opengl_call(glXQueryExtension_func, &ret, dpy, errorBase, eventBase);
+  return ret;
+}
+
+void glXWaitGL (void)
+{
+}
+
+void glXWaitX (void)
+{
+}
+
+#if 0
+GLXFBConfig* fbConfig = NULL;
+
+GLXFBConfig *glXChooseFBConfig( Display *dpy, int screen,
+                                const int *attribList, int *nitems )
+{
+  GLXFBConfig * ret = NULL;
+  do_opengl_call(glXChooseFBConfig_func, &ret, dpy, screen, attribList, nitems);
+  fbConfig = ret = malloc(sizeof(GLXFBConfig) * (*nitems));
+  int i;
+  for(i=0;i<*nitems;i++)
+  {
+    fbConfig[i] = i + 1;
+  }
+  printf("nitems = %d\n", *nitems);
+  return ret;
+}
+
+GLXPbuffer glXCreatePbuffer(Display *dpy,
+                            GLXFBConfig config,
+                            const int *AttributeList)
+{
+  GLXPbuffer ret = NULL;
+  int i = (int)config - 1;
+  printf("fb config %d\n", i);
+  do_opengl_call(glXCreatePbuffer_func, &ret, dpy, i, AttributeList);
+  printf("pbuffer = %p\n", ret);
+  pbuffer = ret;
+  return ret;
+}
+
+XVisualInfo *glXGetVisualFromFBConfig( Display *dpy,
+                                       GLXFBConfig config )
+{
+  int screen = 0;
+      
+  XVisualInfo temp, *vis;
+  long mask;
+  int n;
+  
+  mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+  temp.screen = screen;
+  temp.depth = DefaultDepth(dpy,screen);
+  temp.class = DefaultVisual(dpy,screen)->class;
+  temp.visualid = DefaultVisual(dpy,screen)->visualid;
+  mask |= VisualIDMask;
+
+  vis = XGetVisualInfo( dpy, mask, &temp, &n );
+  
+  int i = (int)config - 1;
+  do_opengl_call(glXGetVisualFromFBConfig_func, vis, dpy, i);
+  
+  return vis;
+  
+}
+
+void glXUseXFont( Font font_id, int first, int count, int list )
+{
+  fprintf(stderr, "glXUseXFont : unsupported call\n");
+  //do_opengl_call(glXUseXFont_func, NULL, font, first, count, list);
+}
+#endif
+
+#include "client_stub.c"
+
+const GLubyte * glGetString( GLenum name )
+{
+  const GLubyte* ret = NULL;
+  do_opengl_call(glGetString_func, &ret, name);
+  return ret;
+}
+
+void glGetConvolutionParameteriv( GLenum target, GLenum pname,
+                                  GLint *params )
+{
+  do_opengl_call(glGetConvolutionParameteriv_func, NULL, target, pname, params);
+}
+
+void glLightfv( GLenum light, GLenum pname, const GLfloat *params )
+{
+  int size = 0;
+  switch(pname)
+  {
+    case GL_AMBIENT:
+    case GL_DIFFUSE:
+    case GL_SPECULAR:
+    case GL_POSITION:
+      size = 4;
+      break;
+      
+    case GL_SPOT_DIRECTION:
+      size = 3;
+      break;
+      
+    case GL_SPOT_EXPONENT:
+    case GL_SPOT_CUTOFF:
+    case GL_CONSTANT_ATTENUATION:
+    case GL_LINEAR_ATTENUATION:
+    case GL_QUADRATIC_ATTENUATION:
+      size = 1;
+      break;
+      
+    default:
+      fprintf(stderr, "unhandled pname = %d\n", pname);
+      return;
+  }
+  do_opengl_call(glLightfv_func, NULL, light, pname, size, params);
+}
+
+void glMaterialfv( GLenum face, GLenum pname, const GLfloat *params )
+{
+  int size = 0;
+  switch(pname)
+  {
+    case GL_AMBIENT:
+    case GL_DIFFUSE:
+    case GL_SPECULAR:
+    case GL_EMISSION:
+    case GL_AMBIENT_AND_DIFFUSE:
+      size = 4;
+      break;
+      
+    case GL_SHININESS:
+      size = 1;
+      break;
+      
+    case GL_COLOR_INDEXES:
+      size = 3;
+      break;
+      
+    default:
+      fprintf(stderr, "unhandled pname = %d\n", pname);
+      return;
+  }
+  do_opengl_call(glMaterialfv_func, NULL, face, pname, size, params);
+}
+
+void glLightModelfv( GLenum pname,
+                     const GLfloat *params )
+{
+  int size = 0;
+  switch(pname)
+  {
+    case GL_LIGHT_MODEL_AMBIENT:
+      size = 4;
+      break;
+      
+    case GL_LIGHT_MODEL_COLOR_CONTROL:
+      fprintf(stderr, "not sure how to handle GL_LIGHT_MODEL_COLOR_CONTROL. Exiting\n");
+      return;
+      
+    case GL_LIGHT_MODEL_LOCAL_VIEWER:
+    case GL_LIGHT_MODEL_TWO_SIDE:
+      size = 1;
+      break;
+    
+    default:
+      fprintf(stderr, "unhandled pname = %d\n", pname);
+      return;
+  }
+  do_opengl_call(glLightModelfv_func, NULL, pname, size, params);
+}
+
+static int glMap1_get_multiplier(GLenum target)
+{
+  switch (target)
+  {
+    case GL_MAP1_VERTEX_3:
+    case GL_MAP1_NORMAL:
+    case GL_MAP1_TEXTURE_COORD_3:
+      return 3;
+      break;
+      
+    case GL_MAP1_VERTEX_4:
+    case GL_MAP1_COLOR_4:
+    case GL_MAP1_TEXTURE_COORD_4:
+      return 4;
+      break;
+      
+    case GL_MAP1_INDEX:
+    case GL_MAP1_TEXTURE_COORD_1:
+      return 1;
+      break;
+      
+    case GL_MAP1_TEXTURE_COORD_2:
+      return 2;
+      break;
+      
+    default:
+      fprintf(stderr, "unhandled target = %d\n", target);
+      return 0;
+  }
+}
+
+void glMap1f( GLenum target,
+              GLfloat u1,
+              GLfloat u2,
+              GLint stride,
+              GLint order,
+              const GLfloat *points )
+{
+  int num_points = order;
+  int multiplier = glMap1_get_multiplier(target);
+  if (multiplier)
+  {
+    num_points *= multiplier;
+    do_opengl_call(glMap1f_func, NULL,
+                  target, u1, u2, stride, order, num_points, points);
+  }
+}
+
+void glMap1d( GLenum target,
+              GLdouble u1,
+              GLdouble u2,
+              GLint stride,
+              GLint order,
+              const GLdouble *points )
+{
+  int num_points = order;
+  int multiplier = glMap1_get_multiplier(target);
+  if (multiplier)
+  {
+    num_points *= multiplier;
+    do_opengl_call(glMap1d_func, NULL,
+                  target, u1, u2, stride, order, num_points, points);
+  }
+}
+
+static int glMap2_get_multiplier(GLenum target)
+{
+  switch (target)
+  {
+    case GL_MAP2_VERTEX_3:
+    case GL_MAP2_NORMAL:
+    case GL_MAP2_TEXTURE_COORD_3:
+      return 3;
+      break;
+      
+    case GL_MAP2_VERTEX_4:
+    case GL_MAP2_COLOR_4:
+    case GL_MAP2_TEXTURE_COORD_4:
+      return 4;
+      break;
+      
+    case GL_MAP2_INDEX:
+    case GL_MAP2_TEXTURE_COORD_1:
+      return 1;
+      break;
+      
+    case GL_MAP2_TEXTURE_COORD_2:
+      return 2;
+      break;
+      
+    default:
+      fprintf(stderr, "unhandled target = %d\n", target);
+      return 0;
+  }
+}
+
+void glMap2f( GLenum target,
+              GLfloat u1,
+              GLfloat u2,
+              GLint ustride,
+              GLint uorder,
+              GLfloat v1,
+              GLfloat v2,
+              GLint vstride,
+              GLint vorder,
+              const GLfloat *points )
+{
+  int num_points = uorder * vorder;
+  int multiplier = glMap2_get_multiplier(target);
+  if (multiplier)
+  {
+    num_points *= multiplier;
+    do_opengl_call(glMap2f_func, NULL,
+                  target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, num_points, points);
+  }
+}
+
+
+void glMap2d( GLenum target,
+              GLdouble u1,
+              GLdouble u2,
+              GLint ustride,
+              GLint uorder,
+              GLdouble v1,
+              GLdouble v2,
+              GLint vstride,
+              GLint vorder,
+              const GLdouble *points )
+{
+  int num_points = uorder * vorder;
+  int multiplier = glMap2_get_multiplier(target);
+  if (multiplier)
+  {
+    num_points *= multiplier;
+    do_opengl_call(glMap2d_func, NULL,
+                  target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, num_points, points);
+  }
+}
+
+void glGenTextures( GLsizei n, GLuint *textures )
+{
+  do_opengl_call(glGenTextures_func, NULL, n, textures);
+}
+
+void glDeleteTextures ( GLsizei n, const GLuint *textures )
+{
+  do_opengl_call(glDeleteTextures_func, NULL, n, n, textures);
+}
+
+void glCallLists( GLsizei n,
+                  GLenum type,
+                  const GLvoid *lists )
+{
+  int size = n;
+  switch(type)
+  {
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+      break;
+      
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+    case GL_2_BYTES:
+      size *= 2;
+      break;
+      
+    case GL_3_BYTES:
+      size *= 3;
+      break;
+      
+    case GL_INT:
+    case GL_UNSIGNED_INT:
+    case GL_FLOAT:
+    case GL_4_BYTES:
+      size *= 4;
+      break;
+      
+    default:
+      fprintf(stderr, "unsupported type = %d\n", type);
+      return;
+  }
+  do_opengl_call(glCallLists_func, NULL, n, type, size, lists);
+}
+
+void EXT_FUNC(glGenProgramsARB) (GLsizei n, GLuint* programs)
+{
+  CHECK_PROC(glGenProgramsARB);
+  do_opengl_call(glGenProgramsARB_func, NULL, n, programs);
+}
+
+void EXT_FUNC(glDeleteProgramsARB) (GLsizei n, const GLuint *programs)
+{
+  CHECK_PROC(glDeleteProgramsARB);
+  do_opengl_call(glDeleteProgramsARB_func, NULL, n, programs);
+}
+
+void EXT_FUNC(glProgramStringARB) (GLenum a, GLenum b, GLsizei c, const GLvoid *d)
+{
+  CHECK_PROC(glProgramStringARB);
+  do_opengl_call(glProgramStringARB_func, NULL, a, b, c, c, d);
+}
+
+void EXT_FUNC(glShaderSourceARB) (GLhandleARB handle , GLsizei size, const GLcharARB* *p_tab_prog, const GLint * d)
+{
+  CHECK_PROC(glShaderSourceARB);
+  if (size == 1 && d == NULL && p_tab_prog != NULL)
+  {
+    do_opengl_call(glShaderSourceARB_func, NULL, handle, *p_tab_prog);
+  }
+  else
+  {
+    fprintf(stderr, "Unsupported parameters for glShaderSourceARB\n");
+  }
+}
+
+GLint EXT_FUNC(glGetUniformLocationARB) (GLhandleARB handle, const GLcharARB *txt)
+{
+  int ret;
+  CHECK_PROC_WITH_RET(glGetUniformLocationARB);
+  do_opengl_call(glGetUniformLocationARB_func, &ret, handle, txt);
+  return ret;
+}
+
+void EXT_FUNC(glCompressedTexImage2DARB)(GLenum target,
+                               GLint level,
+                               GLint internalformat,
+                               GLsizei width,
+                               GLsizei height,
+                               GLint border,
+                               GLsizei imageSize,
+                               const GLvoid * data)
+{
+  CHECK_PROC(glCompressedTexImage2DARB);
+  do_opengl_call(glCompressedTexImage2DARB_func, NULL,
+                 target, level, internalformat, width, height, border, imageSize, imageSize, data);
+}
+
+
+void EXT_FUNC(glCompressedTexSubImage2DARB)(GLenum target,
+                                  GLint level,
+                                  GLint xoffset,
+                                  GLint yoffset,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLenum format,
+                                  GLsizei imageSize,
+                                  const GLvoid * data)
+{
+  CHECK_PROC(glCompressedTexSubImage2DARB);
+  do_opengl_call(glCompressedTexSubImage2DARB_func, NULL,
+                 target, level, xoffset, yoffset, width, height, format, imageSize, imageSize, data);
+}
+
+void EXT_FUNC(glPointParameterfvARB)(GLenum pname, const GLfloat * params)
+{
+  int size;
+  CHECK_PROC(glPointParameterfvARB);
+  size = (pname == GL_POINT_DISTANCE_ATTENUATION) ? 3 : 1;
+  do_opengl_call(glPointParameterfvARB_func, NULL, pname, size, params);
+}
+
+void EXT_FUNC(glGetVertexAttribfvARB)(GLuint index, GLenum pname, GLfloat *params)
+{
+  CHECK_PROC(glGetVertexAttribfvARB);
+  do_opengl_call(glGetVertexAttribfvARB_func, NULL, index, pname, params);
+}
+
+void EXT_FUNC(glGetVertexAttribivARB)(GLuint index, GLenum pname, GLint *params)
+{
+  CHECK_PROC(glGetVertexAttribivARB);
+  do_opengl_call(glGetVertexAttribivARB_func, NULL, index, pname, params);
+}
+
+void EXT_FUNC(glGetVertexAttribdvARB)(GLuint index, GLenum pname, GLdouble *params)
+{
+  CHECK_PROC(glGetVertexAttribdvARB);
+  do_opengl_call(glGetVertexAttribdvARB_func, NULL, index, pname, params);
+}
+
+void EXT_FUNC(glGetProgramLocalParameterfvARB) (GLenum target, GLuint index, GLfloat *params)
+{
+  CHECK_PROC(glGetProgramLocalParameterfvARB);
+  do_opengl_call(glGetProgramLocalParameterfvARB_func, NULL, target, index, params);
+}
+
+void EXT_FUNC(glGetProgramLocalParameterdvARB) (GLenum target, GLuint index, GLdouble *params)
+{
+  CHECK_PROC(glGetProgramLocalParameterdvARB);
+  do_opengl_call(glGetProgramLocalParameterdvARB_func, NULL, target, index, params);
+}
+
+void EXT_FUNC(glGetProgramEnvParameterfvARB) (GLenum target, GLuint index, GLfloat *params)
+{
+  CHECK_PROC(glGetProgramEnvParameterfvARB);
+  do_opengl_call(glGetProgramEnvParameterfvARB_func, NULL, target, index, params);
+}
+
+void EXT_FUNC(glGetProgramEnvParameterdvARB) (GLenum target, GLuint index, GLdouble *params)
+{
+  CHECK_PROC(glGetProgramEnvParameterdvARB);
+  do_opengl_call(glGetProgramEnvParameterdvARB_func, NULL, target, index, params);
+}
+
+void EXT_FUNC(glGetProgramivARB) (GLenum target, GLenum pname, GLint *params)
+{
+  CHECK_PROC(glGetProgramivARB);
+  do_opengl_call(glGetProgramivARB_func, NULL, target, pname, params);
+}
+
+void EXT_FUNC(glGetProgramStringARB) (GLenum target, GLenum pname, GLvoid *string)
+{
+  CHECK_PROC(glGetProgramStringARB);
+  do_opengl_call(glGetProgramStringARB_func, NULL, target, pname, string);
+}
+
+static int getTexImageFactorFromFormat(int format)
+{
+  switch (format)
+  {
+    case GL_COLOR_INDEX:
+    case GL_RED:
+    case GL_GREEN:
+    case GL_BLUE:
+    case GL_ALPHA:
+    case GL_LUMINANCE:
+    case GL_INTENSITY:
+      return 1;
+      break;
+      
+    case GL_LUMINANCE_ALPHA:
+      return 2;
+      break;
+      
+    case GL_RGB:
+    case GL_BGR:
+      return 3;
+      break;
+      
+    case GL_RGBA:
+    case GL_BGRA:
+      return 4;
+      break;
+          
+    default:
+      fprintf(stderr, "unknown texture format : %d\n", format);
+      return 0;
+  }
+}
+
+void glTexImage1D(GLenum target,
+                  GLint level,
+                  GLint internalFormat,
+                  GLsizei width,
+                  GLint border,
+                  GLenum format,
+                  GLenum type,
+                  const GLvoid *pixels )
+{
+ int size = width * getTexImageFactorFromFormat(format);
+  
+  if (type != GL_UNSIGNED_BYTE)
+  {
+    fprintf(stderr, "unknown pixel type : %d\n", type);
+    return;
+  }
+
+  if (pixels == NULL) size = 0;
+  do_opengl_call(glTexImage1D_func, NULL, target, level, internalFormat, width, border, format, type, size, pixels);
+
+}
+
+void glTexImage2D( GLenum target,
+                   GLint level,
+                   GLint internalFormat,
+                   GLsizei width,
+                   GLsizei height,
+                   GLint border,
+                   GLenum format,
+                   GLenum type,
+                   const GLvoid *pixels )
+{
+  int size = width * height * getTexImageFactorFromFormat(format);
+  
+  if (type != GL_UNSIGNED_BYTE)
+  {
+    fprintf(stderr, "unknown pixel type : %d\n", type);
+    return;
+  }
+
+  if (pixels == NULL) size = 0;
+  do_opengl_call(glTexImage2D_func, NULL, target, level, internalFormat, width, height, border, format, type, size, pixels);
+}
+
+void glTexSubImage2D( GLenum target,
+                      GLint level,
+                      GLint xoffset,
+                      GLint yoffset,
+                      GLsizei width,
+                      GLsizei height,
+                      GLenum format,
+                      GLenum type,
+                      const GLvoid *pixels )
+{
+  int size = width * height * getTexImageFactorFromFormat(format);
+  
+  if (type != GL_UNSIGNED_BYTE)
+  {
+    fprintf(stderr, "unknown pixel type : %d\n", type);
+    return;
+  }
+
+  do_opengl_call(glTexSubImage2D_func, NULL, target, level, xoffset, yoffset, width, height, format, type, size, pixels);
+}
+
+void glTexImage3D( GLenum target,
+                   GLint level,
+                   GLint internalFormat,
+                   GLsizei width,
+                   GLsizei height,
+                   GLsizei depth,
+                   GLint border,
+                   GLenum format,
+                   GLenum type,
+                   const GLvoid *pixels )
+{
+  int size = width * height * depth * getTexImageFactorFromFormat(format);
+  
+  if (type != GL_UNSIGNED_BYTE)
+  {
+    fprintf(stderr, "unknown pixel type : %d\n", type);
+    return;
+  }
+
+  do_opengl_call(glTexImage3D_func, NULL, target, level, internalFormat, width, height, depth, border, format, type, size, pixels);
+}
+
+void glGetTexLevelParameteriv( GLenum target,
+                               GLint level,
+                               GLenum pname,
+                               GLint *params )
+{
+  do_opengl_call(glGetTexLevelParameteriv_func, NULL, target, level, pname, params);
+}
+
+void glTexParameterfv( GLenum target,
+                        GLenum pname,
+                        const GLfloat *params )
+{
+  int size = (pname == GL_TEXTURE_BORDER_COLOR) ? 4 : 1;
+  do_opengl_call(glTexParameterfv_func, NULL, target, pname, size, params);
+}
+
+void glTexParameteriv( GLenum target,
+                       GLenum pname,
+                       const GLint *params )
+{
+  int size = (pname == GL_TEXTURE_BORDER_COLOR) ? 4 : 1;
+  do_opengl_call(glTexParameteriv_func, NULL, target, pname, size, params);
+}
+
+void glFogfv( GLenum pname, const GLfloat *params )
+{
+  int size;
+  if (pname == GL_FOG_COLOR)
+    size = 4;
+  else
+    size = 1;
+  do_opengl_call(glFogfv_func, NULL, pname, size, params);
+}
+
+void glBitmap(GLsizei width,
+              GLsizei height,
+              GLfloat xorig,
+              GLfloat yorig,
+              GLfloat xmove,
+              GLfloat ymove,
+              const GLubyte *bitmap ) 
+{
+  int size = width * height;
+  //printf("bitmap %d %d %d\n", width, height, size);
+  do_opengl_call(glBitmap_func, NULL, width, height, xorig, yorig, xmove, ymove, size, bitmap);
+}
+
+void glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params )
+{
+  int size = (pname == GL_TEXTURE_GEN_MODE) ? 1 : 4;
+  do_opengl_call(glTexGenfv_func, NULL, coord, pname, size, params);
+}
+
+void glTexEnvfv( GLenum target,
+                 GLenum pname,
+                 const GLfloat *params )
+{
+  int size = (pname == GL_TEXTURE_ENV_MODE) ? 1 : 4;
+  do_opengl_call(glTexEnvfv_func, NULL, target, pname, size, params);
+}
+
+void glVertexPointer( GLint size,
+                      GLenum type,
+                      GLsizei stride,
+                      const GLvoid *ptr )
+{
+  //printf("glVertexPointer %d %d %d %p\n", size, type, stride, ptr);
+  vertexPointer.size = size;
+  vertexPointer.type = type;
+  vertexPointer.stride = stride;
+  vertexPointer.ptr = ptr;
+}
+
+void glNormalPointer( GLenum type,
+                      GLsizei stride,
+                      const GLvoid *ptr )
+{
+  //printf("glNormalPointer %d %d %p\n", type, stride, ptr);
+  normalPointer.size = 3;
+  normalPointer.type = type;
+  normalPointer.stride = stride;
+  normalPointer.ptr = ptr;
+}
+
+void glColorPointer( GLint size,
+                     GLenum type,
+                     GLsizei stride,
+                     const GLvoid *ptr )
+{
+  //printf("glColorPointer %d %d %d %p\n", size, type, stride, ptr);
+  colorPointer.size = size;
+  colorPointer.type = type;
+  colorPointer.stride = stride;
+  colorPointer.ptr = ptr;
+}
+
+void glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *ptr )
+{
+  //printf("glTexCoordPointer %d %d %d %p\n", size, type, stride, ptr);
+  texCoordPointer[clientActiveTexture].size = size;
+  texCoordPointer[clientActiveTexture].type = type;
+  texCoordPointer[clientActiveTexture].stride = stride;
+  texCoordPointer[clientActiveTexture].ptr = ptr;
+}
+
+static int getMulFactorFromPointerArray(VertexNormalColorPointerStruct* array)
+{
+  switch(array->type)
+  {
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+      return array->stride + array->size;
+      break;
+      
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+      return array->stride + 2 * array->size;
+      break;
+      
+    case GL_INT:
+    case GL_UNSIGNED_INT:
+    case GL_FLOAT:
+      return array->stride + 4 * array->size;
+      break;
+      
+    case GL_DOUBLE:
+      return array->stride + 8 * array->size;
+      break;
+
+    default:
+      fprintf(stderr, "unsupported type = %d\n", array->type);
+      return 0;
+  }
+}
+
+void _glArraySend(int func, VertexNormalColorPointerStruct* array, int nbElts)
+{
+  int data_size = nbElts * getMulFactorFromPointerArray(array);
+  if (func == glNormalPointer_func)
+    do_opengl_call(func, NULL,
+                    array->type, array->stride, data_size, data_size, array->ptr);
+  else
+    do_opengl_call(func, NULL,
+                  array->size, array->type, array->stride, data_size, data_size, array->ptr);
+}
+
+
+void _glArraysSend(int nbElts)
+{
+  if (pointerArraysEnable[GL_VERTEX_ARRAY - GL_VERTEX_ARRAY])
+  {
+    //printf("vertex enable\n");
+    _glArraySend(glVertexPointer_func, &vertexPointer, nbElts);
+  }
+  
+  if (pointerArraysEnable[GL_NORMAL_ARRAY - GL_VERTEX_ARRAY])
+  {
+    //printf("normal enable\n");
+    _glArraySend(glNormalPointer_func, &normalPointer, nbElts);
+  }
+  
+  if (pointerArraysEnable[GL_COLOR_ARRAY - GL_VERTEX_ARRAY])
+  {
+    //printf("color enable\n");
+    _glArraySend(glColorPointer_func, &colorPointer, nbElts);
+  }
+  
+  //if (pointerArraysEnable[GL_TEXTURE_COORD_ARRAY - GL_VERTEX_ARRAY])
+  if (texCoordPointerEnable[clientActiveTexture])
+  {
+    printf("texture enable\n");
+    _glArraySend(glTexCoordPointer_func, &texCoordPointer[clientActiveTexture], nbElts);
+  }
+}
+
+void glDrawArrays( GLenum mode,
+                   GLint first,
+                   GLsizei count )
+{
+  _glArraysSend(first + count);
+  do_opengl_call(glDrawArrays_func, NULL, mode, first, count);
+}
+
+
+void glDrawElements( GLenum mode,
+                     GLsizei count,
+                     GLenum type,
+                     const GLvoid *indices )
+{
+  int i;
+  int size = count;
+  int maxIndice = -1;
+  
+  if (count == 0) return;
+  
+  switch(type)
+  {
+    case GL_UNSIGNED_BYTE:
+    {
+      unsigned char* c = indices;
+      for(i=0;i<count;i++)
+      {
+        if (i == 0 || c[i] > maxIndice) maxIndice = c[i];
+      }
+      break;
+    }
+      
+    case GL_UNSIGNED_SHORT:
+    {
+      size *= 2;
+      unsigned short* s = indices;
+      for(i=0;i<count;i++)
+      {
+        if (i == 0 || s[i] > maxIndice) maxIndice = s[i];
+      }
+      break;
+    }
+      
+    case GL_UNSIGNED_INT:
+    {
+      size *= 4;
+      unsigned int* _int = indices;
+      for(i=0;i<count;i++)
+      {
+        if (i == 0 || _int[i] > maxIndice) maxIndice = _int[i];
+      }
+      break;
+    }
+
+    default:
+      fprintf(stderr, "unsupported type = %d\n", type);
+      return;
+  }
+  
+  //printf("glDrawElements : %d %d %d %p %d\n", mode, count, type, indices, maxIndice);
+
+#if 0
+  do_opengl_call(glBegin_func, NULL, mode);
+  if (type == GL_UNSIGNED_INT)
+  {
+    for(i=0;i<count;i++)
+    {
+      //do_opengl_call(glArrayElement_func, NULL, ((unsigned int*)indices)[i]);
+      int indice = ((unsigned int*)indices)[i];
+      glNormal3fv(normalPointer.ptr + indice * normalPointer.stride);
+      if (pointerArraysEnable[GL_COLOR_ARRAY - GL_VERTEX_ARRAY])
+      {
+        glColor4ubv(colorPointer.ptr + indice * colorPointer.stride);
+      }
+      glVertex3fv(vertexPointer.ptr + indice * vertexPointer.stride);
+      /*glNormal3fv((float*)(VNCArray + 4 * sizeof(float) + indice * STRIDE_GL_ARRAY));
+      if (colorOK)
+        glColor4ubv((unsigned char*)(VNCArray + 8 * sizeof(float) + indice * STRIDE_GL_ARRAY));
+          glVertex3fv((float*)(VNCArray + indice * STRIDE_GL_ARRAY));*/
+    }
+  }
+  else if (type == GL_UNSIGNED_SHORT)
+  {
+    for(i=0;i<count;i++)
+    {
+      do_opengl_call(glArrayElement_func, NULL, ((unsigned short*)indices)[i]);
+    }
+  }
+  else if (type == GL_UNSIGNED_BYTE)
+  {
+    for(i=0;i<count;i++)
+    {
+      do_opengl_call(glArrayElement_func, NULL, ((unsigned char*)indices)[i]);
+    }
+  }
+  else
+  {
+    assert(0);
+  }
+  do_opengl_call(glEnd_func, NULL);
+#else
+  _glArraysSend(1 + maxIndice);
+  do_opengl_call(glDrawElements_func, NULL, mode, count, type, size, indices);
+#endif
+}
+
+typedef struct
+{
+  unsigned int hash;
+  char* name;
+  __GLXextFuncPtr func;
+} AssocProcAdress;
+
+unsigned int str_hash (const void* v)
+{
+  /* 31 bit hash function */
+  const signed char *p = v;
+  unsigned int h = *p;
+
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  return h;
+}
+
+__GLXextFuncPtr glXGetProcAddress (const GLubyte * _name)
+{
+  static int nbElts = 0;
+  static int tabSize = 0;
+  static AssocProcAdress* tab_assoc = NULL;
+  static void* handle = NULL;
+  char tmp[256];
+  
+  const char* name = (const char*)_name;
+  int i;
+  
+  if (name == NULL)
+  {
+    return NULL;
+  }
+  
+  if (tabSize == 0)
+  {
+    tabSize = 500;
+    tab_assoc = calloc(tabSize, sizeof(AssocProcAdress));
+  }
+  int hash = str_hash(name);
+  for(i=0;i<nbElts;i++)
+  {
+    if (tab_assoc[i].hash == hash && strcmp(tab_assoc[i].name, name) == 0)
+    {
+      return (__GLXextFuncPtr)tab_assoc[i].func;
+    }
+  }
+  int ret = 0;
+  do_opengl_call(glXGetProcAddress_fake_func, &ret, name);
+  if (ret == 0)
+  {
+    if (nbElts < tabSize)
+    {
+      tab_assoc[nbElts].hash = hash;
+      tab_assoc[nbElts].name = strdup(name);
+      tab_assoc[nbElts].func = NULL;
+      nbElts ++;
+    }
+    fprintf(stderr, "not found name on server side = %s\n", name);
+    return NULL;
+  }
+  else
+  {
+    void* func;
+    if (handle == NULL)
+    {
+      handle = dlopen("libGL.so",RTLD_LAZY);
+      if (!handle) {
+        fprintf (stderr, "%s\n", dlerror());
+        exit(1);
+      }
+    }
+    func = dlsym(handle, name);
+    if (func == NULL)
+    {
+      fprintf(stderr, "not found name on client side = %s\n", name);
+    }
+    if (nbElts < tabSize)
+    {
+      tab_assoc[nbElts].hash = hash;
+      tab_assoc[nbElts].name = strdup(name);
+      tab_assoc[nbElts].func = func;
+      nbElts ++;
+    }
+    return func;
+  }
+}
+
+__GLXextFuncPtr glXGetProcAddressARB (const GLubyte * name)
+{
+  return glXGetProcAddress(name);
+}
+
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/opengl_func.h qemu/target-i386/opengl_func.h
--- qemu.ori/target-i386/opengl_func.h	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/opengl_func.h	2006-11-14 21:46:24.000000000 +0100
@@ -0,0 +1,424 @@
+/*
+ *  Main header for both host and guest sides
+ * 
+ *  Copyright (c) 2006 Even Rouault
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+enum
+{
+  TYPE_NONE,
+  TYPE_CHAR,
+  TYPE_UNSIGNED_CHAR,
+  TYPE_SHORT,
+  TYPE_UNSIGNED_SHORT,
+  TYPE_INT,
+  TYPE_UNSIGNED_INT,
+  TYPE_POINTER,
+  TYPE_FLOAT,
+  TYPE_DOUBLE,
+  TYPE_NONE_TERMINATED_INT_ARRAY,
+  TYPE_CONST_CHAR,
+  TYPE_1CHAR,
+  TYPE_2CHAR,
+  TYPE_3CHAR,
+  TYPE_4CHAR,
+  TYPE_1SHORT,
+  TYPE_2SHORT,
+  TYPE_3SHORT,
+  TYPE_4SHORT,
+  TYPE_1INT,
+  TYPE_2INT,
+  TYPE_3INT,
+  TYPE_4INT,
+  TYPE_1FLOAT,
+  TYPE_2FLOAT,
+  TYPE_3FLOAT,
+  TYPE_4FLOAT,
+  TYPE_16FLOAT,
+  TYPE_1DOUBLE,
+  TYPE_2DOUBLE,
+  TYPE_3DOUBLE,
+  TYPE_4DOUBLE,
+  TYPE_16DOUBLE,
+  TYPE_OUT_INT_POINTER,
+  TYPE_ARRAY_CHAR,
+  TYPE_ARRAY_INT,
+  TYPE_ARRAY_FLOAT,
+  TYPE_ARRAY_DOUBLE,
+  TYPE_IN_IGNORED_POINTER,
+  TYPE_OUT_CHAR_ARRAY,
+  TYPE_OUT_INT_ARRAY,
+  TYPE_OUT_FLOAT_ARRAY,
+  TYPE_OUT_DOUBLE_ARRAY,
+  TYPE_NULL_TERMINATED_STRING,
+  TYPE_VISUAL_INFO
+};  
+
+static int tab_args_type_length[] =
+{
+  0,
+  sizeof(char),
+  sizeof(unsigned char),
+  sizeof(short),
+  sizeof(unsigned short),
+  sizeof(int),
+  sizeof(unsigned int),
+  sizeof(void*),
+  sizeof(float),
+  sizeof(double),
+  0,
+  0,
+  1 * sizeof(char),
+  2 * sizeof(char),
+  3 * sizeof(char),
+  4 * sizeof(char),
+  1 * sizeof(short),
+  2 * sizeof(short),
+  3 * sizeof(short),
+  4 * sizeof(short),
+  1 * sizeof(int),
+  2 * sizeof(int),
+  3 * sizeof(int),
+  4 * sizeof(int),
+  1 * sizeof(float),
+  2 * sizeof(float),
+  3 * sizeof(float),
+  4 * sizeof(float),
+  16 * sizeof(float),
+  1 * sizeof(double),
+  2 * sizeof(double),
+  3 * sizeof(double),
+  4 * sizeof(double),
+  16 * sizeof(double),
+  sizeof(int),
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  0,
+  sizeof(XVisualInfo)
+};
+
+typedef struct
+{
+  int ret_type;
+  int has_out_parameters;
+  int nb_args;
+  int args_type[0];
+} Signature;
+
+static const int _exit_process_signature[] = {TYPE_NONE, 0, 0};
+
+static const int _changeWindowState_signature[] = {TYPE_NONE, 0, 2, TYPE_INT, TYPE_INT};
+
+static const int _moveResizeWindow_signature[] = {TYPE_NONE, 0, 2, TYPE_INT, TYPE_4INT};
+
+static const int _needSync_signature[] = {TYPE_INT, 0, 0};
+
+/* XVisualInfo* glXChooseVisual( Display *dpy, int screen, int *attribList ) */
+static const int glXChooseVisual_signature[] = {TYPE_VISUAL_INFO, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_NONE_TERMINATED_INT_ARRAY };
+
+/*GLXContext glXCreateContext( Display *dpy, XVisualInfo *vis,
+                             GLXContext shareList, Bool direct )*/
+static const int glXCreateContext_signature[] = {TYPE_POINTER, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_IN_IGNORED_POINTER, TYPE_INT/*TYPE_POINTER*/, TYPE_INT};
+
+/*GLXContext glXGetCurrentContext()*/
+static const int glXGetCurrentContext_signature[] = {TYPE_POINTER, 0, 0};
+
+/* GLXDrawable glXGetCurrentDrawable( void ); */
+static const int glXGetCurrentDrawable_signature[] = {TYPE_POINTER, 0, 0};
+
+/* void glXDestroyContext( Display *dpy, GLXContext ctx ) */
+static const int glXDestroyContext_signature[] = {TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT/*TYPE_POINTER*/};
+
+/* Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx) */
+static const int glXMakeCurrent_signature[] = {TYPE_INT, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT/*TYPE_POINTER*/};
+
+/*int glXGetConfig( Display *dpy, XVisualInfo *visual,
+                  int attrib, int *value )*/
+static const int glXGetConfig_signature[] = {TYPE_INT, 1, 4, TYPE_IN_IGNORED_POINTER, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_OUT_INT_POINTER};
+
+/* void glXSwapBuffers( Display *dpy, GLXDrawable drawable ); */
+static const int glXSwapBuffers_signature[] = {TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT};
+
+/* Bool glXQueryVersion( Display *dpy, int *maj, int *min ) */
+static const int glXQueryVersion_signature[] = {TYPE_INT, 1, 3, TYPE_IN_IGNORED_POINTER, TYPE_OUT_INT_POINTER, TYPE_OUT_INT_POINTER};
+
+/* Bool glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) */
+static const int glXQueryExtension_signature[] = {TYPE_INT, 1, 3, TYPE_IN_IGNORED_POINTER, TYPE_OUT_INT_POINTER, TYPE_OUT_INT_POINTER};
+
+/* GLX 1.1 and later */
+
+/* const char *glXGetClientString( Display *dpy, int name ) */
+static const int glXGetClientString_signature[] = {TYPE_CONST_CHAR, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT};
+
+/*const char *glXQueryExtensionsString( Display *dpy, int screen ) */
+static const int glXQueryExtensionsString_signature[] = {TYPE_CONST_CHAR, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT};
+
+/* const char *glXQueryServerString( Display *dpy, int screen, int name ) */
+static const int glXQueryServerString_signature[] = {TYPE_CONST_CHAR, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT};
+
+
+static const int glXGetProcAddress_fake_signature[] = {TYPE_INT, 0, 1, TYPE_NULL_TERMINATED_STRING};
+
+/* GLX 1.3 and later */
+
+/*
+GLXFBConfig *glXChooseFBConfig( Display *dpy, int screen,
+                                       const int *attribList, int *nitems ); */
+static const int glXChooseFBConfig_signature[] = {TYPE_POINTER, 1, 4, TYPE_POINTER, TYPE_INT, TYPE_NONE_TERMINATED_INT_ARRAY, TYPE_OUT_INT_POINTER};
+
+/* GLXPbuffer glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+                             const int *attribList ) */
+static const int glXCreatePbuffer_signature[] = {TYPE_POINTER, 1, 3, TYPE_POINTER, TYPE_POINTER, TYPE_NONE_TERMINATED_INT_ARRAY};
+
+/*XVisualInfo *glXGetVisualFromFBConfig( Display *dpy,
+                                       GLXFBConfig config ) */
+static const int glXGetVisualFromFBConfig_signature[] = {TYPE_VISUAL_INFO, 0, 3, TYPE_POINTER, TYPE_POINTER};
+
+/* void glXUseXFont( Font font, int first, int count, int list ) */
+static const int glXUseXFont_signature[] = {TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT};
+
+/* Bool glXIsDirect( Display *dpy, GLXContext ctx ) */
+static const int glXIsDirect_signature[] = {TYPE_CHAR, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT };
+
+
+
+/* const GLubyte * glGetString( GLenum name ) */
+static const int glGetString_signature[] = {TYPE_CONST_CHAR, 0, 1, TYPE_INT};
+
+
+/* void glGetIntegerv( GLenum pname, GLint *params ) */
+static const int glGetIntegerv_signature[] = {TYPE_NONE, 1, 2, TYPE_INT, TYPE_OUT_INT_ARRAY};
+
+/* void glGetFloatv( GLenum pname, GLfloat *params ) */
+static const int glGetFloatv_signature[] = {TYPE_NONE, 1, 2, TYPE_INT, TYPE_OUT_FLOAT_ARRAY};
+
+/*void glGetConvolutionParameteriv( GLenum target, GLenum pname,
+                                  GLint *params ) */
+static const int glGetConvolutionParameteriv_signature[] = {TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_INT_ARRAY};
+
+static const int glLightfv_signature[] = {TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT};
+
+static const int glMaterialfv_signature[] = {TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT};
+
+static const int glLightModelfv_signature[] = {TYPE_NONE, 0, 2, TYPE_INT, TYPE_ARRAY_FLOAT};
+
+/* void glMap1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points ) */
+static const int glMap1f_signature[] =
+ {TYPE_NONE, 0, 6, TYPE_INT, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT
+ };
+ 
+static const int glMap1d_signature[] =
+ {TYPE_NONE, 0, 6, TYPE_INT, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, TYPE_INT, TYPE_ARRAY_DOUBLE
+ };
+
+/* void glMap2f( GLenum target,
+              GLfloat u1,
+              GLfloat u2,
+              GLint ustride,
+              GLint uorder,
+              GLfloat v1,
+              GLfloat v2,
+              GLint vstride,
+              GLint vorder,
+              const GLfloat *points ) */
+static const int glMap2f_signature[] =
+ {TYPE_NONE, 0, 10, TYPE_INT, TYPE_FLOAT, TYPE_FLOAT, TYPE_INT, TYPE_INT,
+                              TYPE_FLOAT, TYPE_FLOAT, TYPE_INT, TYPE_INT,
+                              TYPE_ARRAY_FLOAT
+ };
+
+static const int glMap2d_signature[] =
+{TYPE_NONE, 0, 10, TYPE_INT, TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, TYPE_INT,
+                             TYPE_DOUBLE, TYPE_DOUBLE, TYPE_INT, TYPE_INT,
+                             TYPE_ARRAY_DOUBLE
+ };
+
+ /* void glGenTextures( GLsizei n, GLuint *textures ); */
+static const int glGenTextures_signature[] = {TYPE_NONE, 1, 2, TYPE_INT, TYPE_OUT_INT_ARRAY };
+
+/* void glDeleteTextures ( GLsizei n, const GLuint *textures ) */
+static const int glDeleteTextures_signature[] = {TYPE_NONE, 0, 2, TYPE_INT, TYPE_ARRAY_INT };
+
+/* void glCallLists( GLsizei n,
+                  GLenum type,
+                  const GLvoid *lists )*/
+static const int glCallLists_signature[] = {TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+
+/*void glTexImage1D( GLenum target,
+                   GLint level,
+                   GLint internalFormat,
+                   GLsizei width,
+                   GLint border,
+                   GLenum format,
+                   GLenum type,
+                   const GLvoid *pixels ) */
+static const int glTexImage1D_signature[] =
+{TYPE_NONE, 0, 8, TYPE_INT, TYPE_INT, TYPE_INT,TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+
+/*void glTexImage2D( GLenum target,
+                   GLint level,
+                   GLint internalFormat,
+                   GLsizei width,
+                   GLsizei height,
+                   GLint border,
+                   GLenum format,
+                   GLenum type,
+                   const GLvoid *pixels ) */
+static const int glTexImage2D_signature[] =
+{TYPE_NONE, 0, 9, TYPE_INT, TYPE_INT, TYPE_INT,TYPE_INT,TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+/*void glTexSubImage2D( GLenum target,
+                      GLint level,
+                      GLint xoffset,
+                      GLint yoffset,
+                      GLsizei width,
+                      GLsizei height,
+                      GLenum format,
+                      GLenum type,
+                      const GLvoid *pixels )*/
+static const int glCompressedTexImage2DARB_signature[] =
+{TYPE_NONE, 0, 8, TYPE_INT, TYPE_INT,TYPE_INT,TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+
+/*void glTexSubImage2D( GLenum target,
+                      GLint level,
+                      GLint xoffset,
+                      GLint yoffset,
+                      GLsizei width,
+                      GLsizei height,
+                      GLenum format,
+                      GLenum type,
+                      const GLvoid *pixels )*/
+static const int glTexSubImage2D_signature[] =
+{TYPE_NONE, 0, 9, TYPE_INT, TYPE_INT, TYPE_INT,TYPE_INT,TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+/*void glCompressedTexSubImage2DARB(GLenum target,
+                                  GLint level,
+                                  GLint xoffset,
+                                  GLint yoffset,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  GLenum format,
+                                  GLsizei imageSize,
+                                  const GLvoid * data)*/
+static const int glCompressedTexSubImage2DARB_signature[] =
+{TYPE_NONE, 0, 8, TYPE_INT, TYPE_INT,TYPE_INT,TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+/*void glTexImage3D( GLenum target,
+                   GLint level,
+                   GLint internalFormat,
+                   GLsizei width,
+                   GLsizei height,
+                   GLsizei depth,
+                   GLint border,
+                   GLenum format,
+                   GLenum type,
+                   const GLvoid *pixels )*/
+static const int glTexImage3D_signature[] =
+{TYPE_NONE, 0, 10, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT,TYPE_INT,TYPE_INT,TYPE_INT,TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+/* void glGetTexLevelParameteriv( GLenum target, GLint level, GLenum pname, GLint *params ) */
+static const int glGetTexLevelParameteriv_signature[] = { TYPE_NONE, 1, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_OUT_INT_POINTER };
+
+/* void glFogfv( GLenum pname, const GLfloat *params ); */
+static const int glFogfv_signature[] = { TYPE_NONE, 0, 2, TYPE_INT, TYPE_ARRAY_FLOAT };
+
+/*void glBitmap( GLsizei width,
+               GLsizei height,
+               GLfloat xorig,
+               GLfloat yorig,
+               GLfloat xmove,
+               GLfloat ymove,
+               const GLubyte *bitmap ) */
+static const int glBitmap_signature[] = { TYPE_NONE, 0, 7, TYPE_INT, TYPE_INT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT,TYPE_ARRAY_CHAR };
+
+/* void glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params ); */
+static const int glTexGenfv_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT };
+
+/* void glTexEnvfv( GLenum target,
+                 GLenum pname,
+                 const GLfloat *params ) */
+static const int glTexEnvfv_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT };
+
+/*void glTexParameterfv( GLenum target,
+                       GLenum pname,
+                       const GLfloat *params )*/
+static const int glTexParameterfv_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_FLOAT };
+static const int glTexParameteriv_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_ARRAY_INT };
+
+/* void glPointParameterfvARB(GLenum pname, const GLfloat * params) */
+static const int glPointParameterfvARB_signature[] = { TYPE_NONE, 0, 2, TYPE_INT, TYPE_ARRAY_FLOAT };
+
+/* void glGenProgramsARB(GLsizei n, GLuint * program) */
+static const int glGenProgramsARB_signature[] = { TYPE_NONE, 1, 2, TYPE_INT, TYPE_OUT_INT_POINTER };
+
+/* void glProgramStringARB (GLenum a, GLenum b, GLsizei c, const GLvoid *d) */
+static const int glProgramStringARB_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+/* void glDeleteProgramsARB (GLsizei n, const GLuint *programs) */
+static const int glDeleteProgramsARB_signature[] = { TYPE_NONE, 0, 2, TYPE_INT, TYPE_ARRAY_INT };
+
+/* void glShaderSourceARB (GLhandleARB handle , GLsizei size, const GLcharARB* *p_tab_prog, const GLint * d) */
+/* --> void glShaderSourceARB (GLhandleARB handle , const GLcharARB* prog) */
+static const int glShaderSourceARB_signature[] = { TYPE_NONE, 0, 2, TYPE_INT, TYPE_NULL_TERMINATED_STRING };
+
+/* GLint glGetUniformLocationARB (GLhandleARB handle, const GLcharARB *txt) */
+static const int glGetUniformLocationARB_signature[] = { TYPE_INT, 0, 2, TYPE_INT, TYPE_NULL_TERMINATED_STRING };
+
+/* void EXT_FUNC(glGetVertexAttribfvARB)(GLuint index, GLenum pname, GLfloat *params) */
+static const int glGetVertexAttribfvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_FLOAT_ARRAY };
+static const int glGetVertexAttribivARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_INT_ARRAY };
+static const int glGetVertexAttribdvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_DOUBLE_ARRAY };
+
+/* void EXT_FUNC(glGetProgramLocalParameterfvARB) (GLenum target, GLuint index, GLfloat *params) */
+static const int glGetProgramLocalParameterfvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_FLOAT_ARRAY };
+static const int glGetProgramLocalParameterdvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_DOUBLE_ARRAY };
+static const int glGetProgramEnvParameterfvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_FLOAT_ARRAY };
+static const int glGetProgramEnvParameterdvARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_DOUBLE_ARRAY };
+
+/* void EXT_FUNC(glGetProgramivARB) (GLenum target, GLenum pname, GLint *params) */
+static const int glGetProgramivARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_INT_POINTER };
+
+/* void EXT_FUNC(glGetProgramStringARB) (GLenum target, GLenum pname, GLvoid *string) */
+static const int glGetProgramStringARB_signature[] = { TYPE_NONE, 1, 3, TYPE_INT, TYPE_INT, TYPE_OUT_CHAR_ARRAY };
+
+/*void glVertexPointer( GLint size,
+                      GLenum type,
+                      GLsizei stride,
+                      const GLvoid *ptr )*/
+static const int glVertexPointer_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+static const int glNormalPointer_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+static const int glColorPointer_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+static const int glTexCoordPointer_signature[] = { TYPE_NONE, 0, 5, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+static const int glDrawArrays_signature[] = { TYPE_NONE, 0, 3, TYPE_INT, TYPE_INT, TYPE_INT };
+
+/*void glDrawElements( GLenum mode,
+                     GLsizei count,
+                     GLenum type,
+                     const GLvoid *indices )*/
+static const int glDrawElements_signature[] = { TYPE_NONE, 0, 4, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_ARRAY_CHAR };
+
+#include "gl_func.h"
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/parse_gl_h.c qemu/target-i386/parse_gl_h.c
--- qemu.ori/target-i386/parse_gl_h.c	1970-01-01 01:00:00.000000000 +0100
+++ qemu/target-i386/parse_gl_h.c	2006-11-14 21:54:22.000000000 +0100
@@ -0,0 +1,645 @@
+/*
+ *  Parse gl.h et glx.h to auto-generate source code
+ * 
+ *  Copyright (c) 2006 Even Rouault
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* gcc parse_gl_h.c -o parse_gl_h && ./parse_gl_h */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int isExt(const char* name)
+{
+  return (strstr(name, "ARB") != NULL) ||
+         (strstr(name, "EXT") != NULL) ||
+         (strstr(name, "ATI") != NULL) ||
+         (strstr(name, "NV") != NULL) ||
+         (strstr(name, "MESA") != NULL) ||
+         (strstr(name, "SGI") != NULL);
+}
+
+char* get_arg_type(char* s)
+{
+  while(*s == ' ' || *s == '\t') s++;
+  char* n = s;
+  char* c = strstr(n, "const");
+  if (c)
+    n += 6;
+    
+  char* t = strstr(n, " ");
+  if (t)
+  {
+    if (t[1] == '*')
+      t += 2;
+    t[0] = 0;
+    char* ori = t;
+    t = strstr(t+1, "[");
+    if (t)
+    {
+      memmove(ori, t, strlen(t));
+      strstr(ori, "]")[1] = 0;
+    }
+  }
+  return strdup(s);
+}
+
+typedef struct
+{
+  char* type;
+  char* name;
+  int nargs;
+  char** args;
+  int ok;
+} FuncDesc;
+
+char* get_type_string(char* type)
+{
+  if (strstr(type, "[16]"))
+  {
+    if (strstr(type, "float"))
+      return ("TYPE_16FLOAT");
+    else if (strstr(type, "double"))
+      return ("TYPE_16DOUBLE");
+    else
+    {
+      printf("inconnu %s\n", type);
+      exit(-1);
+    }
+  }
+  else if (strcmp(type, "void") == 0)
+    return("TYPE_NONE");
+  else if (strcmp(type, "GLbyte") == 0)
+    return("TYPE_CHAR");
+  else if (strcmp(type, "GLubyte") == 0 ||
+           strcmp(type, "GLboolean") == 0)
+    return("TYPE_UNSIGNED_CHAR");
+  else if (strcmp(type, "GLshort") == 0)
+    return("TYPE_SHORT");
+  else if (strcmp(type, "GLushort") == 0 ||
+           strcmp(type, "GLhalfNV") == 0)
+    return("TYPE_UNSIGNED_SHORT");
+  else if (strcmp(type, "GLint") == 0 ||
+           strcmp(type, "GLsizei") == 0)
+    return("TYPE_INT");
+  else if (strcmp(type, "GLenum") == 0 ||
+           strcmp(type, "GLuint") == 0 ||
+           strcmp(type, "GLhandleARB") == 0 ||
+           strcmp(type, "GLbitfield") == 0)
+    return("TYPE_UNSIGNED_INT");
+  else if (strcmp(type, "GLfloat") == 0 ||
+           strcmp(type, "GLclampf") == 0)
+    return("TYPE_FLOAT");
+  else if (strcmp(type, "GLdouble") == 0 ||
+           strcmp(type, "GLclampd") == 0)
+    return("TYPE_DOUBLE");
+  else
+  {
+    printf("inconnu %s\n", type);
+    exit(-1);
+  }
+}
+
+typedef struct
+{
+  char* letter;
+  char* signature_type_name;
+  char* gl_c_type_name;
+  char* c_type_name;
+} ForIsKnownArgVector;
+
+int is_known_arg_vector(FuncDesc* desc, char** p_signature_type_name, char** p_c_type_name)
+{
+  static ForIsKnownArgVector my_tab[] =
+  {
+    { "b", "CHAR", "byte", "char" },
+    { "s", "SHORT", "short", "short" },
+    { "i", "INT", "int", "int" },
+    { "ub", "CHAR", "byte", "unsigned char" },
+    { "us", "SHORT", "short", "unsigned short" },
+    { "ui", "INT", "int", "unsigned int" },
+    { "Nb", "CHAR", "byte", "char" },
+    { "Ns", "SHORT", "short", "short" },
+    { "Ni", "INT", "int", "int" },
+    { "Nub", "CHAR", "byte", "unsigned char" },
+    { "Nus", "SHORT", "short", "unsigned short" },
+    { "Nui", "INT", "int", "unsigned int" },
+    
+    { "f", "FLOAT", "float", "float" },
+    { "d", "DOUBLE", "double", "double" },
+  };
+      
+  if (desc->nargs == 0)
+    return 0;
+  
+  int i , j;
+  
+  static char signatures[14][4][20] = {0};
+  char signature[10];
+  
+  for(i=0;i<14;i++)
+  {
+    for(j=1;j<=4;j++)
+    {
+      sprintf(signature, "%d%sv", j, my_tab[i].letter);
+      if (strstr(desc->name, signature) &&
+          strstr(desc->args[desc->nargs - 1], my_tab[i].gl_c_type_name) &&
+          strstr(desc->args[desc->nargs - 1], "*"))
+      {
+        if (p_signature_type_name)
+        {
+          if (signatures[i][j][0] == 0)
+            sprintf(signatures[i][j], "TYPE_%d%s", j, my_tab[i].signature_type_name);
+          *p_signature_type_name = signatures[i][j];
+        }
+        if (p_c_type_name) *p_c_type_name = my_tab[i].c_type_name;
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+int parse(FILE* f, FuncDesc* funcDesc, int ignoreEXT)
+{
+  char buffer[256];
+  int funcDescCount = 0;
+  while(fgets(buffer, 256, f))
+  {
+    if (strncmp(buffer, "GLAPI", 5) == 0 && strstr(buffer, "APIENTRY") && strstr(buffer, "("))
+    {
+      if (strstr(buffer, "glDrawArrays"))
+      {
+        continue;
+      }
+      if (strstr(buffer, "glGetIntegerv"))
+      {
+        continue;
+      }
+      
+      char** args = malloc(15 * sizeof(char*));
+      int narg = 0;
+      char* type = buffer + 6;
+      char* n = strstr(type, "GLAPIENTRY") ? strstr(type, "GLAPIENTRY") : strstr(type, "APIENTRY");
+      int skip_length = strstr(type, "GLAPIENTRY") ? 11 : 9;
+      n[-1] = 0;
+      type = strdup(type);
+      n += skip_length;
+      char* fonc = n;
+      n = strstr(n, "(");
+      if (n[-1] == ' ') n[-1] = 0;
+      n[0] = 0;
+      fonc = strdup(fonc);
+      /*if (strstr(fonc, "glLockArraysEXT") || strstr(fonc, "glUnlockArraysEXT"))
+      {
+      }
+      else*/
+      if ((ignoreEXT == 1 && isExt(fonc)) || (ignoreEXT == 0 && !isExt(fonc)))
+      {
+        free(type);
+        free(fonc);
+        continue;
+      }
+      n++;
+      while(1)
+      {
+        char* virg = strstr(n, ",");
+        if (virg)
+        {
+          args[narg] = n;
+          virg[0] = 0;
+          args[narg] = get_arg_type(args[narg]);
+          narg++;
+          n = virg+1;
+        }
+        else
+          break;
+      }
+      while (strstr(n, ")") == 0)
+      {
+        fgets(buffer, 256, f);
+        n = buffer;
+        while(1)
+        {
+          char* virg = strstr(n, ",");
+          if (virg)
+          {
+            args[narg] = n;
+            virg[0] = 0;
+            args[narg] = get_arg_type(args[narg]);
+            narg++;
+            n = virg+1;
+          }
+          else
+            break;
+        }
+      }
+      char* par = strstr(n, ")");
+      args[narg] = n;
+      par[0] = 0;
+      args[narg] = get_arg_type(args[narg]);
+      narg++;
+      int i;
+      
+      
+      /*printf("%s %s (", type, fonc);
+      for(i=0;i<narg;i++)
+      {
+      printf("%s,", args[i]);
+    }
+      printf(")\n");*/
+      
+      funcDesc[funcDescCount].type = type;
+      funcDesc[funcDescCount].name = fonc;
+      funcDesc[funcDescCount].nargs = narg;
+      funcDesc[funcDescCount].args = args;
+      funcDescCount++;
+      /*
+      for(i=0;i<narg;i++)
+      {
+      free(args[i]);
+    }
+      free(fonc);
+      free(type);*/
+    }
+  }
+  return funcDescCount;
+}
+
+int main(int argc, char* argv[])
+{
+  FuncDesc funcDesc[10000];
+  int funcDescCount = 0;
+  
+  FILE* f = fopen("/usr/include/GL/gl.h", "r");
+  funcDescCount += parse(f, &funcDesc[funcDescCount], 1);
+  fclose(f);
+  
+  f = fopen("/usr/include/GL/glext.h", "r");
+  funcDescCount += parse(f, &funcDesc[funcDescCount], 0);
+  fclose(f);
+  
+  FILE* header = fopen("gl_func.h", "w");
+  FILE* client_stub = fopen("client_stub.c", "w");
+  FILE* server_stub = fopen("server_stub.c", "w");
+  
+  fprintf(header, "/* This is a generated file. DO NOT EDIT ! */\n\n");
+  fprintf(header, "#define COMPOSE(x,y) x##y\n");
+  fprintf(header, "#define MAGIC_MACRO(x)  COMPOSE(x,_func)\n");
+  fprintf(header, "enum {\n"
+                  "#include \"gl_func_perso.h\"\n");
+  
+  fprintf(client_stub, "/* This is a generated file. DO NOT EDIT ! */\n\n");
+  
+  fprintf(server_stub, "/* This is a generated file. DO NOT EDIT ! */\n\n");
+  
+  int first = 1;
+  
+  int i;
+  for(i=0;i<funcDescCount;i++)
+  {
+    funcDesc[i].ok = 0;
+    char* name = funcDesc[i].name;
+    char* type = funcDesc[i].type;
+    if ((strcmp(type, "void") == 0 || strcmp(type, "GLboolean") == 0 ||
+        strcmp(type, "GLuint") == 0 || strcmp(type, "GLint") == 0 ||
+       strcmp(type, "GLenum") == 0) || strcmp(type, "GLhandleARB") == 0)
+    {
+      int pointer = 0;
+      int j;
+      
+      for(j=0;j<funcDesc[i].nargs-1;j++)
+      {
+        if (strstr(funcDesc[i].args[j], "[16]") == NULL)
+        {
+          pointer |= strstr(funcDesc[i].args[j], "*") != NULL;
+          pointer |= strstr(funcDesc[i].args[j], "[") != NULL;
+        }
+      }
+      if (pointer == 0)
+      {
+        if (is_known_arg_vector(&funcDesc[i], NULL, NULL))
+        {
+        }
+        else
+        {
+          if (funcDesc[i].nargs-1 >= 0)
+          {
+            j = funcDesc[i].nargs-1;
+            if (strstr(funcDesc[i].args[j], "[16]") == NULL)
+            {
+              pointer |= strstr(funcDesc[i].args[j], "*") != NULL;
+              pointer |= strstr(funcDesc[i].args[j], "[") != NULL;
+            }
+          }
+        }
+      }
+      if (pointer && funcDesc[i].nargs == 1 &&
+          (strstr(funcDesc[i].name, "Matrixf") || strstr(funcDesc[i].name, "Matrixd")))
+      {
+        free(funcDesc[i].args[0]);
+        if (strstr(funcDesc[i].name, "Matrixf"))
+          funcDesc[i].args[0] = strdup("GLfloat m[16]");
+        else
+          funcDesc[i].args[0] = strdup("GLdouble m[16]");
+        pointer = 0;
+      }
+      if (pointer == 0)
+      {
+        funcDesc[i].ok = 1;
+        if (first == 1)
+        {
+          first = 0;
+        }
+        fprintf(header, "  %s_func,\n", funcDesc[i].name);
+        if (funcDesc[i].nargs == 1 && strcmp(funcDesc[i].args[0], "void") == 0)
+        {
+          funcDesc[i].nargs = 0;
+        }
+        /*printf("%s %s (", funcDesc[i].type, funcDesc[i].name);
+        for(j=0;j<funcDesc[i].nargs;j++)
+        {
+          printf("%s,", funcDesc[i].args[j]);
+        }
+        printf(")\n");*/
+      }
+    }
+  }
+  
+  fprintf(header, "  GL_N_CALLS\n};\n");
+  
+  
+  fprintf(server_stub, "void execute_func(int func_number, int* pret_int, char* pret_char)\n");
+  fprintf(server_stub, "{\n");
+  fprintf(server_stub, "  if (display_function_call) fprintf(stderr, \"%%s\\n\", tab_opengl_calls_name[func_number]);\n", funcDesc[i].name);
+  fprintf(server_stub, "  switch(func_number)\n");
+  fprintf(server_stub, "  {\n");
+  
+  for(i=0;i<funcDescCount;i++)
+  {
+    if (funcDesc[i].ok)
+    {
+      fprintf(header, "static const int %s_signature[] = { %s, 0, ", funcDesc[i].name, get_type_string(funcDesc[i].type));
+      fprintf(header, "%d", funcDesc[i].nargs);
+      int j;
+      char* signature_type_name;
+      if (is_known_arg_vector(&funcDesc[i], &signature_type_name, NULL))
+      {
+        for(j=0;j<funcDesc[i].nargs - 1;j++)
+        {
+          fprintf(header, ", %s", get_type_string(funcDesc[i].args[j]));
+        }
+        fprintf(header, ", %s", signature_type_name);
+      }
+      else
+      {
+        for(j=0;j<funcDesc[i].nargs;j++)
+        {
+          fprintf(header, ", %s", get_type_string(funcDesc[i].args[j]));
+        }
+      }
+      fprintf(header, "};\n");
+      
+      if (isExt(funcDesc[i].name))
+        fprintf(client_stub, "%s EXT_FUNC(%s) (", funcDesc[i].type, funcDesc[i].name);
+      else
+        fprintf(client_stub, "%s %s(", funcDesc[i].type, funcDesc[i].name);
+      
+      for(j=0;j<funcDesc[i].nargs;j++)
+      {
+        if (j != 0) fprintf(client_stub,", ");
+        if (strstr(funcDesc[i].args[j], "16"))
+        {
+          if (strstr(funcDesc[i].args[j], "float"))
+          {
+            fprintf(client_stub, "const GLfloat arg_%d[16]", j);
+          }
+          else if (strstr(funcDesc[i].args[j], "double"))
+          {
+            fprintf(client_stub, "const GLdouble arg_%d[16]", j);
+          }
+          else
+          {
+            exit(-1);
+          }
+        }
+        else
+          fprintf(client_stub, "%s arg_%d", funcDesc[i].args[j], j);
+      }
+      fprintf(client_stub, ")\n");
+      fprintf(client_stub, "{\n");
+      if (strcmp(funcDesc[i].type, "void") != 0)
+      {
+        fprintf(client_stub, "  %s ret;\n", funcDesc[i].type);
+        if (isExt(funcDesc[i].name))
+          fprintf(client_stub, "  CHECK_PROC_WITH_RET(%s);\n", funcDesc[i].name);
+      }
+      else
+      {
+        if (isExt(funcDesc[i].name))
+          fprintf(client_stub, "  CHECK_PROC(%s);\n", funcDesc[i].name);
+      }
+      
+      fprintf(client_stub, "  do_opengl_call(%s_func, %s",
+              funcDesc[i].name, (strcmp(funcDesc[i].type, "void") == 0) ? "NULL" : "&ret");
+      for(j=0;j<funcDesc[i].nargs;j++)
+      {
+        fprintf(client_stub, ", arg_%d", j);
+      }
+      fprintf(client_stub, ");\n");
+      if (strcmp(funcDesc[i].type, "void") != 0)
+      {
+        fprintf(client_stub, "  return ret;\n");
+      }
+      fprintf(client_stub, "}\n\n");
+      
+      
+      fprintf(server_stub, "    case %s_func:\n", funcDesc[i].name);
+      fprintf(server_stub, "    {\n");
+      
+      if (isExt(funcDesc[i].name))
+      {
+        fprintf(server_stub, "      GET_EXT_PTR(%s, %s, (", funcDesc[i].type, funcDesc[i].name);
+        for(j=0;j<funcDesc[i].nargs;j++)
+        {
+          if (j != 0) fprintf(server_stub,", ");
+          if (strstr(funcDesc[i].args[j], "16"))
+          {
+            if (strstr(funcDesc[i].args[j], "float"))
+            {
+              fprintf(server_stub, "const GLfloat arg_%d[16]", j);
+            }
+            else if (strstr(funcDesc[i].args[j], "double"))
+            {
+              fprintf(server_stub, "const GLdouble arg_%d[16]", j);
+            }
+            else
+            {
+              exit(-1);
+            }
+          }
+          else
+            fprintf(server_stub, "%s arg_%d", funcDesc[i].args[j], j);
+        }
+        fprintf(server_stub, "));\n");
+      }
+      
+      fprintf(server_stub, "      ");
+      
+      if (strcmp(funcDesc[i].type, "void") == 0)
+        ;
+      else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_INT") == 0 ||
+               strcmp(get_type_string(funcDesc[i].type), "TYPE_UNSIGNED_INT") == 0)
+        fprintf(server_stub, "*pret_int = ");
+      else if (strcmp(get_type_string(funcDesc[i].type), "TYPE_CHAR") == 0 ||
+               strcmp(get_type_string(funcDesc[i].type), "TYPE_UNSIGNED_CHAR") == 0)
+        fprintf(server_stub, "*pret_char = ");
+      else
+      {
+        fprintf(stderr, "unknown ret type = %s\n", get_type_string(funcDesc[i].type));
+        exit(-1);
+      }
+      /*if (strstr(funcDesc[i].name, "EXT"))
+      {
+        char* dup = strdup(funcDesc[i].name);
+        *strstr(dup, "EXT") = 0;
+        fprintf(server_stub, "%s(", dup);
+        free(dup);
+      }
+      else*/
+      { 
+        if (isExt(funcDesc[i].name))
+          fprintf(server_stub, "ptr_func(");
+        else
+          fprintf(server_stub, "%s(", funcDesc[i].name);
+      }
+      char* c_type_name;
+      if (is_known_arg_vector(&funcDesc[i], NULL, &c_type_name))
+      {
+        for(j=0;j<funcDesc[i].nargs - 1;j++)
+        {
+          if (j != 0) fprintf(server_stub,", ");
+          const char* symbolic_type = get_type_string(funcDesc[i].args[j]);
+          if (strcmp(symbolic_type, "TYPE_CHAR") == 0)
+            fprintf(server_stub, "ARG_TO_CHAR(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_CHAR(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_SHORT") == 0)
+            fprintf(server_stub, "ARG_TO_SHORT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_SHORT") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_SHORT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_INT") == 0)
+            fprintf(server_stub, "ARG_TO_INT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_INT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0)
+            fprintf(server_stub, "ARG_TO_FLOAT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0)
+            fprintf(server_stub, "ARG_TO_FLOAT16_ARRAY(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0)
+            fprintf(server_stub, "ARG_TO_DOUBLE(args[%d])", j);
+          else if ( strcmp(symbolic_type, "TYPE_16DOUBLE") == 0)
+            fprintf(server_stub, "ARG_TO_DOUBLE16_ARRAY(args[%d])", j);
+          else
+          {
+            fprintf(stderr, "Unknown : %s\n", symbolic_type);
+            exit(-1);
+          }
+        }
+        if (j != 0) fprintf(server_stub,", ");
+        fprintf(server_stub, "(%s*)args[%d]", c_type_name, j);
+      }
+      else
+      {
+        for(j=0;j<funcDesc[i].nargs;j++)
+        {
+          if (j != 0) fprintf(server_stub,", ");
+          const char* symbolic_type = get_type_string(funcDesc[i].args[j]);
+          if (strcmp(symbolic_type, "TYPE_CHAR") == 0)
+            fprintf(server_stub, "ARG_TO_CHAR(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_CHAR") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_CHAR(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_SHORT") == 0)
+            fprintf(server_stub, "ARG_TO_SHORT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_SHORT") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_SHORT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_INT") == 0)
+            fprintf(server_stub, "ARG_TO_INT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_UNSIGNED_INT") == 0)
+            fprintf(server_stub, "ARG_TO_UNSIGNED_INT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_FLOAT") == 0)
+            fprintf(server_stub, "ARG_TO_FLOAT(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_16FLOAT") == 0)
+            fprintf(server_stub, "ARG_TO_FLOAT16_ARRAY(args[%d])", j);
+          else if (strcmp(symbolic_type, "TYPE_DOUBLE") == 0)
+            fprintf(server_stub, "ARG_TO_DOUBLE(args[%d])", j);
+          else if ( strcmp(symbolic_type, "TYPE_16DOUBLE") == 0)
+            fprintf(server_stub, "ARG_TO_DOUBLE16_ARRAY(args[%d])", j);
+          else
+          {
+            fprintf(stderr, "Unknown : %s\n", symbolic_type);
+            exit(-1);
+          }
+        }
+      }
+      fprintf(server_stub, ");\n");
+      
+      fprintf(server_stub, "      break;\n");
+      fprintf(server_stub, "    }\n");
+    }
+  }
+  
+  fprintf(server_stub, "    default:\n");
+  fprintf(server_stub, "      fprintf(stderr, \"unknown=%%d\", func_number);\n");
+  fprintf(server_stub, "      break;\n");
+  fprintf(server_stub, "  }\n");
+  fprintf(server_stub, "}\n");
+
+  fprintf(header, "#undef MAGIC_MACRO\n");
+  fprintf(header, "#define MAGIC_MACRO(x)  COMPOSE(x,_signature)\n");
+  fprintf(header, "static const int* tab_opengl_calls[GL_N_CALLS] =\n");
+  fprintf(header, "{\n");
+  fprintf(header, "#include \"gl_func_perso.h\"\n");
+  for(i=0;i<funcDescCount;i++)
+  {
+    if (funcDesc[i].ok)
+    {
+      fprintf(header, "  %s_signature,\n", funcDesc[i].name);
+    }
+  }
+  fprintf(header, "};\n\n");
+
+  fprintf(header, "#undef MAGIC_MACRO\n");
+  fprintf(header, "#define MAGIC_MACRO(x)  #x\n");
+  fprintf(header, "static const char* tab_opengl_calls_name[GL_N_CALLS] =\n");
+  fprintf(header, "{\n");
+  fprintf(header, "#include \"gl_func_perso.h\"\n");
+  for(i=0;i<funcDescCount;i++)
+  {
+    if (funcDesc[i].ok)
+    {
+      fprintf(header, "  \"%s\",\n", funcDesc[i].name);
+    }
+  }
+  fprintf(header, "};\n\n");
+  
+  fclose(header);
+  fclose(server_stub);
+  fclose(client_stub);
+
+  return 0;
+}
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/target-i386/translate.c qemu/target-i386/translate.c
--- qemu.ori/target-i386/translate.c	2006-11-14 00:18:10.000000000 +0100
+++ qemu/target-i386/translate.c	2006-11-14 21:46:24.000000000 +0100
@@ -2244,16 +2244,25 @@ static void gen_exception(DisasContext *
     s->is_jmp = 3;
 }
 
+extern int enable_gl;
+
 /* an interrupt is different from an exception because of the
    priviledge checks */
 static void gen_interrupt(DisasContext *s, int intno, 
                           target_ulong cur_eip, target_ulong next_eip)
 {
+  if (enable_gl && intno == 0x99)
+  {
+    gen_op_int99();
+  }
+  else
+  {
     if (s->cc_op != CC_OP_DYNAMIC)
         gen_op_set_cc_op(s->cc_op);
     gen_jmp_im(cur_eip);
     gen_op_raise_interrupt(intno, (int)(next_eip - cur_eip));
     s->is_jmp = 3;
+  }
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
diff -Nrup --exclude=CVS --exclude='*~' --exclude='config-host*' --exclude=Makefile --exclude=config.mak --exclude=config.h qemu.ori/vl.c qemu/vl.c
--- qemu.ori/vl.c	2006-11-14 00:18:09.000000000 +0100
+++ qemu/vl.c	2006-11-14 21:46:24.000000000 +0100
@@ -162,6 +162,7 @@ int vnc_display = -1;
 int acpi_enabled = 1;
 int fd_bootchk = 1;
 int no_reboot = 0;
+int enable_gl = 0;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -842,6 +843,8 @@ static int timer_load(QEMUFile *f, void 
     return 0;
 }
 
+extern int doing_opengl;
+
 #ifdef _WIN32
 void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, 
                                  DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
@@ -886,8 +889,9 @@ static void host_alarm_handler(int host_
         SetEvent(host_alarm);
 #endif
         CPUState *env = cpu_single_env;
-        if (env) {
-            /* stop the currently executing cpu because a timer occured */
+        if (env && !doing_opengl) {
+          //printf("alarm handler\n");
+          /* stop the currently executing cpu because a timer occured */
             cpu_interrupt(env, CPU_INTERRUPT_EXIT);
 #ifdef USE_KQEMU
             if (env->kqemu_enabled) {
@@ -5792,7 +5796,7 @@ int main_loop(void)
                 }
             }
             cur_cpu = env;
-
+            
             if (shutdown_requested) {
                 ret = EXCP_INTERRUPT;
                 break;
@@ -5934,6 +5938,7 @@ void help(void)
            "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
            "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
+           "-enable-gl      (Experimental !) Enable accelerated OpenGL\n"
 #endif
            "-no-reboot      exit instead of rebooting\n"
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
@@ -6017,6 +6022,10 @@ enum {
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
     QEMU_OPTION_no_reboot,
+    
+#ifdef TARGET_I386
+    QEMU_OPTION_enable_gl,
+#endif
 };
 
 typedef struct QEMUOption {
@@ -6094,6 +6103,10 @@ const QEMUOption qemu_options[] = {
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { "no-reboot", 0, QEMU_OPTION_no_reboot },
+    
+#ifdef TARGET_I386
+    { "enable-gl", 0, QEMU_OPTION_enable_gl },
+#endif
     { NULL },
 };
 
@@ -6741,6 +6754,11 @@ int main(int argc, char **argv)
             case QEMU_OPTION_no_reboot:
                 no_reboot = 1;
                 break;
+#ifdef TARGET_I386
+              case QEMU_OPTION_enable_gl:
+                enable_gl = 1;
+                break;
+#endif
             }
         }
     }

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-11-20  3:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-16 20:34 [Qemu-devel] [PATCH] Experimental initial patch providing accelerated OpenGL for Linux i386 (2nd attempt to post) Even Rouault
2006-11-16 21:13 ` Even Rouault
2006-11-16 22:41 ` Fabrice Bellard
2006-11-17  1:25   ` Paul Brook
2006-11-18 12:59   ` Even Rouault
2006-11-18 17:40     ` Fabrice Bellard
2006-11-19 19:01     ` Avi Kivity
2006-11-17  7:16 ` Stefan Kombrink
2006-11-17  7:29 ` Laurent Desnogues
2006-11-20  3:48 ` [Qemu-devel] [PATCH] Experimental initial patch providingaccelerated " Kazu
  -- strict thread matches above, loose matches on Subject: below --
2006-11-16 20:36 [Qemu-devel] [PATCH] Experimental initial patch providing accelerated " Even Rouault

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).