gllindrv.cpp revision 648f4eb3997820a317f8aa900598a4b7fe425c23
b614993b942a5222f6d88ae5e9974334484d74f2nd/** @file
b614993b942a5222f6d88ae5e9974334484d74f2nd *
b614993b942a5222f6d88ae5e9974334484d74f2nd * VBox OpenGL
5f5d1b4cc970b7f06ff8ef6526128e9a27303d88nd *
b614993b942a5222f6d88ae5e9974334484d74f2nd * Simple buffered OpenGL functions
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd *
031b91a62d25106ae69d4693475c79618dd5e884fielding * Contributor: Alexander Eichner
031b91a62d25106ae69d4693475c79618dd5e884fielding */
031b91a62d25106ae69d4693475c79618dd5e884fielding
031b91a62d25106ae69d4693475c79618dd5e884fielding/*
031b91a62d25106ae69d4693475c79618dd5e884fielding * Copyright (C) 2006-2007 innotek GmbH
031b91a62d25106ae69d4693475c79618dd5e884fielding *
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * This file is part of VirtualBox Open Source Edition (OSE), as
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * available from http://www.virtualbox.org. This file is free software;
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * you can redistribute it and/or modify it under the terms of the GNU
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * General Public License as published by the Free Software Foundation,
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * distribution. VirtualBox OSE is distributed in the hope that it will
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * be useful, but WITHOUT ANY WARRANTY of any kind.
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd *
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * If you received this file as part of a commercial VirtualBox
816bc7965d58c92c0d02fd42d6ea58090f70c6bdnd * distribution, then only the terms of your commercial VirtualBox
7db9f691a00ead175b03335457ca296a33ddf31bnd * license agreement apply instead of the previous paragraph.
c82fca6d3f5608b946f18d37e8710b1d71e3478dnd *
b614993b942a5222f6d88ae5e9974334484d74f2nd */
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd#include "vboxgl.h"
b614993b942a5222f6d88ae5e9974334484d74f2nd#define LOG_GROUP LOG_GROUP_SHARED_OPENGL
b614993b942a5222f6d88ae5e9974334484d74f2nd#include <VBox/log.h>
b614993b942a5222f6d88ae5e9974334484d74f2nd#include <string.h>
b614993b942a5222f6d88ae5e9974334484d74f2nd#include <stdio.h>
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd/*static int (*X_handler)(Display *, XErrorEvent *) = NULL;
b614993b942a5222f6d88ae5e9974334484d74f2ndstatic int x_errhandler(Display *d, XErrorEvent *e)
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd return (X_handler(d, e));
b614993b942a5222f6d88ae5e9974334484d74f2nd}
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2ndstatic int (*XIO_handler)(Display *) = NULL;
b614993b942a5222f6d88ae5e9974334484d74f2ndstatic int xio_errhandler(Display *d)
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd return (XIO_handler(d));
b614993b942a5222f6d88ae5e9974334484d74f2nd}*/
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2ndstatic Bool WaitForNotify( Display *dpy, XEvent *event, XPointer arg ) {
b614993b942a5222f6d88ae5e9974334484d74f2nd return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
b614993b942a5222f6d88ae5e9974334484d74f2nd}
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd/* from http://www.mesa3d.org/brianp/sig97/exten.htm */
b614993b942a5222f6d88ae5e9974334484d74f2ndGLboolean vboxglCheckExtension(Display *dpy, int screenNum, char *extName )
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd /*
b614993b942a5222f6d88ae5e9974334484d74f2nd ** Search for extName in the extensions string. Use of strstr()
b614993b942a5222f6d88ae5e9974334484d74f2nd ** is not sufficient because extension names can be prefixes of
b614993b942a5222f6d88ae5e9974334484d74f2nd ** other extension names. Could use strtok() but the constant
b614993b942a5222f6d88ae5e9974334484d74f2nd ** string returned by glGetString can be in read-only memory.
b614993b942a5222f6d88ae5e9974334484d74f2nd */
b614993b942a5222f6d88ae5e9974334484d74f2nd char *p = (char *) glXQueryExtensionsString(dpy, screenNum);
b614993b942a5222f6d88ae5e9974334484d74f2nd char *end;
b614993b942a5222f6d88ae5e9974334484d74f2nd int extNameLen;
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd extNameLen = strlen(extName);
b614993b942a5222f6d88ae5e9974334484d74f2nd end = p + strlen(p);
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd while (p < end) {
b614993b942a5222f6d88ae5e9974334484d74f2nd int n = strcspn(p, " ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
b614993b942a5222f6d88ae5e9974334484d74f2nd return GL_TRUE;
b614993b942a5222f6d88ae5e9974334484d74f2nd }
b614993b942a5222f6d88ae5e9974334484d74f2nd p += (n + 1);
b614993b942a5222f6d88ae5e9974334484d74f2nd }
b614993b942a5222f6d88ae5e9974334484d74f2nd return GL_FALSE;
b614993b942a5222f6d88ae5e9974334484d74f2nd}
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd/**
b614993b942a5222f6d88ae5e9974334484d74f2nd * Print parameters for a GLXFBConfig to stdout.
b614993b942a5222f6d88ae5e9974334484d74f2nd * Input: dpy - the X display
b614993b942a5222f6d88ae5e9974334484d74f2nd * screen - the X screen number
b614993b942a5222f6d88ae5e9974334484d74f2nd * fbConfig - the fbconfig handle
b614993b942a5222f6d88ae5e9974334484d74f2nd * horizFormat - if true, print in horizontal format
b614993b942a5222f6d88ae5e9974334484d74f2nd */
b614993b942a5222f6d88ae5e9974334484d74f2ndvoid
b614993b942a5222f6d88ae5e9974334484d74f2ndPrintFBConfigInfo(Display *dpy, int screen, GLXFBConfig config)
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd int bufferSize, level, doubleBuffer, stereo, auxBuffers;
b614993b942a5222f6d88ae5e9974334484d74f2nd int redSize, greenSize, blueSize, alphaSize;
b614993b942a5222f6d88ae5e9974334484d74f2nd int depthSize, stencilSize;
b614993b942a5222f6d88ae5e9974334484d74f2nd int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize;
b614993b942a5222f6d88ae5e9974334484d74f2nd int sampleBuffers, samples;
b614993b942a5222f6d88ae5e9974334484d74f2nd int drawableType, renderType, xRenderable, xVisual, id;
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_BUFFER_SIZE, &bufferSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_LEVEL, &level);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_DOUBLEBUFFER, &doubleBuffer);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_STEREO, &stereo);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_AUX_BUFFERS, &auxBuffers);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_RED_SIZE, &redSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_GREEN_SIZE, &greenSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_BLUE_SIZE, &blueSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_ALPHA_SIZE, &alphaSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_DEPTH_SIZE, &depthSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_STENCIL_SIZE, &stencilSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_RED_SIZE, &accumRedSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_GREEN_SIZE, &accumGreenSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_BLUE_SIZE, &accumBlueSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_ACCUM_ALPHA_SIZE, &accumAlphaSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_SAMPLE_BUFFERS, &sampleBuffers);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_SAMPLES, &samples);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_DRAWABLE_TYPE, &drawableType);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_RENDER_TYPE, &renderType);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_X_RENDERABLE, &xRenderable);
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_X_VISUAL_TYPE, &xVisual);
b614993b942a5222f6d88ae5e9974334484d74f2nd if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX))
b614993b942a5222f6d88ae5e9974334484d74f2nd xVisual = -1;
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd glXGetFBConfigAttrib(dpy, config, GLX_FBCONFIG_ID, &id);
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd printf("Id 0x%x\n", id);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Buffer Size: %d\n", bufferSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Level: %d\n", level);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no");
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Stereo: %s\n", stereo ? "yes" : "no");
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Aux Buffers: %d\n", auxBuffers);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Red Size: %d\n", redSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Green Size: %d\n", greenSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Blue Size: %d\n", blueSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Alpha Size: %d\n", alphaSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Depth Size: %d\n", depthSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Stencil Size: %d\n", stencilSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Accum Red Size: %d\n", accumRedSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Accum Green Size: %d\n", accumGreenSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Accum Blue Size: %d\n", accumBlueSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Accum Alpha Size: %d\n", accumAlphaSize);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Sample Buffers: %d\n", sampleBuffers);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Samples/Pixel: %d\n", samples);
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" Drawable Types: ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if (drawableType & GLX_WINDOW_BIT) printf("Window ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if (drawableType & GLX_PIXMAP_BIT) printf("Pixmap ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if (drawableType & GLX_PBUFFER_BIT) printf("PBuffer");
b614993b942a5222f6d88ae5e9974334484d74f2nd printf("\n");
860b4efe27e7c1c9a2bf5c872b29c90f76849b51jim printf(" Render Types: ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA ");
b614993b942a5222f6d88ae5e9974334484d74f2nd if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI ");
b614993b942a5222f6d88ae5e9974334484d74f2nd printf("\n");
b614993b942a5222f6d88ae5e9974334484d74f2nd printf(" X Renderable: %s\n", xRenderable ? "yes" : "no");
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd}
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd/**
b614993b942a5222f6d88ae5e9974334484d74f2nd * Global init of VBox OpenGL for windows
b614993b942a5222f6d88ae5e9974334484d74f2nd *
b614993b942a5222f6d88ae5e9974334484d74f2nd * @returns VBox error code
b614993b942a5222f6d88ae5e9974334484d74f2nd */
b614993b942a5222f6d88ae5e9974334484d74f2ndint vboxglGlobalInit()
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd Log(("vboxglGlobalInit\n"));
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd /*vboxInitOpenGLExtensions();*/
b614993b942a5222f6d88ae5e9974334484d74f2nd return VINF_SUCCESS;
b614993b942a5222f6d88ae5e9974334484d74f2nd}
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd/**
b614993b942a5222f6d88ae5e9974334484d74f2nd * Enable OpenGL
b614993b942a5222f6d88ae5e9974334484d74f2nd *
b614993b942a5222f6d88ae5e9974334484d74f2nd * @returns VBox error code
b614993b942a5222f6d88ae5e9974334484d74f2nd * @param pClient Client context
b614993b942a5222f6d88ae5e9974334484d74f2nd */
b614993b942a5222f6d88ae5e9974334484d74f2ndint vboxglEnableOpenGL(PVBOXOGLCTX pClient)
b614993b942a5222f6d88ae5e9974334484d74f2nd{
b614993b942a5222f6d88ae5e9974334484d74f2nd Display *dpy;
b614993b942a5222f6d88ae5e9974334484d74f2nd static int attribs[] = {
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_RENDER_TYPE, GLX_RGBA_BIT,
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_DOUBLEBUFFER, True, /* Request a double-buffered color buffer with */
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_RED_SIZE, 1, /* the maximum number of bits per component */
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_GREEN_SIZE, 1,
b614993b942a5222f6d88ae5e9974334484d74f2nd GLX_BLUE_SIZE, 1,
b614993b942a5222f6d88ae5e9974334484d74f2nd None
b614993b942a5222f6d88ae5e9974334484d74f2nd };
b614993b942a5222f6d88ae5e9974334484d74f2nd int screen_num;
b614993b942a5222f6d88ae5e9974334484d74f2nd XSetWindowAttributes attr;
b614993b942a5222f6d88ae5e9974334484d74f2nd unsigned long mask;
b614993b942a5222f6d88ae5e9974334484d74f2nd int returnedFBConfigs;
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd if (!pClient->glxContext)
b614993b942a5222f6d88ae5e9974334484d74f2nd {
b614993b942a5222f6d88ae5e9974334484d74f2nd /* we have to set up a rendering context to be able to use glGetString
b614993b942a5222f6d88ae5e9974334484d74f2nd * a window is created but is not mapped to screen (so it's not visible')
b614993b942a5222f6d88ae5e9974334484d74f2nd * and a GLXContext is bound to it */
b614993b942a5222f6d88ae5e9974334484d74f2nd screen_num = DefaultScreen(pClient->dpy);
b614993b942a5222f6d88ae5e9974334484d74f2nd pClient->enable.fbConfig = pClient->glxChooseFBConfig(pClient->dpy, screen_num, attribs, &returnedFBConfigs);
b614993b942a5222f6d88ae5e9974334484d74f2nd Log(("vboxglGetString: returned FBConfigs: %d\n", returnedFBConfigs));
b614993b942a5222f6d88ae5e9974334484d74f2nd pClient->enable.visinfo = pClient->glxGetVisualFromFBConfig(pClient->dpy, fbConfig[0]);
b614993b942a5222f6d88ae5e9974334484d74f2nd /* Create Window */
b614993b942a5222f6d88ae5e9974334484d74f2nd attr.background_pixel = 0;
b614993b942a5222f6d88ae5e9974334484d74f2nd attr.border_pixel = 0;
b614993b942a5222f6d88ae5e9974334484d74f2nd attr.colormap = XCreateColormap(pClient->dpy, RootWindow(dpy, screen_num), visinfo->visual, AllocNone);
b614993b942a5222f6d88ae5e9974334484d74f2nd attr.event_mask = StructureNotifyMask | ExposureMask;
b614993b942a5222f6d88ae5e9974334484d74f2nd mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
b614993b942a5222f6d88ae5e9974334484d74f2nd pClient->enable.win = XCreateWindow(pClient->dpy, RootWindow(pClient->dpy, screen_num), 0, 0, 100, 100,
b614993b942a5222f6d88ae5e9974334484d74f2nd 0, visinfo->depth, InputOutput,
b614993b942a5222f6d88ae5e9974334484d74f2nd visinfo->visual, mask, &attr);
b614993b942a5222f6d88ae5e9974334484d74f2nd /* Create Context */
b614993b942a5222f6d88ae5e9974334484d74f2nd pClient->enable.ctx = pClient->glxCreateNewContext(pClient->dpy, fbConfig[0], GLX_RGBA_TYPE, NULL, True);
b614993b942a5222f6d88ae5e9974334484d74f2nd
b614993b942a5222f6d88ae5e9974334484d74f2nd glXMakeCurrent(pClient->dpy, pClient->enable.win, pClient->enable.ctx);
}
else
{
glXMakeCurrent(pClient->dpy, pClient->xWindow, pClient->glxContext);
}
return VINF_SUCCESS;
}
/**
* Disable OpenGL
*
* @returns VBox error code
* @param pClient Client context
*/
int vboxglDisableOpenGL(PVBOXOGLCTX pClient)
{
/* Free all data */
glFlush();
if (!pClient->glxContext)
{
glXMakeCurrent(pClient->dpy, 0, NULL);
XDestroyWindow(pClient->dpy, pClient->enable.win);
glXDestroyContext(pClient->dpy, pClient->enable.ctx);
XFree(pClient->enable.visinfo);
XFree(pClient->enable.fbConfig);
}
return VINF_SUCCESS;
}
/**
* Client connect init
*
* @returns VBox error code
* @param pClient Client context
*/
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;
}
/**
* Client disconnect cleanup
*
* @returns VBox error code
* @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)
{
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);
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);
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);
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);
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);
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, 2);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iLayerPlane);
Log(("DrvCreateLayerContext %x\n", hdc));
#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
#else
AssertFailed();
#endif
}
void vboxglDrvShareLists(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
OGL_CMD(DrvShareLists, 3);
OGL_PARAM(HGLRC, hglrc1);
OGL_PARAM(HGLRC, hglrc2);
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvRealizeLayerPalette(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
OGL_CMD(DrvRealizeLayerPalette, 3);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iLayerPlane);
OGL_PARAM(BOOL, bRealize);
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvSwapLayerBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
OGL_CMD(DrvSwapLayerBuffers, 2);
OGL_PARAM(HDC, hdc);
OGL_PARAM(UINT, fuPlanes);
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvSetPixelFormat(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
int screen_num;
OGL_CMD(DrvSetPixelFormat, 4);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iPixelFormat);
OGL_PARAM(uint32_t, cx);
OGL_PARAM(uint32_t, cy);
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);
glXSwapBuffers(pClient->dpy, pClient->xWindow);
pClient->lastretval = 1;
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvDescribeLayerPlane(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
PLAYERPLANEDESCRIPTOR plpd;
OGL_CMD(DrvDescribeLayerPlane, 4);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iPixelFormat);
OGL_PARAM(int, iLayerPlane);
OGL_PARAM(UINT, nBytes);
Assert(pClient->cbLastParam == nBytes);
plpd = (PLAYERPLANEDESCRIPTOR)pClient->pLastParam;
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvSetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
OGL_CMD(DrvSetLayerPaletteEntries, 5);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iLayerPlane);
OGL_PARAM(int, iStart);
OGL_PARAM(int, cEntries);
OGL_MEMPARAM(COLORREF, pcr);
pClient->lastretval = 0; /** @todo */
pClient->fHasLastError = true;
pClient->ulLastError = glGetError();
}
void vboxglDrvGetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
{
COLORREF *pcr;
OGL_CMD(DrvGetLayerPaletteEntries, 4);
OGL_PARAM(HDC, hdc);
OGL_PARAM(int, iLayerPlane);
OGL_PARAM(int, iStart);
OGL_PARAM(int, cEntries);
Assert(pClient->cbLastParam == sizeof(COLORREF)*cEntries);
pcr = (COLORREF *)pClient->pLastParam;
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);
OGL_PARAM(int, iPixelFormat);
OGL_PARAM(UINT, nBytes);
Assert(pClient->cbLastParam == nBytes);
ppfd = (LPPIXELFORMATDESCRIPTOR)pClient->pLastParam;
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)
{
RTUINTPTR pfnProc = (RTUINTPTR)glXGetProcAddress((const GLubyte *)pszExtFunctionName);
Log(("vboxDrvIsExtensionAvailable %s -> %d\n", pszExtFunctionName, !!pfnProc));
return pfnProc;
}