VirtualBox

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

Last change on this file since 35845 was 35845, checked in by vboxsync, 14 years ago

crOpenGL: proper deadlock fix for r69838

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