VirtualBox

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

Last change on this file since 20961 was 19878, checked in by vboxsync, 15 years ago

crOpenGL: cleanup on failures

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.7 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#define DLL_SUFFIX ".dll"
23#define DLL_PREFIX "VBoxOGL"
24#elif defined(DARWIN)
25#define DLL_SUFFIX ".dylib"
26#define DLL_PREFIX "VBoxOGL"
27/*
28#define DLL_SUFFIX ".bundle"
29#define DLL_PREFIX ""
30*/
31#else
32#ifdef AIX
33#define DLL_SUFFIX ".o"
34#define DLL_PREFIX "VBoxOGL"
35#else
36#define DLL_SUFFIX ".so"
37#define DLL_PREFIX "VBoxOGL"
38#endif
39#endif
40
41extern void __buildDispatch( SPU *spu );
42
43static char *__findDLL( char *name, char *dir )
44{
45 static char path[8092];
46
47 if (!dir)
48 {
49#if defined(DARWIN)
50 char szSharedLibPath[8092];
51 int rc = RTPathAppPrivateArch (szSharedLibPath, sizeof(szSharedLibPath));
52 if (RT_SUCCESS(rc))
53 sprintf ( path, "%s/%s%sspu%s", szSharedLibPath, DLL_PREFIX, name, DLL_SUFFIX );
54 else
55#endif /* DARWIN */
56 sprintf ( path, "%s%sspu%s", DLL_PREFIX, name, DLL_SUFFIX );
57 }
58 else
59 {
60 sprintf ( path, "%s/%s%sspu%s", dir, DLL_PREFIX, name, DLL_SUFFIX );
61 }
62 return path;
63}
64
65/**
66 * Load a single SPU from disk and initialize it. Is there any reason
67 * to export this from the SPU loader library? */
68
69SPU * crSPULoad( SPU *child, int id, char *name, char *dir, void *server )
70{
71 SPU *the_spu;
72 char *path;
73
74 CRASSERT( name != NULL );
75
76 the_spu = (SPU*)crAlloc( sizeof( *the_spu ) );
77 the_spu->id = id;
78 the_spu->privatePtr = NULL;
79 path = __findDLL( name, dir );
80 the_spu->dll = crDLLOpen( path, 0/*resolveGlobal*/ );
81 the_spu->entry_point =
82 (SPULoadFunction) crDLLGetNoError( the_spu->dll, SPU_ENTRY_POINT_NAME );
83 if (!the_spu->entry_point)
84 {
85 crError( "Couldn't load the SPU entry point \"%s\" from SPU \"%s\"!",
86 SPU_ENTRY_POINT_NAME, name );
87 crSPUUnloadChain(the_spu);
88 return NULL;
89 }
90
91 /* This basicall calls the SPU's SPULoad() function */
92 if (!the_spu->entry_point( &(the_spu->name), &(the_spu->super_name),
93 &(the_spu->init), &(the_spu->self),
94 &(the_spu->cleanup),
95 &(the_spu->options),
96 &(the_spu->spu_flags)) )
97 {
98 crError( "I found the SPU \"%s\", but loading it failed!", name );
99 crSPUUnloadChain(the_spu);
100 return NULL;
101 }
102#ifdef IN_GUEST
103 if (crStrcmp(the_spu->name,"error"))
104 {
105 /* the default super/base class for an SPU is the error SPU */
106 if (the_spu->super_name == NULL)
107 {
108 the_spu->super_name = "error";
109 }
110 the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
111 }
112#else
113 if (crStrcmp(the_spu->name,"hosterror"))
114 {
115 /* the default super/base class for an SPU is the error SPU */
116 if (the_spu->super_name == NULL)
117 {
118 the_spu->super_name = "hosterror";
119 }
120 the_spu->superSPU = crSPULoad( child, id, the_spu->super_name, dir, server );
121 }
122#endif
123 else
124 {
125 the_spu->superSPU = NULL;
126 }
127 crDebug("Initializing %s SPU", name);
128 the_spu->function_table = the_spu->init( id, child, the_spu, 0, 1 );
129 if (!the_spu->function_table) {
130 crDebug("Failed to init %s SPU", name);
131 crSPUUnloadChain(the_spu);
132 return NULL;
133 }
134 __buildDispatch( the_spu );
135 /*crDebug( "initializing dispatch table %p (for SPU %s)", (void*)&(the_spu->dispatch_table), name );*/
136 crSPUInitDispatchTable( &(the_spu->dispatch_table) );
137 /*crDebug( "Done initializing the dispatch table for SPU %s, calling the self function", name );*/
138
139 the_spu->dispatch_table.server = server;
140 the_spu->self( &(the_spu->dispatch_table) );
141 /*crDebug( "Done with the self function" );*/
142
143 return the_spu;
144}
145
146/**
147 * Load the entire chain of SPUs and initialize all of them.
148 * This function returns the first one in the chain.
149 */
150SPU *
151crSPULoadChain( int count, int *ids, char **names, char *dir, void *server )
152{
153 int i;
154 SPU *child_spu = NULL;
155 CRASSERT( count > 0 );
156
157 for (i = count-1 ; i >= 0 ; i--)
158 {
159 int spu_id = ids[i];
160 char *spu_name = names[i];
161 SPU *the_spu, *temp;
162
163 /* This call passes the previous version of spu, which is the SPU's
164 * "child" in this chain. */
165
166 the_spu = crSPULoad( child_spu, spu_id, spu_name, dir, server );
167 if (!the_spu) {
168 return NULL;
169 }
170
171 if (child_spu != NULL)
172 {
173 /* keep track of this so that people can pass functions through but
174 * still get updated when API's change on the fly. */
175 for (temp = the_spu ; temp ; temp = temp->superSPU )
176 {
177 struct _copy_list_node *node = (struct _copy_list_node *) crAlloc( sizeof( *node ) );
178 node->copy = &(temp->dispatch_table);
179 node->next = child_spu->dispatch_table.copyList;
180 child_spu->dispatch_table.copyList = node;
181 }
182 }
183 child_spu = the_spu;
184 }
185 return child_spu;
186}
187
188
189#if 00
190/* XXXX experimental code - not used at this time */
191/**
192 * Like crSPUChangeInterface(), but don't loop over all functions in
193 * the table to search for 'old_func'.
194 */
195void
196crSPUChangeFunction(SPUDispatchTable *table, unsigned int funcOffset,
197 void *newFunc)
198{
199 SPUGenericFunction *f = (SPUGenericFunction *) table + funcOffset;
200 struct _copy_list_node *temp;
201
202 CRASSERT(funcOffset < sizeof(*table) / sizeof(SPUGenericFunction));
203
204 printf("%s\n", __FUNCTION__);
205 if (table->mark == 1)
206 return;
207 table->mark = 1;
208 *f = newFunc;
209
210 /* update all copies of this table */
211#if 1
212 for (temp = table->copyList ; temp ; temp = temp->next)
213 {
214 crSPUChangeFunction( temp->copy, funcOffset, newFunc );
215 }
216#endif
217 if (table->copy_of != NULL)
218 {
219 crSPUChangeFunction( table->copy_of, funcOffset, newFunc );
220 }
221#if 0
222 for (temp = table->copyList ; temp ; temp = temp->next)
223 {
224 crSPUChangeFunction( temp->copy, funcOffset, newFunc );
225 }
226#endif
227 table->mark = 0;
228}
229#endif
230
231
232
233/**
234 * Call the cleanup() function for each SPU in a chain, close the SPU
235 * DLLs and free the SPU objects.
236 * \param headSPU pointer to the first SPU in the chain
237 */
238void
239crSPUUnloadChain(SPU *headSPU)
240{
241 SPU *the_spu = headSPU, *next_spu;
242
243 while (the_spu)
244 {
245 crDebug("Cleaning up SPU %s", the_spu->name);
246
247 if (the_spu->cleanup)
248 the_spu->cleanup();
249
250 next_spu = the_spu->superSPU;
251 crDLLClose(the_spu->dll);
252 crFree(the_spu);
253 the_spu = next_spu;
254 }
255}
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