VirtualBox

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

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

crOpenGL: don't add explicit writebacks to guest buffers

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