VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c@ 48429

Last change on this file since 48429 was 48356, checked in by vboxsync, 11 years ago

crOpenGL: dummy window handling, shared context creation, window destruction fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 53.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 "cr_environment.h"
8#include "cr_string.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_spu.h"
12#include "cr_environment.h"
13#include "renderspu.h"
14#include "cr_extstring.h"
15
16#include <iprt/asm.h>
17
18uint32_t renderspuContextRelease(ContextInfo *context);
19uint32_t renderspuContextRetain(ContextInfo *context);
20
21static void
22DoSync(void)
23{
24 CRMessage *in, out;
25
26 out.header.type = CR_MESSAGE_OOB;
27
28 if (render_spu.is_swap_master)
29 {
30 int a;
31
32 for (a = 0; a < render_spu.num_swap_clients; a++)
33 {
34 crNetGetMessage( render_spu.swap_conns[a], &in );
35 crNetFree( render_spu.swap_conns[a], in);
36 }
37
38 for (a = 0; a < render_spu.num_swap_clients; a++)
39 crNetSend( render_spu.swap_conns[a], NULL, &out, sizeof(CRMessage));
40 }
41 else
42 {
43 crNetSend( render_spu.swap_conns[0], NULL, &out, sizeof(CRMessage));
44
45 crNetGetMessage( render_spu.swap_conns[0], &in );
46 crNetFree( render_spu.swap_conns[0], in);
47 }
48}
49
50
51
52/*
53 * Visual functions
54 */
55
56/**
57 * used for debugging and giving info to the user.
58 */
59void
60renderspuMakeVisString( GLbitfield visAttribs, char *s )
61{
62 s[0] = 0;
63
64 if (visAttribs & CR_RGB_BIT)
65 crStrcat(s, "RGB");
66 if (visAttribs & CR_ALPHA_BIT)
67 crStrcat(s, "A");
68 if (visAttribs & CR_DOUBLE_BIT)
69 crStrcat(s, ", Doublebuffer");
70 if (visAttribs & CR_STEREO_BIT)
71 crStrcat(s, ", Stereo");
72 if (visAttribs & CR_DEPTH_BIT)
73 crStrcat(s, ", Z");
74 if (visAttribs & CR_STENCIL_BIT)
75 crStrcat(s, ", Stencil");
76 if (visAttribs & CR_ACCUM_BIT)
77 crStrcat(s, ", Accum");
78 if (visAttribs & CR_MULTISAMPLE_BIT)
79 crStrcat(s, ", Multisample");
80 if (visAttribs & CR_OVERLAY_BIT)
81 crStrcat(s, ", Overlay");
82 if (visAttribs & CR_PBUFFER_BIT)
83 crStrcat(s, ", PBuffer");
84}
85
86GLboolean renderspuInitVisual(VisualInfo *pVisInfo, const char *displayName, GLbitfield visAttribs)
87{
88 pVisInfo->displayName = crStrdup(displayName);
89 pVisInfo->visAttribs = visAttribs;
90 return renderspu_SystemInitVisual(pVisInfo);
91}
92
93/*
94 * Find a VisualInfo which matches the given display name and attribute
95 * bitmask, or return a pointer to a new visual.
96 */
97VisualInfo *
98renderspuFindVisual(const char *displayName, GLbitfield visAttribs)
99{
100 int i;
101
102 if (!displayName)
103 displayName = "";
104
105 /* first, try to find a match */
106#if defined(WINDOWS) || defined(DARWIN)
107 for (i = 0; i < render_spu.numVisuals; i++) {
108 if (visAttribs == render_spu.visuals[i].visAttribs) {
109 return &(render_spu.visuals[i]);
110 }
111 }
112#elif defined(GLX)
113 for (i = 0; i < render_spu.numVisuals; i++) {
114 if (crStrcmp(displayName, render_spu.visuals[i].displayName) == 0
115 && visAttribs == render_spu.visuals[i].visAttribs) {
116 return &(render_spu.visuals[i]);
117 }
118 }
119#endif
120
121 if (render_spu.numVisuals >= MAX_VISUALS)
122 {
123 crWarning("Render SPU: Couldn't create a visual, too many visuals already");
124 return NULL;
125 }
126
127 /* create a new visual */
128 i = render_spu.numVisuals;
129 if (renderspuInitVisual(&(render_spu.visuals[i]), displayName, visAttribs)) {
130 render_spu.numVisuals++;
131 return &(render_spu.visuals[i]);
132 }
133 else {
134 crWarning("Render SPU: Couldn't get a visual, renderspu_SystemInitVisual failed");
135 return NULL;
136 }
137}
138
139static ContextInfo * renderspuCreateContextInternal(const char *dpyName, GLint visBits, GLint idCtx, ContextInfo * sharedContext)
140{
141 ContextInfo *context;
142 VisualInfo *visual;
143
144 if (idCtx <= 0)
145 {
146 idCtx = (GLint)crHashtableAllocKeys(render_spu.contextTable, 1);
147 if (idCtx <= 0)
148 {
149 crWarning("failed to allocate context id");
150 return NULL;
151 }
152 }
153 else
154 {
155 if (crHashtableIsKeyUsed(render_spu.contextTable, idCtx))
156 {
157 crWarning("the specified ctx key %d is in use", idCtx);
158 return NULL;
159 }
160 }
161
162
163 if (!dpyName || crStrlen(render_spu.display_string)>0)
164 dpyName = render_spu.display_string;
165
166 visual = renderspuFindVisual(dpyName, visBits);
167 if (!visual)
168 return NULL;
169
170 context = (ContextInfo *) crCalloc(sizeof(ContextInfo));
171 if (!context)
172 return NULL;
173 context->BltInfo.Base.id = idCtx;
174 context->shared = sharedContext;
175 if (!renderspu_SystemCreateContext(visual, context, sharedContext))
176 return NULL;
177
178 crHashtableAdd(render_spu.contextTable, idCtx, context);
179
180 context->BltInfo.Base.visualBits = visual->visAttribs;
181 /*
182 crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d",
183 dpyName, visBits, context->BltInfo.Base.id);
184 */
185
186 if (sharedContext)
187 renderspuContextRetain(sharedContext);
188
189 context->cRefs = 1;
190
191 return context;
192}
193
194GLint renderspuCreateContextEx(const char *dpyName, GLint visBits, GLint id, GLint shareCtx)
195{
196 ContextInfo *context, *sharedContext = NULL;
197
198 if (shareCtx) {
199 sharedContext
200 = (ContextInfo *) crHashtableSearch(render_spu.contextTable, shareCtx);
201 CRASSERT(sharedContext);
202 }
203
204 context = renderspuCreateContextInternal(dpyName, visBits, id, sharedContext);
205 if (context)
206 return context->BltInfo.Base.id;
207 return -1;
208}
209
210/*
211 * Context functions
212 */
213
214GLint RENDER_APIENTRY
215renderspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx)
216{
217 return renderspuCreateContextEx(dpyName, visBits, 0, shareCtx);
218}
219
220static void renderspuDestroyContextTerminate( ContextInfo *context )
221{
222 CRASSERT(context->BltInfo.Base.id == -1);
223 renderspu_SystemDestroyContext( context );
224 if (context->extensionString) {
225 crFree(context->extensionString);
226 context->extensionString = NULL;
227 }
228
229 if (context->shared)
230 renderspuContextRelease( context->shared );
231
232 crFree(context);
233}
234
235uint32_t renderspuContextRetain( ContextInfo *context )
236{
237 Assert(context->cRefs);
238 return ASMAtomicIncU32(&context->cRefs);
239}
240
241uint32_t renderspuContextRelease( ContextInfo *context )
242{
243 uint32_t cRefs = ASMAtomicDecU32(&context->cRefs);
244 if (!cRefs)
245 renderspuDestroyContextTerminate( context );
246 else
247 CRASSERT(cRefs < UINT32_MAX/2);
248 return cRefs;
249}
250
251uint32_t renderspuContextMarkDeletedAndRelease( ContextInfo *context )
252{
253 /* invalidate the context id to mark it as deleted */
254 context->BltInfo.Base.id = -1;
255
256 /* some drivers do not like when the base (shared) context is deleted before its referals,
257 * this is why we keep a context refference counting the base (shared) context will be destroyed as soon as*/
258 return renderspuContextRelease( context );
259}
260
261ContextInfo * renderspuDefaultSharedContextAcquire()
262{
263 ContextInfo * pCtx = render_spu.defaultSharedContext;
264 if (!pCtx)
265 return NULL;
266
267 renderspuContextRetain(pCtx);
268 return pCtx;
269}
270
271void renderspuDefaultSharedContextRelease(ContextInfo * pCtx)
272{
273 renderspuContextRelease(pCtx);
274}
275
276
277static void RENDER_APIENTRY
278renderspuDestroyContext( GLint ctx )
279{
280 ContextInfo *context, *curCtx;
281
282 CRASSERT(ctx);
283
284 if (ctx == CR_RENDER_DEFAULT_CONTEXT_ID)
285 {
286 crWarning("request to destroy a default context, ignoring");
287 return;
288 }
289
290 context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
291
292 if (!context)
293 {
294 crWarning("request to delete inexistent context");
295 return;
296 }
297
298 if (render_spu.defaultSharedContext == context)
299 {
300 renderspuSetDefaultSharedContext(NULL);
301 }
302
303 curCtx = GET_CONTEXT_VAL();
304 CRASSERT(curCtx);
305 if (curCtx == context)
306 {
307 renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID );
308 curCtx = GET_CONTEXT_VAL();
309 Assert(curCtx);
310 Assert(curCtx != context);
311 }
312
313 crHashtableDelete(render_spu.contextTable, ctx, NULL);
314
315 renderspuContextMarkDeletedAndRelease(context);
316}
317
318WindowInfo* renderspuGetDummyWindow(GLint visBits)
319{
320 WindowInfo *window = (WindowInfo *) crHashtableSearch(render_spu.dummyWindowTable, visBits);
321 if (!window)
322 {
323 window = (WindowInfo *)crAlloc(sizeof (*window));
324 if (!window)
325 {
326 crWarning("crAlloc failed");
327 return NULL;
328 }
329
330 if (!renderspuWindowInit(window, NULL, visBits, -1))
331 {
332 crWarning("renderspuWindowInit failed");
333 crFree(window);
334 return NULL;
335 }
336
337 crHashtableAdd(render_spu.dummyWindowTable, visBits, window);
338 }
339
340 return window;
341}
342
343void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow, ContextInfo *context)
344{
345 if (window && context)
346 {
347#ifdef CHROMIUM_THREADSAFE
348 crSetTSD(&_RenderTSD, context);
349#else
350 render_spu.currentContext = context;
351#endif
352 context->currentWindow = window;
353 if (!window)
354 {
355 crDebug("Render SPU: MakeCurrent invalid window id: %d", window->BltInfo.Base.id);
356 return;
357 }
358 if (!context)
359 {
360 crDebug("Render SPU: MakeCurrent invalid context id: %d", context->BltInfo.Base.id);
361 return;
362 }
363
364 renderspu_SystemMakeCurrent( window, nativeWindow, context );
365 if (!context->everCurrent) {
366 /* print OpenGL info */
367 const char *extString = (const char *) render_spu.ws.glGetString( GL_EXTENSIONS );
368 /*
369 crDebug( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) );
370 */
371 crInfo( "Render SPU: GL_VENDOR: %s", render_spu.ws.glGetString( GL_VENDOR ) );
372 crInfo( "Render SPU: GL_RENDERER: %s", render_spu.ws.glGetString( GL_RENDERER ) );
373 crInfo( "Render SPU: GL_VERSION: %s", render_spu.ws.glGetString( GL_VERSION ) );
374 crInfo( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) );
375 if (crStrstr(extString, "GL_ARB_window_pos"))
376 context->haveWindowPosARB = GL_TRUE;
377 else
378 context->haveWindowPosARB = GL_FALSE;
379 context->everCurrent = GL_TRUE;
380 }
381 if (window->BltInfo.Base.id == CR_RENDER_DEFAULT_WINDOW_ID && window->mapPending &&
382 !render_spu.render_to_app_window && !render_spu.render_to_crut_window) {
383 /* Window[CR_RENDER_DEFAULT_CONTEXT_ID] is special, it's the default window and normally hidden.
384 * If the mapPending flag is set, then we should now make the window
385 * visible.
386 */
387 /*renderspu_SystemShowWindow( window, GL_TRUE );*/
388 window->mapPending = GL_FALSE;
389 }
390 window->everCurrent = GL_TRUE;
391 }
392 else if (!window && !context)
393 {
394 renderspu_SystemMakeCurrent( NULL, 0, NULL );
395#ifdef CHROMIUM_THREADSAFE
396 crSetTSD(&_RenderTSD, NULL);
397#else
398 render_spu.currentContext = NULL;
399#endif
400 }
401 else
402 {
403 crError("renderspuMakeCurrent invalid ids: crWindow(%d), ctx(%d)",
404 window ? window->BltInfo.Base.id : 0,
405 context ? context->BltInfo.Base.id : 0);
406 }
407}
408
409void RENDER_APIENTRY
410renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
411{
412 WindowInfo *window = NULL;
413 ContextInfo *context = NULL;
414
415 /*
416 crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx);
417 */
418
419 if (crWindow)
420 {
421 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow);
422 if (!window)
423 {
424 crWarning("invalid window %d specified", crWindow);
425 return;
426 }
427 }
428
429 if (ctx)
430 {
431 context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
432 if (!context)
433 {
434 crWarning("invalid context %d specified", ctx);
435 return;
436 }
437 }
438
439 if (!context != !window)
440 {
441 crWarning("either window %d or context %d are zero", crWindow, ctx);
442 return;
443 }
444
445 renderspuPerformMakeCurrent(window, nativeWindow, context);
446}
447
448GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id )
449{
450 crMemset(window, 0, sizeof (*window));
451 RTCritSectInit(&window->CompositorLock);
452 window->fCompositorPresentEmpty = GL_FALSE;
453 window->pCompositor = NULL;
454
455 window->BltInfo.Base.id = id;
456
457 window->x = render_spu.defaultX;
458 window->y = render_spu.defaultY;
459 window->BltInfo.width = render_spu.defaultWidth;
460 window->BltInfo.height = render_spu.defaultHeight;
461
462 /* Set window->title, replacing %i with the window ID number */
463 {
464 const char *s = crStrstr(render_spu.window_title, "%i");
465 if (s) {
466 int i, j, k;
467 window->title = crAlloc(crStrlen(render_spu.window_title) + 10);
468 for (i = 0; render_spu.window_title[i] != '%'; i++)
469 window->title[i] = render_spu.window_title[i];
470 k = sprintf(window->title + i, "%d", window->BltInfo.Base.id);
471 CRASSERT(k < 10);
472 i++; /* skip the 'i' after the '%' */
473 j = i + k;
474 for (; (window->title[j] = s[i]) != 0; i++, j++)
475 ;
476 }
477 else {
478 window->title = crStrdup(render_spu.window_title);
479 }
480 }
481
482 window->BltInfo.Base.visualBits = visual->visAttribs;
483
484
485 /*
486 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
487 */
488 /* Have GLX/WGL/AGL create the window */
489 if (!renderspu_SystemVBoxCreateWindow( visual, showIt, window ))
490 {
491 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
492 return GL_FALSE;
493 }
494
495 window->visible = !!showIt;
496
497 CRASSERT(window->visual == visual);
498 return GL_TRUE;
499}
500
501/*
502 * Window functions
503 */
504GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
505{
506 VisualInfo *visual;
507
508 crMemset(pWindow, 0, sizeof (*pWindow));
509
510 if (!dpyName || crStrlen(render_spu.display_string) > 0)
511 dpyName = render_spu.display_string;
512
513 visual = renderspuFindVisual( dpyName, visBits );
514 if (!visual)
515 {
516 crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
517 return GL_FALSE;
518 }
519
520 /*
521 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
522 */
523 /* Have GLX/WGL/AGL create the window */
524 if (!renderspuWindowInitWithVisual( pWindow, visual, 0, id ))
525 {
526 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
527 return GL_FALSE;
528 }
529
530 return GL_TRUE;
531}
532
533GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id )
534{
535 WindowInfo *window;
536
537 if (id <= 0)
538 {
539 id = (GLint)crHashtableAllocKeys(render_spu.windowTable, 1);
540 if (id <= 0)
541 {
542 crWarning("failed to allocate window id");
543 return -1;
544 }
545 }
546 else
547 {
548 if (crHashtableIsKeyUsed(render_spu.windowTable, id))
549 {
550 crWarning("the specified window key %d is in use", id);
551 return -1;
552 }
553 }
554
555 /* Allocate WindowInfo */
556 window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
557 if (!window)
558 {
559 crWarning( "Render SPU: Couldn't create a window" );
560 return -1;
561 }
562
563 if (!renderspuWindowInit(window, dpyName, visBits, id))
564 {
565 crWarning("renderspuWindowInit failed");
566 crFree(window);
567 return -1;
568 }
569
570 crHashtableAdd(render_spu.windowTable, id, window);
571 return window->BltInfo.Base.id;
572}
573
574GLint RENDER_APIENTRY
575renderspuWindowCreate( const char *dpyName, GLint visBits )
576{
577 return renderspuWindowCreateEx( dpyName, visBits, 0 );
578}
579
580static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
581{
582 ContextInfo *pCtx = (ContextInfo *) data1;
583 WindowInfo *pWindow = data2;
584 (void) key;
585
586 if (pCtx->currentWindow==pWindow)
587 {
588 WindowInfo* pDummy = renderspuGetDummyWindow(pCtx->BltInfo.Base.visualBits);
589 if (pDummy)
590 {
591 renderspuPerformMakeCurrent(pDummy, 0, pCtx);
592 }
593 else
594 {
595 crWarning("failed to get dummy window");
596 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
597 }
598 }
599}
600
601void renderspuWindowTerm( WindowInfo *window )
602{
603 GET_CONTEXT(pOldCtx);
604 WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
605 CRASSERT(!pOldCtx == !pOldWindow);
606 /* ensure no concurrent draws can take place */
607 renderspuVBoxCompositorSet(window, NULL);
608 renderspuVBoxPresentBlitterCleanup(window);
609 renderspu_SystemDestroyWindow( window );
610 RTCritSectDelete(&window->CompositorLock);
611 /* check if this window is bound to some ctx. Note: window pointer is already freed here */
612 crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
613 /* restore current context */
614 {
615 GET_CONTEXT(pNewCtx);
616 WindowInfo * pNewWindow = pNewCtx ? pNewCtx->currentWindow : NULL;
617 CRASSERT(!pNewCtx == !pNewWindow);
618
619 if (pOldWindow == window)
620 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
621 else if (pNewCtx != pOldCtx || pOldWindow != pNewWindow)
622 {
623 if (pOldCtx)
624 renderspuPerformMakeCurrent(pOldWindow, 0, pOldCtx);
625 else
626 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
627 }
628 }
629}
630
631void
632RENDER_APIENTRY renderspuWindowDestroy( GLint win )
633{
634 WindowInfo *window;
635
636 CRASSERT(win >= 0);
637 if (win == CR_RENDER_DEFAULT_WINDOW_ID)
638 {
639 crWarning("request to destroy a default mural, ignoring");
640 return;
641 }
642 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
643 if (window) {
644 crDebug("Render SPU: Destroy window (%d)", win);
645 renderspuWindowTerm( window );
646
647 /* remove window info from hash table, and free it */
648 crHashtableDelete(render_spu.windowTable, win, crFree);
649
650 }
651 else {
652 crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
653 }
654}
655
656
657static void RENDER_APIENTRY
658renderspuWindowSize( GLint win, GLint w, GLint h )
659{
660 WindowInfo *window;
661 CRASSERT(win >= 0);
662 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
663 if (window) {
664 if (w != window->BltInfo.width
665 || h != window->BltInfo.height)
666 {
667 /* window is resized, compositor data is no longer valid
668 * this set also ensures all redraw operations are done in the redraw thread
669 * and that no redraw is started until new Present request comes containing a valid presentation data */
670 renderspuVBoxCompositorSet( window, NULL);
671 renderspu_SystemWindowSize( window, w, h );
672 window->BltInfo.width = w;
673 window->BltInfo.height = h;
674 }
675 }
676 else {
677 crDebug("Render SPU: Attempt to resize invalid window (%d)", win);
678 }
679}
680
681
682static void RENDER_APIENTRY
683renderspuWindowPosition( GLint win, GLint x, GLint y )
684{
685 if (!render_spu.ignore_window_moves) {
686 WindowInfo *window;
687 CRASSERT(win >= 0);
688 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
689 if (window) {
690 renderspu_SystemWindowPosition( window, x, y );
691 window->x = x;
692 window->y = y;
693 }
694 else {
695 crDebug("Render SPU: Attempt to move invalid window (%d)", win);
696 }
697 }
698}
699
700static void RENDER_APIENTRY
701renderspuWindowVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
702{
703 WindowInfo *window;
704 CRASSERT(win >= 0);
705 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
706 if (window) {
707 renderspu_SystemWindowVisibleRegion( window, cRects, pRects );
708 }
709 else {
710 crDebug("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
711 }
712}
713
714static void RENDER_APIENTRY
715renderspuWindowShow( GLint win, GLint flag )
716{
717 WindowInfo *window;
718 CRASSERT(win >= 0);
719 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
720 if (window) {
721 GLboolean visible;
722 if (window->nativeWindow) {
723 /* We're rendering back to the native app window instead of the
724 * new window which we (the Render SPU) created earlier.
725 * So, we never want to show the Render SPU's window.
726 */
727 flag = 0;
728 }
729
730 visible = !!flag;
731
732 if (window->visible != visible)
733 {
734 renderspu_SystemShowWindow( window, visible );
735 window->visible = visible;
736 }
737 }
738 else {
739 crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win);
740 }
741}
742
743static void RENDER_APIENTRY
744renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
745{
746 WindowInfo *window;
747 CRASSERT(win >= 0);
748 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
749 if (window) {
750 if (pCompositor && CrVrScrCompositorIsEmpty(pCompositor) && !window->fCompositorPresentEmpty)
751 pCompositor = NULL;
752
753 if (pCompositor)
754 window->fCompositorPresentEmpty = GL_FALSE;
755
756 renderspuVBoxCompositorSet( window, pCompositor);
757 if (pCompositor)
758 {
759 renderspu_SystemVBoxPresentComposition(window, pChangedEntry);
760 }
761 }
762 else {
763 crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win);
764 }
765}
766
767void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
768{
769 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
770 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
771 CrVrScrCompositorIterInit(pCompositor, &CIter);
772 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
773 {
774 uint32_t cRegions;
775 const RTRECT *paSrcRegions, *paDstRegions;
776 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
777 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
778 if (RT_SUCCESS(rc))
779 {
780 uint32_t i;
781 for (i = 0; i < cRegions; ++i)
782 {
783 RTRECT DstRect;
784 DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
785 DstRect.yTop = paDstRegions[i].yTop * scaleY;
786 DstRect.xRight = paDstRegions[i].xRight * scaleX;
787 DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
788 CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, &paSrcRegions[i], &DstRect, 1, fFlags);
789 }
790 }
791 else
792 {
793 crWarning("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
794 }
795 }
796}
797
798void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
799{
800 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
801 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
802 CrVrScrCompositorIterInit(pCompositor, &CIter);
803 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
804 {
805 uint32_t cRegions;
806 const RTRECT *paSrcRegions, *paDstRegions;
807 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
808 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
809 if (RT_SUCCESS(rc))
810 {
811 CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, paSrcRegions, paDstRegions, cRegions, fFlags);
812 }
813 else
814 {
815 crWarning("Blit: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
816 }
817 }
818}
819
820void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
821{
822 if (!window->pBlitter)
823 return;
824
825 if (render_spu.blitterTable)
826 {
827 const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
828 if (pBltInfo->Base.id == window->BltInfo.Base.id)
829 {
830 CrBltMuralSetCurrent(window->pBlitter, NULL);
831 }
832 }
833 else
834 {
835 CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
836 CrBltMuralSetCurrent(window->pBlitter, NULL);
837 CrBltTerm(window->pBlitter);
838 }
839 window->pBlitter = NULL;
840}
841
842PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
843{
844 PCR_BLITTER pBlitter = window->pBlitter;
845 if (!pBlitter)
846 {
847 if (render_spu.blitterTable)
848 {
849 crHashtableLock(render_spu.blitterTable);
850 pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
851 }
852
853 if (!pBlitter)
854 {
855 int rc;
856 ContextInfo * pDefaultCtxInfo;
857
858 pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
859 if (!pBlitter)
860 {
861 crWarning("failed to allocate blitter");
862 return NULL;
863 }
864
865 pDefaultCtxInfo = renderspuDefaultSharedContextAcquire();
866 if (!pDefaultCtxInfo)
867 {
868 crWarning("no default ctx info!");
869 crFree(pBlitter);
870 return NULL;
871 }
872
873 rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, render_spu.blitterDispatch);
874
875 /* we can release it either way, since it will be retained when used as a shared context */
876 renderspuDefaultSharedContextRelease(pDefaultCtxInfo);
877
878 if (!RT_SUCCESS(rc))
879 {
880 crWarning("CrBltInit failed, rc %d", rc);
881 crFree(pBlitter);
882 return NULL;
883 }
884
885 if (render_spu.blitterTable)
886 {
887 crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
888 }
889 }
890
891 if (render_spu.blitterTable)
892 crHashtableUnlock(render_spu.blitterTable);
893
894 Assert(pBlitter);
895 window->pBlitter = pBlitter;
896 }
897
898 CrBltMuralSetCurrent(pBlitter, &window->BltInfo);
899 return pBlitter;
900}
901
902int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
903{
904 int rc;
905 PCR_BLITTER_CONTEXT pCtxInfo = NULL;
906 PCR_BLITTER_WINDOW pWindowInfo = NULL;
907 GET_CONTEXT(pCtx);
908
909 if (pCtx)
910 {
911 if (pCtx->currentWindow)
912 {
913 pCtxInfo = &pCtx->BltInfo;
914 pWindowInfo = &pCtx->currentWindow->BltInfo;
915 }
916 }
917
918 CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
919
920 rc = CrBltEnter(pBlitter, pCtxInfo, pWindowInfo);
921 if (!RT_SUCCESS(rc))
922 {
923 crWarning("CrBltEnter failed, rc %d", rc);
924 return rc;
925 }
926 return VINF_SUCCESS;
927}
928
929PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData )
930{
931 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet(window);
932 if (pBlitter)
933 {
934 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
935 if (RT_SUCCESS(rc))
936 {
937 return pBlitter;
938 }
939 }
940 return NULL;
941}
942
943PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
944{
945 if (!window->pBlitter)
946 {
947 struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
948 /* just use compositor lock to synchronize */
949 pTmpCompositor = renderspuVBoxCompositorAcquire(window);
950 CRASSERT(pTmpCompositor);
951 if (pTmpCompositor)
952 {
953 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet( window );
954 if (pBlitter)
955 {
956 if (!CrBltIsEverEntered(pBlitter))
957 {
958 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
959 if (RT_SUCCESS(rc))
960 {
961 CrBltLeave(pBlitter);
962 }
963 else
964 {
965 crWarning("renderspuVBoxPresentBlitterEnter failed rc %d", rc);
966 }
967 }
968 }
969 else
970 {
971 crWarning("renderspuVBoxPresentBlitterGet failed");
972 }
973
974 renderspuVBoxCompositorRelease(window);
975 }
976 else
977 {
978 crWarning("renderspuVBoxCompositorAcquire failed");
979 }
980 }
981 return window->pBlitter;
982}
983
984void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
985{
986 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
987 if (!pBlitter)
988 return;
989
990 renderspuVBoxCompositorBlit(pCompositor, pBlitter);
991
992 renderspu_SystemSwapBuffers(window, 0);
993
994 CrBltLeave(pBlitter);
995}
996
997void renderspuVBoxCompositorSet( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor)
998{
999 int rc;
1000 /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
1001 * no need to synch here
1002 * the lock is actually needed to ensure we're in synch with the redraw thread */
1003 if (window->pCompositor == pCompositor)
1004 return;
1005 rc = RTCritSectEnter(&window->CompositorLock);
1006 if (RT_SUCCESS(rc))
1007 {
1008 window->pCompositor = pCompositor;
1009 RTCritSectLeave(&window->CompositorLock);
1010 return;
1011 }
1012 else
1013 {
1014 crWarning("RTCritSectEnter failed rc %d", rc);
1015 }
1016}
1017
1018static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
1019{
1020 WindowInfo *window = (WindowInfo *) data1;
1021 renderspuVBoxCompositorSet(window, NULL);
1022}
1023
1024void renderspuVBoxCompositorClearAll()
1025{
1026 /* we need to clear window compositor, which is not that trivial though,
1027 * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
1028 * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
1029 * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
1030 * and the table can be modified from that thread only as well */
1031 crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
1032}
1033
1034struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
1035{
1036 int rc = RTCritSectEnter(&window->CompositorLock);
1037 if (RT_SUCCESS(rc))
1038 {
1039 VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
1040 if (pCompositor)
1041 return pCompositor;
1042
1043 /* if no compositor is set, release the lock and return */
1044 RTCritSectLeave(&window->CompositorLock);
1045 }
1046 else
1047 {
1048 crWarning("RTCritSectEnter failed rc %d", rc);
1049 }
1050 return NULL;
1051}
1052
1053int renderspuVBoxCompositorLock(WindowInfo *window)
1054{
1055 int rc = RTCritSectEnter(&window->CompositorLock);
1056 AssertRC(rc);
1057 return rc;
1058}
1059
1060int renderspuVBoxCompositorUnlock(WindowInfo *window)
1061{
1062 int rc = RTCritSectLeave(&window->CompositorLock);
1063 AssertRC(rc);
1064 return rc;
1065}
1066
1067int renderspuVBoxCompositorTryAcquire(WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
1068{
1069 int rc = RTCritSectTryEnter(&window->CompositorLock);
1070 if (RT_SUCCESS(rc))
1071 {
1072 *ppCompositor = window->pCompositor;
1073 if (*ppCompositor)
1074 return VINF_SUCCESS;
1075
1076 /* if no compositor is set, release the lock and return */
1077 RTCritSectLeave(&window->CompositorLock);
1078 rc = VERR_INVALID_STATE;
1079 }
1080 else
1081 {
1082 *ppCompositor = NULL;
1083 }
1084 return rc;
1085}
1086
1087void renderspuVBoxCompositorRelease( WindowInfo *window)
1088{
1089 int rc;
1090 Assert(window->pCompositor);
1091 if (CrVrScrCompositorIsEmpty(window->pCompositor) && RTCritSectGetRecursion(&window->CompositorLock) == 1)
1092 window->pCompositor = NULL;
1093 rc = RTCritSectLeave(&window->CompositorLock);
1094 if (!RT_SUCCESS(rc))
1095 {
1096 crWarning("RTCritSectLeave failed rc %d", rc);
1097 }
1098}
1099
1100
1101/*
1102 * Set the current raster position to the given window coordinate.
1103 */
1104static void
1105SetRasterPos( GLint winX, GLint winY )
1106{
1107 GLfloat fx, fy;
1108
1109 /* Push current matrix mode and viewport attributes */
1110 render_spu.self.PushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
1111
1112 /* Setup projection parameters */
1113 render_spu.self.MatrixMode( GL_PROJECTION );
1114 render_spu.self.PushMatrix();
1115 render_spu.self.LoadIdentity();
1116 render_spu.self.MatrixMode( GL_MODELVIEW );
1117 render_spu.self.PushMatrix();
1118 render_spu.self.LoadIdentity();
1119
1120 render_spu.self.Viewport( winX - 1, winY - 1, 2, 2 );
1121
1122 /* set the raster (window) position */
1123 /* huh ? */
1124 fx = (GLfloat) (winX - (int) winX);
1125 fy = (GLfloat) (winY - (int) winY);
1126 render_spu.self.RasterPos4f( fx, fy, 0.0, 1.0 );
1127
1128 /* restore matrices, viewport and matrix mode */
1129 render_spu.self.PopMatrix();
1130 render_spu.self.MatrixMode( GL_PROJECTION );
1131 render_spu.self.PopMatrix();
1132
1133 render_spu.self.PopAttrib();
1134}
1135
1136
1137/*
1138 * Draw the mouse pointer bitmap at (x,y) in window coords.
1139 */
1140static void DrawCursor( GLint x, GLint y )
1141{
1142#define POINTER_WIDTH 32
1143#define POINTER_HEIGHT 32
1144 /* Somebody artistic could probably do better here */
1145 static const char *pointerImage[POINTER_HEIGHT] =
1146 {
1147 "XX..............................",
1148 "XXXX............................",
1149 ".XXXXX..........................",
1150 ".XXXXXXX........................",
1151 "..XXXXXXXX......................",
1152 "..XXXXXXXXXX....................",
1153 "...XXXXXXXXXXX..................",
1154 "...XXXXXXXXXXXXX................",
1155 "....XXXXXXXXXXXXXX..............",
1156 "....XXXXXXXXXXXXXXXX............",
1157 ".....XXXXXXXXXXXXXXXXX..........",
1158 ".....XXXXXXXXXXXXXXXXXXX........",
1159 "......XXXXXXXXXXXXXXXXXXXX......",
1160 "......XXXXXXXXXXXXXXXXXXXXXX....",
1161 ".......XXXXXXXXXXXXXXXXXXXXXXX..",
1162 ".......XXXXXXXXXXXXXXXXXXXXXXXX.",
1163 "........XXXXXXXXXXXXX...........",
1164 "........XXXXXXXX.XXXXX..........",
1165 ".........XXXXXX...XXXXX.........",
1166 ".........XXXXX.....XXXXX........",
1167 "..........XXX.......XXXXX.......",
1168 "..........XX.........XXXXX......",
1169 "......................XXXXX.....",
1170 ".......................XXXXX....",
1171 "........................XXX.....",
1172 ".........................X......",
1173 "................................",
1174 "................................",
1175 "................................",
1176 "................................",
1177 "................................",
1178 "................................"
1179
1180 };
1181 static GLubyte pointerBitmap[POINTER_HEIGHT][POINTER_WIDTH / 8];
1182 static GLboolean firstCall = GL_TRUE;
1183 GLboolean lighting, depthTest, scissorTest;
1184
1185 if (firstCall) {
1186 /* Convert pointerImage into pointerBitmap */
1187 GLint i, j;
1188 for (i = 0; i < POINTER_HEIGHT; i++) {
1189 for (j = 0; j < POINTER_WIDTH; j++) {
1190 if (pointerImage[POINTER_HEIGHT - i - 1][j] == 'X') {
1191 GLubyte bit = 128 >> (j & 0x7);
1192 pointerBitmap[i][j / 8] |= bit;
1193 }
1194 }
1195 }
1196 firstCall = GL_FALSE;
1197 }
1198
1199 render_spu.self.GetBooleanv(GL_LIGHTING, &lighting);
1200 render_spu.self.GetBooleanv(GL_DEPTH_TEST, &depthTest);
1201 render_spu.self.GetBooleanv(GL_SCISSOR_TEST, &scissorTest);
1202 render_spu.self.Disable(GL_LIGHTING);
1203 render_spu.self.Disable(GL_DEPTH_TEST);
1204 render_spu.self.Disable(GL_SCISSOR_TEST);
1205 render_spu.self.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1206
1207 render_spu.self.Color3f(1, 1, 1);
1208
1209 /* save current raster pos */
1210 render_spu.self.PushAttrib(GL_CURRENT_BIT);
1211 SetRasterPos(x, y);
1212 render_spu.self.Bitmap(POINTER_WIDTH, POINTER_HEIGHT, 1.0, 31.0, 0, 0,
1213 (const GLubyte *) pointerBitmap);
1214 /* restore current raster pos */
1215 render_spu.self.PopAttrib();
1216
1217 if (lighting)
1218 render_spu.self.Enable(GL_LIGHTING);
1219 if (depthTest)
1220 render_spu.self.Enable(GL_DEPTH_TEST);
1221 if (scissorTest)
1222 render_spu.self.Enable(GL_SCISSOR_TEST);
1223}
1224
1225void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags )
1226{
1227 WindowInfo *w = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1228
1229 if (!w)
1230 {
1231 crDebug("Render SPU: SwapBuffers invalid window id: %d", window);
1232 return;
1233 }
1234
1235 if (flags & CR_SUPPRESS_SWAP_BIT)
1236 {
1237 render_spu.self.Finish();
1238 return;
1239 }
1240
1241 if (render_spu.drawCursor)
1242 DrawCursor( render_spu.cursorX, render_spu.cursorY );
1243
1244 if (render_spu.swap_master_url)
1245 DoSync();
1246
1247 renderspu_SystemSwapBuffers( w, flags );
1248}
1249
1250
1251/*
1252 * Barrier functions
1253 * Normally, we'll have a crserver somewhere that handles the barrier calls.
1254 * However, if we're running the render SPU on the client node, then we
1255 * should handle barriers here. The threadtest demo illustrates this.
1256 * If we have N threads calling using this SPU we need these barrier
1257 * functions to synchronize them.
1258 */
1259
1260static void RENDER_APIENTRY renderspuBarrierCreateCR( GLuint name, GLuint count )
1261{
1262 Barrier *b;
1263
1264 if (render_spu.ignore_papi)
1265 return;
1266
1267 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1268 if (b) {
1269 /* HACK -- this allows everybody to create a barrier, and all
1270 but the first creation are ignored, assuming the count
1271 match. */
1272 if ( b->count != count ) {
1273 crError( "Render SPU: Barrier name=%u created with count=%u, but already "
1274 "exists with count=%u", name, count, b->count );
1275 }
1276 }
1277 else {
1278 b = (Barrier *) crAlloc( sizeof(Barrier) );
1279 b->count = count;
1280 crInitBarrier( &b->barrier, count );
1281 crHashtableAdd( render_spu.barrierHash, name, b );
1282 }
1283}
1284
1285static void RENDER_APIENTRY renderspuBarrierDestroyCR( GLuint name )
1286{
1287 if (render_spu.ignore_papi)
1288 return;
1289 crHashtableDelete( render_spu.barrierHash, name, crFree );
1290}
1291
1292static void RENDER_APIENTRY renderspuBarrierExecCR( GLuint name )
1293{
1294 Barrier *b;
1295
1296 if (render_spu.ignore_papi)
1297 return;
1298
1299 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1300 if (b) {
1301 crWaitBarrier( &(b->barrier) );
1302 }
1303 else {
1304 crWarning("Render SPU: Bad barrier name %d in BarrierExec()", name);
1305 }
1306}
1307
1308
1309/*
1310 * Semaphore functions
1311 * XXX we should probably implement these too, for the same reason as
1312 * barriers (see above).
1313 */
1314
1315static void RENDER_APIENTRY renderspuSemaphoreCreateCR( GLuint name, GLuint count )
1316{
1317 (void) name;
1318 (void) count;
1319}
1320
1321static void RENDER_APIENTRY renderspuSemaphoreDestroyCR( GLuint name )
1322{
1323 (void) name;
1324}
1325
1326static void RENDER_APIENTRY renderspuSemaphorePCR( GLuint name )
1327{
1328 (void) name;
1329}
1330
1331static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
1332{
1333 (void) name;
1334}
1335
1336
1337/*
1338 * Misc functions
1339 */
1340void renderspuSetDefaultSharedContext(ContextInfo *pCtx)
1341{
1342 if (pCtx == render_spu.defaultSharedContext)
1343 return;
1344
1345 renderspu_SystemDefaultSharedContextChanged(render_spu.defaultSharedContext, pCtx);
1346
1347 if (render_spu.defaultSharedContext)
1348 renderspuContextRelease(render_spu.defaultSharedContext);
1349
1350 if (pCtx)
1351 renderspuContextRetain(pCtx);
1352 render_spu.defaultSharedContext = pCtx;
1353}
1354
1355
1356static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
1357{
1358
1359 switch (target)
1360 {
1361 case GL_HH_SET_DEFAULT_SHARED_CTX:
1362 {
1363 ContextInfo * pCtx = NULL;
1364 if (value)
1365 pCtx = (ContextInfo *)crHashtableSearch(render_spu.contextTable, value);
1366 else
1367 crWarning("invalid default shared context id %d", value);
1368
1369 renderspuSetDefaultSharedContext(pCtx);
1370 break;
1371 }
1372 default:
1373// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
1374 break;
1375 }
1376}
1377
1378static void RENDER_APIENTRY
1379renderspuChromiumParameterfCR(GLenum target, GLfloat value)
1380{
1381 (void) target;
1382 (void) value;
1383
1384#if 0
1385 switch (target) {
1386 default:
1387 crWarning("Unhandled target in renderspuChromiumParameterfCR()");
1388 break;
1389 }
1390#endif
1391}
1392
1393
1394static void RENDER_APIENTRY
1395renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
1396 const GLvoid *values)
1397{
1398 int client_num;
1399 unsigned short port;
1400 CRMessage *msg, pingback;
1401 unsigned char *privbuf = NULL;
1402
1403 switch (target) {
1404
1405 case GL_GATHER_CONNECT_CR:
1406 if (render_spu.gather_userbuf_size)
1407 privbuf = (unsigned char *)crAlloc(1024*768*4);
1408
1409 port = ((GLint *) values)[0];
1410
1411 if (render_spu.gather_conns == NULL)
1412 render_spu.gather_conns = crAlloc(render_spu.server->numClients*sizeof(CRConnection *));
1413 else
1414 {
1415 crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
1416 }
1417
1418 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1419 {
1420 switch (render_spu.server->clients[client_num]->conn->type)
1421 {
1422 case CR_TCPIP:
1423 crDebug("Render SPU: AcceptClient from %s on %d",
1424 render_spu.server->clients[client_num]->conn->hostname, render_spu.gather_port);
1425 render_spu.gather_conns[client_num] =
1426 crNetAcceptClient("tcpip", NULL, port, 1024*1024, 1);
1427 break;
1428
1429 case CR_GM:
1430 render_spu.gather_conns[client_num] =
1431 crNetAcceptClient("gm", NULL, port, 1024*1024, 1);
1432 break;
1433
1434 default:
1435 crError("Render SPU: Unknown Network Type to Open Gather Connection");
1436 }
1437
1438
1439 if (render_spu.gather_userbuf_size)
1440 {
1441 render_spu.gather_conns[client_num]->userbuf = privbuf;
1442 render_spu.gather_conns[client_num]->userbuf_len = render_spu.gather_userbuf_size;
1443 }
1444 else
1445 {
1446 render_spu.gather_conns[client_num]->userbuf = NULL;
1447 render_spu.gather_conns[client_num]->userbuf_len = 0;
1448 }
1449
1450 if (render_spu.gather_conns[client_num])
1451 {
1452 crDebug("Render SPU: success! from %s", render_spu.gather_conns[client_num]->hostname);
1453 }
1454 }
1455
1456 break;
1457
1458 case GL_GATHER_DRAWPIXELS_CR:
1459 pingback.header.type = CR_MESSAGE_OOB;
1460
1461 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1462 {
1463 crNetGetMessage(render_spu.gather_conns[client_num], &msg);
1464 if (msg->header.type == CR_MESSAGE_GATHER)
1465 {
1466 crNetFree(render_spu.gather_conns[client_num], msg);
1467 }
1468 else
1469 {
1470 crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
1471 client_num, render_spu.server->numClients-1);
1472 }
1473 }
1474
1475 /*
1476 * We're only hitting the case if we're not actually calling
1477 * child.SwapBuffers from readback, so a switch about which
1478 * call to DoSync() we really want [this one, or the one
1479 * in SwapBuffers above] is not necessary -- karl
1480 */
1481
1482 if (render_spu.swap_master_url)
1483 DoSync();
1484
1485 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1486 crNetSend(render_spu.gather_conns[client_num], NULL, &pingback,
1487 sizeof(CRMessageHeader));
1488
1489 render_spu.self.RasterPos2i(((GLint *)values)[0], ((GLint *)values)[1]);
1490 render_spu.self.DrawPixels( ((GLint *)values)[2], ((GLint *)values)[3],
1491 ((GLint *)values)[4], ((GLint *)values)[5],
1492 render_spu.gather_conns[0]->userbuf);
1493
1494
1495 render_spu.self.SwapBuffers(((GLint *)values)[6], 0);
1496 break;
1497
1498 case GL_CURSOR_POSITION_CR:
1499 if (type == GL_INT && count == 2) {
1500 render_spu.cursorX = ((GLint *) values)[0];
1501 render_spu.cursorY = ((GLint *) values)[1];
1502 crDebug("Render SPU: GL_CURSOR_POSITION_CR (%d, %d)", render_spu.cursorX, render_spu.cursorY);
1503 }
1504 else {
1505 crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
1506 }
1507 break;
1508
1509 case GL_WINDOW_SIZE_CR:
1510 /* XXX this is old code that should be removed.
1511 * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
1512 */
1513 {
1514 GLint w, h;
1515 WindowInfo *window;
1516 CRASSERT(type == GL_INT);
1517 CRASSERT(count == 2);
1518 CRASSERT(values);
1519 w = ((GLint*)values)[0];
1520 h = ((GLint*)values)[1];
1521 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
1522 if (window)
1523 {
1524 renderspu_SystemWindowSize(window, w, h);
1525 }
1526 }
1527 break;
1528
1529 default:
1530#if 0
1531 crWarning("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target);
1532#endif
1533 break;
1534 }
1535}
1536
1537
1538static void RENDER_APIENTRY
1539renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
1540 GLsizei count, GLvoid *values)
1541{
1542 switch (target) {
1543 case GL_WINDOW_SIZE_CR:
1544 {
1545 GLint x, y, w, h, *size = (GLint *) values;
1546 WindowInfo *window;
1547 CRASSERT(type == GL_INT);
1548 CRASSERT(count == 2);
1549 CRASSERT(values);
1550 size[0] = size[1] = 0; /* default */
1551 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1552 if (window)
1553 {
1554 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1555 size[0] = w;
1556 size[1] = h;
1557 }
1558 }
1559 break;
1560 case GL_WINDOW_POSITION_CR:
1561 /* return window position, as a screen coordinate */
1562 {
1563 GLint *pos = (GLint *) values;
1564 GLint x, y, w, h;
1565 WindowInfo *window;
1566 CRASSERT(type == GL_INT);
1567 CRASSERT(count == 2);
1568 CRASSERT(values);
1569 pos[0] = pos[1] = 0; /* default */
1570 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1571 if (window)
1572 {
1573 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1574 pos[0] = x;/*window->x;*/
1575 pos[1] = y;/*window->y;*/
1576 }
1577 }
1578 break;
1579 case GL_MAX_WINDOW_SIZE_CR:
1580 {
1581 GLint *maxSize = (GLint *) values;
1582 WindowInfo *window;
1583 CRASSERT(type == GL_INT);
1584 CRASSERT(count == 2);
1585 CRASSERT(values);
1586 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1587 if (window)
1588 {
1589 renderspu_SystemGetMaxWindowSize(window, maxSize + 0, maxSize + 1);
1590 }
1591 }
1592 break;
1593 case GL_WINDOW_VISIBILITY_CR:
1594 {
1595 GLint *vis = (GLint *) values;
1596 WindowInfo *window;
1597 CRASSERT(type == GL_INT);
1598 CRASSERT(count == 1);
1599 CRASSERT(values);
1600 vis[0] = 0; /* default */
1601 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1602 if (window)
1603 {
1604 vis[0] = window->visible;
1605 }
1606 }
1607 break;
1608 default:
1609 ; /* nothing - silence compiler */
1610 }
1611}
1612
1613
1614static void RENDER_APIENTRY
1615renderspuBoundsInfoCR( CRrecti *bounds, GLbyte *payload, GLint len,
1616 GLint num_opcodes )
1617{
1618 (void) bounds;
1619 (void) payload;
1620 (void) len;
1621 (void) num_opcodes;
1622 /* draw the bounding box */
1623 if (render_spu.draw_bbox) {
1624 GET_CONTEXT(context);
1625 WindowInfo *window = context->currentWindow;
1626 GLint x, y, w, h;
1627
1628 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1629
1630 render_spu.self.PushMatrix();
1631 render_spu.self.LoadIdentity();
1632 render_spu.self.MatrixMode(GL_PROJECTION);
1633 render_spu.self.PushMatrix();
1634 render_spu.self.LoadIdentity();
1635 render_spu.self.Ortho(0, w, 0, h, -1, 1);
1636 render_spu.self.Color3f(1, 1, 1);
1637 render_spu.self.Begin(GL_LINE_LOOP);
1638 render_spu.self.Vertex2i(bounds->x1, bounds->y1);
1639 render_spu.self.Vertex2i(bounds->x2, bounds->y1);
1640 render_spu.self.Vertex2i(bounds->x2, bounds->y2);
1641 render_spu.self.Vertex2i(bounds->x1, bounds->y2);
1642 render_spu.self.End();
1643 render_spu.self.PopMatrix();
1644 render_spu.self.MatrixMode(GL_MODELVIEW);
1645 render_spu.self.PopMatrix();
1646 }
1647}
1648
1649
1650static void RENDER_APIENTRY
1651renderspuWriteback( GLint *writeback )
1652{
1653 (void) writeback;
1654}
1655
1656
1657static void
1658remove_trailing_space(char *s)
1659{
1660 int k = crStrlen(s);
1661 while (k > 0 && s[k-1] == ' ')
1662 k--;
1663 s[k] = 0;
1664}
1665
1666static const GLubyte * RENDER_APIENTRY
1667renderspuGetString(GLenum pname)
1668{
1669 static char tempStr[1000];
1670 GET_CONTEXT(context);
1671
1672 if (pname == GL_EXTENSIONS)
1673 {
1674 const char *nativeExt;
1675 char *crExt, *s1, *s2;
1676
1677 if (!render_spu.ws.glGetString)
1678 return NULL;
1679
1680 nativeExt = (const char *) render_spu.ws.glGetString(GL_EXTENSIONS);
1681 if (!nativeExt) {
1682 /* maybe called w/out current context. */
1683 return NULL;
1684 }
1685
1686 crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
1687 s1 = crStrIntersect(nativeExt, crExt);
1688 remove_trailing_space(s1);
1689 s2 = crStrjoin3(s1, " ", crChromiumExtensions);
1690 remove_trailing_space(s2);
1691 crFree(crExt);
1692 crFree(s1);
1693 if (context->extensionString)
1694 crFree(context->extensionString);
1695 context->extensionString = s2;
1696 return (const GLubyte *) s2;
1697 }
1698 else if (pname == GL_VENDOR)
1699 return (const GLubyte *) CR_VENDOR;
1700 else if (pname == GL_VERSION)
1701 return render_spu.ws.glGetString(GL_VERSION);
1702 else if (pname == GL_RENDERER) {
1703#ifdef VBOX
1704 snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1705#else
1706 sprintf(tempStr, "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1707#endif
1708 return (const GLubyte *) tempStr;
1709 }
1710#ifdef CR_OPENGL_VERSION_2_0
1711 else if (pname == GL_SHADING_LANGUAGE_VERSION)
1712 return render_spu.ws.glGetString(GL_SHADING_LANGUAGE_VERSION);
1713#endif
1714#ifdef GL_CR_real_vendor_strings
1715 else if (pname == GL_REAL_VENDOR)
1716 return render_spu.ws.glGetString(GL_VENDOR);
1717 else if (pname == GL_REAL_VERSION)
1718 return render_spu.ws.glGetString(GL_VERSION);
1719 else if (pname == GL_REAL_RENDERER)
1720 return render_spu.ws.glGetString(GL_RENDERER);
1721 else if (pname == GL_REAL_EXTENSIONS)
1722 return render_spu.ws.glGetString(GL_EXTENSIONS);
1723#endif
1724 else
1725 return NULL;
1726}
1727
1728static void renderspuReparentWindowCB(unsigned long key, void *data1, void *data2)
1729{
1730 WindowInfo *pWindow = (WindowInfo *)data1;
1731
1732 renderspu_SystemReparentWindow(pWindow);
1733}
1734
1735DECLEXPORT(void) renderspuReparentWindow(GLint window)
1736{
1737 WindowInfo *pWindow;
1738 CRASSERT(window >= 0);
1739
1740 pWindow = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1741
1742 if (!pWindow)
1743 {
1744 crDebug("Render SPU: Attempt to reparent invalid window (%d)", window);
1745 return;
1746 }
1747
1748 renderspu_SystemReparentWindow(pWindow);
1749
1750 /* special case: reparent all internal windows as well */
1751 if (window == CR_RENDER_DEFAULT_WINDOW_ID)
1752 {
1753 crHashtableWalk(render_spu.dummyWindowTable, renderspuReparentWindowCB, NULL);
1754 }
1755}
1756
1757#define FILLIN( NAME, FUNC ) \
1758 table[i].name = crStrdup(NAME); \
1759 table[i].fn = (SPUGenericFunction) FUNC; \
1760 i++;
1761
1762
1763/* These are the functions which the render SPU implements, not OpenGL.
1764 */
1765int
1766renderspuCreateFunctions(SPUNamedFunctionTable table[])
1767{
1768 int i = 0;
1769 FILLIN( "SwapBuffers", renderspuSwapBuffers );
1770 FILLIN( "CreateContext", renderspuCreateContext );
1771 FILLIN( "DestroyContext", renderspuDestroyContext );
1772 FILLIN( "MakeCurrent", renderspuMakeCurrent );
1773 FILLIN( "WindowCreate", renderspuWindowCreate );
1774 FILLIN( "WindowDestroy", renderspuWindowDestroy );
1775 FILLIN( "WindowSize", renderspuWindowSize );
1776 FILLIN( "WindowPosition", renderspuWindowPosition );
1777 FILLIN( "WindowVisibleRegion", renderspuWindowVisibleRegion );
1778 FILLIN( "WindowShow", renderspuWindowShow );
1779 FILLIN( "BarrierCreateCR", renderspuBarrierCreateCR );
1780 FILLIN( "BarrierDestroyCR", renderspuBarrierDestroyCR );
1781 FILLIN( "BarrierExecCR", renderspuBarrierExecCR );
1782 FILLIN( "BoundsInfoCR", renderspuBoundsInfoCR );
1783 FILLIN( "SemaphoreCreateCR", renderspuSemaphoreCreateCR );
1784 FILLIN( "SemaphoreDestroyCR", renderspuSemaphoreDestroyCR );
1785 FILLIN( "SemaphorePCR", renderspuSemaphorePCR );
1786 FILLIN( "SemaphoreVCR", renderspuSemaphoreVCR );
1787 FILLIN( "Writeback", renderspuWriteback );
1788 FILLIN( "ChromiumParameteriCR", renderspuChromiumParameteriCR );
1789 FILLIN( "ChromiumParameterfCR", renderspuChromiumParameterfCR );
1790 FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
1791 FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
1792 FILLIN( "GetString", renderspuGetString );
1793 FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
1794
1795 return i;
1796}
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