diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/spu_loader | |
parent | Initial commit. (diff) | |
download | virtualbox-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.kup | 0 | ||||
-rw-r--r-- | src/VBox/GuestHost/OpenGL/spu_loader/choosevisual.c | 329 | ||||
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/spu_loader/dispatch.py | 126 | ||||
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/spu_loader/dispatchheader.py | 78 | ||||
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/spu_loader/glloader.py | 609 | ||||
-rw-r--r-- | src/VBox/GuestHost/OpenGL/spu_loader/loader.def | 21 | ||||
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/spu_loader/spuchange.py | 73 | ||||
-rwxr-xr-x | src/VBox/GuestHost/OpenGL/spu_loader/spucopy.py | 80 | ||||
-rw-r--r-- | src/VBox/GuestHost/OpenGL/spu_loader/spuinit.c | 225 | ||||
-rw-r--r-- | src/VBox/GuestHost/OpenGL/spu_loader/spuload.c | 290 |
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; + } +} |