This is the new version of the patch.
It removes the need for a global display variable and replaces the
PixelFormat to XVisualInfo conversion code with one which uses
GLXFBConfig. All demos are now working with nvidia drivers.

Alexander Eichner

Am Mittwoch, den 11.07.2007, 12:59 +0200 schrieb Alexander Eichner:
> there were some things left in the Makefile.kmk from a previous attempt
> to get Display variable via global qApp object.
> Prevents VirtualBox from building on other Distros like Fedira 7.
> Removed it. Updated patch attached.
> 
> Alexander
> 
> Am Mittwoch, den 11.07.2007, 11:51 +0200 schrieb Alexander Eichner:
> > the attached patch adds basic Shared OpenGL support for Windows guests
> > on Linux hosts.
> > It currently works with the mesa software renderer.
> > tests with the accelerated but proprietary nvidia driver resulted in a
> > segmentation fault.
> > Another problem is that it needs a global Display variable which is
> > defined in the VirtualBox frontend.
> > The patched is released under the MIT license
> > 
> > Regards,
> > Alexander Eichner
> > _______________________________________________
> > vbox-dev mailing list
> > [email protected]
> > http://vbox.innotek.de/mailman/listinfo/vbox-dev
> _______________________________________________
> vbox-dev mailing list
> [email protected]
> http://vbox.innotek.de/mailman/listinfo/vbox-dev
Index: include/VBox/HostServices/VBoxOGLOp.h
===================================================================
--- include/VBox/HostServices/VBoxOGLOp.h	(Revision 3615)
+++ include/VBox/HostServices/VBoxOGLOp.h	(Arbeitskopie)
@@ -1846,11 +1846,12 @@
     vboxglDrvDescribePixelFormat,
     vboxglDrvSetPixelFormat,
     vboxglDrvSwapBuffers,
-
+
+#ifdef __WIN__
     /* OpenGL Extensions */
     vboxwglSwapIntervalEXT,
     vboxwglGetSwapIntervalEXT,
-
+#endif
 };
 #endif
 
Index: src/VBox/HostServices/SharedOpenGL/service.cpp
===================================================================
--- src/VBox/HostServices/SharedOpenGL/service.cpp	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/service.cpp	(Arbeitskopie)
@@ -285,13 +285,16 @@
                     rc = VERR_INVALID_PARAMETER;
                 }
                 else
