VirtualBox

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

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

crogl: auto-flush on thread switch functionality

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.0 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 = 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 while (writeback)
101 crNetRecv();
102 }
103 }
104}
105
106#define PACK_FORCED_SYNC
107
108void PACKSPU_APIENTRY packspu_Flush( void )
109{
110 GET_THREAD(thread);
111 int writeback = 1;
112 int found=0;
113
114 if (!thread->bInjectThread)
115 {
116 crPackFlush();
117 if (packspuSyncOnFlushes())
118 {
119 crPackWriteback(&writeback);
120 packspuFlush( (void *) thread );
121 while (writeback)
122 crNetRecv();
123 }
124 }
125 else
126 {
127 int i;
128
129 crLockMutex(&_PackMutex);
130
131 /*Make sure we process commands in order they should appear, so flush other threads first*/
132 for (i=0; i<MAX_THREADS; ++i)
133 {
134 if (pack_spu.thread[i].inUse
135 && (thread != &pack_spu.thread[i]) && pack_spu.thread[i].netServer.conn
136 && pack_spu.thread[i].packer && pack_spu.thread[i].packer->currentBuffer)
137 {
138#ifdef PACK_FORCED_SYNC
139 CRPackContext *pc = pack_spu.thread[i].packer;
140 unsigned char *data_ptr;
141
142 CR_GET_BUFFERED_POINTER( pc, 16 );
143 WRITE_DATA( 0, GLint, 16 );
144 WRITE_DATA( 4, GLenum, CR_WRITEBACK_EXTEND_OPCODE );
145 WRITE_NETWORK_POINTER( 8, (void *) &writeback );
146 WRITE_OPCODE( pc, CR_EXTEND_OPCODE );
147 CR_UNLOCK_PACKER_CONTEXT(pc);
148#endif
149 packspuFlush((void *) &pack_spu.thread[i]);
150
151 if (pack_spu.thread[i].netServer.conn->u32ClientID == thread->netServer.conn->u32InjectClientID)
152 {
153 found=1;
154 }
155
156#ifdef PACK_FORCED_SYNC
157 while (writeback)
158 crNetRecv();
159#endif
160 }
161 }
162
163 if (!found)
164 {
165 /*Thread we're supposed to inject commands for has been detached,
166 so there's nothing to sync with and we should just pass commands through our own connection.
167 */
168 thread->netServer.conn->u32InjectClientID=0;
169 }
170
171#ifdef PACK_FORCED_SYNC
172 writeback = 1;
173 crPackWriteback(&writeback);
174#endif
175 packspuFlush((void *) thread);
176
177#ifdef PACK_FORCED_SYNC
178 while (writeback)
179 crNetRecv();
180#endif
181 crUnlockMutex(&_PackMutex);
182 }
183}
184
185GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits )
186{
187 GET_THREAD(thread);
188 static int num_calls = 0;
189 int writeback = pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
190 GLint return_val = (GLint) 0;
191
192 if (!thread) {
193 thread = packspuNewThread( crThreadID() );
194 }
195 CRASSERT(thread);
196 CRASSERT(thread->packer);
197
198 crPackSetContext(thread->packer);
199
200 if (pack_spu.swap)
201 {
202 crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
203 }
204 else
205 {
206 crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
207 }
208 packspuFlush(thread);
209 if (!(thread->netServer.conn->actual_network))
210 {
211 return num_calls++;
212 }
213 else
214 {
215 while (writeback)
216 crNetRecv();
217 if (pack_spu.swap)
218 {
219 return_val = (GLint) SWAP32(return_val);
220 }
221 return return_val;
222 }
223}
224
225
226
227GLboolean PACKSPU_APIENTRY
228packspu_AreTexturesResident( GLsizei n, const GLuint * textures,
229 GLboolean * residences )
230{
231 GET_THREAD(thread);
232 int writeback = 1;
233 GLboolean return_val = GL_TRUE;
234 GLsizei i;
235
236 if (!(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
237 {
238 crError( "packspu_AreTexturesResident doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" );
239 }
240
241 if (pack_spu.swap)
242 {
243 crPackAreTexturesResidentSWAP( n, textures, residences, &return_val, &writeback );
244 }
245 else
246 {
247 crPackAreTexturesResident( n, textures, residences, &return_val, &writeback );
248 }
249 packspuFlush( (void *) thread );
250
251 while (writeback)
252 crNetRecv();
253
254 /* Since the Chromium packer/unpacker can't return both 'residences'
255 * and the function's return value, compute the return value here.
256 */
257 for (i = 0; i < n; i++) {
258 if (!residences[i]) {
259 return_val = GL_FALSE;
260 break;
261 }
262 }
263
264 return return_val;
265}
266
267
268GLboolean PACKSPU_APIENTRY
269packspu_AreProgramsResidentNV( GLsizei n, const GLuint * ids,
270 GLboolean * residences )
271{
272 GET_THREAD(thread);
273 int writeback = 1;
274 GLboolean return_val = GL_TRUE;
275 GLsizei i;
276
277 if (!(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
278 {
279 crError( "packspu_AreProgramsResidentNV doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!" );
280 }
281 if (pack_spu.swap)
282 {
283 crPackAreProgramsResidentNVSWAP( n, ids, residences, &return_val, &writeback );
284 }
285 else
286 {
287 crPackAreProgramsResidentNV( n, ids, residences, &return_val, &writeback );
288 }
289 packspuFlush( (void *) thread );
290
291 while (writeback)
292 crNetRecv();
293
294 /* Since the Chromium packer/unpacker can't return both 'residences'
295 * and the function's return value, compute the return value here.
296 */
297 for (i = 0; i < n; i++) {
298 if (!residences[i]) {
299 return_val = GL_FALSE;
300 break;
301 }
302 }
303
304 return return_val;
305}
306
307void PACKSPU_APIENTRY packspu_GetPolygonStipple( GLubyte * mask )
308{
309 GET_THREAD(thread);
310 int writeback = 1;
311
312 if (pack_spu.swap)
313 {
314 crPackGetPolygonStippleSWAP( mask, &writeback );
315 }
316 else
317 {
318 crPackGetPolygonStipple( mask, &writeback );
319 }
320
321#ifdef CR_ARB_pixel_buffer_object
322 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
323#endif
324 {
325 packspuFlush( (void *) thread );
326 while (writeback)
327 crNetRecv();
328 }
329}
330
331void PACKSPU_APIENTRY packspu_GetPixelMapfv( GLenum map, GLfloat * values )
332{
333 GET_THREAD(thread);
334 int writeback = 1;
335
336 if (pack_spu.swap)
337 {
338 crPackGetPixelMapfvSWAP( map, values, &writeback );
339 }
340 else
341 {
342 crPackGetPixelMapfv( map, values, &writeback );
343 }
344
345#ifdef CR_ARB_pixel_buffer_object
346 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
347#endif
348 {
349 packspuFlush( (void *) thread );
350 while (writeback)
351 crNetRecv();
352 }
353}
354
355void PACKSPU_APIENTRY packspu_GetPixelMapuiv( GLenum map, GLuint * values )
356{
357 GET_THREAD(thread);
358 int writeback = 1;
359
360 if (pack_spu.swap)
361 {
362 crPackGetPixelMapuivSWAP( map, values, &writeback );
363 }
364 else
365 {
366 crPackGetPixelMapuiv( map, values, &writeback );
367 }
368
369#ifdef CR_ARB_pixel_buffer_object
370 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
371#endif
372 {
373 packspuFlush( (void *) thread );
374 while (writeback)
375 crNetRecv();
376 }
377}
378
379void PACKSPU_APIENTRY packspu_GetPixelMapusv( GLenum map, GLushort * values )
380{
381 GET_THREAD(thread);
382 int writeback = 1;
383
384 if (pack_spu.swap)
385 {
386 crPackGetPixelMapusvSWAP( map, values, &writeback );
387 }
388 else
389 {
390 crPackGetPixelMapusv( map, values, &writeback );
391 }
392
393#ifdef CR_ARB_pixel_buffer_object
394 if (!crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
395#endif
396 {
397 packspuFlush( (void *) thread );
398 while (writeback)
399 crNetRecv();
400 }
401}
402
403static void packspuFluchOnThreadSwitch(GLboolean fEnable)
404{
405 GET_THREAD(thread);
406 if (thread->currentContext->fAutoFlush == fEnable)
407 return;
408
409 thread->currentContext->fAutoFlush = fEnable;
410 thread->currentContext->currentThread = fEnable ? thread : NULL;
411}
412
413void PACKSPU_APIENTRY packspu_ChromiumParameteriCR(GLenum target, GLint value)
414{
415 if (GL_FLUSH_ON_THREAD_SWITCH_CR==target)
416 {
417 /* this is a pure packspu state, don't propagate it any further */
418 packspuFluchOnThreadSwitch(value);
419 return;
420 }
421 if (GL_SHARE_CONTEXT_RESOURCES_CR==target)
422 {
423 crStateShareContext(value);
424 }
425 crPackChromiumParameteriCR(target, value);
426}
427
428#ifdef CHROMIUM_THREADSAFE
429void PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(void)
430{
431 crLockMutex(&_PackMutex);
432 {
433 int i;
434 GET_THREAD(thread);
435 CRASSERT(!thread);
436 CRASSERT((pack_spu.numThreads>0) && (pack_spu.numThreads<MAX_THREADS));
437
438 for (i=0; i<MAX_THREADS; ++i)
439 {
440 if (!pack_spu.thread[i].inUse)
441 {
442 thread = &pack_spu.thread[i];
443 break;
444 }
445 }
446 CRASSERT(thread);
447
448 thread->inUse = GL_TRUE;
449 thread->id = crThreadID();
450 thread->currentContext = NULL;
451 thread->bInjectThread = GL_TRUE;
452
453 thread->netServer.name = crStrdup(pack_spu.name);
454 thread->netServer.buffer_size = 64 * 1024;
455
456 crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer));
457 CRASSERT(thread->netServer.conn);
458
459 CRASSERT(thread->packer == NULL);
460 thread->packer = crPackNewContext( pack_spu.swap );
461 CRASSERT(thread->packer);
462 crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
463 thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
464 thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;
465
466 crPackSetBuffer( thread->packer, &thread->buffer );
467 crPackFlushFunc( thread->packer, packspuFlush );
468 crPackFlushArg( thread->packer, (void *) thread );
469 crPackSendHugeFunc( thread->packer, packspuHuge );
470 crPackSetContext( thread->packer );
471
472 crSetTSD(&_PackTSD, thread);
473
474 pack_spu.numThreads++;
475 }
476 crUnlockMutex(&_PackMutex);
477}
478
479GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(void)
480{
481 GLuint ret;
482
483 crLockMutex(&_PackMutex);
484 {
485 GET_THREAD(thread);
486 CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM);
487 ret = thread->netServer.conn->u32ClientID;
488 }
489 crUnlockMutex(&_PackMutex);
490
491 return ret;
492}
493
494void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id)
495{
496 crLockMutex(&_PackMutex);
497 {
498 GET_THREAD(thread);
499
500 CRASSERT(thread && thread->netServer.conn && thread->netServer.conn->type==CR_VBOXHGCM && thread->bInjectThread);
501 thread->netServer.conn->u32InjectClientID = id;
502 }
503 crUnlockMutex(&_PackMutex);
504}
505
506void PACKSPU_APIENTRY packspu_VBoxPackAttachThread()
507{
508#if 0
509 int i;
510 GET_THREAD(thread);
511
512 for (i=0; i<MAX_THREADS; ++i)
513 {
514 if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID())
515 {
516 crError("2nd attach to same thread");
517 }
518 }
519#endif
520
521 crSetTSD(&_PackTSD, NULL);
522}
523
524void PACKSPU_APIENTRY packspu_VBoxPackDetachThread()
525{
526 int i;
527 GET_THREAD(thread);
528
529 if (thread)
530 {
531 crLockMutex(&_PackMutex);
532
533 for (i=0; i<MAX_THREADS; ++i)
534 {
535 if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i]
536 && thread->id==crThreadID() && thread->netServer.conn)
537 {
538 CRASSERT(pack_spu.numThreads>0);
539
540 packspuFlush((void *) thread);
541
542 if (pack_spu.thread[i].packer)
543 {
544 CR_LOCK_PACKER_CONTEXT(thread->packer);
545 crPackSetContext(NULL);
546 CR_UNLOCK_PACKER_CONTEXT(thread->packer);
547 crPackDeleteContext(pack_spu.thread[i].packer);
548 }
549 crNetFreeConnection(pack_spu.thread[i].netServer.conn);
550
551 pack_spu.numThreads--;
552 /*note can't shift the array here, because other threads have TLS references to array elements*/
553 crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo));
554
555 crSetTSD(&_PackTSD, NULL);
556
557 if (i==pack_spu.idxThreadInUse)
558 {
559 for (i=0; i<MAX_THREADS; ++i)
560 {
561 if (pack_spu.thread[i].inUse)
562 {
563 pack_spu.idxThreadInUse=i;
564 break;
565 }
566 }
567 }
568
569 break;
570 }
571 }
572
573 for (i=0; i<CR_MAX_CONTEXTS; ++i)
574 {
575 ContextInfo *ctx = &pack_spu.context[i];
576 if (ctx->currentThread == thread)
577 {
578 CRASSERT(ctx->fAutoFlush);
579 ctx->currentThread = NULL;
580 }
581 }
582
583 crUnlockMutex(&_PackMutex);
584 }
585}
586
587#ifdef WINDOWS
588#define WIN32_LEAN_AND_MEAN
589#include <windows.h>
590BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
591{
592 (void) lpvReserved;
593
594 switch (fdwReason)
595 {
596 case DLL_PROCESS_ATTACH:
597 {
598 crInitMutex(&_PackMutex);
599 break;
600 }
601
602 case DLL_PROCESS_DETACH:
603 {
604 crFreeMutex(&_PackMutex);
605 crNetTearDown();
606 break;
607 }
608
609 case DLL_THREAD_ATTACH:
610 {
611 packspu_VBoxPackAttachThread();
612 break;
613 }
614
615 case DLL_THREAD_DETACH:
616 {
617 packspu_VBoxPackDetachThread();
618 break;
619 }
620
621 default:
622 break;
623 }
624
625 return TRUE;
626}
627#endif
628
629#else /*ifdef CHROMIUM_THREADSAFE*/
630void PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(void)
631{
632}
633
634GLuint PACKSPU_APIENTRY packspu_VBoxPackGetInjectID(void)
635{
636 return 0;
637}
638
639void PACKSPU_APIENTRY packspu_VBoxPackSetInjectID(GLuint id)
640{
641 (void) id;
642}
643
644void PACKSPU_APIENTRY packspu_VBoxPackAttachThread()
645{
646}
647
648void PACKSPU_APIENTRY packspu_VBoxPackDetachThread()
649{
650}
651#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