VirtualBox

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

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

crOgl/wddm: per-context connections

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