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
Index: include/VBox/HostServices/VBoxOGLOp.h
===================================================================
--- include/VBox/HostServices/VBoxOGLOp.h (Revision 3516)
+++ 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 3516)
+++ 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 3516)
+++ src/VBox/HostServices/SharedOpenGL/gllindrv.cpp (Arbeitskopie)
@@ -22,16 +22,50 @@
#include "vboxgl.h"
#define LOG_GROUP LOG_GROUP_SHARED_OPENGL
-#include <VBox/log.h>
-
+#include <VBox/log.h>
+#include <string.h>
+
+extern Display *globalDisplay;
+
+/* 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;
+}
+
+
+
+
/**
* Global init of VBox OpenGL for windows
*
* @returns VBox error code
*/
int vboxglGlobalInit()
-{
- vboxInitOpenGLExtensions();
+{
+ Log(("vboxglGlobalInit\n"));
+
+ /*vboxInitOpenGLExtensions();*/
return VINF_SUCCESS;
}
@@ -41,9 +75,34 @@
* @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->VisualIDMapper = NULL;
+ pClient->xwin = 0;
+
+ pClient->dpy = globalDisplay;
+
+ if (pClient->dpy) {
+ int screenNum;
+
+ XLockDisplay(pClient->dpy);
+
+ screenNum = DefaultScreen(pClient->dpy);
+ if (vboxglCheckExtension(pClient->dpy, screenNum, "GLX_EXT_import_context")) {
+ pClient->getContextIDPtr = (GLXContextID (*)(const GLXContext))glXGetProcAddress((const GLubyte *)"glXGetContextIDEXT");
+ pClient->importContextEXTPtr = (GLXContext (*)(Display *, GLXContextID))glXGetProcAddress((const GLubyte *) "glXImportContextEXT");
+ if (pClient->getContextIDPtr && pClient->importContextEXTPtr)
+ rc = VINF_SUCCESS;
+ }
+
+ XUnlockDisplay(pClient->dpy);
+ }
+
+ return rc;
}
/**
@@ -53,70 +112,185 @@
* @param pClient Client context
*/
int vboxglDisconnect(PVBOXOGLCTX pClient)
-{
+{
+ Log(("vboxglDisconnect\n"));
+
+#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
+ if (pClient->dpy) {
+ if (pClient->xwin != 0) {
+ XUnmapWindow(pClient->dpy, pClient->xwin);
+ XDestroyWindow(pClient->dpy, pClient->xwin);
+ }
+ if (pClient->curVisualInfo) {
+ XFree(pClient->curVisualInfo);
+ }
+ if (pClient->VisualIDMapper) {
+ RTMemFree(pClient->VisualIDMapper);
+ }
+ }
+ pClient->dpy = NULL;
+ pClient->xwin = 0;
+#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;
+ GLXContextID glrc;
+ int screen_num;
+ 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
+
+ XLockDisplay(pClient->dpy);
+
+ screen_num = DefaultScreen(pClient->dpy);
+ visinfo = pClient->curVisualInfo;
+
+ /* choose a standard */
+ if (visinfo == NULL) {
+ static int attribs[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None
+ };
+
+ visinfo = glXChooseVisual(pClient->dpy, screen_num, attribs);
+ }
+
+ if (pClient->xwin == 0) {
+
+ if (pClient->win_width == 0)
+ pClient->win_width = 100;
+
+ if (pClient->win_height == 0)
+ pClient->win_height = 100;
+
+ /* 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;
+ screen_num = DefaultScreen(pClient->dpy);
+ pClient->xwin = XCreateWindow(pClient->dpy,
+ RootWindow(pClient->dpy, screen_num),
+ 0, 0, pClient->win_width, pClient->win_height, 0,
+ visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr);
+ XMapWindow(pClient->dpy, pClient->xwin);
+ }
+ XResizeWindow(pClient->dpy, pClient->xwin, pClient->win_width, pClient->win_height);
+
+ pClient->ctx = glXCreateContext(pClient->dpy, visinfo, NULL, True);
+ //glrc = pClient->getContextIDPtr(ctx);
+ XUnlockDisplay(pClient->dpy);
+ 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));
+ XLockDisplay(pClient->dpy);
+ //ctx = pClient->importContextEXTPtr(pClient->dpy, hglrc);
+ glXDestroyContext(pClient->dpy, VBOX_OGL_GUEST_TO_HOST_HDC(hglrc));
+ XUnlockDisplay(pClient->dpy);
+ 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
+ XLockDisplay(pClient->dpy);
+ //ctx = pClient->importContextEXTPtr(pClient->dpy, hglrc);
+ pClient->lastretval = glXMakeCurrent(pClient->dpy, pClient->xwin, VBOX_OGL_GUEST_TO_HOST_HDC(hglrc));
+ XUnlockDisplay(pClient->dpy);
+ 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));
+ XLockDisplay(pClient->dpy);
+ //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);
+ XUnlockDisplay(pClient->dpy);
+ 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));
+ XLockDisplay(pClient->dpy);
+ /* clear current selection */
+ pClient->lastretval = glXMakeCurrent(pClient->dpy, pClient->xwin, NULL);
+ XUnlockDisplay(pClient->dpy);
+ 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 +298,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 +310,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 +320,64 @@
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);
+{
+ XVisualInfo templateVisInfo, *VisualInfos = NULL;
+ long visualMask;
+ int screenNum, numVisuals;
+
+ 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));
+
+ XLockDisplay(pClient->dpy);
+ /* Get XVisualInfo based on the given ID */
+ screenNum = DefaultScreen(pClient->dpy);
+ templateVisInfo.visualid = pClient->VisualIDMapper[iPixelFormat];
+ templateVisInfo.screen = screenNum;
+ visualMask = VisualIDMask | VisualScreenMask;
+ VisualInfos = XGetVisualInfo(pClient->dpy, visualMask, &templateVisInfo, &numVisuals);
+ Log(("Window width: %d Window height: %d\n", cx, cy));
+ pClient->win_width = cx;
+ pClient->win_height = cy;
+ if (VisualInfos) {
+ /* Free old if available*/
+ if (pClient->curVisualInfo)
+ XFree(pClient->curVisualInfo);
+
+ pClient->curVisualInfo = VisualInfos;
+ pClient->lastretval = true;
+ } else {
+ pClient->lastretval = false;
+ }
+ XUnlockDisplay(pClient->dpy);
+ pClient->fHasLastError = true;
+ pClient->ulLastError = glGetError();
}
void vboxglDrvSwapBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
OGL_CMD(DrvSwapBuffers, 1);
OGL_PARAM(HDC, hdc);
+
+ XLockDisplay(pClient->dpy);
+
+ glXSwapBuffers(pClient->dpy, pClient->xwin);
+
+ XUnlockDisplay(pClient->dpy);
- pClient->lastretval = 0; /** @todo */
+ pClient->lastretval = 1;
+ pClient->fHasLastError = true;
+ pClient->ulLastError = glGetError();
}
void vboxglDrvDescribeLayerPlane(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
@@ -174,7 +392,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 +405,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 +422,17 @@
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;
+ XVisualInfo templateVisualInfo, *matchingVisualInfo;
+ int numVisuals, screenNum, returnNumVisuals, glxReturnValue;
+ long maskVisualInfo;
OGL_CMD(DrvDescribePixelFormat, 3);
OGL_PARAM(HDC, hdc);
@@ -213,12 +440,79 @@
OGL_PARAM(UINT, nBytes);
Assert(pClient->cbLastParam == nBytes);
ppfd = (LPPIXELFORMATDESCRIPTOR)pClient->pLastParam;
-
- pClient->lastretval = 0; /** @todo */
+
+ XLockDisplay(pClient->dpy);
+ /* First get number of all visuals for the return value */
+ screenNum = DefaultScreen(pClient->dpy);
+ templateVisualInfo.screen = screenNum;
+ maskVisualInfo = VisualScreenMask;
+ matchingVisualInfo = XGetVisualInfo(pClient->dpy, maskVisualInfo,
+ &templateVisualInfo,
+ &returnNumVisuals);
+ if (!pClient->VisualIDMapper) {
+ /* Create the PixelFormat to XVisualInfo->visualid mapper
+ * because the Visual ID's are not contiguos and don't start at 1*/
+ int actualVisual = 0;
+
+ pClient->VisualIDMapper = (VisualID *)RTMemAlloc(returnNumVisuals * sizeof(VisualID));
+ for (actualVisual = 0; actualVisual < returnNumVisuals; actualVisual++) {
+ pClient->VisualIDMapper[actualVisual] = matchingVisualInfo[actualVisual].visualid;
+ }
+ }
+ XFree(matchingVisualInfo);
+
+ if (nBytes == sizeof(PIXELFORMATDESCRIPTOR)) {
+ /* Get XVisualInfo which matches iPixelFormat */
+ templateVisualInfo.screen = screenNum;
+ templateVisualInfo.visualid = pClient->VisualIDMapper[iPixelFormat];
+ maskVisualInfo = VisualIDMask | VisualScreenMask;
+ matchingVisualInfo = XGetVisualInfo(pClient->dpy, maskVisualInfo,
+ &templateVisualInfo,
+ &numVisuals);
+ if (matchingVisualInfo) {
+ Log(("Filling values into PIXELFORMATDESCRIPTOR\n"));
+ /* translate all values to theire corresponding Windows ones */
+ ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ ppfd->nVersion = 1;
+ ppfd->cColorBits = (BYTE)matchingVisualInfo->bits_per_rgb;
+ ppfd->iLayerType = PFD_MAIN_PLANE;
+ /* Set dwFlags */
+ ppfd->dwFlags = PFD_DRAW_TO_WINDOW;
+ if (!glXGetConfig(pClient->dpy, matchingVisualInfo, GLX_USE_GL, &glxReturnValue)) {
+ if (glxReturnValue)
+ ppfd->dwFlags |= PFD_SUPPORT_OPENGL;
+ }
+ if (!glXGetConfig(pClient->dpy, matchingVisualInfo, GLX_DOUBLEBUFFER, &glxReturnValue)) {
+ if (glxReturnValue)
+ ppfd->dwFlags |= PFD_DOUBLEBUFFER;
+ }
+ /* Set iPixelType */
+ if (!glXGetConfig(pClient->dpy, matchingVisualInfo, GLX_RGBA, &glxReturnValue)) {
+ if (glxReturnValue)
+ ppfd->iPixelType = PFD_TYPE_RGBA;
+ else
+ ppfd->iPixelType = PFD_TYPE_COLORINDEX;
+ }
+ /* Set cDepthBits */
+ if (!glXGetConfig(pClient->dpy, matchingVisualInfo, GLX_DEPTH_SIZE, &glxReturnValue)) {
+ ppfd->cDepthBits = glxReturnValue;
+ } else {
+ ppfd->cDepthBits = 0;
+ }
+ /** @todo Fill in the rest */
+ XFree(matchingVisualInfo);
+ }
+ }
+ XUnlockDisplay(pClient->dpy);
+ pClient->lastretval = returnNumVisuals;
+ 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 3516)
+++ src/VBox/HostServices/SharedOpenGL/vboxgl.cpp (Arbeitskopie)
@@ -47,6 +47,8 @@
const GLubyte *pName;
uint32_t cbLen;
int rc = VINF_SUCCESS;
+
+ Log(("vboxglGetString\n"));
#ifdef __WIN__
PIXELFORMATDESCRIPTOR pfd;
@@ -66,6 +68,43 @@
HGLRC hRC = wglCreateContext(hdc);
wglMakeCurrent(hdc, hRC);
+#elif defined __LINUX__
+ Display *dpy;
+ static int attribs[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None
+ };
+ XVisualInfo *visinfo;
+ int screen_num;
+ GLXContext ctx;
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window win;
+
+ /* 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 */
+ XLockDisplay(pClient->dpy);
+ dpy = pClient->dpy;
+ screen_num = DefaultScreen(dpy);
+ visinfo = glXChooseVisual(dpy, screen_num, attribs);
+ /* 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 = glXCreateContext(dpy, visinfo, NULL, True);
+ glXMakeCurrent(dpy, win, ctx);
#endif
pName = glGetString(name);
@@ -90,7 +129,13 @@
#ifdef __WIN__
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
- ReleaseDC(0, hdc);
+ ReleaseDC(0, hdc);
+#elif defined __LINUX__
+ /* Free all data */
+ glXDestroyContext(dpy, ctx);
+ XFree(visinfo);
+ XDestroyWindow(dpy, win);
+ XUnlockDisplay(pClient->dpy);
#endif
return rc;
}
@@ -114,7 +159,9 @@
Log(("vboxglFlushBuffer cCommands=%d cbCmdBuffer=%x\n", cCommands, cbCmdBuffer));
pClient->fHasLastError = false;
-
+
+ XLockDisplay(pClient->dpy);
+ glXMakeCurrent(pClient->dpy, pClient->xwin, pClient->ctx);
for (i=0;i<cCommands;i++)
{
PVBOX_OGL_CMD pCmd = (PVBOX_OGL_CMD)pCmdBuffer;
@@ -142,6 +189,8 @@
*pLastError = pClient->ulLastError;
else
*pLastError = glGetError();
+
+ XUnlockDisplay(pClient->dpy);
#ifdef DEBUG
Log(("Flush: last return value=%VX64\n", *pLastRetVal));
Index: src/VBox/HostServices/SharedOpenGL/gldrv.h
===================================================================
--- src/VBox/HostServices/SharedOpenGL/gldrv.h (Revision 3516)
+++ src/VBox/HostServices/SharedOpenGL/gldrv.h (Arbeitskopie)
@@ -22,17 +22,32 @@
#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->ctx
#endif
+#endif
typedef struct
{
@@ -44,10 +59,21 @@
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 xwin;
+ XVisualInfo *curVisualInfo;
+ int win_width, win_height;
+ VisualID *VisualIDMapper;
+ GLXContext ctx;
+ glXGetContextIDEXTProc getContextIDPtr;
+ glXImportContextEXTProc importContextEXTPtr;
#endif
+#endif
} VBOXOGLCTX, *PVBOXOGLCTX;
@@ -66,12 +92,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 +168,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 3516)
+++ 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 3516)
+++ src/VBox/HostServices/SharedOpenGL/Makefile.kmk (Arbeitskopie)
@@ -31,7 +31,9 @@
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_INCS.linux = \
+ /usr/include/qt3
VBoxSharedOpenGL_SOURCES = \
service.cpp \
@@ -53,7 +55,12 @@
$(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 \
+ qt-mt
include $(PATH_KBUILD)/subfooter.kmk
Index: src/VBox/Frontends/VirtualBox/src/main.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/main.cpp (Revision 3516)
+++ src/VBox/Frontends/VirtualBox/src/main.cpp (Arbeitskopie)
@@ -53,8 +53,12 @@
# define REG_PC REG_EIP
#endif
+/** XXX: For Shared OpenGL support*/
+#if defined(Q_WS_X11)
+#include <X11/Xlib.h>
+Display *globalDisplay __attribute__ ((visibility ("default")));
+#endif
-
/**
* the signal handler that prints out a backtrace of the call stack.
* the code is taken from http://www.linuxjournal.com/article/6391.
@@ -131,10 +135,17 @@
sigaction (SIGUSR1, &sa, NULL);
#endif
+#if defined(Q_WS_X11)
+ XInitThreads();
+
qInstallMsgHandler (QtMessageOutput);
+ globalDisplay = XOpenDisplay(NULL);
+ QIApplication a (globalDisplay, argc, argv);
+#else
+ qInstallMsgHandler (QtMessageOutput);
QIApplication a (argc, argv);
-
+#endif
/* weird palette test */
#if 0
QPalette pal = a.palette();
@@ -202,6 +213,10 @@
}
}
+#if defined(Q_WS_X11)
+ XCloseDisplay(globalDisplay);
+#endif
+
LogFlowFunc (("rc=%d\n", rc));
LogFlowFuncLeave();
Index: src/VBox/Main/VMMDevInterface.cpp
===================================================================
--- src/VBox/Main/VMMDevInterface.cpp (Revision 3516)
+++ src/VBox/Main/VMMDevInterface.cpp (Arbeitskopie)
@@ -544,7 +544,6 @@
{
LogRel(("Failed to load Shared OpenGL service %Vrc\n", rc));
}
-
pDrvIns->pDrvHlp->pfnSSMRegister(pDrvIns, "HGCM", 0, HGCM_SSM_VERSION, 4096/* bad guess */, NULL, iface_hgcmSave, NULL, NULL, iface_hgcmLoad, NULL);
#endif /* VBOX_HGCM */
_______________________________________________
vbox-dev mailing list
[email protected]
http://vbox.innotek.de/mailman/listinfo/vbox-dev