VirtualBox

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

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

crOpenGL/wddm: basics for miniport-based visible rects processing (guest part); export flushToHost command

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