VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_context.c@ 43409

Last change on this file since 43409 was 42591, checked in by vboxsync, 12 years ago

crOpenGL: fix ocasional packspu init misbeave

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.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 "packspu.h"
8#include "cr_mem.h"
9#include "cr_packfunctions.h"
10#include "cr_string.h"
11#include "packspu_proto.h"
12
13#define MAGIC_OFFSET 3000
14
15/*
16 * Allocate a new ThreadInfo structure, setup a connection to the
17 * server, allocate/init a packer context, bind this ThreadInfo to
18 * the calling thread with crSetTSD().
19 * We'll always call this function at least once even if we're not
20 * using threads.
21 */
22ThreadInfo *packspuNewThread(
23#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
24 struct VBOXUHGSMI *pHgsmi
25#endif
26)
27{
28 ThreadInfo *thread=NULL;
29 int i;
30
31#ifdef CHROMIUM_THREADSAFE
32 crLockMutex(&_PackMutex);
33#else
34 CRASSERT(pack_spu.numThreads == 0);
35#endif
36
37#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
38 CRASSERT(!CRPACKSPU_IS_WDDM_CRHGSMI() == !pHgsmi);
39#endif
40
41 CRASSERT(pack_spu.numThreads < MAX_THREADS);
42 for (i=0; i<MAX_THREADS; ++i)
43 {
44 if (!pack_spu.thread[i].inUse)
45 {
46 thread = &pack_spu.thread[i];
47 break;
48 }
49 }
50 CRASSERT(thread);
51
52 thread->inUse = GL_TRUE;
53 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
54 thread->id = crThreadID();
55 else
56 thread->id = THREAD_OFFSET_MAGIC + i;
57 thread->currentContext = NULL;
58 thread->bInjectThread = GL_FALSE;
59
60 /* connect to the server */
61 thread->netServer.name = crStrdup( pack_spu.name );
62 thread->netServer.buffer_size = pack_spu.buffer_size;
63 packspuConnectToServer( &(thread->netServer)
64#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
65 , pHgsmi
66#endif
67 );
68 CRASSERT(thread->netServer.conn);
69 /* packer setup */
70 CRASSERT(thread->packer == NULL);
71 thread->packer = crPackNewContext( pack_spu.swap );
72 CRASSERT(thread->packer);
73 crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->netServer.conn),
74 thread->netServer.conn->buffer_size, thread->netServer.conn->mtu );
75 thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;
76 crPackSetBuffer( thread->packer, &thread->buffer );
77 crPackFlushFunc( thread->packer, packspuFlush );
78 crPackFlushArg( thread->packer, (void *) thread );
79 crPackSendHugeFunc( thread->packer, packspuHuge );
80
81 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
82 {
83 crPackSetContext( thread->packer );
84 }
85
86
87#ifdef CHROMIUM_THREADSAFE
88 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
89 {
90 crSetTSD(&_PackTSD, thread);
91 }
92#endif
93
94 pack_spu.numThreads++;
95
96#ifdef CHROMIUM_THREADSAFE
97 crUnlockMutex(&_PackMutex);
98#endif
99 return thread;
100}
101
102GLint PACKSPU_APIENTRY
103packspu_VBoxConCreate(struct VBOXUHGSMI *pHgsmi)
104{
105#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
106 ThreadInfo * thread;
107 CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI());
108 CRASSERT(pHgsmi);
109
110 thread = packspuNewThread(pHgsmi);
111
112 if (thread)
113 {
114 CRASSERT(thread->id);
115 CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread)
116 && GET_THREAD_VAL_ID(thread->id) == thread);
117 return thread->id;
118 }
119 crError("packspuNewThread failed");
120#endif
121 return 0;
122}
123
124void PACKSPU_APIENTRY
125packspu_VBoxConFlush(GLint con)
126{
127#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
128 GET_THREAD_ID(thread, con);
129 CRASSERT(con);
130 CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI());
131 CRASSERT(thread->packer);
132 packspuFlush((void *) thread);
133#endif
134}
135
136void PACKSPU_APIENTRY
137packspu_VBoxConDestroy(GLint con)
138{
139#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
140 GET_THREAD_ID(thread, con);
141 CRASSERT(con);
142 CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI());
143 CRASSERT(pack_spu.numThreads>0);
144 CRASSERT(thread->packer);
145 packspuFlush((void *) thread);
146
147 crLockMutex(&_PackMutex);
148
149 crPackDeleteContext(thread->packer);
150
151 crNetFreeConnection(thread->netServer.conn);
152
153 pack_spu.numThreads--;
154 /*note can't shift the array here, because other threads have TLS references to array elements*/
155 crMemZero(thread, sizeof(ThreadInfo));
156
157#if 0
158 if (&pack_spu.thread[pack_spu.idxThreadInUse]==thread)
159 {
160 int i;
161 crError("Should not be here since idxThreadInUse should be always 0 for the dummy connection created in packSPUInit!");
162 for (i=0; i<MAX_THREADS; ++i)
163 {
164 if (pack_spu.thread[i].inUse)
165 {
166 pack_spu.idxThreadInUse=i;
167 break;
168 }
169 }
170 }
171#endif
172 crUnlockMutex(&_PackMutex);
173#endif
174}
175
176
177GLint PACKSPU_APIENTRY
178packspu_VBoxCreateContext( GLint con, const char *dpyName, GLint visual, GLint shareCtx )
179{
180 GET_THREAD(thread);
181 CRPackContext * curPacker = crPackGetContext();
182 ThreadInfo *curThread = thread;
183 int writeback = 1;
184 GLint serverCtx = (GLint) -1;
185 int slot;
186
187 CRASSERT(!curThread == !curPacker);
188 CRASSERT(!curThread || !curPacker || curThread->packer == curPacker);
189#ifdef CHROMIUM_THREADSAFE
190 crLockMutex(&_PackMutex);
191#endif
192
193#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
194 CRASSERT(!con == !CRPACKSPU_IS_WDDM_CRHGSMI());
195#endif
196
197 if (CRPACKSPU_IS_WDDM_CRHGSMI())
198 {
199 if (!con)
200 {
201 crError("connection should be specified!");
202 return -1;
203 }
204 thread = GET_THREAD_VAL_ID(con);
205 }
206 else
207 {
208 CRASSERT(!con);
209 if (!thread)
210 {
211 thread = packspuNewThread(
212#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
213 NULL
214#endif
215 );
216 }
217 }
218 CRASSERT(thread);
219 CRASSERT(thread->packer);
220
221 if (shareCtx > 0) {
222 /* translate to server ctx id */
223 shareCtx -= MAGIC_OFFSET;
224 if (shareCtx >= 0 && shareCtx < pack_spu.numContexts) {
225 shareCtx = pack_spu.context[shareCtx].serverCtx;
226 }
227 }
228
229 crPackSetContext( thread->packer );
230
231 /* Pack the command */
232 if (pack_spu.swap)
233 crPackCreateContextSWAP( dpyName, visual, shareCtx, &serverCtx, &writeback );
234 else
235 crPackCreateContext( dpyName, visual, shareCtx, &serverCtx, &writeback );
236
237 /* Flush buffer and get return value */
238 packspuFlush(thread);
239 if (!(thread->netServer.conn->actual_network))
240 {
241 /* HUMUNGOUS HACK TO MATCH SERVER NUMBERING
242 *
243 * The hack exists solely to make file networking work for now. This
244 * is totally gross, but since the server expects the numbers to start
245 * from 5000, we need to write them out this way. This would be
246 * marginally less gross if the numbers (500 and 5000) were maybe
247 * some sort of #define'd constants somewhere so the client and the
248 * server could be aware of how each other were numbering things in
249 * cases like file networking where they actually
250 * care.
251 *
252 * -Humper
253 *
254 */
255 serverCtx = 5000;
256 }
257 else {
258 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
259
260 if (pack_spu.swap) {
261 serverCtx = (GLint) SWAP32(serverCtx);
262 }
263 if (serverCtx < 0) {
264#ifdef CHROMIUM_THREADSAFE
265 crUnlockMutex(&_PackMutex);
266#endif
267 crWarning("Failure in packspu_CreateContext");
268
269 if (CRPACKSPU_IS_WDDM_CRHGSMI())
270 {
271 /* restore the packer context to the tls */
272 crPackSetContext(curPacker);
273 }
274 return -1; /* failed */
275 }
276 }
277
278 /* find an empty context slot */
279 for (slot = 0; slot < pack_spu.numContexts; slot++) {
280 if (!pack_spu.context[slot].clientState) {
281 /* found empty slot */
282 break;
283 }
284 }
285 if (slot == pack_spu.numContexts) {
286 pack_spu.numContexts++;
287 }
288
289 if (CRPACKSPU_IS_WDDM_CRHGSMI())
290 {
291 thread->currentContext = &pack_spu.context[slot];
292 pack_spu.context[slot].currentThread = thread;
293 }
294
295 /* Fill in the new context info */
296 /* XXX fix-up sharedCtx param here */
297 pack_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL);
298 pack_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE;
299 pack_spu.context[slot].serverCtx = serverCtx;
300
301#ifdef CHROMIUM_THREADSAFE
302 crUnlockMutex(&_PackMutex);
303#endif
304
305 if (CRPACKSPU_IS_WDDM_CRHGSMI())
306 {
307 /* restore the packer context to the tls */
308 crPackSetContext(curPacker);
309 }
310
311 return MAGIC_OFFSET + slot;
312}
313
314GLint PACKSPU_APIENTRY
315packspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx )
316{
317 return packspu_VBoxCreateContext( 0, dpyName, visual, shareCtx );
318}
319
320
321void PACKSPU_APIENTRY packspu_DestroyContext( GLint ctx )
322{
323 GET_THREAD(thread);
324 ThreadInfo *curThread = thread;
325 const int slot = ctx - MAGIC_OFFSET;
326 ContextInfo *context, *curContext;
327 CRPackContext * curPacker = crPackGetContext();
328
329 CRASSERT(slot >= 0);
330 CRASSERT(slot < pack_spu.numContexts);
331
332 context = &(pack_spu.context[slot]);
333
334 if (CRPACKSPU_IS_WDDM_CRHGSMI())
335 {
336 thread = context->currentThread;
337 crPackSetContext(thread->packer);
338 CRASSERT(!(thread->packer == curPacker) == !(thread == curThread));
339 }
340 CRASSERT(thread);
341 curContext = curThread ? curThread->currentContext : NULL;
342
343 if (pack_spu.swap)
344 crPackDestroyContextSWAP( context->serverCtx );
345 else
346 crPackDestroyContext( context->serverCtx );
347
348 crStateDestroyContext( context->clientState );
349
350 context->clientState = NULL;
351 context->serverCtx = 0;
352 context->currentThread = NULL;
353
354 if (curContext == context)
355 {
356 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
357 {
358 curThread->currentContext = NULL;
359 }
360 else
361 {
362 CRASSERT(thread == curThread);
363 crSetTSD(&_PackTSD, NULL);
364 crPackSetContext(NULL);
365 }
366 crStateMakeCurrent( NULL );
367 }
368 else
369 {
370 if (CRPACKSPU_IS_WDDM_CRHGSMI())
371 {
372 crPackSetContext(curPacker);
373 }
374 }
375}
376
377void PACKSPU_APIENTRY packspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx )
378{
379 ThreadInfo *thread;
380 GLint serverCtx;
381 ContextInfo *newCtx;
382
383 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
384 {
385 thread = GET_THREAD_VAL();
386 if (!thread) {
387 thread = packspuNewThread(
388#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
389 NULL
390#endif
391 );
392 }
393 CRASSERT(thread);
394 CRASSERT(thread->packer);
395 }
396
397 if (ctx) {
398 const int slot = ctx - MAGIC_OFFSET;
399
400 CRASSERT(slot >= 0);
401 CRASSERT(slot < pack_spu.numContexts);
402
403 newCtx = &pack_spu.context[slot];
404 CRASSERT(newCtx->clientState); /* verify valid */
405
406 if (CRPACKSPU_IS_WDDM_CRHGSMI())
407 {
408 thread = newCtx->currentThread;
409 CRASSERT(thread);
410 crSetTSD(&_PackTSD, thread);
411 crPackSetContext( thread->packer );
412 }
413 else
414 {
415 if (!newCtx->fAutoFlush)
416 {
417 if (newCtx->currentThread && newCtx->currentThread != thread)
418 {
419 crLockMutex(&_PackMutex);
420 /* do a flush for the previously assigned thread
421 * to ensure all commands issued there are submitted */
422 if (newCtx->currentThread
423 && newCtx->currentThread->inUse
424 && newCtx->currentThread->netServer.conn
425 && newCtx->currentThread->packer && newCtx->currentThread->packer->currentBuffer)
426 {
427 packspuFlush((void *) newCtx->currentThread);
428 }
429 crUnlockMutex(&_PackMutex);
430 }
431 newCtx->currentThread = thread;
432 }
433
434 thread->currentContext = newCtx;
435 crPackSetContext( thread->packer );
436 }
437
438 crStateMakeCurrent( newCtx->clientState );
439 //crStateSetCurrentPointers(newCtx->clientState, &thread->packer->current);
440 serverCtx = pack_spu.context[slot].serverCtx;
441 }
442 else {
443 crStateMakeCurrent( NULL );
444 if (CRPACKSPU_IS_WDDM_CRHGSMI())
445 {
446 thread = GET_THREAD_VAL();
447 if (!thread)
448 {
449 CRASSERT(crPackGetContext() == NULL);
450 return;
451 }
452 CRASSERT(thread->currentContext);
453 CRASSERT(thread->packer == crPackGetContext());
454 }
455 else
456 {
457 thread->currentContext = NULL;
458 }
459 newCtx = NULL;
460 serverCtx = 0;
461 }
462
463 if (pack_spu.swap)
464 crPackMakeCurrentSWAP( window, nativeWindow, serverCtx );
465 else
466 crPackMakeCurrent( window, nativeWindow, serverCtx );
467
468 {
469 GET_THREAD(t);
470 (void) t;
471 CRASSERT(t);
472 }
473}
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