VirtualBox

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

Last change on this file since 42520 was 42520, checked in by vboxsync, 13 years ago

crOpenGL: debug assertion fixes

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

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