-                {
+                {
+#ifdef __WIN__
                     /* Execute the function. */
                     if (vboxwglGetProcAddress(pszExtFnName))
                         rc = VINF_SUCCESS;
                     else
                         rc = VERR_FILE_NOT_FOUND;
-
+#else
+                        rc = VERR_FILE_NOT_FOUND;
+#endif
                     if (VBOX_SUCCESS(rc))
                     {
                         /* Update parameters.*/
Index: src/VBox/HostServices/SharedOpenGL/gllindrv.cpp
===================================================================
--- src/VBox/HostServices/SharedOpenGL/gllindrv.cpp	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/gllindrv.cpp	(Arbeitskopie)
@@ -22,16 +22,138 @@
 
 #include "vboxgl.h"
 #define LOG_GROUP LOG_GROUP_SHARED_OPENGL
-#include <VBox/log.h>
-
+#include <VBox/log.h>
+#include <string.h>
+#include <stdio.h>
+
+/*static int (*X_handler)(Display *, XErrorEvent *) = NULL;
+static int x_errhandler(Display *d, XErrorEvent *e)
+{
+    return (X_handler(d, e));
+}
+
+static int (*XIO_handler)(Display *) = NULL;
+static int xio_errhandler(Display *d)
+{
+    return (XIO_handler(d));
+}*/
+
+static Bool WaitForNotify( Display *dpy, XEvent *event, XPointer arg ) {
+    return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
+}
+
+/* from http://www.mesa3d.org/brianp/sig97/exten.htm */
+GLboolean vboxglCheckExtension(Display *dpy, int screenNum, char *extName )
+{
+   /*
+    ** Search for extName in the extensions string.  Use of strstr()
+    ** is not sufficient because extension names can be prefixes of
+    ** other extension names.  Could use strtok() but the constant
+    ** string returned by glGetString can be in read-only memory.
+    */
+    char *p = (char *) glXQueryExtensionsString(dpy, screenNum);
+    char *end;
+    int extNameLen;
+
+    extNameLen = strlen(extName);
+    end = p + strlen(p);
+
+    while (p < end) {
+        int n = strcspn(p, " ");
+        if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
+            return GL_TRUE;
+        }
+        p += (n + 1);
+    }
+    return GL_FALSE;
+}
+
+
+/**
+ * Print parameters for a GLXFBConfig to stdout.
+ * Input:  dpy - the X display
+ *         screen - the X screen number
+ *         fbConfig - the fbconfig handle
+ *         horizFormat - if true, print in horizontal format
+ */
+void
+PrintFBConfigInfo(Display *dpy, int screen, GLXFBConfig config)
+{
+   int bufferSize, level, doubleBuffer, stereo, auxBuffers;
+   int redSize, greenSize, blueSize, alphaSize;
+   int depthSize, stencilSize;
+   int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
+   int sampleBuffers, samples;
+   int drawableType, renderType, xRenderable, xVisual, id;
+
+   /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
+   glXGetFBConfigAttrib(dpy, config, GLX_BUFFER_SIZE, &bufferSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_LEVEL, &level);
+   glXGetFBConfigAttrib(dpy, config, GLX_DOUBLEBUFFER, &doubleBuffer);
+   glXGetFBConfigAttrib(dpy, config, GLX_STEREO, &stereo);
+   glXGetFBConfigAttrib(dpy, config, GLX_AUX_BUFFERS, &auxBuffers);
+   glXGetFBConfigAttrib(dpy, config, GLX_RED_SIZE, &redSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_GREEN_SIZE, &greenSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_BLUE_SIZE, &blueSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_ALPHA_SIZE, &alphaSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_DEPTH_SIZE, &depthSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_STENCIL_SIZE, &stencilSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_RED_SIZE, &accumRedSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_GREEN_SIZE, &accumGreenSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_BLUE_SIZE, &accumBlueSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_ALPHA_SIZE, &accumAlphaSize);
+   glXGetFBConfigAttrib(dpy, config, GLX_SAMPLE_BUFFERS, &sampleBuffers);
+   glXGetFBConfigAttrib(dpy, config, GLX_SAMPLES, &samples);
+   glXGetFBConfigAttrib(dpy, config, GLX_DRAWABLE_TYPE, &drawableType);
+   glXGetFBConfigAttrib(dpy, config, GLX_RENDER_TYPE, &renderType);
+   glXGetFBConfigAttrib(dpy, config, GLX_X_RENDERABLE, &xRenderable);
+   glXGetFBConfigAttrib(dpy, config, GLX_X_VISUAL_TYPE, &xVisual);
+   if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
+      xVisual = -1;
+
+   glXGetFBConfigAttrib(dpy, config, GLX_FBCONFIG_ID, &id);
+
+      printf("Id 0x%x\n", id);
+      printf("  Buffer Size: %d\n", bufferSize);
+      printf("  Level: %d\n", level);
+      printf("  Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
+      printf("  Stereo: %s\n", stereo ? "yes" : "no");
+      printf("  Aux Buffers: %d\n", auxBuffers);
+      printf("  Red Size: %d\n", redSize);
+      printf("  Green Size: %d\n", greenSize);
+      printf("  Blue Size: %d\n", blueSize);
+      printf("  Alpha Size: %d\n", alphaSize);
+      printf("  Depth Size: %d\n", depthSize);
+      printf("  Stencil Size: %d\n", stencilSize);
+      printf("  Accum Red Size: %d\n", accumRedSize);
+      printf("  Accum Green Size: %d\n", accumGreenSize);
+      printf("  Accum Blue Size: %d\n", accumBlueSize);
+      printf("  Accum Alpha Size: %d\n", accumAlphaSize);
+      printf("  Sample Buffers: %d\n", sampleBuffers);
+      printf("  Samples/Pixel: %d\n", samples);
+      printf("  Drawable Types: ");
+      if (drawableType & GLX_WINDOW_BIT)  printf("Window ");
+      if (drawableType & GLX_PIXMAP_BIT)  printf("Pixmap ");
+      if (drawableType & GLX_PBUFFER_BIT)  printf("PBuffer");
+      printf("\n");
+      printf("  Render Types: ");
+      if (renderType & GLX_RGBA_BIT_SGIX)  printf("RGBA ");
+      if (renderType & GLX_COLOR_INDEX_BIT_SGIX)  printf("CI ");
+      printf("\n");
+      printf("  X Renderable: %s\n", xRenderable ? "yes" : "no");
+
+}
+
 /**
  * Global init of VBox OpenGL for windows
  *
  * @returns VBox error code
  */
 int vboxglGlobalInit()
-{
-    vboxInitOpenGLExtensions();
+{
+    Log(("vboxglGlobalInit\n"));
+
+    /*vboxInitOpenGLExtensions();*/
     return VINF_SUCCESS;
 }
 
@@ -41,9 +163,48 @@
  * @returns VBox error code
  * @param   pClient         Client context
  */
-int vboxglConnect(PVBOXOGLCTX pClient)
-{
-    return VINF_SUCCESS;
+int vboxglConnect(PVBOXOGLCTX pClient)
+{
+    int rc = VERR_NOT_IMPLEMENTED;
+    Log(("vboxglConnect\n"));
+    //pClient->getContextIDPtr = NULL;
+    //pClient->importContextEXTPtr = NULL;
+    pClient->PixelFormatToFBConfigMapper = NULL;
+    pClient->xWindow = 0;
+
+    pClient->dpy = XOpenDisplay(NULL);
+
+    if (pClient->dpy) {
+        int  screenNum, major, minor;
+
+        screenNum = DefaultScreen(pClient->dpy);
+        glXQueryVersion(pClient->dpy, &major, &minor);
+
+        if ((major == 1) && (minor >= 3)) {
+            Log(("Server GLX 1.3 supported\n"));
+            pClient->glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGSGIXPROC) glXGetProcAddress( 
+                                          (GLubyte *) "glXChooseFBConfig");
+            pClient->glxGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) glXGetProcAddress( 
+                                                 (GLubyte *) "glXGetVisualFromFBConfig");
+            pClient->glxCreateNewContext = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) glXGetProcAddress(
+                                            (GLubyte *) "glXCreateNewContext");
+        } else if (vboxglCheckExtension(pClient->dpy, screenNum, "GLX_SGIX_fbconfig")) {
+            Log(("GLX_SGIX_fbconfig extension supported\n"));
+            pClient->glxChooseFBConfig = (PFNGLXCHOOSEFBCONFIGSGIXPROC) glXGetProcAddress( 
+                                          (GLubyte *) "glXChooseFBConfigSGIX");
+            pClient->glxGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) glXGetProcAddress( 
+                                                 (GLubyte *) "glXGetVisualFromFBConfigSGIX");
+            pClient->glxCreateNewContext = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) glXGetProcAddress(
+                                            (GLubyte *) "glXCreateContextWithConfigSGIX");
+        } else {
+                Log(("Error no FBConfig supported\n"));
+                rc = VERR_NOT_IMPLEMENTED;
+        }
+        if (pClient->glxChooseFBConfig && pClient->glxGetVisualFromFBConfig && pClient->glxCreateNewContext)
+            rc = VINF_SUCCESS;
+    }
+
+    return rc;
 }
 
 /**
@@ -53,70 +214,185 @@
  * @param   pClient         Client context
  */
 int vboxglDisconnect(PVBOXOGLCTX pClient)
