VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/spu_loader/spuload.c@ 66051

Last change on this file since 66051 was 66051, checked in by vboxsync, 8 years ago

bugref:7513: crOpenGL maintenance: make the SPU loader fail gracefully if it cannot find a shared library.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.9 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_environment.h"
9#include "cr_string.h"
10#include "cr_dll.h"
11#include "cr_error.h"
12#include "cr_spu.h"
13
14
15#include <iprt/param.h>
16#include <iprt/string.h>
17#include <iprt/path.h>
18
19#include <stdio.h>
20
21#ifdef WINDOWS
22#ifdef VBOX_WDDM_WOW64
23#define DLL_SUFFIX "-x86.dll"
24#else
25#define DLL_SUFFIX ".dll"
26#endif
27#define DLL_PREFIX "VBoxOGL"
28#define snprintf _snprintf
29#elif defined(DARWIN)
30#define DLL_SUFFIX ".dylib"
31#define DLL_PREFIX "VBoxOGL"
32/*
33#define DLL_SUFFIX ".bundle"
34#define DLL_PREFIX ""
35*/
36#else
37#ifdef AIX
38#define DLL_SUFFIX ".o"
39#define DLL_PREFIX "VBoxOGL"
40#else
41#define DLL_SUFFIX ".so"
42#define DLL_PREFIX "VBoxOGL"
43#endif
44#endif
45
46extern void __buildDispatch( SPU *spu );
47
48static char *__findDLL( char *name, char *dir )
49{
50 static char path[8092];
51
52 if (!dir)
53 {
54#if defined(DARWIN)
55 char szSharedLibPath[8092];
56 int rc = RTPathAppPrivateArch (szSharedLibPath, sizeof(szSharedLibPath));
57 if (RT_SUCCESS(rc))
58 sprintf ( path, "%s/%s%sspu%s", szSharedLibPath, DLL_PREFIX, name, DLL_SUFFIX );
59 else
60#endif /* DARWIN */
61#ifdef VBOX
62 snprintf ( path, sizeof(path), "%s%sspu%s", DLL_PREFIX, name, DLL_SUFFIX );
63#else
64 sprintf ( path, "%s%sspu%s", DLL_PREFIX, name, DLL_SUFFIX );
65#endif
66 }
67 else
68 {
69#ifdef VBOX
70 snprintf ( path, sizeof(path), "%s/%s%sspu%s", dir, DLL_PREFIX, name, DLL_SUFFIX );
71#else
72 sprintf ( path, "%s/%s%sspu%s", dir, DLL_PREFIX, name, DLL_SUFFIX );
73#endif
74 }
75 return path;
76}
77
78/**
79 * Load a single SPU from disk and initialize it. Is there any reason
80 * to export this from the SPU loader library? */
81
82SPU * crSPULoad( SPU *child, int id, char *name, char *dir, void *server )
83{
84 SPU *the_spu;
85 char *path;
86 bool fNeedSuperSPU = false;
87
88 CRASSERT( name != NULL );
89
90 the_spu = (SPU*)crAlloc( sizeof( *the_spu ) );
91 /* ensure all fields are initially zero,
92 * NOTE: what actually MUST be zero at this point is the_spu->superSPU, otherwise
93 * crSPUUnloadChain in the failure branches below will misbehave */
94 crMemset(the_spu, 0, sizeof (*the_spu));
95 the_spu->id = id;
96 the_spu->privatePtr = NULL;
97 path = __findDLL( name, dir );
98 the_spu->dll = crDLLOpen( path, 0/*resolveGlobal*/ );
99 if (the_spu->dll == NULL)
100 {
101 crError("Couldn't load the DLL \"%s\"!\n", path);
102 crFree(the_spu);
103 return NULL;
104 }
105#if defined(DEBUG_misha) && defined(RT_OS_WINDOWS)
106 crDbgCmdSymLoadPrint(path, the_spu->dll->hinstLib);
107#endif
108 the_spu->entry_point =
109 (SPULoadFunction) crDLLGetNoError( the_spu->dll, SPU_ENTRY_POINT_NAME );
110 if (!the_spu->entry_point)
111 {
112 crError( "Couldn't load the SPU entry point \"%s\" from SPU \"%s\"!",
113 SPU_ENTRY_POINT_NAME, name );
114 crSPUUnloadChain(the_spu);
115 return NULL;
116 }
117
118 /* This basically calls the SPU's SPULoad() function */
119 if (!the_spu->entry_point( &(the_spu->name), &(the_spu->super_name),
120 &(the_spu->init), &(the_spu->self),
121 &(the_spu->cleanup),
122 &(the_spu->options),
123 &(the_spu->spu_flags)) )
124 {
125 crError( "I found the SPU \"%s\", but loading it failed!", name );
126 crSPUUnloadChain(the_spu);
127 return NULL;
128 }
129#ifdef IN_GUEST
130 if (crStrcmp(the_spu->name,"error"))
131 {
132 /* the default super/base class for an SPU is the error SPU */
133 if (the_spu->super_name == NULL)
134 {
135 the_spu->super_name = "error";
136 }
137 the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
138 fNeedSuperSPU = true;
139 }
140#else
141 if (crStrcmp(the_spu->name,"hosterror"))
142 {
143 /* the default super/base class for an SPU is the error SPU */
144 if (the_spu->super_name == NULL)
145 {
146 the_spu->super_name = "hosterror";
147 }
148 the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
149 fNeedSuperSPU = true;
150 }
151#endif
152 else
153 {
154 the_spu->superSPU = NULL;
155 }
156 if (fNeedSuperSPU && !the_spu->superSPU)
157 {
158 crError( "Unable to load super SPU \"%s\" of \"%s\"!", the_spu->super_name, name );
159 crSPUUnloadChain(the_spu);
160 return NULL;
161 }
162 crDebug("Initializing %s SPU", name);
163 the_spu->function_table = the_spu->init( id, child, the_spu, 0, 1 );
164 if (!the_spu->function_table) {
165 crDebug("Failed to init %s SPU", name);
166 crSPUUnloadChain(the_spu);
167 return NULL;
168 }
169 __buildDispatch( the_spu );
170 /*crDebug( "initializing dispatch table %p (for SPU %s)", (void*)&(the_spu->dispatch_table), name );*/
171 crSPUInitDispatchTable( &(the_spu->dispatch_table) );
172 /*crDebug( "Done initializing the dispatch table for SPU %s, calling the self function", name );*/
173
174 the_spu->dispatch_table.server = server;
175 the_spu->self( &(the_spu->dispatch_table) );
176 /*crDebug( "Done with the self function" );*/
177
178 return the_spu;
179}
180
181/**
182 * Load the entire chain of SPUs and initialize all of them.
183 * This function returns the first one in the chain.
184 */
185SPU *
186crSPULoadChain( int count, int *ids, char **names, char *dir, void *server )
187{
188 int i;
189 SPU *child_spu = NULL;
190 CRASSERT( count > 0 );
191
192 for (i = count-1 ; i >= 0 ; i--)
193 {
194 int spu_id = ids[i];
195 char *spu_name = names[i];
196 SPU *the_spu, *temp;
197
198 /* This call passes the previous version of spu, which is the SPU's
199 * "child" in this chain. */
200
201 the_spu = crSPULoad( child_spu, spu_id, spu_name, dir, server );
202 if (!the_spu) {
203 return NULL;
204 }
205
206 if (child_spu != NULL)
207 {
208 /* keep track of this so that people can pass functions through but
209 * still get updated when API's change on the fly. */
210 for (temp = the_spu ; temp ; temp = temp->superSPU )
211 {
212 struct _copy_list_node *node = (struct _copy_list_node *) crAlloc( sizeof( *node ) );
213 node->copy = &(temp->dispatch_table);
214 node->next = child_spu->dispatch_table.copyList;
215 child_spu->dispatch_table.copyList = node;
216 }
217 }
218 child_spu = the_spu;
219 }
220 return child_spu;
221}
222
223
224#if 00
225/* XXXX experimental code - not used at this time */
226/**
227 * Like crSPUChangeInterface(), but don't loop over all functions in
228 * the table to search for 'old_func'.
229 */
230void
231crSPUChangeFunction(SPUDispatchTable *table, unsigned int funcOffset,
232 void *newFunc)
233{
234 SPUGenericFunction *f = (SPUGenericFunction *) table + funcOffset;
235 struct _copy_list_node *temp;
236
237 CRASSERT(funcOffset < sizeof(*table) / sizeof(SPUGenericFunction));
238
239 printf("%s\n", __FUNCTION__);
240 if (table->mark == 1)
241 return;
242 table->mark = 1;
243 *f = newFunc;
244
245 /* update all copies of this table */
246#if 1
247 for (temp = table->copyList ; temp ; temp = temp->next)
248 {
249 crSPUChangeFunction( temp->copy, funcOffset, newFunc );
250 }
251#endif
252 if (table->copy_of != NULL)
253 {
254 crSPUChangeFunction( table->copy_of, funcOffset, newFunc );
255 }
256#if 0
257 for (temp = table->copyList ; temp ; temp = temp->next)
258 {
259 crSPUChangeFunction( temp->copy, funcOffset, newFunc );
260 }
261#endif
262 table->mark = 0;
263}
264#endif
265
266
267
268/**
269 * Call the cleanup() function for each SPU in a chain, close the SPU
270 * DLLs and free the SPU objects.
271 * \param headSPU pointer to the first SPU in the chain
272 */
273void
274crSPUUnloadChain(SPU *headSPU)
275{
276 SPU *the_spu = headSPU, *next_spu;
277
278 while (the_spu)
279 {
280 crDebug("Cleaning up SPU %s", the_spu->name);
281
282 if (the_spu->cleanup)
283 the_spu->cleanup();
284
285 next_spu = the_spu->superSPU;
286 crDLLClose(the_spu->dll);
287 crFree(the_spu);
288 the_spu = next_spu;
289 }
290}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette