summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/spu_loader
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/spu_loader
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/spu_loader')
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/Makefile.kup0
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/choosevisual.c329
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/spu_loader/dispatch.py126
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py78
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/spu_loader/glloader.py609
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/loader.def21
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/spu_loader/spuchange.py73
-rwxr-xr-xsrc/VBox/GuestHost/OpenGL/spu_loader/spucopy.py80
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/spuinit.c225
-rw-r--r--src/VBox/GuestHost/OpenGL/spu_loader/spuload.c290
10 files changed, 1831 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/Makefile.kup b/src/VBox/GuestHost/OpenGL/spu_loader/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/Makefile.kup
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/choosevisual.c b/src/VBox/GuestHost/OpenGL/spu_loader/choosevisual.c
new file mode 100644
index 00000000..1dc797e1
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/choosevisual.c
@@ -0,0 +1,329 @@
+
+#include "chromium.h"
+#include "cr_spu.h"
+#include "cr_error.h"
+#include "cr_string.h"
+
+
+/**
+ * Wrappers for glXChooseVisual/etc.
+ *
+ * By using this function, the fake GLX, render SPU, tilesort SPU,
+ * etc can be assured of getting the same GLX visual for a set of CR_*_BIT
+ * visual flags. This helps ensure that render_to_app_window will work
+ * properly.
+ */
+
+
+#if defined(WINDOWS)
+int
+crChooseVisual(const crOpenGLInterface *ws, int visBits)
+{
+ /* placeholder */
+ return 0;
+}
+#endif
+
+
+#if defined(DARWIN)
+int
+crChooseVisual(const crOpenGLInterface *ws, int visBits)
+{
+ /* placeholder */
+ return 0;
+}
+#endif
+
+
+#if defined(GLX)
+
+XVisualInfo *
+crChooseVisual(const crOpenGLInterface *ws, Display *dpy, int screen,
+ GLboolean directColor, int visBits)
+{
+ XVisualInfo *vis;
+ int errorBase, eventBase;
+
+ if (ws->glXQueryExtension(dpy, &errorBase, &eventBase))
+ {
+
+ if (ws->glXChooseVisual)
+ {
+ /* Use the real OpenGL's glXChooseVisual function */
+ int attribList[100];
+ int i = 0;
+
+ /* Build the attribute list */
+ if (visBits & CR_RGB_BIT)
+ {
+ attribList[i++] = GLX_RGBA;
+ attribList[i++] = GLX_RED_SIZE;
+ attribList[i++] = 1;
+ attribList[i++] = GLX_GREEN_SIZE;
+ attribList[i++] = 1;
+ attribList[i++] = GLX_BLUE_SIZE;
+ attribList[i++] = 1;
+ }
+
+ if (visBits & CR_ALPHA_BIT)
+ {
+ attribList[i++] = GLX_ALPHA_SIZE;
+ attribList[i++] = 1;
+ }
+
+ if (visBits & CR_DOUBLE_BIT)
+ {
+ attribList[i++] = GLX_DOUBLEBUFFER;
+ }
+
+ if (visBits & CR_STEREO_BIT)
+ {
+ attribList[i++] = GLX_STEREO;
+ }
+
+ if (visBits & CR_DEPTH_BIT)
+ {
+ attribList[i++] = GLX_DEPTH_SIZE;
+ attribList[i++] = 1;
+ }
+
+ if (visBits & CR_STENCIL_BIT)
+ {
+ attribList[i++] = GLX_STENCIL_SIZE;
+ attribList[i++] = 1;
+ }
+
+ if (visBits & CR_ACCUM_BIT)
+ {
+ attribList[i++] = GLX_ACCUM_RED_SIZE;
+ attribList[i++] = 1;
+ attribList[i++] = GLX_ACCUM_GREEN_SIZE;
+ attribList[i++] = 1;
+ attribList[i++] = GLX_ACCUM_BLUE_SIZE;
+ attribList[i++] = 1;
+ if (visBits & CR_ALPHA_BIT)
+ {
+ attribList[i++] = GLX_ACCUM_ALPHA_SIZE;
+ attribList[i++] = 1;
+ }
+ }
+
+ if (visBits & CR_MULTISAMPLE_BIT)
+ {
+ attribList[i++] = GLX_SAMPLE_BUFFERS_SGIS;
+ attribList[i++] = 1;
+ attribList[i++] = GLX_SAMPLES_SGIS;
+ attribList[i++] = 4;
+ }
+
+ if (visBits & CR_OVERLAY_BIT)
+ {
+ attribList[i++] = GLX_LEVEL;
+ attribList[i++] = 1;
+ }
+
+ if (directColor)
+ {
+ /*
+ * See if we have have GLX_EXT_visual_info so we
+ * can grab a Direct Color visual
+ */
+#ifdef GLX_EXT_visual_info
+ if (crStrstr(ws->glXQueryExtensionsString(dpy, screen),
+ "GLX_EXT_visual_info"))
+ {
+ attribList[i++] = GLX_X_VISUAL_TYPE_EXT;
+ attribList[i++] = GLX_DIRECT_COLOR_EXT;
+ }
+#endif
+ }
+
+ /* End the list */
+ attribList[i++] = None;
+
+ vis = ws->glXChooseVisual(dpy, screen, attribList);
+ return vis;
+ }
+ else
+ {
+ /* Don't use glXChooseVisual, use glXGetConfig.
+ *
+ * Here's the deal:
+ * Some (all?) versions of the libGL.so that's shipped with ATI's
+ * drivers aren't built with the -Bsymbolic flag. That's bad.
+ *
+ * If we call the glXChooseVisual() function that's built into ATI's
+ * libGL, it in turn calls the glXGetConfig() function. Now, there's
+ * a glXGetConfig function in libGL.so **AND** there's a glXGetConfig
+ * function in Chromium's libcrfaker.so library. Unfortunately, the
+ * later one gets called instead of the former. At this point, things
+ * go haywire. If -Bsymbolic were used, this would not happen.
+ */
+ XVisualInfo templateVis;
+ long templateFlags;
+ int count, i, visType;
+
+ visType = directColor ? DirectColor : TrueColor;
+
+ /* Get list of candidate visuals */
+ templateFlags = VisualScreenMask | VisualClassMask;
+ templateVis.screen = screen;
+#if defined(__cplusplus) || defined(c_plusplus)
+ templateVis.c_class = visType;
+#else
+ templateVis.class = visType;
+#endif
+
+ vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
+ /* find first visual that's good enough */
+ for (i = 0; i < count; i++)
+ {
+ int val;
+
+ /* Need exact match on RGB, DOUBLEBUFFER, STEREO, LEVEL, MULTISAMPLE */
+ ws->glXGetConfig(dpy, vis + i, GLX_RGBA, &val);
+ if (((visBits & CR_RGB_BIT) && !val) ||
+ (((visBits & CR_RGB_BIT) == 0) && val))
+ {
+ continue;
+ }
+
+ ws->glXGetConfig(dpy, vis + i, GLX_DOUBLEBUFFER, &val);
+ if (((visBits & CR_DOUBLE_BIT) && !val) ||
+ (((visBits & CR_DOUBLE_BIT) == 0) && val))
+ {
+ continue;
+ }
+
+ ws->glXGetConfig(dpy, vis + i, GLX_STEREO, &val);
+ if (((visBits & CR_STEREO_BIT) && !val) ||
+ (((visBits & CR_STEREO_BIT) == 0) && val))
+ {
+ continue;
+ }
+
+ ws->glXGetConfig(dpy, vis + i, GLX_LEVEL, &val);
+ if (((visBits & CR_OVERLAY_BIT) && !val) ||
+ (((visBits & CR_OVERLAY_BIT) == 0) && val))
+ {
+ continue;
+ }
+
+ ws->glXGetConfig(dpy, vis + i, GLX_SAMPLE_BUFFERS_SGIS, &val);
+ if (visBits & CR_MULTISAMPLE_BIT)
+ {
+ if (!val)
+ continue;
+ ws->glXGetConfig(dpy, vis + i, GLX_SAMPLES_SGIS, &val);
+ if (val < 4)
+ continue;
+ }
+ else {
+ /* don't want multisample */
+ if (val)
+ continue;
+ }
+
+ /* Need good enough for ALPHA, DEPTH, STENCIL, ACCUM */
+ if (visBits & CR_ALPHA_BIT)
+ {
+ ws->glXGetConfig(dpy, vis + i, GLX_ALPHA_SIZE, &val);
+ if (!val)
+ continue;
+ }
+
+ if (visBits & CR_DEPTH_BIT)
+ {
+ ws->glXGetConfig(dpy, vis + i, GLX_DEPTH_SIZE, &val);
+ if (!val)
+ continue;
+ }
+
+ if (visBits & CR_STENCIL_BIT)
+ {
+ ws->glXGetConfig(dpy, vis + i, GLX_STENCIL_SIZE, &val);
+ if (!val)
+ continue;
+ }
+
+ if (visBits & CR_ACCUM_BIT)
+ {
+ ws->glXGetConfig(dpy, vis + i, GLX_ACCUM_RED_SIZE, &val);
+ if (!val)
+ continue;
+ if (visBits & CR_ALPHA_BIT)
+ {
+ ws->glXGetConfig(dpy, vis + i, GLX_ACCUM_ALPHA_SIZE, &val);
+ if (!val)
+ continue;
+ }
+ }
+
+ /* If we get here, we found a good visual.
+ * Now, we need to get a new XVisualInfo pointer in case the caller
+ * calls XFree on it.
+ */
+ templateFlags = VisualScreenMask | VisualIDMask;
+ templateVis.screen = screen;
+ templateVis.visualid = vis[i].visual->visualid;
+ XFree(vis); /* free the list */
+ vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
+ return vis;
+ }
+
+ /* if we get here, we failed to find a sufficient visual */
+ return NULL;
+ }
+ }
+ else
+ {
+ /* use Xlib instead of GLX */
+ XVisualInfo templateVis, *best;
+ long templateFlags;
+ int i, count, visType;
+
+ if (visBits & CR_RGB_BIT)
+ visType = directColor ? DirectColor : TrueColor;
+ else
+ visType = PseudoColor;
+
+ /* Get list of candidate visuals */
+ templateFlags = VisualScreenMask | VisualClassMask;
+ templateVis.screen = screen;
+#if defined(__cplusplus) || defined(c_plusplus)
+ templateVis.c_class = visType;
+#else
+ templateVis.class = visType;
+#endif
+
+ vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
+ if (!vis)
+ return NULL;
+
+ /* okay, select the RGB visual with the most depth */
+ best = vis + 0;
+ for (i = 1; i < count; i++)
+ {
+ if (vis[i].depth > best->depth &&
+ vis[i].bits_per_rgb > best->bits_per_rgb )
+ best = vis + i;
+ }
+
+ if (best)
+ {
+ /* If we get here, we found a good visual.
+ * Now, we need to get a new XVisualInfo pointer in case the caller
+ * calls XFree on it.
+ */
+ templateFlags = VisualScreenMask | VisualIDMask;
+ templateVis.screen = screen;
+ templateVis.visualid = best->visualid;
+ XFree(vis); /* free the list */
+ best = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
+ }
+
+ return best;
+ }
+}
+
+#endif /* GLX */
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py b/src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py
new file mode 100755
index 00000000..581121d5
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py
@@ -0,0 +1,126 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys
+import apiutil
+
+
+apiutil.CopyrightC()
+
+print("""
+
+/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY dispatch.py SCRIPT */
+
+#include "cr_spu.h"
+#include "cr_string.h"
+#include "cr_error.h"
+
+
+static SPUGenericFunction __findFunc( char *name, SPU *spu )
+{
+ SPUNamedFunctionTable *temp;
+
+ if (spu == NULL)
+ return NULL;
+
+ for (temp = spu->function_table->table ; temp->name != NULL ; temp++)
+ {
+ if (!crStrcmp(name, temp->name))
+ {
+ return temp->fn;
+ }
+ }
+ return __findFunc(name, spu->superSPU);
+}
+
+
+/*
+ * This function is not public outside the loader SPU.
+ */
+extern void __buildDispatch( SPU *spu );
+
+void __buildDispatch( SPU *spu )
+{""")
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+for func_name in keys:
+ print('\tspu->dispatch_table.%s = (%sFunc_t) __findFunc( "%s", spu );' % (func_name,func_name,func_name))
+print('}')
+
+
+print("""
+
+/*
+ * Public function:
+ * Search a SPU named function table for a specific function. Return
+ * a pointer to it or NULL if not found.
+ */
+SPUGenericFunction crSPUFindFunction( const SPUNamedFunctionTable *table, const char *fname )
+{
+ const SPUNamedFunctionTable *temp;
+
+ for (temp = table ; temp->name != NULL ; temp++)
+ {
+ if (!crStrcmp(fname, temp->name))
+ {
+ return temp->fn;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * Public function:
+ * Initializes the pointers in an SPUDispatchTable by looking for functions
+ * in an SPUNamedFunctionTable.
+ * It doesn't know anything about SPUs and SPU inheritance.
+ */
+void crSPUInitDispatch( SPUDispatchTable *dispatch, const SPUNamedFunctionTable *table )
+{""")
+
+for func_name in keys:
+ print('\tdispatch->%s = (%sFunc_t) crSPUFindFunction(table, "%s");' % (func_name, func_name, func_name))
+print('}')
+
+
+
+print("""
+/*
+ * Generic no-op function
+ */
+static int NopFunction(void)
+{
+/*
+ crWarning("Calling generic no-op function in dispatch.c");
+*/
+ return 0;
+}
+
+
+/*
+ * Scan the given dispatch table for NULL pointers. Hook in the generic
+ * no-op function wherever we find a NULL pointer.
+ */
+void crSPUInitDispatchNops(SPUDispatchTable *table)
+{
+ /*
+ * This is a bit tricky. We walk over all the function pointers in
+ * the SPUDispatchTable struct, checking for NULL and setting NULL
+ * pointers to point to NopFunction().
+ * But we have to stop when we get to the copyList pointer!
+ */
+ const int numEntries = (void **) &(table->copyList) - (void **) &(table->Accum);
+ void **ptr = (void **) table;
+ int i;
+ for (i = 0; i < numEntries; i++) {
+ if (ptr[i] == NULL) {
+ /*printf("!!!!!!!Warning entry[%d] = NULL\n", i);*/
+ ptr[i] = (void *)(uintptr_t)NopFunction;
+ }
+ }
+}
+""")
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py b/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py
new file mode 100755
index 00000000..f3f15bee
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+# This script generates the spu_dispatch_table.h file from gl_header.parsed
+
+from __future__ import print_function
+import sys, string
+
+import apiutil
+
+
+apiutil.CopyrightC()
+
+print("""
+/* DO NOT EDIT - THIS FILE GENERATED BY THE dispatchheader.py SCRIPT */
+
+#ifndef CR_SPU_DISPATCH_TABLE_H
+#define CR_SPU_DISPATCH_TABLE_H
+
+#ifdef WINDOWS
+#define SPU_APIENTRY __stdcall
+#else
+#define SPU_APIENTRY
+#endif
+
+#include "chromium.h"
+#include "state/cr_statetypes.h"
+""")
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+
+
+print('/* Offsets of each function within the dispatch table */')
+offset = 0
+for func_name in keys:
+ print('#define DISPATCH_OFFSET_%s %d' % (func_name, offset))
+ offset += 1
+print('')
+
+print('/* Function typedefs */')
+for func_name in keys:
+ return_type = apiutil.ReturnType(func_name)
+ params = apiutil.Parameters(func_name)
+
+ print('typedef %s (SPU_APIENTRY *%sFunc_t)(%s);' % (return_type, func_name, apiutil.MakePrototypeString(params)))
+print('')
+
+print('struct _copy_list_node;')
+print('')
+print('/* Prototype for SPU internal state load/unload callbacks. */')
+print('')
+print('typedef int (*SPUStateFunc_t)(void *);')
+print('')
+print('/* The SPU dispatch table */')
+print('typedef struct _spu_dispatch_table {')
+
+for func_name in keys:
+ print("\t%sFunc_t %s; " % ( func_name, func_name ))
+
+print("""
+ struct _copy_list_node *copyList;
+ struct _spu_dispatch_table *copy_of;
+ int mark;
+ void *server;
+ SPUStateFunc_t spu_save_state; /* Save SPU internal state callback (optional) */
+ SPUStateFunc_t spu_load_state; /* Load SPU internal state callback (optional) */
+} SPUDispatchTable;
+
+struct _copy_list_node {
+ SPUDispatchTable *copy;
+ struct _copy_list_node *next;
+};
+
+
+#endif /* CR_SPU_DISPATCH_TABLE_H */
+""")
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py b/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
new file mode 100755
index 00000000..c73c12f1
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/glloader.py
@@ -0,0 +1,609 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+
+from __future__ import print_function
+import sys
+import apiutil
+
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+
+apiutil.CopyrightC()
+
+print("""
+/* DO NOT EDIT - THIS FILE GENERATED BY THE glloader.py SCRIPT */
+#include "cr_error.h"
+#include "cr_dll.h"
+#include "cr_spu.h"
+#include "cr_string.h"
+#include "cr_error.h"
+#include "cr_environment.h"
+
+#include <stdio.h>
+#if defined(WINDOWS)
+# ifdef VBOX
+# include <iprt/win/windows.h>
+# else
+#include <windows.h>
+# endif
+#include <process.h>
+#include <direct.h>
+#define SYSTEM_GL "opengl32.dll"
+#elif defined (DARWIN)
+#define SYSTEM_GL "libGL.dylib"
+#define SYSTEM_CGL "OpenGL"
+# ifndef VBOX_WITH_COCOA_QT
+# define SYSTEM_AGL "AGL"
+# endif
+#include <string.h> /* VBOX */
+#elif defined(IRIX) || defined(IRIX64) || defined(Linux) || defined(FreeBSD) || defined(AIX) || defined(SunOS) || defined(OSF1)
+#include <string.h>
+#if defined(AIX)
+#define SYSTEM_GL "libGL.o"
+#else
+#define SYSTEM_GL "libGL.so.1"
+#endif
+typedef void (*glxfuncptr)(void);
+extern glxfuncptr glxGetProcAddressARB( const GLubyte *name );
+#else
+#error I don't know where your system's GL lives. Too bad.
+#endif
+
+static CRDLL *glDll = NULL;
+
+#ifdef DARWIN
+#define SYSTEM_GL_LIB_DIR "/System/Library/Frameworks/OpenGL.framework/Libraries"
+#define SYSTEM_CGL_DIR "/System/Library/Frameworks/OpenGL.framework"
+static CRDLL *cglDll = NULL;
+# ifndef VBOX_WITH_COCOA_QT
+# define SYSTEM_AGL_DIR "/System/Library/Frameworks/AGL.framework"
+static CRDLL *aglDll = NULL;
+# endif
+#endif
+
+#if defined(WINDOWS)
+#define GLLOADER_APIENTRY __stdcall
+#else
+#define GLLOADER_APIENTRY
+#endif
+
+/*
+ * Add an entry to the SPUNamedFunctionTable
+ */
+static int
+fillin(SPUNamedFunctionTable *entry, const char *funcName, SPUGenericFunction funcPtr)
+{
+ if (funcPtr) {
+ entry->name = crStrdup(funcName);
+ entry->fn = funcPtr;
+ return 1;
+ }
+ return 0;
+}
+
+#ifndef WINDOWS
+/*static int FileExists(char *directory, char *filename)
+{
+ FILE *f;
+ char fullFilename[8096];
+
+ crStrcpy(fullFilename, directory);
+ crStrcat(fullFilename, "/");
+ crStrcat(fullFilename, filename);
+
+ f = fopen(fullFilename, "r");
+ if (f) {
+ fclose(f);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}*/
+#endif
+
+
+/*
+ * Locate the native OpenGL library, open it and return shared library
+ * handle.
+ */
+static CRDLL *
+__findSystemLib( const char *provided_system_path, char *lib )
+{
+ CRDLL *dll;
+ char system_path[8096];
+
+ memset(system_path, 0, sizeof(system_path));
+
+ if (provided_system_path && (crStrlen(provided_system_path) > 0) )
+ {
+ crStrcpy( system_path, provided_system_path );
+ }
+ else
+ {
+#if defined(WINDOWS)
+ GetSystemDirectory(system_path, MAX_PATH);
+#elif defined(IRIX) || defined(IRIX64)
+#ifdef IRIX_64BIT
+ crStrcpy( system_path, "/usr/lib64" );
+#else
+ crStrcpy( system_path, "/usr/lib32" );
+#endif
+#elif defined(PLAYSTATION2)
+ crStrcpy( system_path, "/usr/X11R6/lib" );
+#else
+ /* On RedHat 9, the correct default system directory
+ * is /usr/lib/tls/ (and if /usr/lib/ is used,
+ * the dynamic loader will generate a floating point
+ * exception SIGFPE). On other systems, including
+ * earlier versions of RedHat, the OpenGL library
+ * lives in /usr/lib. We'll use the /usr/lib/tls/
+ * version if it exists; otherwise, we'll use /usr/lib.
+ */
+ /*crStrcpy(system_path, "/usr/lib");*/
+#if defined(__linux__) && defined(__amd64__)
+ /*if (sizeof(void *) == 8 && FileExists("/usr/lib64", lib)) {
+ crStrcat(system_path, "64");
+ }*/
+#endif
+ /*if (FileExists("/usr/lib/tls", lib) ||
+ FileExists("/usr/lib64/tls", lib)) {
+ crStrcat(system_path, "/tls");
+ }*/
+#endif
+ }
+#if !defined(__linux__) && !defined(SunOS) && !defined(__FreeBSD__)
+ crStrcat( system_path, "/" );
+#endif
+#if !defined(CR_NO_GL_SYSTEM_PATH)
+ crStrcat( system_path, lib );
+ dll = crDLLOpen(system_path, 1 /*resolveGlobal*/);
+#else
+ dll = crDLLOpen(lib, 1 /*resolveGlobal*/);
+#endif
+ return dll;
+}
+
+
+static CRDLL *
+#ifdef DARWIN
+__findSystemGL( const char *provided_system_path, const char *default_system_path, char *provided_lib_name )
+#else
+__findSystemGL( const char *provided_system_path )
+#endif
+{
+#ifdef DARWIN
+ const char *the_path = (provided_system_path && crStrlen(provided_system_path) > 0) ? provided_system_path : default_system_path;
+
+ /* Fallback for loading frameworks */
+ if( !provided_lib_name )
+ return crDLLOpen( the_path, 1 );
+ else
+ return __findSystemLib( the_path, provided_lib_name );
+#else
+ return __findSystemLib( provided_system_path, SYSTEM_GL );
+#endif
+}
+
+static SPUGenericFunction
+findExtFunction( const crOpenGLInterface *interface, const char *funcName )
+{
+#ifdef WINDOWS
+ if (interface->wglGetProcAddress)
+ return (SPUGenericFunction) interface->wglGetProcAddress( funcName );
+ else
+ return (SPUGenericFunction) NULL;
+#else
+ /* XXX for some reason, the NVIDIA glXGetProcAddressARB() function
+ * returns pointers that cause Chromium to crash. If we use the
+ * pointer returned by crDLLGetNoError() instead, we're OK.
+ */
+ SPUGenericFunction f = crDLLGetNoError(glDll, funcName);
+ if (f)
+ return f;
+#if !defined(DARWIN)
+ else if (interface->glXGetProcAddressARB)
+ return interface->glXGetProcAddressARB( (const GLubyte *) funcName );
+#endif
+ else
+ return NULL;
+#endif
+}
+""")
+
+
+def IsExtensionFunc(func_name):
+ """Determine if the named function is a core function, or extension."""
+ cat = apiutil.Category(func_name)
+ if cat == "1.0" or cat == "1.1" or cat == "1.2" or cat == "1.3":
+ return 0
+ else:
+ return 1
+
+#
+# Generate a no-op function.
+#
+def GenerateNop(func_name):
+ return_type = apiutil.ReturnType(func_name);
+ params = apiutil.Parameters(func_name)
+ print('static %s GLLOADER_APIENTRY Nop%s(%s)' % (return_type, func_name, apiutil.MakeDeclarationString(params)))
+ print('{')
+ for (name, type, vecSize) in params:
+ if name != "":
+ print('\t(void) %s;' % name)
+ if apiutil.ReturnType(func_name) != 'void':
+ print('\treturn 0;')
+ print('}')
+ print('')
+
+
+
+#
+# Make no-op funcs for all OpenGL extension functions
+#
+for func_name in keys:
+ if IsExtensionFunc(func_name):
+ GenerateNop(func_name)
+
+
+#
+# Generate the crLoadOpenGL() function
+#
+print("""
+void
+crUnloadOpenGL( void )
+{
+ crDLLClose( glDll );
+ glDll = NULL;
+
+#ifdef DARWIN
+ crDLLClose( cglDll );
+ cglDll = NULL;
+
+# ifndef VBOX_WITH_COCOA_QT
+ crDLLClose( aglDll );
+ aglDll = NULL;
+# endif
+#endif
+}
+
+/*
+ * Initialize the 'interface' structure with the WGL or GLX window system
+ * interface functions.
+ * Then, fill in the table with (name, pointer) pairs for all the core
+ * OpenGL entrypoint functions. But only if table is not NULL
+ * Return: number of entries placed in table[], or 0 if error.
+ */
+int
+crLoadOpenGL( crOpenGLInterface *interface, SPUNamedFunctionTable table[] )
+{
+ static const char *coreFunctions[] = {
+""")
+
+for func_name in keys:
+ if not IsExtensionFunc(func_name):
+ print('\t\t"gl%s",' % func_name)
+
+print("""
+ NULL
+ };
+ SPUNamedFunctionTable *entry = table;
+ int i;
+
+ const char *env_syspath = crGetenv( "CR_SYSTEM_GL_PATH" );
+#ifdef DARWIN
+ const char *env_cgl_syspath = crGetenv( "CR_SYSTEM_CGL_PATH" );
+# ifndef VBOX_WITH_COCOA_QT
+ const char *env_agl_syspath = crGetenv( "CR_SYSTEM_AGL_PATH" );
+# endif
+#endif
+
+ crDebug( "Looking for the system's OpenGL library..." );
+#ifdef DARWIN
+ glDll = __findSystemGL( env_syspath, SYSTEM_GL_LIB_DIR, SYSTEM_GL );
+#else
+ glDll = __findSystemGL( env_syspath );
+#endif
+ if (!glDll)
+ {
+ crError("Unable to find system OpenGL!");
+ return 0;
+ }
+
+ crDebug( "Found it in %s.", !env_syspath ? "default path" : env_syspath );
+
+#ifdef DARWIN
+ crDebug( "Looking for the system's CGL library..." );
+ cglDll = __findSystemGL( env_cgl_syspath, SYSTEM_CGL_DIR, SYSTEM_CGL );
+ if (!cglDll)
+ {
+ crError("Unable to find system CGL!");
+ return 0;
+ }
+
+ crDebug( "Found it in %s.", !env_cgl_syspath ? "default path" : env_cgl_syspath );
+
+# ifndef VBOX_WITH_COCOA_QT
+ crDebug( "Looking for the system's AGL library..." );
+ aglDll = __findSystemGL( env_agl_syspath, SYSTEM_AGL_DIR, SYSTEM_AGL );
+ if (!aglDll)
+ {
+ crError("Unable to find system AGL!");
+ return 0;
+ }
+
+ crDebug( "Found it in %s.", !env_agl_syspath ? "default path" : env_agl_syspath );
+# endif
+#endif
+""")
+
+useful_wgl_functions = [
+ "wglGetProcAddress",
+ "wglMakeCurrent",
+ "wglSwapBuffers",
+ "wglCreateContext",
+ "wglDeleteContext",
+ "wglShareLists",
+ "wglGetCurrentContext",
+ "wglChoosePixelFormat",
+ "wglDescribePixelFormat",
+ "wglSetPixelFormat",
+ "wglChoosePixelFormatEXT",
+ "wglGetPixelFormatAttribivEXT",
+ "wglGetPixelFormatAttribfvEXT",
+ "glGetString"
+]
+useful_agl_functions = [
+ "aglCreateContext",
+ "aglDestroyContext",
+ "aglSetCurrentContext",
+ "aglSwapBuffers",
+ "aglChoosePixelFormat",
+ "aglDestroyPixelFormat",
+ "aglDescribePixelFormat",
+ "aglGetCurrentContext",
+ "aglSetDrawable",
+ "aglGetDrawable",
+ "aglSetFullScreen",
+ "aglUpdateContext",
+ "aglUseFont",
+ "aglSetInteger",
+ "aglGetInteger",
+ "aglGetError",
+ "aglEnable",
+ "aglDisable"
+]
+in_gl_functions = [
+ "CGLGetCurrentContext",
+ "CGLSetCurrentContext"
+]
+useful_cgl_functions = [
+ "CGLChoosePixelFormat",
+ "CGLDestroyPixelFormat",
+ "CGLDescribePixelFormat",
+ "CGLQueryRendererInfo",
+ "CGLDestroyRendererInfo",
+ "CGLDescribeRenderer",
+ "CGLCreateContext",
+ "CGLDestroyContext",
+ "CGLCopyContext",
+ "CGLCreatePBuffer",
+ "CGLDestroyPBuffer",
+ "CGLDescribePBuffer",
+ "CGLTexImagePBuffer",
+ "CGLSetOffScreen",
+ "CGLGetOffScreen",
+ "CGLSetFullScreen",
+ "CGLSetPBuffer",
+ "CGLGetPBuffer",
+ "CGLClearDrawable",
+ "CGLFlushDrawable",
+ "CGLEnable",
+ "CGLDisable",
+ "CGLIsEnabled",
+ "CGLSetParameter",
+ "CGLGetParameter",
+ "CGLSetVirtualScreen",
+ "CGLGetVirtualScreen",
+ "CGLSetOption",
+ "CGLGetOption",
+ "CGLGetVersion",
+ "CGLErrorString",
+ "CGLSetSurface",
+ "CGLGetSurface",
+ "CGLUpdateContext",
+ "glGetString"
+]
+useful_glx_functions = [
+ "glXGetConfig",
+ "glXQueryExtension",
+ "glXQueryVersion",
+ "glXQueryExtensionsString",
+ "glXChooseVisual",
+ "glXCreateContext",
+ "glXDestroyContext",
+ "glXUseXFont",
+ "glXIsDirect",
+ "glXMakeCurrent",
+ "glGetString",
+ "glXSwapBuffers",
+ "glXGetCurrentDisplay",
+ "glXGetCurrentContext",
+ "glXGetClientString",
+ "glXWaitGL",
+ "glXWaitX",
+ "glXCopyContext"
+]
+possibly_useful_glx_functions = [
+ "glXGetProcAddressARB",
+ "glXJoinSwapGroupNV",
+ "glXBindSwapBarrierNV",
+ "glXQuerySwapGroupNV",
+ "glXQueryMaxSwapGroupsNV",
+ "glXQueryFrameCountNV",
+ "glXResetFrameCountNV",
+ "glXChooseFBConfig",
+ "glXGetFBConfigs",
+ "glXGetFBConfigAttrib",
+ "glXGetVisualFromFBConfig",
+ "glXCreateNewContext",
+ "glXCreatePbuffer",
+ "glXDestroyPbuffer",
+ "glXQueryContext",
+ "glXQueryDrawable",
+ "glXMakeContextCurrent",
+ "glXCreateWindow",
+ "glXGetVisualFromFBConfig",
+]
+
+print('#ifdef WINDOWS')
+
+for fun in useful_wgl_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(glDll, "%s");' % (fun,fun,fun))
+
+print('#elif defined(DARWIN)')
+print('# ifndef VBOX_WITH_COCOA_QT')
+for fun in useful_agl_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(aglDll, "%s");' % (fun,fun,fun))
+print('# endif')
+
+for fun in useful_cgl_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(cglDll, "%s");' % (fun, fun,fun))
+
+for fun in in_gl_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(glDll, "%s");' % (fun, fun,fun))
+
+print('#else')
+print('\t/* GLX */')
+
+# XXX merge these loops?
+for fun in useful_glx_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(glDll, "%s");' % (fun, fun, fun))
+for fun in possibly_useful_glx_functions:
+ print('\tinterface->%s = (%sFunc_t) crDLLGetNoError(glDll, "%s");' % (fun, fun, fun))
+print('#endif')
+
+print("""
+ if (!entry)
+ return 1; /* token value */
+
+ for (i = 0; coreFunctions[i]; i++) {
+ const char *name = coreFunctions[i];
+ if (fillin(entry, name + 2, crDLLGetNoError(glDll, name)))
+ entry++;
+ else
+ crDebug("glLoader: NULL function %s", name);
+ }
+
+ /* end of table markers */
+ entry->name = NULL;
+ entry->fn = NULL;
+ return entry - table; /* number of entries filled */
+}
+
+
+/*
+ * Fill in table[] with all the OpenGL extension functions that we're
+ * interested in.
+ */
+int
+crLoadOpenGLExtensions( const crOpenGLInterface *interface, SPUNamedFunctionTable table[] )
+{
+ struct extfunc {
+ const char *funcName;""")
+max_aliases = apiutil.ReverseAliasesMaxCount()
+for i in range(1, 1 + max_aliases):
+ print("\t\tconst char *aliasName%d;" % i)
+print(""" SPUGenericFunction nopFunction;
+ };
+ static const struct extfunc functions[] = {
+""")
+
+for func_name in keys:
+ if IsExtensionFunc(func_name):
+ if apiutil.Category(func_name) == "Chromium":
+ prefix = "cr"
+ else:
+ prefix = "gl"
+ s = '\t\t{ "' + prefix + func_name + '"'
+ aliases = apiutil.ReverseAliases(func_name)
+ s += ''.join([', "' + prefix + a + '"' for a in aliases]) + ', NULL' * (max_aliases - len(aliases))
+ s += ', (SPUGenericFunction) Nop' + func_name + ' },'
+ print(s)
+
+print('\t\t{ NULL%s, NULL}' % (', NULL' * max_aliases))
+print("""
+ };
+ const struct extfunc *func;
+ SPUNamedFunctionTable *entry = table;
+
+#ifdef WINDOWS
+ if (interface->wglGetProcAddress == NULL)
+ crWarning("Unable to find wglGetProcAddress() in system GL library");
+#elif !defined(DARWIN)
+ if (interface->glXGetProcAddressARB == NULL)
+ crWarning("Unable to find glXGetProcAddressARB() in system GL library");
+#endif
+
+ for (func = functions; func->funcName; func++) {
+ SPUGenericFunction f = findExtFunction(interface, func->funcName);""")
+for i in range(1, 1 + max_aliases):
+ print(""" if (!f && func->aliasName%d) {
+ f = findExtFunction(interface, func->aliasName%d);
+ }"""% (i, i))
+print(""" if (!f) {
+ f = func->nopFunction;
+ }
+ (void) fillin(entry, func->funcName + 2 , f); /* +2 to skip "gl" */
+ entry++;
+ }
+
+ /* end of list */
+ entry->name = NULL;
+ entry->fn = NULL;
+ return entry - table; /* number of entries filled */
+}
+""")
+
+
+print("""
+
+#ifdef USE_OSMESA
+int crLoadOSMesa( OSMesaContext (**createContext)( GLenum format, OSMesaContext sharelist ),
+ GLboolean (**makeCurrent)( OSMesaContext ctx, GLubyte *buffer,
+ GLenum type, GLsizei width, GLsizei height ),
+ void (**destroyContext)( OSMesaContext ctx ))
+{
+ static CRDLL *osMesaDll = NULL;
+
+ const char *env_syspath = crGetenv( "CR_SYSTEM_GL_PATH" );
+
+ crDebug( "Looking for the system's OSMesa library..." );
+ osMesaDll = __findSystemLib( env_syspath, "libOSMesa.so" );
+ if (!osMesaDll)
+ {
+ crError("Unable to find system OSMesa!");
+ return 0;
+ }
+
+ crDebug( "Found it in %s.", !env_syspath ? "default path" : env_syspath );
+
+ *createContext = (OSMesaContext (*) ( GLenum format, OSMesaContext sharelist ))
+ crDLLGetNoError(osMesaDll, "OSMesaCreateContext");
+
+ *makeCurrent = (GLboolean (*) ( OSMesaContext ctx, GLubyte *buffer,
+ GLenum type, GLsizei width, GLsizei height ))
+ crDLLGetNoError(osMesaDll, "OSMesaMakeCurrent");
+
+ *destroyContext = (void (*) ( OSMesaContext ctx))
+ crDLLGetNoError(osMesaDll, "OSMesaDestroyContext");
+
+ return 1;
+}
+#endif
+
+""")
+
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/loader.def b/src/VBox/GuestHost/OpenGL/spu_loader/loader.def
new file mode 100644
index 00000000..42065235
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/loader.def
@@ -0,0 +1,21 @@
+; Copyright (c) 2001, Stanford University
+; All rights reserved.
+;
+; See the file LICENSE.txt for information on redistributing this software.
+EXPORTS
+crSPULoad
+crSPULoadChain
+crSPUUnloadChain
+crSPUCopyDispatchTable
+crSPUFindFunction
+crSPUChangeInterface
+crSPUInitDispatchTable
+crSPUInitDispatchNops
+crSPUInitDispatch
+crSPUSetDefaultParams
+crSPUGetEnumIndex
+crLoadOpenGLExtensions
+crLoadOpenGL
+crUnloadOpenGL
+crChooseVisual
+crSPUChangeDispatch
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py b/src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py
new file mode 100755
index 00000000..7562348e
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py
@@ -0,0 +1,73 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys
+import apiutil
+
+
+apiutil.CopyrightC()
+
+print("""
+
+/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY spuchange.py SCRIPT */
+
+#include "cr_spu.h"
+#include "cr_error.h"
+
+void crSPUChangeInterface(SPUDispatchTable *table, void *orig_func, void *new_func)
+{
+ struct _copy_list_node *temp;
+ if (table->mark == 1)
+ {
+ return;
+ }
+ if (orig_func == new_func)
+ {
+ return;
+ }
+ table->mark = 1;
+""")
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+for func_name in keys:
+ print('\tif ((uintptr_t)table->%s == (uintptr_t)orig_func)' % func_name)
+ print('\t{')
+ print('\t\ttable->%s = (%sFunc_t)(uintptr_t)new_func;' % (func_name, func_name))
+ print('\t\tfor (temp = table->copyList ; temp ; temp = temp->next)')
+ print('\t\t{')
+ print('\t\t\tcrSPUChangeInterface(temp->copy, orig_func, new_func);')
+ print('\t\t}')
+ print('\t}')
+
+print("""
+ if (table->copy_of != NULL)
+ {
+ crSPUChangeInterface(table->copy_of, orig_func, new_func);
+ }
+ for (temp = table->copyList; temp; temp = temp->next)
+ {
+ crSPUChangeInterface(temp->copy, orig_func, new_func);
+ }
+ table->mark = 0;
+""")
+print('}')
+
+print("""
+void crSPUChangeDispatch(SPUDispatchTable *dispatch, const SPUNamedFunctionTable *newtable)
+{
+ SPUGenericFunction func;
+""")
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+for func_name in keys:
+ print('\tfunc = crSPUFindFunction(newtable, "%s");' % func_name)
+ print('\tif (func && ((SPUGenericFunction)dispatch->%s!=func))' % func_name)
+ print('\t{')
+ print('\t\tcrDebug("%%s changed from %%p to %%p", "gl%s", (void *)(uintptr_t)dispatch->%s, (void *)(uintptr_t)func);' % (func_name, func_name))
+ print('\t\tcrSPUChangeInterface(dispatch, (void *)(uintptr_t)dispatch->%s, (void *)(uintptr_t)func);' % func_name)
+ print('\t}\n')
+print("""
+}
+""")
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py b/src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py
new file mode 100755
index 00000000..bf1990a1
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2001, Stanford University
+# All rights reserved.
+#
+# See the file LICENSE.txt for information on redistributing this software.
+
+from __future__ import print_function
+import sys
+import apiutil
+
+
+apiutil.CopyrightC()
+
+print("""
+
+/* DO NOT EDIT - THIS FILE AUTOMATICALLY GENERATED BY spucopy.py SCRIPT */
+
+#include "cr_spu.h"
+#include "cr_mem.h"
+
+void crSPUCopyDispatchTable( SPUDispatchTable *dst, SPUDispatchTable *src )
+{
+""")
+
+keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
+for func_name in keys:
+ print('\tdst->%s = src->%s;' % (func_name, func_name))
+
+# if the destination is already a copy of something, we'd better make sure
+# that we take it off its source's copy list first.
+
+print("""
+ if (dst->copy_of != NULL)
+ {
+ /*
+ * dst was already a copy, go back to the original,
+ * and remove dst from the original's copyList.
+ */
+ struct _copy_list_node *temp, *prior = NULL;
+ for (temp = dst->copy_of->copyList; temp; prior = temp, temp = temp->next)
+ {
+ if (temp->copy == dst)
+ {
+ if (prior)
+ {
+ prior->next = temp->next;
+ }
+ else
+ {
+ dst->copy_of->copyList = temp->next;
+ }
+ crFree( temp );
+ break;
+ }
+ }
+ }
+ /*
+ * Now that dst->copy_of is unused, set it to point to our
+ * new original.
+ */
+ if (src->copy_of)
+ {
+ dst->copy_of = src->copy_of;
+ }
+ else
+ {
+ dst->copy_of = src;
+ }
+ /*
+ * Create a new copy node, so the src can keep track of the
+ * new copy (i.e. dst).
+ */
+ {
+ struct _copy_list_node *copynode;
+ copynode = (struct _copy_list_node*)crAlloc( sizeof( *copynode ) );
+ copynode->copy = dst;
+ copynode->next = src->copyList;
+ src->copyList = copynode;
+ }
+}
+""")
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spuinit.c b/src/VBox/GuestHost/OpenGL/spu_loader/spuinit.c
new file mode 100644
index 00000000..5591df9b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/spuinit.c
@@ -0,0 +1,225 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_spu.h"
+#include "cr_error.h"
+#include "cr_string.h"
+#include <stdio.h>
+
+/**
+ * \mainpage spu_loader
+ *
+ * \section Spu_loaderIntroduction Introduction
+ *
+ * Chromium consists of all the top-level files in the cr
+ * directory. The spu_loader module basically takes care of API dispatch,
+ * and OpenGL state management.
+ *
+ */
+void crSPUInitDispatchTable( SPUDispatchTable *table )
+{
+ table->copyList = NULL;
+ table->copy_of = NULL;
+ table->mark = 0;
+ table->server = NULL;
+}
+
+#if 0 /* unused */
+
+static int validate_int( const char *response,
+ const char *min,
+ const char *max )
+{
+ int i, imin, imax;
+ if (sscanf(response, "%d", &i) != 1)
+ return 0;
+ if (min && sscanf(min, "%d", &imin) == 1 && imin > i)
+ return 0;
+ if (max && sscanf(max, "%d", &imax) == 1 && imax < i)
+ return 0;
+ return 1;
+}
+
+static int validate_float( const char *response,
+ const char *min,
+ const char *max )
+{
+ float f, fmin, fmax;
+ if (sscanf(response, "%f", &f) != 1)
+ return 0;
+ if (min && sscanf(min, "%f", &fmin) == 1 && fmin > f)
+ return 0;
+ if (max && sscanf(max, "%f", &fmax) == 1 && fmax < f)
+ return 0;
+ return 1;
+}
+
+static int validate_one_option( const SPUOptions *opt,
+ const char *response,
+ const char *min,
+ const char *max )
+{
+ switch (opt->type) {
+ case CR_BOOL:
+ return validate_int( response, "0", "1" );
+ case CR_INT:
+ return validate_int( response, min, max );
+ case CR_FLOAT:
+ return validate_float( response, min, max );
+ case CR_ENUM:
+ /* Make sure response string is present in the min string.
+ * For enums, the min string is a comma-separated list of valid values.
+ */
+ CRASSERT(opt->numValues == 1); /* an enum limitation for now */
+ {
+ const char *p = crStrstr(min, response);
+ if (!p)
+ return 0; /* invalid value! */
+ if (p[-1] != '\'')
+ return 0; /* right substring */
+ if (p[crStrlen(response)] != '\'')
+ return 0; /* left substring */
+ return 1;
+ }
+ default:
+ return 0;
+ }
+}
+
+
+/**
+ * Make sure the response matches the opt's parameters (right number
+ * and type of values, etc.)
+ * Return 1 if OK, 0 if error.
+ */
+static int validate_option( const SPUOptions *opt, const char *response )
+{
+ const char *min = opt->min;
+ const char *max = opt->max;
+ int i = 0;
+ int retval;
+
+ if (opt->type == CR_STRING)
+ return 1;
+
+ CRASSERT(opt->numValues > 0);
+
+ /* skip leading [ for multi-value options */
+ if (opt->numValues > 1) {
+ /* multi-valued options must be enclosed in brackets */
+ if (*response != '[')
+ return 0;
+ response++; /* skip [ */
+ /* make sure min and max are bracketed as well */
+ if (min) {
+ CRASSERT(*min == '['); /* error in <foo>spu_config.c code!!! */
+ min++;
+ }
+ if (max) {
+ CRASSERT(*max == '['); /* error in <foo>spu_config.c code!!! */
+ max++;
+ }
+ }
+
+ for (;;)
+ {
+ if (!validate_one_option( opt, response, min, max ))
+ {
+ retval = 0;
+ break;
+ }
+ if (++i == opt->numValues)
+ {
+ retval = 1; /* all done! */
+ break;
+ }
+ /* advance pointers to next item */
+ if (min)
+ {
+ while (*min != ' ' && *min)
+ min++;
+ while (*min == ' ')
+ min++;
+ }
+ if (max)
+ {
+ while (*max != ' ' && *max)
+ max++;
+ while (*max == ' ')
+ max++;
+ }
+ if (response)
+ {
+ while (*response != ' ' && *response)
+ response++;
+ while (*response == ' ')
+ response++;
+ }
+ }
+
+ return retval;
+}
+
+#endif /* unused */
+
+/** Use the default values for all the options:
+ */
+void crSPUSetDefaultParams( void *spu, SPUOptions *options )
+{
+ int i;
+
+ for (i = 0 ; options[i].option ; i++)
+ {
+ SPUOptions *opt = &options[i];
+ opt->cb( spu, opt->deflt );
+ }
+}
+
+
+/**
+ * Find the index of the given enum value in the SPUOption's list of
+ * possible enum values.
+ * Return the enum index, or -1 if not found.
+ */
+int crSPUGetEnumIndex( const SPUOptions *options, const char *optName, const char *value )
+{
+ const SPUOptions *opt;
+ const int valueLen = crStrlen(value);
+
+ /* first, find the right option */
+ for (opt = options; opt->option; opt++) {
+ if (crStrcmp(opt->option, optName) == 0) {
+ char **values;
+ int i;
+
+ CRASSERT(opt->type == CR_ENUM);
+
+ /* break into array of strings */
+ /* min string should be of form "'enum1', 'enum2', 'enum3', etc" */
+ values = crStrSplit(opt->min, ",");
+
+ /* search the array */
+ for (i = 0; values[i]; i++) {
+ /* find leading quote */
+ const char *e = crStrchr(values[i], '\'');
+ CRASSERT(e);
+ if (e) {
+ /* test for match */
+ if (crStrncmp(value, e + 1, valueLen) == 0 && e[valueLen + 1] == '\'') {
+ crFreeStrings(values);
+ return i;
+ }
+ }
+ }
+
+ /* enum value not found! */
+ crFreeStrings(values);
+ return -1;
+ }
+ }
+
+ return -1;
+}
diff --git a/src/VBox/GuestHost/OpenGL/spu_loader/spuload.c b/src/VBox/GuestHost/OpenGL/spu_loader/spuload.c
new file mode 100644
index 00000000..8930ef9a
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/spu_loader/spuload.c
@@ -0,0 +1,290 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "cr_mem.h"
+#include "cr_environment.h"
+#include "cr_string.h"
+#include "cr_dll.h"
+#include "cr_error.h"
+#include "cr_spu.h"
+
+
+#include <iprt/param.h>
+#include <iprt/string.h>
+#include <iprt/path.h>
+
+#include <stdio.h>
+
+#ifdef WINDOWS
+#ifdef VBOX_WDDM_WOW64
+#define DLL_SUFFIX "-x86.dll"
+#else
+#define DLL_SUFFIX ".dll"
+#endif
+#define DLL_PREFIX "VBoxOGL"
+#define snprintf _snprintf
+#elif defined(DARWIN)
+#define DLL_SUFFIX ".dylib"
+#define DLL_PREFIX "VBoxOGL"
+/*
+#define DLL_SUFFIX ".bundle"
+#define DLL_PREFIX ""
+*/
+#else
+#ifdef AIX
+#define DLL_SUFFIX ".o"
+#define DLL_PREFIX "VBoxOGL"
+#else
+#define DLL_SUFFIX ".so"
+#define DLL_PREFIX "VBoxOGL"
+#endif
+#endif
+
+extern void __buildDispatch( SPU *spu );
+
+static char *__findDLL( char *name, char *dir )
+{
+ static char path[8092];
+
+ if (!dir)
+ {
+#if defined(DARWIN)
+ char szSharedLibPath[8092];
+ int rc = RTPathAppPrivateArch (szSharedLibPath, sizeof(szSharedLibPath));
+ if (RT_SUCCESS(rc))
+ sprintf ( path, "%s/%s%sspu%s", szSharedLibPath, DLL_PREFIX, name, DLL_SUFFIX );
+ else
+#endif /* DARWIN */
+#ifdef VBOX
+ snprintf ( path, sizeof(path), "%s%sspu%s", DLL_PREFIX, name, DLL_SUFFIX );
+#else
+ sprintf ( path, "%s%sspu%s", DLL_PREFIX, name, DLL_SUFFIX );
+#endif
+ }
+ else
+ {
+#ifdef VBOX
+ snprintf ( path, sizeof(path), "%s/%s%sspu%s", dir, DLL_PREFIX, name, DLL_SUFFIX );
+#else
+ sprintf ( path, "%s/%s%sspu%s", dir, DLL_PREFIX, name, DLL_SUFFIX );
+#endif
+ }
+ return path;
+}
+
+/**
+ * Load a single SPU from disk and initialize it. Is there any reason
+ * to export this from the SPU loader library? */
+
+SPU * crSPULoad( SPU *child, int id, char *name, char *dir, void *server )
+{
+ SPU *the_spu;
+ char *path;
+ bool fNeedSuperSPU = false;
+
+ CRASSERT( name != NULL );
+
+ the_spu = (SPU*)crAlloc( sizeof( *the_spu ) );
+ /* ensure all fields are initially zero,
+ * NOTE: what actually MUST be zero at this point is the_spu->superSPU, otherwise
+ * crSPUUnloadChain in the failure branches below will misbehave */
+ crMemset(the_spu, 0, sizeof (*the_spu));
+ the_spu->id = id;
+ the_spu->privatePtr = NULL;
+ path = __findDLL( name, dir );
+ the_spu->dll = crDLLOpen( path, 0/*resolveGlobal*/ );
+ if (the_spu->dll == NULL)
+ {
+ crError("Couldn't load the DLL \"%s\"!\n", path);
+ crFree(the_spu);
+ return NULL;
+ }
+#if defined(DEBUG_misha) && defined(RT_OS_WINDOWS)
+ crDbgCmdSymLoadPrint(path, the_spu->dll->hinstLib);
+#endif
+ the_spu->entry_point =
+ (SPULoadFunction) crDLLGetNoError( the_spu->dll, SPU_ENTRY_POINT_NAME );
+ if (!the_spu->entry_point)
+ {
+ crError( "Couldn't load the SPU entry point \"%s\" from SPU \"%s\"!",
+ SPU_ENTRY_POINT_NAME, name );
+ crSPUUnloadChain(the_spu);
+ return NULL;
+ }
+
+ /* This basically calls the SPU's SPULoad() function */
+ if (!the_spu->entry_point( &(the_spu->name), &(the_spu->super_name),
+ &(the_spu->init), &(the_spu->self),
+ &(the_spu->cleanup),
+ &(the_spu->options),
+ &(the_spu->spu_flags)) )
+ {
+ crError( "I found the SPU \"%s\", but loading it failed!", name );
+ crSPUUnloadChain(the_spu);
+ return NULL;
+ }
+#ifdef IN_GUEST
+ if (crStrcmp(the_spu->name,"error"))
+ {
+ /* the default super/base class for an SPU is the error SPU */
+ if (the_spu->super_name == NULL)
+ {
+ the_spu->super_name = "error";
+ }
+ the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
+ fNeedSuperSPU = true;
+ }
+#else
+ if (crStrcmp(the_spu->name,"hosterror"))
+ {
+ /* the default super/base class for an SPU is the error SPU */
+ if (the_spu->super_name == NULL)
+ {
+ the_spu->super_name = "hosterror";
+ }
+ the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
+ fNeedSuperSPU = true;
+ }
+#endif
+ else
+ {
+ the_spu->superSPU = NULL;
+ }
+ if (fNeedSuperSPU && !the_spu->superSPU)
+ {
+ crError( "Unable to load super SPU \"%s\" of \"%s\"!", the_spu->super_name, name );
+ crSPUUnloadChain(the_spu);
+ return NULL;
+ }
+ crDebug("Initializing %s SPU", name);
+ the_spu->function_table = the_spu->init( id, child, the_spu, 0, 1 );
+ if (!the_spu->function_table) {
+ crDebug("Failed to init %s SPU", name);
+ crSPUUnloadChain(the_spu);
+ return NULL;
+ }
+ __buildDispatch( the_spu );
+ /*crDebug( "initializing dispatch table %p (for SPU %s)", (void*)&(the_spu->dispatch_table), name );*/
+ crSPUInitDispatchTable( &(the_spu->dispatch_table) );
+ /*crDebug( "Done initializing the dispatch table for SPU %s, calling the self function", name );*/
+
+ the_spu->dispatch_table.server = server;
+ the_spu->self( &(the_spu->dispatch_table) );
+ /*crDebug( "Done with the self function" );*/
+
+ return the_spu;
+}
+
+/**
+ * Load the entire chain of SPUs and initialize all of them.
+ * This function returns the first one in the chain.
+ */
+SPU *
+crSPULoadChain( int count, int *ids, char **names, char *dir, void *server )
+{
+ int i;
+ SPU *child_spu = NULL;
+ CRASSERT( count > 0 );
+
+ for (i = count-1 ; i >= 0 ; i--)
+ {
+ int spu_id = ids[i];
+ char *spu_name = names[i];
+ SPU *the_spu, *temp;
+
+ /* This call passes the previous version of spu, which is the SPU's
+ * "child" in this chain. */
+
+ the_spu = crSPULoad( child_spu, spu_id, spu_name, dir, server );
+ if (!the_spu) {
+ return NULL;
+ }
+
+ if (child_spu != NULL)
+ {
+ /* keep track of this so that people can pass functions through but
+ * still get updated when API's change on the fly. */
+ for (temp = the_spu ; temp ; temp = temp->superSPU )
+ {
+ struct _copy_list_node *node = (struct _copy_list_node *) crAlloc( sizeof( *node ) );
+ node->copy = &(temp->dispatch_table);
+ node->next = child_spu->dispatch_table.copyList;
+ child_spu->dispatch_table.copyList = node;
+ }
+ }
+ child_spu = the_spu;
+ }
+ return child_spu;
+}
+
+
+#if 00
+/* XXXX experimental code - not used at this time */
+/**
+ * Like crSPUChangeInterface(), but don't loop over all functions in
+ * the table to search for 'old_func'.
+ */
+void
+crSPUChangeFunction(SPUDispatchTable *table, unsigned int funcOffset,
+ void *newFunc)
+{
+ SPUGenericFunction *f = (SPUGenericFunction *) table + funcOffset;
+ struct _copy_list_node *temp;
+
+ CRASSERT(funcOffset < sizeof(*table) / sizeof(SPUGenericFunction));
+
+ printf("%s\n", __FUNCTION__);
+ if (table->mark == 1)
+ return;
+ table->mark = 1;
+ *f = newFunc;
+
+ /* update all copies of this table */
+#if 1
+ for (temp = table->copyList ; temp ; temp = temp->next)
+ {
+ crSPUChangeFunction( temp->copy, funcOffset, newFunc );
+ }
+#endif
+ if (table->copy_of != NULL)
+ {
+ crSPUChangeFunction( table->copy_of, funcOffset, newFunc );
+ }
+#if 0
+ for (temp = table->copyList ; temp ; temp = temp->next)
+ {
+ crSPUChangeFunction( temp->copy, funcOffset, newFunc );
+ }
+#endif
+ table->mark = 0;
+}
+#endif
+
+
+
+/**
+ * Call the cleanup() function for each SPU in a chain, close the SPU
+ * DLLs and free the SPU objects.
+ * \param headSPU pointer to the first SPU in the chain
+ */
+void
+crSPUUnloadChain(SPU *headSPU)
+{
+ SPU *the_spu = headSPU, *next_spu;
+
+ while (the_spu)
+ {
+ crDebug("Cleaning up SPU %s", the_spu->name);
+
+ if (the_spu->cleanup)
+ the_spu->cleanup();
+
+ next_spu = the_spu->superSPU;
+ crDLLClose(the_spu->dll);
+ crFree(the_spu);
+ the_spu = next_spu;
+ }
+}