-{
+{
+    Log(("vboxglDisconnect\n"));
+
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+    if (pClient->dpy) {
+        if (pClient->xWindow != 0) {
+            XUnmapWindow(pClient->dpy, pClient->xWindow);
+            XDestroyWindow(pClient->dpy, pClient->xWindow);
+        }
+        if (pClient->PixelFormatToFBConfigMapper) {
+            XFree(pClient->PixelFormatToFBConfigMapper);
+        }
+        XCloseDisplay(pClient->dpy);
+    }
+    pClient->dpy = NULL;
+    pClient->xWindow = 0;
+    pClient->actFBConfig = NULL;
+#endif
     return VINF_SUCCESS;
 }
 
 /* Driver functions */
 void vboxglDrvCreateContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
-    OGL_CMD(DrvCreateContext, 4);
+{
+    XSetWindowAttributes attr;
+    XVisualInfo *visinfo = NULL;
+    unsigned long mask;
+    //GLXContext ctx;
+    GLXFBConfig fbConfig;
+    GLXContextID glrc;
+    int screen_num;
+    XEvent event;
+    OGL_CMD(DrvCreateContext, 1);
     OGL_PARAM(HDC, hdc);
-    OGL_PARAM(uint32_t, cx);
-    OGL_PARAM(uint32_t, cy);
-    OGL_PARAM(BYTE, cColorBits);
-    OGL_PARAM(BYTE, iPixelType);
-    OGL_PARAM(BYTE, cDepthBits);
 
-    pClient->lastretval = 0; /** @todo */
+    Log(("DrvCreateContext %x\n", hdc));
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+
+    screen_num = DefaultScreen(pClient->dpy);
+    fbConfig = pClient->actFBConfig;
+
+#if 0
+    if (!fbConfig) {
+        /* Create a standard fbconfig */
+        int returnedNumFBConfigs;
+        GLXFBConfig *returnedFBConfigs;
+        static int attribs[] = {
+            GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+            GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+            GLX_DOUBLEBUFFER,  True,  /* Request a double-buffered color buffer with */
+            GLX_RED_SIZE,      1,     /* the maximum number of bits per component    */
+            GLX_GREEN_SIZE,    1, 
+            GLX_BLUE_SIZE,     1,
+            None
+        };
+
+        Log(("Warning: no GLXFBConfig set creating standard one\n"));
+        returnedFBConfigs = pClient->glxChooseFBConfig(pClient->dpy, screen_num, attribs, &returnedNumFBConfigs);
+        if (!returnedNumFBConfigs) {
+            pClient->lastretval = 0;
+            pClient->fHasLastError = true;
+            pClient->ulLastError   = glGetError();
+            return;
+        }
+        fbConfig = returnedFBConfigs[0];
+    }
+#endif
+
+    visinfo = pClient->glxGetVisualFromFBConfig(pClient->dpy, fbConfig);
+
+    if (pClient->xWindow == 0) {
+
+	/* window attributes */
+	attr.background_pixel = 0;
+	attr.border_pixel = 0;
+	attr.colormap = XCreateColormap(pClient->dpy, RootWindow(pClient->dpy, screen_num ), visinfo->visual, AllocNone);
+	attr.event_mask = StructureNotifyMask | ExposureMask;
+	mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+	pClient->xWindow = XCreateWindow(pClient->dpy, 
+	                                RootWindow(pClient->dpy, screen_num), 
+	                                0, 0, pClient->winWidth, pClient->winHeight, 0,
+	                                visinfo->depth, InputOutput,
+	                                visinfo->visual, mask, &attr);
+    }
+    XResizeWindow(pClient->dpy, pClient->xWindow, pClient->winWidth, pClient->winHeight);
+    pClient->glxContext = pClient->glxCreateNewContext(pClient->dpy, fbConfig, GLX_RGBA_TYPE, NULL, True);
+
+    XMapWindow(pClient->dpy, pClient->xWindow);
+    XIfEvent(pClient->dpy, &event, WaitForNotify, (XPointer)pClient->xWindow );
+    //glrc = pClient->getContextIDPtr(ctx);
+    glrc = 1;
+    Assert(glrc);
+#else
+    AssertFailed();
+    glrc = 0;
+#endif
+
+    pClient->lastretval = (uint64_t)glrc;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvDeleteContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
+{
+    //GLXContext ctx;
     OGL_CMD(DrvDeleteContext, 1);
     OGL_PARAM(HGLRC, hglrc);
-    /** @todo */
-    pClient->lastretval = 0; /** @todo */
+    Log(("DrvDeleteContext %x\n", hglrc));
+    //ctx = pClient->importContextEXTPtr(pClient->dpy, hglrc);
+    glXDestroyContext(pClient->dpy, VBOX_OGL_GUEST_TO_HOST_HDC(hglrc));
+    pClient->lastretval = 1;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvSetContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
+{
+    //GLXContext ctx;
     OGL_CMD(DrvSetContext, 2);
     OGL_PARAM(HDC, hdc);
     OGL_PARAM(HGLRC, hglrc);
-
-    pClient->lastretval = 0; /** @todo */
+    Log(("DrvSetContext %x %x\n", hdc, hglrc));
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+    //ctx = pClient->importContextEXTPtr(pClient->dpy, hglrc);
+    pClient->lastretval = glXMakeCurrent(pClient->dpy, pClient->xWindow, 
+                                         VBOX_OGL_GUEST_TO_HOST_HDC(hglrc));
+    if (!pClient->lastretval)
+        Log(("glXMakeCurrent failed\n"));
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
+#else
+    AssertFailed();
+#endif
 }
 
 void vboxglDrvCopyContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
+{
+    //GLXContext ctxSrc, ctxDst;
     OGL_CMD(DrvDeleteContext, 3);
     OGL_PARAM(HGLRC, hglrcSrc);
     OGL_PARAM(HGLRC, hglrcDst);
     OGL_PARAM(UINT,  mask);
-    pClient->lastretval = 0; /** @todo */
+    Log(("DrvCopyContext %x %x %x\n", hglrcSrc, hglrcDst, mask));
+    //ctxSrc = pClient->importContextEXTPtr(pClient->dpy, hglrcSrc);
+    //ctxDst = pClient->importContextEXTPtr(pClient->dpy, hglrcDst);
+    glXCopyContext(pClient->dpy, VBOX_OGL_GUEST_TO_HOST_HDC(hglrc), VBOX_OGL_GUEST_TO_HOST_HDC(hglrc), mask);
+    pClient->lastretval = 1;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvReleaseContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
+{
     OGL_CMD(DrvReleaseContext, 1);
     OGL_PARAM(HGLRC, hglrc);
-    pClient->lastretval = 0; /** @todo */
+    Log(("DrvReleaseContext %x\n", hglrc));
+    /* clear current selection */
+    pClient->lastretval = glXMakeCurrent(pClient->dpy, 0, NULL);
+
+    if (!pClient->lastretval)
+        Log(("glXMakeCurrent failed\n"));
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvCreateLayerContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
 {
-    OGL_CMD(DrvCreateLayerContext, 5);
+    OGL_CMD(DrvCreateLayerContext, 2);
     OGL_PARAM(HDC, hdc);
     OGL_PARAM(int, iLayerPlane);
-    OGL_PARAM(uint32_t, cx);
-    OGL_PARAM(uint32_t, cy);
-    OGL_PARAM(BYTE, cColorBits);
-    OGL_PARAM(BYTE, iPixelType);
-    OGL_PARAM(BYTE, cDepthBits);
+
+    Log(("DrvCreateLayerContext %x\n", hdc));
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
+#else
     AssertFailed();
-    /** @todo create memory dc with the parameters above */
-    pClient->lastretval = 0; /** @todo */
+#endif
 }
 
 void vboxglDrvShareLists(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -124,7 +400,9 @@
     OGL_CMD(DrvShareLists, 3);
     OGL_PARAM(HGLRC, hglrc1);
     OGL_PARAM(HGLRC, hglrc2);
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 
@@ -134,7 +412,9 @@
     OGL_PARAM(HDC, hdc);
     OGL_PARAM(int, iLayerPlane);
     OGL_PARAM(BOOL, bRealize);
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvSwapLayerBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -142,24 +422,43 @@
     OGL_CMD(DrvSwapLayerBuffers, 2);
     OGL_PARAM(HDC, hdc);
     OGL_PARAM(UINT, fuPlanes);
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvSetPixelFormat(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
-{
-    OGL_CMD(DrvSetPixelFormat, 2);
+{
+    int screen_num;
+    OGL_CMD(DrvSetPixelFormat, 4);
     OGL_PARAM(HDC, hdc);
-    OGL_PARAM(int, iPixelFormat);
+    OGL_PARAM(int, iPixelFormat);
+    OGL_PARAM(uint32_t, cx);
+    OGL_PARAM(uint32_t, cy);
 
-    pClient->lastretval = 0; /** @todo */
+    Log(("vboxDrvSetPixelFormat %d\n", iPixelFormat));
+
+    /* Get GLXFBConfig based on the given ID */
+    pClient->actFBConfig = pClient->PixelFormatToFBConfigMapper[iPixelFormat-1];
+    screen_num = DefaultScreen(pClient->dpy);
+    PrintFBConfigInfo(pClient->dpy, screen_num, pClient->actFBConfig);
+    Log(("Window width: %d Window height: %d\n", cx, cy));
+    pClient->winWidth = cx;
+    pClient->winHeight = cy;
+    pClient->lastretval = true;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvSwapBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
 {
     OGL_CMD(DrvSwapBuffers, 1);
     OGL_PARAM(HDC, hdc);
-
-    pClient->lastretval = 0; /** @todo */
+
+    glXSwapBuffers(pClient->dpy, pClient->xWindow);
+    pClient->lastretval = 1;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvDescribeLayerPlane(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -174,7 +473,9 @@
     Assert(pClient->cbLastParam == nBytes);
     plpd = (PLAYERPLANEDESCRIPTOR)pClient->pLastParam;
 
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvSetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -185,7 +486,9 @@
     OGL_PARAM(int, iStart);
     OGL_PARAM(int, cEntries);
     OGL_MEMPARAM(COLORREF, pcr);
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvGetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -200,12 +503,16 @@
 
     Assert(pClient->cbLastParam == sizeof(COLORREF)*cEntries);
     pcr = (COLORREF *)pClient->pLastParam;
-    pClient->lastretval = 0; /** @todo */
+    pClient->lastretval = 0; /** @todo */
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 void vboxglDrvDescribePixelFormat(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
 {
     LPPIXELFORMATDESCRIPTOR ppfd;
+    GLXFBConfig *allFBConfigs, matchingFBConfig;
+    int screenNum, glxReturnValue;
 
     OGL_CMD(DrvDescribePixelFormat, 3);
     OGL_PARAM(HDC, hdc);
@@ -213,12 +520,82 @@
     OGL_PARAM(UINT, nBytes);
     Assert(pClient->cbLastParam == nBytes);
     ppfd = (LPPIXELFORMATDESCRIPTOR)pClient->pLastParam;
-
-    pClient->lastretval = 0; /** @todo */
+
+    Log(("iPixelFormat: %d\n", iPixelFormat));
+
+    if (!pClient->PixelFormatToFBConfigMapper) {
+        /* First get number of all visuals for the return value */
+        screenNum = DefaultScreen(pClient->dpy);
+        allFBConfigs = glXGetFBConfigs(pClient->dpy, screenNum, 
+                                            &pClient->numFBConfigs);
+        pClient->PixelFormatToFBConfigMapper = allFBConfigs;
+    }
+
+    if (nBytes == sizeof(PIXELFORMATDESCRIPTOR)) {
+        int redSize, greenSize, blueSize, alphaSize, xVisual, xRenderable;
+        /* Get GLXFBConfig which matches iPixelFormat */
+        matchingFBConfig = pClient->PixelFormatToFBConfigMapper[iPixelFormat-1];
+
+        Log(("Filling values into PIXELFORMATDESCRIPTOR\n"));
+        /* translate all values to theire corresponding Windows ones */
+        ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
+        ppfd->nVersion = 1;
+        ppfd->iLayerType = PFD_MAIN_PLANE;
+        ppfd->dwFlags =  0;
+
+        /* Set cColorBits */
+        glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_RED_SIZE, &redSize);
+        glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_GREEN_SIZE, &greenSize);
+        glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_BLUE_SIZE, &blueSize);
+        glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_ALPHA_SIZE, &alphaSize);
+        ppfd->cColorBits = redSize + greenSize + blueSize;
+        ppfd->cRedBits = redSize;
+        ppfd->cBlueBits = blueSize;
+        ppfd->cGreenBits = greenSize;
+        ppfd->cAlphaBits = alphaSize;
+
+        /* Set dwFlags */
+        if (!glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_DRAWABLE_TYPE, &glxReturnValue)) {
+            glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_VISUAL_ID, &xVisual);
+            glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_X_RENDERABLE, &xRenderable);
+            if ((glxReturnValue & GLX_WINDOW_BIT) && xVisual)
+                ppfd->dwFlags |= (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
+        }
+        if (!glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_DOUBLEBUFFER, &glxReturnValue)) {
+            if (glxReturnValue)
+                ppfd->dwFlags |= PFD_DOUBLEBUFFER;
+        }
+        /* Set iPixelType */
+        if (!glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_RENDER_TYPE, &glxReturnValue)) {
+            if (glxReturnValue & GLX_RGBA_BIT)
+                ppfd->iPixelType = PFD_TYPE_RGBA;
+            else if ((glxReturnValue & GLX_COLOR_INDEX_BIT) & !(glxReturnValue & GLX_RGBA_BIT))
+                ppfd->iPixelType = PFD_TYPE_COLORINDEX;
+        }
+        /* Set cDepthBits */
+        if (!glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_DEPTH_SIZE, &glxReturnValue)) {
+            ppfd->cDepthBits = glxReturnValue;
+        } else {
+            ppfd->cDepthBits = 0;
+        }
+        /* Set cStencilBits */
+        if (!glXGetFBConfigAttrib(pClient->dpy, matchingFBConfig, GLX_STENCIL_SIZE, &glxReturnValue)) {
+            ppfd->cStencilBits = glxReturnValue;
+        } else {
+            ppfd->cStencilBits = 0;
+        }
+        /** @todo Fill in the rest */
+    }
+
+    pClient->lastretval = pClient->numFBConfigs;
+    pClient->fHasLastError = true;
+    pClient->ulLastError   = glGetError();
 }
 
 RTUINTPTR vboxDrvIsExtensionAvailable(char *pszExtFunctionName)
-{
-    return 0;
+{
+    RTUINTPTR pfnProc = (RTUINTPTR)glXGetProcAddress((const GLubyte *)pszExtFunctionName);
+    Log(("vboxDrvIsExtensionAvailable %s -> %d\n", pszExtFunctionName, !!pfnProc));
+    return pfnProc;
 }
 
Index: src/VBox/HostServices/SharedOpenGL/vboxgl.cpp
===================================================================
--- src/VBox/HostServices/SharedOpenGL/vboxgl.cpp	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/vboxgl.cpp	(Arbeitskopie)
@@ -30,9 +30,7 @@
 
 #define LOG_GROUP LOG_GROUP_SHARED_OPENGL
 #include <VBox/log.h>
-
-
-
+
 /**
  * glGetString implementation
  *
@@ -47,7 +45,8 @@
     const GLubyte *pName;
     uint32_t cbLen;
     int      rc = VINF_SUCCESS;
-
+
+    Log(("vboxglGetString\n"));
 #ifdef __WIN__
     PIXELFORMATDESCRIPTOR pfd;
     int iFormat;
@@ -66,8 +65,54 @@
 
     HGLRC hRC = wglCreateContext(hdc);
     wglMakeCurrent(hdc, hRC);
+#elif defined __LINUX__
+    Display *dpy;
+    static int attribs[] = {
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
+        GLX_DOUBLEBUFFER,  True,  /* Request a double-buffered color buffer with */
+        GLX_RED_SIZE,      1,     /* the maximum number of bits per component    */
+        GLX_GREEN_SIZE,    1, 
+        GLX_BLUE_SIZE,     1,
+        None
+    };
+    GLXFBConfig *fbConfig;
+    XVisualInfo *visinfo;
+    int screen_num;
+    GLXContext ctx;
+    XSetWindowAttributes attr;
+    unsigned long mask;
+    Window win;
+    int returnedFBConfigs;
+
+    if (!pClient->glxContext) {
+        /* we have to set up a rendering context to be able to use glGetString
+         * a window is created but is not mapped to screen (so it's not visible') 
+         * and a GLXContext is bound to it */
+        dpy = pClient->dpy;
+        screen_num = DefaultScreen(dpy);
+        fbConfig = pClient->glxChooseFBConfig(dpy, screen_num, attribs, &returnedFBConfigs);
+        Log(("vboxglGetString: returned FBConfigs: %d\n", returnedFBConfigs));
+        visinfo = pClient->glxGetVisualFromFBConfig( dpy, fbConfig[0]);
+        /* Create Window */
+        attr.background_pixel = 0;
+        attr.border_pixel = 0;
+        attr.colormap = XCreateColormap(dpy, RootWindow(dpy, screen_num), visinfo->visual, AllocNone);
+        attr.event_mask = StructureNotifyMask | ExposureMask;
+        mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+        win = XCreateWindow(dpy, RootWindow(dpy, screen_num), 0, 0, 100, 100,
+		           0, visinfo->depth, InputOutput,
+		           visinfo->visual, mask, &attr);
+        /* Create Context */
+        ctx = pClient->glxCreateNewContext(dpy, fbConfig[0], GLX_RGBA_TYPE, NULL, True);
+    } else {
+       dpy = pClient->dpy;
+       win = pClient->xWindow;
+       ctx = pClient->glxContext;
+    }
+
+    glXMakeCurrent(dpy, win, ctx);
 #endif
-
     pName = glGetString(name);
     if (pName == NULL)
     {
@@ -90,7 +135,17 @@
 #ifdef __WIN__
     wglMakeCurrent(NULL, NULL);
     wglDeleteContext(hRC);
-    ReleaseDC(0, hdc);
+    ReleaseDC(0, hdc);
+#elif defined __LINUX__
+    /* Free all data */
+    glFlush();
+    if (!pClient->glxContext) {
+        glXMakeCurrent(dpy, 0, NULL);
+        XDestroyWindow(dpy, win);
+        glXDestroyContext(dpy, ctx);
+        XFree(visinfo);
+        XFree(fbConfig);
+    }
 #endif
     return rc;
 }
@@ -114,7 +169,7 @@
     Log(("vboxglFlushBuffer cCommands=%d cbCmdBuffer=%x\n", cCommands, cbCmdBuffer));
 
     pClient->fHasLastError = false;
-
+
     for (i=0;i<cCommands;i++)
     {
         PVBOX_OGL_CMD pCmd = (PVBOX_OGL_CMD)pCmdBuffer;
@@ -142,7 +197,7 @@
         *pLastError = pClient->ulLastError;
     else
         *pLastError = glGetError();
-
+
 #ifdef DEBUG
     Log(("Flush: last return value=%VX64\n", *pLastRetVal));
     switch(*pLastError)
Index: src/VBox/HostServices/SharedOpenGL/gldrv.h
===================================================================
--- src/VBox/HostServices/SharedOpenGL/gldrv.h	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/gldrv.h	(Arbeitskopie)
@@ -22,17 +22,31 @@
 #ifndef __VBOXGLWIN__H
 #define __VBOXGLWIN__H
 
-#include <iprt/types.h>
+#include <iprt/types.h>
+#include <iprt/mem.h>
 
 #ifdef __WIN__
 #define VBOX_OGL_DEBUG_WINDOW_OUTPUT
 #endif
+
+#ifdef __LINUX__
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
+typedef GLXContextID (*glXGetContextIDEXTProc) (const GLXContext);
+typedef GLXContext (*glXImportContextEXTProc) (Display *, GLXContextID);
+
+#define VBOX_OGL_DEBUG_WINDOW_OUTPUT
+#endif
 
-#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
-#define VBOX_OGL_GUEST_TO_HOST_HDC(a)       pClient->hdc
-#else
-#define VBOX_OGL_GUEST_TO_HOST_HDC(a)       a
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+#if defined(__WIN__)
+#define VBOX_OGL_GUEST_TO_HOST_HDC(a)       pClient->hdc
+#elif defined(__LINUX__)
+#define VBOX_OGL_GUEST_TO_HOST_HDC(a)       pClient->glxContext
 #endif
+#endif
 
 typedef struct
 {
@@ -44,10 +58,25 @@
     uint8_t    *pLastParam;
     uint32_t    cbLastParam;
 
-#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+#ifdef __WIN__
     HWND        hwnd;
-    HDC         hdc;
+    HDC         hdc;
+#elif defined __LINUX__
+    Display     *dpy;
+    Window      xWindow;
+    GLXFBConfig actFBConfig;
+    int         winWidth, winHeight;
+    GLXFBConfig *PixelFormatToFBConfigMapper;
+    int         numFBConfigs;
+    GLXContext  glxContext;
+    PFNGLXCHOOSEFBCONFIGSGIXPROC glxChooseFBConfig;
+    PFNGLXGETVISUALFROMFBCONFIGSGIXPROC glxGetVisualFromFBConfig;
+    PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC glxCreateNewContext;
+    //glXGetContextIDEXTProc getContextIDPtr;
+    //glXImportContextEXTProc importContextEXTPtr;
 #endif
+#endif
 } VBOXOGLCTX, *PVBOXOGLCTX;
 
 
@@ -66,12 +95,24 @@
 typedef void *      LPVOID;
 typedef int16_t     SHORT;
 typedef uint16_t    USHORT;
-typedef int64_t     INT64;
-typedef int32_t     INT32;
+typedef int64_t     INT64;
+typedef int32_t     INT32;
 typedef float       FLOAT; /* ??? */
 
 #define DECLARE_HANDLE(a)  typedef HANDLE a
 #define WINAPI
+
+#define PFD_DOUBLEBUFFER   0x00000001
+#define PFD_STEREO         0x00000002
+#define PFD_DRAW_TO_WINDOW 0x00000004
+#define PFD_SUPPORT_OPENGL 0x00000020
+
+#define PFD_TYPE_RGBA       0
+#define PFD_TYPE_COLORINDEX 1
+
+#define PFD_MAIN_PLANE 0
+#define PFD_OVERLAY_PLANE 1
+#define PFD_UNDERLAY_PLANE (-1)
 
 typedef struct
 {
@@ -130,7 +171,7 @@
     BYTE  bReserved;
     COLORREF crTransparent;
 } LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, LPLAYERPLANEDESCRIPTOR;
-
+
 #endif
 
 void vboxglDrvReleaseContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
Index: src/VBox/HostServices/SharedOpenGL/vboxgl.h
===================================================================
--- src/VBox/HostServices/SharedOpenGL/vboxgl.h	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/vboxgl.h	(Arbeitskopie)
@@ -92,10 +92,11 @@
  *
  * @returns VBox error code
  * @param   pszFunctionName     OpenGL extension function name
- */
+ */
+#ifdef __WIN__
 bool vboxwglGetProcAddress(char *pszFunctionName);
+#endif
 
-
 /* OpenGL wrappers */
 void vboxglArrayElement(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
 void vboxglBegin(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
@@ -351,9 +352,11 @@
 void vboxglGetTexLevelParameterfv (VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
 void vboxglGetTexLevelParameteriv (VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
 void vboxglGetTexImage (VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
-
+
+#ifdef __WIN__
 void vboxwglSwapIntervalEXT (VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
 void vboxwglGetSwapIntervalEXT (VBOXOGLCTX *pClient, uint8_t *pCmdBuffer);
+#endif
 
 /* after the above */
 #include <VBox/HostServices/VBoxOpenGLSvc.h>
Index: src/VBox/HostServices/SharedOpenGL/Makefile.kmk
===================================================================
--- src/VBox/HostServices/SharedOpenGL/Makefile.kmk	(Revision 3615)
+++ src/VBox/HostServices/SharedOpenGL/Makefile.kmk	(Arbeitskopie)
@@ -31,7 +31,8 @@
 VBoxSharedOpenGL_DEFS      = VBOX_HGCM VBOX_OGL_HOST_SIDE
 VBoxSharedOpenGL_INCS.win  = \
 	$(PATH_TOOL_$(VBOX_VCC_TOOL)_ATLMFC_INC) \
-	$(VBOX_PATH_SDK)
+	$(VBOX_PATH_SDK)
+VBoxSharedOpenGL_CXXFLAGS.linux = -pthread
 
 VBoxSharedOpenGL_SOURCES = \
 	service.cpp \
@@ -53,7 +54,11 @@
 	$(LIB_RUNTIME) \
 	$(LIB_REM)
 VBoxSharedOpenGL_LIBS.win = \
-        $(PATH_SDK_WINPSDK_LIB)/opengl32.lib
+        $(PATH_SDK_WINPSDK_LIB)/opengl32.lib
+VBoxSharedOpenGL_LIBPATH.linux = \
+	$(VBOX_LIBPATH_X11)
+VBoxSharedOpenGL_LIBS.linux = \
+	GL
 
 include $(PATH_KBUILD)/subfooter.kmk
 
_______________________________________________
vbox-dev mailing list
[email protected]
http://vbox.innotek.de/mailman/listinfo/vbox-dev

Reply via email to