VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/pack/packspu_misc.c@ 42591

Last change on this file since 42591 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: 18.3 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_packfunctions.h"
8#include "packspu.h"
9#include "packspu_proto.h"
10#include "cr_mem.h"
11
12void PACKSPU_APIENTRY packspu_ChromiumParametervCR(GLenum target, GLenum type, GLsizei count, const GLvoid *values)
13{
14
15 CRMessage msg;
16 int len;
17
18 GET_THREAD(thread);
19
20
21 switch(target)
22 {
23 case GL_GATHER_PACK_CR:
24 /* flush the current pack buffer */
25 packspuFlush( (void *) thread );
26
27 /* the connection is thread->server.conn */
28 msg.header.type = CR_MESSAGE_GATHER;
29 msg.gather.offset = 69;
30 len = sizeof(CRMessageGather);
31 crNetSend(thread->netServer.conn, NULL, &msg, len);
32 break;
33
34 default:
35 if (pack_spu.swap)
36 crPackChromiumParametervCRSWAP(target, type, count, values);
37 else
38 crPackChromiumParametervCR(target, type, count, values);
39 }
40
41
42}
43
44GLboolean packspuSyncOnFlushes()
45{
46 GLint buffer;
47
48 /*Seems to still cause issues, always sync for now*/
49 return 1;
50
51 crStateGetIntegerv(GL_DRAW_BUFFER, &buffer);
52 /*Usually buffer==GL_BACK, so put this extra check to simplify boolean eval on runtime*/
53 return (buffer != GL_BACK)
54 && (buffer == GL_FRONT_LEFT
55 || buffer == GL_FRONT_RIGHT
56 || buffer == GL_FRONT
57 || buffer == GL_FRONT_AND_BACK
58 || buffer == GL_LEFT
59 || buffer == GL_RIGHT);
60}
61
62void PACKSPU_APIENTRY packspu_DrawBuffer(GLenum mode)
63{
64 GLboolean hadtoflush;
65
66 hadtoflush = packspuSyncOnFlushes();
67
68 crStateDrawBuffer(mode);
69 crPackDrawBuffer(mode);
70
71 if (hadtoflush && !packspuSyncOnFlushes())
72 packspu_Flush();
73}
74
75void PACKSPU_APIENTRY packspu_Finish( void )
76{
77 GET_THREAD(thread);
78 GLint writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
79
80 if (pack_spu.swap)
81 {
82 crPackFinishSWAP();
83 }
84 else
85 {
86 crPackFinish();
87 }
88
89 if (packspuSyncOnFlushes())
90 {
91 if (writeback)
92 {
93 if (pack_spu.swap)
94 crPackWritebackSWAP(&writeback);
95 else
96 crPackWriteback(&writeback);
97
98 packspuFlush( (void *) thread );
99
100 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
101 }
102 }
103}
104
105void PACKSPU_APIENTRY packspu_Flush( void )
106{
107 GET_THREAD(thread);
108 int writeback=1;
109 int found=0;
110
111 if (!thread->bInjectThread)
112 {
113 crPackFlush();
114 if (packspuSyncOnFlushes())
115 {
116 crPackWriteback(&writeback);
117 packspuFlush( (void *) thread );
118 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
119 }
120 }
121 else
122 {
123 int i;
124
125 crLockMutex(&_PackMutex);
126
127 /*Make sure we process commands in order they should appear, so flush other threads first*/
128 for (i=0; i<MAX_THREADS; ++i)
129 {
130 if (pack_spu.thread[i].inUse
131 && (thread != &pack_spu.thread[i]) && pack_spu.thread[i].netServer.conn
132 && pack_spu.thread[i].packer && pack_spu.thread[i].packer->currentBuffer)
133 {
134 packspuFlush((void *) &pack_spu.thread[i]);
135
136 if (pack_spu.thread[i].netServer.conn->u32ClientID == thread->netServer.conn->u32InjectClientID)
137 {
138 found=1;
139 }
140
141 }
142 }
143
144 if (!found)
145 {
146 /*Thread we're supposed to inject commands for has been detached,
147 so there's nothing to sync with and we should just pass commands through our own connection.
148 */
149 thread->netServer.conn->u32InjectClientID=0;
150 }
151
152 packspuFlush((void *) thread);
153
154 crUnlockMutex(&_PackMutex);
155 }
156}
157
158void PACKSPU_APIENTRY packspu_VBoxWindowDestroy( GLint con, GLint window )
159{
160 if (CRPACKSPU_IS_WDDM_CRHGSMI())
161 {
162 GET_THREAD(thread);
163 if (con)
164 {
165 CRPackContext * curPacker = crPackGetContext();
166 CRASSERT(!thread || !thread->bInjectThread);
167 thread = GET_THREAD_VAL_ID(con);
168 crPackSetContext(thread->packer);
169 crPackWindowDestroy(window);
170 if (curPacker != thread->packer)
171 crPackSetContext(curPacker);
172 return;
173 }
174 CRASSERT(thread);
175 CRASSERT(thread->bInjectThread);
176 }
177 crPackWindowDestroy(window);
178}
179
180GLint PACKSPU_APIENTRY packspu_VBoxWindowCreate( GLint con, const char *dpyName, GLint visBits )
181{
182 GET_THREAD(thread);
183 static int num_calls = 0;
184 int writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
185 GLint return_val = (GLint) 0;
186 ThreadInfo *curThread = thread;
187 GLint retVal;
188
189 if (CRPACKSPU_IS_WDDM_CRHGSMI())
190 {
191 if (!con)
192 {
193 crError("connection expected!");
194 return 0;
195 }
196 thread = GET_THREAD_VAL_ID(con);
197 }
198 else
199 {
200 CRASSERT(!con);
201 if (!thread) {
202 thread = packspuNewThread(
203#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
204 NULL
205#endif
206 );
207 }
208 }
209 CRASSERT(thread);
210 CRASSERT(thread->packer);
211 CRASSERT(crPackGetContext() == (curThread ? curThread->packer : NULL));
212
213 crPackSetContext(thread->packer);
214
215 if (pack_spu.swap)
216 {
217 crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
218 }
219 else
220 {
221 crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
222 }
223 packspuFlush(thread);
224 if (!(thread->netServer.conn->actual_network))
225 {
226 retVal = num_calls++;
227 }
228 else
229 {
230 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
231 if (pack_spu.swap)
232 {
233 return_val = (GLint) SWAP32(return_val);
234 }
235 retVal = return_val;
236 }
237
238 if (CRPACKSPU_IS_WDDM_CRHGSMI())
239 {
240 if (thread != curThread)
241 {
242 if (curThread)
243 crPackSetContext(curThread->packer);
244 else
245 crPackSetContext(NULL);
246 }
247 }
248
249 return retVal;
250}
251
252GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits )
253{
254 return packspu_VBoxWindowCreate( 0, dpyName, visBits );
255}
256
257GLboolean PACKSPU_APIENTRY
258packspu_AreTexturesResident( GLsizei n, const GLuint * textures,
259 GLboolean * residences )
260{
261 GET_THREAD(thread);
262 int writeback = 1;
263 GLboolean return_val = GL_TRUE;
264 GLsizei i;
265
266 if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
267 {
268 crError( "packspu_AreTexturesResident doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" );
269 }
270
271 if (pack_spu.swap)
272 {
273 crPackAreTexturesResidentSWAP( n, textures, residences, &return_val, &writeback );
274 }
275 else
276 {
277 crPackAreTexturesResident( n, textures, residences, &return_val, &writeback );
278 }
279 packspuFlush( (void *) thread );
280
281 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
282
283 /* Since the Chromium packer/unpacker can't return both 'residences'
284 * and the function's return value, compute the return value here.
285 */
286 for (i = 0; i < n; i++) {
287 if (!residences[i]) {
288 return_val = GL_FALSE;
289 break;
290 }
291 }
292
293 return return_val;
294}
295
296
297GLboolean PACKSPU_APIENTRY
298packspu_AreProgramsResidentNV( GLsizei n, const GLuint * ids,
299 GLboolean * residences )
300{
301 GET_THREAD(thread);
302 int writeback = 1;
303 GLboolean return_val = GL_TRUE;
304 GLsizei i;
305
306 if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
307 {
308 crError( "packspu_AreProgramsResidentNV doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" );
309 }
310 if (pack_spu.swap)
311 {
312 crPackAreProgramsResidentNVSWAP( n, ids, residences, &return_val, &writeback );
313 }
314 else
315 {
316 crPackAreProgramsResidentNV( n, ids, residences, &return_val, &writeback );
317 }
318 packspuFlush( (void *) thread );
319
320 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
321
322 /* Since the Chromium packer/unpacker can't return both 'residences'
323 * and the function's return value, compute the return value here.
324 */
325 for (i = 0; i < n; i++) {
326 if (!residences[i]) {
327 return_val = GL_FALSE;
328 break;
329 }
330 }
331
332 return return_val;
333}
334
335void PACKSPU_APIENTRY packspu_GetPolygonStipple( GLubyte * mask )
336{
337 GET_THREAD(thread);
338 int writeback = 1;
339
340 if (pack_spu.swap)
341 {
342 crPackGetPolygonStippleSWAP( mask, &writeback );
343 }
344 else
345 {
346 crPackGetPolygonStipple( mask, &writeback );
347 }
348
349#ifdef CR_ARB_pixel_buffer_object
350 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
351#endif
352 {
353 packspuFlush( (void *) thread );
354 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
355 }
356}
357
358void PACKSPU_APIENTRY packspu_GetPixelMapfv( GLenum map, GLfloat * values )
359{
360 GET_THREAD(thread);
361 int writeback = 1;
362
363 if (pack_spu.swap)
364 {
365 crPackGetPixelMapfvSWAP( map, values, &writeback );
366 }
367 else
368 {
369 crPackGetPixelMapfv( map, values, &writeback );
370 }
371
372#ifdef CR_ARB_pixel_buffer_object
373 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
374#endif
375 {
376 packspuFlush( (void *) thread );
377 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
378 }
379}
380
381void PACKSPU_APIENTRY packspu_GetPixelMapuiv( GLenum map, GLuint * values )
382{
383 GET_THREAD(thread);
384 int writeback = 1;
385
386 if (pack_spu.swap)
387 {
388 crPackGetPixelMapuivSWAP( map, values, &writeback );
389 }
390 else
391 {
392 crPackGetPixelMapuiv( map, values, &writeback );
393 }
394
395#ifdef CR_ARB_pixel_buffer_object
396 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
397#endif
398 {
399 packspuFlush( (void *) thread );
400 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
401 }
402}
403
404void PACKSPU_APIENTRY packspu_GetPixelMapusv( GLenum map, GLushort * values )
405{
406 GET_THREAD(thread);
407 int writeback = 1;
408
409 if (pack_spu.swap)
410 {
411 crPackGetPixelMapusvSWAP( map, values, &writeback );
412 }
413 else
414 {
415 crPackGetPixelMapusv( map, values, &writeback );
416 }
417
418#ifdef CR_ARB_pixel_buffer_object
419 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
420#endif
421 {
422 packspuFlush( (void *) thread );
423 CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
424 }
425}
426
427static void packspuFluchOnThreadSwitch(GLboolean fEnable)
428{
429 GET_THREAD(thread);
430 if (thread->currentContext->fAutoFlush == fEnable)
431 return;
432
433 thread->currentContext->fAutoFlush = fEnable;
434 thread->currentContext->currentThread = fEnable ? thread : NULL;
435}
436
437void PACKSPU_APIENTRY packspu_ChromiumParameteriCR(GLenum target, GLint value)
438{
439 switch (target)
440 {
441 case GL_FLUSH_ON_THREAD_SWITCH_CR:
442 /* this is a pure packspu state, don't propagate it any further */
443 packspuFluchOnThreadSwitch(value);
444 return;
445 case GL_SHARE_CONTEXT_RESOURCES_CR:
446 crStateShareContext(value);
447 break;
448 case GL_RCUSAGE_TEXTURE_SET_CR:
449 crStateSetTextureUsed(value, GL_TRUE);
450 break;
451 case GL_RCUSAGE_TEXTURE_CLEAR_CR:
452 crStateSetTextureUsed(value, GL_FALSE);
453 break;
454 default:
455 break;
456 }
457 crPackChromiumParameteriCR(target, value);
458}
459
460#ifdef CHROMIUM_THREADSAFE
461GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi)
462{
463 GLint con = 0;
464 int i;
465 GET_THREAD(thread);
466 CRASSERT(!thread);
467 crLockMutex(&_PackMutex);
468 {
469 CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI() || (pack_spu.numThreads>0));
470 CRASSERT(pack_spu.numThreads<MAX_THREADS);
471 for (i=0; i<MAX_THREADS; ++i)
472 {
473 if (!pack_spu.thread[i].inUse)
474 {
475 thread = &pack_spu.thread[i];
476 break;
477 }
478 }
479 CRASSERT(thread);
480
481 thread->inUse = GL_TRUE;
482 if (!CRPACKSPU_IS_WDDM_CRHGSMI())
483 thread->id = crThreadID();
484 else
485 thread->id = THREAD_OFFSET_MAGIC + i;
486 thread->currentContext = NULL;
487 thread->bInjectThread = GL_TRUE;
488
489 thread->netServer.name = crStrdup(pack_spu.name);
490 thread->netServer.buffer_size = 64 * 1024;
491
492 packspuConnectToServer(&(thread->netServer)
493#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
494 , pHgsmi
495#endif
496 );
497 CRASSERT(thread->netServer.conn);
498
499 CRASSERT(thread->packer == NULL);
500 thread->packer = crPackNewContext( pack_spu.swap );
501 CRASSERT(thread->packer);
502 crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
503 thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
504 thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;
505
506 crPackSetBuffer( thread->packer, &thread->buffer );
507 crPackFlushFunc( thread->packer, packspuFlush );
508 crPackFlushArg( thread->packer, (void *) thread );
509 crPackSendHugeFunc( thread->packer, packspuHuge );
510 crPackSetContext( thread->packer );
511
512 crSetTSD(&_PackTSD, thread);
513
514 pack_spu.numThreads++;
515 }
516 crUnlockMutex(&_PackMutex);
517
518 if (CRPACKSPU_IS_WDDM_CRHGSMI())
519 {
520 CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread)
521 && GET_THREAD_VAL_ID(thread->id) == thread);
522 con = thread->id;
523 }
524 return con;
525}
526
527GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(GLint con)
528{
529 GLuint ret;
530
531 crLockMutex(&_PackMutex);
532 {
533 ThreadInfo *thread = NULL;
534 if (CRPACKSPU_IS_WDDM_CRHGSMI())
535 {
536 if (!con)
537 {
538 crError("connection expected!");
539 return 0;
540 }
541 thread = GET_THREAD_VAL_ID(con);
542 }
543 else
544 {
545 CRASSERT(!con);
546 thread = GET_THREAD_VAL();
547 }
548 CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM);
549 ret = thread->netServer.conn->u32ClientID;
550 }
551 crUnlockMutex(&_PackMutex);
552
553 return ret;
554}
555
556void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id)
557{
558 crLockMutex(&_PackMutex);
559 {
560 GET_THREAD(thread);
561
562 CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM && thread->bInjectThread);
563 thread->netServer.conn->u32InjectClientID = id;
564 }
565 crUnlockMutex(&_PackMutex);
566}
567
568void PACKSPU_APIENTRY packspu_VBoxAttachThread()
569{
570#if 0
571 int i;
572 GET_THREAD(thread);
573
574 for (i=0; i<MAX_THREADS; ++i)
575 {
576 if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID())
577 {
578 crError("2nd attach to same thread");
579 }
580 }
581#endif
582
583 crSetTSD(&_PackTSD, NULL);
584
585 crStateVBoxAttachThread();
586}
587
588void PACKSPU_APIENTRY packspu_VBoxDetachThread()
589{
590 if (CRPACKSPU_IS_WDDM_CRHGSMI())
591 {
592 crPackSetContext(NULL);
593 crSetTSD(&_PackTSD, NULL);
594 }
595 else
596 {
597 int i;
598 GET_THREAD(thread);
599 if (thread)
600 {
601 crLockMutex(&_PackMutex);
602
603 for (i=0; i<MAX_THREADS; ++i)
604 {
605 if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i]
606 && thread->id==crThreadID() && thread->netServer.conn)
607 {
608 CRASSERT(pack_spu.numThreads>0);
609
610 packspuFlush((void *) thread);
611
612 if (pack_spu.thread[i].packer)
613 {
614 CR_LOCK_PACKER_CONTEXT(thread->packer);
615 crPackSetContext(NULL);
616 CR_UNLOCK_PACKER_CONTEXT(thread->packer);
617 crPackDeleteContext(pack_spu.thread[i].packer);
618 }
619 crNetFreeConnection(pack_spu.thread[i].netServer.conn);
620
621 pack_spu.numThreads--;
622 /*note can't shift the array here, because other threads have TLS references to array elements*/
623 crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo));
624
625 crSetTSD(&_PackTSD, NULL);
626
627 if (i==pack_spu.idxThreadInUse)
628 {
629 for (i=0; i<MAX_THREADS; ++i)
630 {
631 if (pack_spu.thread[i].inUse)
632 {
633 pack_spu.idxThreadInUse=i;
634 break;
635 }
636 }
637 }
638
639 break;
640 }
641 }
642
643 for (i=0; i<CR_MAX_CONTEXTS; ++i)
644 {
645 ContextInfo *ctx = &pack_spu.context[i];
646 if (ctx->currentThread == thread)
647 {
648 CRASSERT(ctx->fAutoFlush);
649 ctx->currentThread = NULL;
650 }
651 }
652
653 crUnlockMutex(&_PackMutex);
654 }
655 }
656
657 crStateVBoxDetachThread();
658}
659
660#ifdef WINDOWS
661#define WIN32_LEAN_AND_MEAN
662#include <windows.h>
663BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
664{
665 (void) lpvReserved;
666
667 switch (fdwReason)
668 {
669 case DLL_PROCESS_ATTACH:
670 {
671 crInitMutex(&_PackMutex);
672 break;
673 }
674
675 case DLL_PROCESS_DETACH:
676 {
677 crFreeMutex(&_PackMutex);
678 crNetTearDown();
679 break;
680 }
681
682 case DLL_THREAD_ATTACH:
683 case DLL_THREAD_DETACH:
684 default:
685 break;
686 }
687
688 return TRUE;
689}
690#endif
691
692#else /*ifdef CHROMIUM_THREADSAFE*/
693GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi)
694{
695}
696
697GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(GLint con)
698{
699 return 0;
700}
701
702void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id)
703{
704 (void) id;
705}
706
707void PACKSPU_APIENTRY packspu_VBoxPackAttachThread()
708{
709}
710
711void PACKSPU_APIENTRY packspu_VBoxPackDetachThread()
712{
713}
714#endif /*CHROMIUM_THREADSAFE*/
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