VirtualBox

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

Last change on this file since 52494 was 52494, checked in by vboxsync, 10 years ago

crOpenGL/osx: more sync with main thread

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 56.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_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->pCompositor = NULL;
453
454 window->BltInfo.Base.id = id;
455
456 window->x = render_spu.defaultX;
457 window->y = render_spu.defaultY;
458 window->BltInfo.width = render_spu.defaultWidth;
459 window->BltInfo.height = render_spu.defaultHeight;
460
461 /* Set window->title, replacing %i with the window ID number */
462 {
463 const char *s = crStrstr(render_spu.window_title, "%i");
464 if (s) {
465 int i, j, k;
466 window->title = crAlloc(crStrlen(render_spu.window_title) + 10);
467 for (i = 0; render_spu.window_title[i] != '%'; i++)
468 window->title[i] = render_spu.window_title[i];
469 k = sprintf(window->title + i, "%d", window->BltInfo.Base.id);
470 CRASSERT(k < 10);
471 i++; /* skip the 'i' after the '%' */
472 j = i + k;
473 for (; (window->title[j] = s[i]) != 0; i++, j++)
474 ;
475 }
476 else {
477 window->title = crStrdup(render_spu.window_title);
478 }
479 }
480
481 window->BltInfo.Base.visualBits = visual->visAttribs;
482
483
484 /*
485 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
486 */
487 /* Have GLX/WGL/AGL create the window */
488 if (!renderspu_SystemVBoxCreateWindow( visual, showIt, window ))
489 {
490 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
491 return GL_FALSE;
492 }
493
494 window->visible = !!showIt;
495
496 CRASSERT(window->visual == visual);
497 return GL_TRUE;
498}
499
500/*
501 * Window functions
502 */
503GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
504{
505 VisualInfo *visual;
506
507 crMemset(pWindow, 0, sizeof (*pWindow));
508
509 if (!dpyName || crStrlen(render_spu.display_string) > 0)
510 dpyName = render_spu.display_string;
511
512 visual = renderspuFindVisual( dpyName, visBits );
513 if (!visual)
514 {
515 crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
516 return GL_FALSE;
517 }
518
519 /*
520 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
521 */
522 /* Have GLX/WGL/AGL create the window */
523 if (!renderspuWindowInitWithVisual( pWindow, visual, 0, id ))
524 {
525 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
526 return GL_FALSE;
527 }
528
529 return GL_TRUE;
530}
531
532GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id )
533{
534 WindowInfo *window;
535
536 if (id <= 0)
537 {
538 id = (GLint)crHashtableAllocKeys(render_spu.windowTable, 1);
539 if (id <= 0)
540 {
541 crWarning("failed to allocate window id");
542 return -1;
543 }
544 }
545 else
546 {
547 if (crHashtableIsKeyUsed(render_spu.windowTable, id))
548 {
549 crWarning("the specified window key %d is in use", id);
550 return -1;
551 }
552 }
553
554 /* Allocate WindowInfo */
555 window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
556 if (!window)
557 {
558 crWarning( "Render SPU: Couldn't create a window" );
559 return -1;
560 }
561
562 if (!renderspuWindowInit(window, dpyName, visBits, id))
563 {
564 crWarning("renderspuWindowInit failed");
565 crFree(window);
566 return -1;
567 }
568
569 crHashtableAdd(render_spu.windowTable, id, window);
570 return window->BltInfo.Base.id;
571}
572
573GLint RENDER_APIENTRY
574renderspuWindowCreate( const char *dpyName, GLint visBits )
575{
576 return renderspuWindowCreateEx( dpyName, visBits, 0 );
577}
578
579static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
580{
581 ContextInfo *pCtx = (ContextInfo *) data1;
582 WindowInfo *pWindow = data2;
583 (void) key;
584
585 if (pCtx->currentWindow==pWindow)
586 {
587 WindowInfo* pDummy = renderspuGetDummyWindow(pCtx->BltInfo.Base.visualBits);
588 if (pDummy)
589 {
590 renderspuPerformMakeCurrent(pDummy, 0, pCtx);
591 }
592 else
593 {
594 crWarning("failed to get dummy window");
595 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
596 }
597 }
598}
599
600void renderspuWindowTermBase( WindowInfo *window )
601{
602 renderspuVBoxCompositorSet(window, NULL);
603 renderspuVBoxPresentBlitterCleanup(window);
604 renderspu_SystemDestroyWindow( window );
605 RTCritSectDelete(&window->CompositorLock);
606}
607
608void renderspuWindowTerm( WindowInfo *window )
609{
610 GET_CONTEXT(pOldCtx);
611 WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
612 CRASSERT(!pOldCtx == !pOldWindow);
613 /* ensure no concurrent draws can take place */
614 renderspuWindowTermBase(window);
615 /* check if this window is bound to some ctx. Note: window pointer is already freed here */
616 crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
617 /* restore current context */
618 {
619 GET_CONTEXT(pNewCtx);
620 WindowInfo * pNewWindow = pNewCtx ? pNewCtx->currentWindow : NULL;
621 CRASSERT(!pNewCtx == !pNewWindow);
622
623 if (pOldWindow == window)
624 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
625 else if (pNewCtx != pOldCtx || pOldWindow != pNewWindow)
626 {
627 if (pOldCtx)
628 renderspuPerformMakeCurrent(pOldWindow, 0, pOldCtx);
629 else
630 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
631 }
632 }
633}
634
635void
636RENDER_APIENTRY renderspuWindowDestroy( GLint win )
637{
638 WindowInfo *window;
639
640 CRASSERT(win >= 0);
641 if (win == CR_RENDER_DEFAULT_WINDOW_ID)
642 {
643 crWarning("request to destroy a default mural, ignoring");
644 return;
645 }
646 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
647 if (window) {
648 crDebug("Render SPU: Destroy window (%d)", win);
649 renderspuWindowTerm( window );
650
651 /* remove window info from hash table, and free it */
652 crHashtableDelete(render_spu.windowTable, win, crFree);
653
654 }
655 else {
656 crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
657 }
658}
659
660
661static void RENDER_APIENTRY
662renderspuWindowSize( GLint win, GLint w, GLint h )
663{
664 WindowInfo *window;
665 CRASSERT(win >= 0);
666 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
667 if (window) {
668 if (w != window->BltInfo.width
669 || h != window->BltInfo.height)
670 {
671 /* window is resized, compositor data is no longer valid
672 * this set also ensures all redraw operations are done in the redraw thread
673 * and that no redraw is started until new Present request comes containing a valid presentation data */
674 renderspuVBoxCompositorSet( window, NULL);
675 renderspu_SystemWindowSize( window, w, h );
676 window->BltInfo.width = w;
677 window->BltInfo.height = h;
678 }
679 }
680 else {
681 crDebug("Render SPU: Attempt to resize invalid window (%d)", win);
682 }
683}
684
685
686static void RENDER_APIENTRY
687renderspuWindowPosition( GLint win, GLint x, GLint y )
688{
689 if (!render_spu.ignore_window_moves) {
690 WindowInfo *window;
691 CRASSERT(win >= 0);
692 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
693 if (window) {
694 renderspu_SystemWindowPosition( window, x, y );
695 window->x = x;
696 window->y = y;
697 }
698 else {
699 crDebug("Render SPU: Attempt to move invalid window (%d)", win);
700 }
701 }
702}
703
704#ifdef DEBUG_misha
705# define CR_DBG_DUMP_VISIBLE_REGIONS
706#endif
707
708#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
709static void renderspuDbgDumpVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
710{
711 GLint i;
712 const RTRECT *pRtRects = (const RTRECT *)((const void*)pRects);
713
714 crInfo("Window %d, Vidible Regions%d", win, cRects);
715 for (i = 0; i < cRects; ++i)
716 {
717 crInfo("%d: (%d,%d), (%d,%d)", i, pRtRects[i].xLeft, pRtRects[i].yTop, pRtRects[i].xRight, pRtRects[i].yBottom);
718 }
719 crInfo("======");
720}
721#endif
722
723static void RENDER_APIENTRY
724renderspuWindowVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
725{
726 WindowInfo *window;
727 CRASSERT(win >= 0);
728
729#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
730 renderspuDbgDumpVisibleRegion(win, cRects, pRects);
731#endif
732
733 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
734 if (window) {
735 renderspu_SystemWindowVisibleRegion( window, cRects, pRects );
736 }
737 else {
738 crWarning("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
739 }
740}
741
742static void RENDER_APIENTRY
743renderspuWindowShow( GLint win, GLint flag )
744{
745 WindowInfo *window;
746 CRASSERT(win >= 0);
747 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
748 if (window) {
749 GLboolean visible;
750 if (window->nativeWindow) {
751 /* We're rendering back to the native app window instead of the
752 * new window which we (the Render SPU) created earlier.
753 * So, we never want to show the Render SPU's window.
754 */
755 flag = 0;
756 }
757
758 visible = !!flag;
759
760// if (window->visible != visible)
761 {
762 renderspu_SystemShowWindow( window, visible );
763 window->visible = visible;
764 }
765 }
766 else {
767 crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win);
768 }
769}
770
771static void RENDER_APIENTRY
772renderspuVBoxPresentComposition( GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
773{
774 WindowInfo *window;
775 CRASSERT(win >= 0);
776 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
777 if (window) {
778 if (renderspuVBoxCompositorSet(window, pCompositor))
779 {
780 renderspu_SystemVBoxPresentComposition(window, pChangedEntry);
781 }
782 }
783 else {
784 crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win);
785 }
786}
787
788void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
789{
790 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
791 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
792 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
793 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
794 {
795 uint32_t cRegions;
796 const RTRECT *paSrcRegions, *paDstRegions;
797 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
798 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
799 if (RT_SUCCESS(rc))
800 {
801 uint32_t i;
802 for (i = 0; i < cRegions; ++i)
803 {
804 RTRECT DstRect;
805 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
806 DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
807 DstRect.yTop = paDstRegions[i].yTop * scaleY;
808 DstRect.xRight = paDstRegions[i].xRight * scaleX;
809 DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
810 CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), &paSrcRegions[i], &DstRect, 1, fFlags);
811 }
812 }
813 else
814 {
815 crWarning("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
816 }
817 }
818}
819
820void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
821{
822 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
823 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
824 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
825 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
826 {
827 uint32_t cRegions;
828 const RTRECT *paSrcRegions, *paDstRegions;
829 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
830 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
831 if (RT_SUCCESS(rc))
832 {
833 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
834 CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), paSrcRegions, paDstRegions, cRegions, fFlags);
835 }
836 else
837 {
838 crWarning("Blit: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
839 }
840 }
841}
842
843void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
844{
845 if (!window->pBlitter)
846 return;
847
848 if (render_spu.blitterTable)
849 {
850 const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
851 if (pBltInfo && pBltInfo->Base.id == window->BltInfo.Base.id)
852 {
853 CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
854 }
855 }
856 else
857 {
858 CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
859 CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
860 CrBltTerm(window->pBlitter);
861 }
862 window->pBlitter = NULL;
863}
864
865PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
866{
867 PCR_BLITTER pBlitter = window->pBlitter;
868 if (!pBlitter)
869 {
870 if (render_spu.blitterTable)
871 {
872 crHashtableLock(render_spu.blitterTable);
873 pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
874 }
875
876 if (!pBlitter)
877 {
878 int rc;
879 ContextInfo * pDefaultCtxInfo;
880
881 pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
882 if (!pBlitter)
883 {
884 crWarning("failed to allocate blitter");
885 return NULL;
886 }
887
888 pDefaultCtxInfo = renderspuDefaultSharedContextAcquire();
889 if (!pDefaultCtxInfo)
890 {
891 crWarning("no default ctx info!");
892 crFree(pBlitter);
893 return NULL;
894 }
895
896 rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, &render_spu.blitterDispatch);
897
898 /* we can release it either way, since it will be retained when used as a shared context */
899 renderspuDefaultSharedContextRelease(pDefaultCtxInfo);
900
901 if (!RT_SUCCESS(rc))
902 {
903 crWarning("CrBltInit failed, rc %d", rc);
904 crFree(pBlitter);
905 return NULL;
906 }
907
908 if (render_spu.blitterTable)
909 {
910 crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
911 }
912 }
913
914 if (render_spu.blitterTable)
915 crHashtableUnlock(render_spu.blitterTable);
916
917 Assert(pBlitter);
918 window->pBlitter = pBlitter;
919 }
920
921 CrBltMuralSetCurrentInfo(pBlitter, &window->BltInfo);
922 return pBlitter;
923}
924
925int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
926{
927 int rc;
928
929 CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
930
931 rc = CrBltEnter(pBlitter);
932 if (!RT_SUCCESS(rc))
933 {
934 crWarning("CrBltEnter failed, rc %d", rc);
935 return rc;
936 }
937 return VINF_SUCCESS;
938}
939
940PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData, bool fRedraw )
941{
942 PCR_BLITTER pBlitter = fRedraw ? window->pBlitter : renderspuVBoxPresentBlitterGet(window);
943 if (pBlitter)
944 {
945 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
946 if (RT_SUCCESS(rc))
947 {
948 return pBlitter;
949 }
950 }
951 return NULL;
952}
953
954PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
955{
956 if (!window->pBlitter)
957 {
958 const struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
959 /* just use compositor lock to synchronize */
960 pTmpCompositor = renderspuVBoxCompositorAcquire(window);
961 CRASSERT(pTmpCompositor);
962 if (pTmpCompositor)
963 {
964 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet( window );
965 if (pBlitter)
966 {
967 if (!CrBltIsEverEntered(pBlitter))
968 {
969 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
970 if (RT_SUCCESS(rc))
971 {
972 CrBltLeave(pBlitter);
973 }
974 else
975 {
976 crWarning("renderspuVBoxPresentBlitterEnter failed rc %d", rc);
977 }
978 }
979 }
980 else
981 {
982 crWarning("renderspuVBoxPresentBlitterGet failed");
983 }
984
985 renderspuVBoxCompositorRelease(window);
986 }
987 else
988 {
989 crWarning("renderspuVBoxCompositorAcquire failed");
990 }
991 }
992 return window->pBlitter;
993}
994
995void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor,
996 const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData,
997 bool fRedraw )
998{
999 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData, fRedraw);
1000 if (!pBlitter)
1001 return;
1002
1003 renderspuVBoxCompositorBlit(pCompositor, pBlitter);
1004
1005 renderspu_SystemSwapBuffers(window, 0);
1006
1007 CrBltLeave(pBlitter);
1008}
1009
1010GLboolean renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
1011{
1012 int rc;
1013 GLboolean fEmpty = pCompositor && CrVrScrCompositorIsEmpty(pCompositor);
1014 GLboolean fNeedPresent;
1015
1016 /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
1017 * no need to synch here
1018 * the lock is actually needed to ensure we're in synch with the redraw thread */
1019 if (window->pCompositor == pCompositor && !fEmpty)
1020 return !!pCompositor;
1021
1022 rc = RTCritSectEnter(&window->CompositorLock);
1023 if (RT_SUCCESS(rc))
1024 {
1025 if (!fEmpty)
1026 fNeedPresent = !!pCompositor;
1027 else
1028 {
1029 fNeedPresent = renderspu_SystemWindowNeedEmptyPresent(window);
1030 pCompositor = NULL;
1031 }
1032
1033 window->pCompositor = !fEmpty ? pCompositor : NULL;
1034 RTCritSectLeave(&window->CompositorLock);
1035 return fNeedPresent;
1036 }
1037 else
1038 {
1039 WARN(("RTCritSectEnter failed rc %d", rc));
1040 }
1041
1042 return GL_FALSE;
1043}
1044
1045static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
1046{
1047 WindowInfo *window = (WindowInfo *) data1;
1048 renderspuVBoxCompositorSet(window, NULL);
1049}
1050
1051void renderspuVBoxCompositorClearAll()
1052{
1053 /* we need to clear window compositor, which is not that trivial though,
1054 * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
1055 * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
1056 * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
1057 * and the table can be modified from that thread only as well */
1058 crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
1059}
1060
1061const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
1062{
1063 int rc = RTCritSectEnter(&window->CompositorLock);
1064 if (RT_SUCCESS(rc))
1065 {
1066 const VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
1067 if (pCompositor)
1068 {
1069 Assert(!CrVrScrCompositorIsEmpty(window->pCompositor));
1070 return pCompositor;
1071 }
1072
1073 /* if no compositor is set, release the lock and return */
1074 RTCritSectLeave(&window->CompositorLock);
1075 }
1076 else
1077 {
1078 crWarning("RTCritSectEnter failed rc %d", rc);
1079 }
1080 return NULL;
1081}
1082
1083int renderspuVBoxCompositorLock(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
1084{
1085 int rc = RTCritSectEnter(&window->CompositorLock);
1086 if (RT_SUCCESS(rc))
1087 {
1088 if (ppCompositor)
1089 *ppCompositor = window->pCompositor;
1090 }
1091 else
1092 WARN(("RTCritSectEnter failed %d", rc));
1093 return rc;
1094}
1095
1096int renderspuVBoxCompositorUnlock(WindowInfo *window)
1097{
1098 int rc = RTCritSectLeave(&window->CompositorLock);
1099 AssertRC(rc);
1100 return rc;
1101}
1102
1103int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
1104{
1105 int rc = RTCritSectTryEnter(&window->CompositorLock);
1106 if (RT_SUCCESS(rc))
1107 {
1108 *ppCompositor = window->pCompositor;
1109 if (*ppCompositor)
1110 {
1111 Assert(!CrVrScrCompositorIsEmpty(window->pCompositor));
1112 return VINF_SUCCESS;
1113 }
1114
1115 /* if no compositor is set, release the lock and return */
1116 RTCritSectLeave(&window->CompositorLock);
1117 rc = VERR_INVALID_STATE;
1118 }
1119 else
1120 {
1121 *ppCompositor = NULL;
1122 }
1123 return rc;
1124}
1125
1126void renderspuVBoxCompositorRelease( WindowInfo *window)
1127{
1128 int rc;
1129 Assert(window->pCompositor);
1130 Assert(!CrVrScrCompositorIsEmpty(window->pCompositor));
1131 rc = RTCritSectLeave(&window->CompositorLock);
1132 if (!RT_SUCCESS(rc))
1133 {
1134 crWarning("RTCritSectLeave failed rc %d", rc);
1135 }
1136}
1137
1138
1139/*
1140 * Set the current raster position to the given window coordinate.
1141 */
1142static void
1143SetRasterPos( GLint winX, GLint winY )
1144{
1145 GLfloat fx, fy;
1146
1147 /* Push current matrix mode and viewport attributes */
1148 render_spu.self.PushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
1149
1150 /* Setup projection parameters */
1151 render_spu.self.MatrixMode( GL_PROJECTION );
1152 render_spu.self.PushMatrix();
1153 render_spu.self.LoadIdentity();
1154 render_spu.self.MatrixMode( GL_MODELVIEW );
1155 render_spu.self.PushMatrix();
1156 render_spu.self.LoadIdentity();
1157
1158 render_spu.self.Viewport( winX - 1, winY - 1, 2, 2 );
1159
1160 /* set the raster (window) position */
1161 /* huh ? */
1162 fx = (GLfloat) (winX - (int) winX);
1163 fy = (GLfloat) (winY - (int) winY);
1164 render_spu.self.RasterPos4f( fx, fy, 0.0, 1.0 );
1165
1166 /* restore matrices, viewport and matrix mode */
1167 render_spu.self.PopMatrix();
1168 render_spu.self.MatrixMode( GL_PROJECTION );
1169 render_spu.self.PopMatrix();
1170
1171 render_spu.self.PopAttrib();
1172}
1173
1174
1175/*
1176 * Draw the mouse pointer bitmap at (x,y) in window coords.
1177 */
1178static void DrawCursor( GLint x, GLint y )
1179{
1180#define POINTER_WIDTH 32
1181#define POINTER_HEIGHT 32
1182 /* Somebody artistic could probably do better here */
1183 static const char *pointerImage[POINTER_HEIGHT] =
1184 {
1185 "XX..............................",
1186 "XXXX............................",
1187 ".XXXXX..........................",
1188 ".XXXXXXX........................",
1189 "..XXXXXXXX......................",
1190 "..XXXXXXXXXX....................",
1191 "...XXXXXXXXXXX..................",
1192 "...XXXXXXXXXXXXX................",
1193 "....XXXXXXXXXXXXXX..............",
1194 "....XXXXXXXXXXXXXXXX............",
1195 ".....XXXXXXXXXXXXXXXXX..........",
1196 ".....XXXXXXXXXXXXXXXXXXX........",
1197 "......XXXXXXXXXXXXXXXXXXXX......",
1198 "......XXXXXXXXXXXXXXXXXXXXXX....",
1199 ".......XXXXXXXXXXXXXXXXXXXXXXX..",
1200 ".......XXXXXXXXXXXXXXXXXXXXXXXX.",
1201 "........XXXXXXXXXXXXX...........",
1202 "........XXXXXXXX.XXXXX..........",
1203 ".........XXXXXX...XXXXX.........",
1204 ".........XXXXX.....XXXXX........",
1205 "..........XXX.......XXXXX.......",
1206 "..........XX.........XXXXX......",
1207 "......................XXXXX.....",
1208 ".......................XXXXX....",
1209 "........................XXX.....",
1210 ".........................X......",
1211 "................................",
1212 "................................",
1213 "................................",
1214 "................................",
1215 "................................",
1216 "................................"
1217
1218 };
1219 static GLubyte pointerBitmap[POINTER_HEIGHT][POINTER_WIDTH / 8];
1220 static GLboolean firstCall = GL_TRUE;
1221 GLboolean lighting, depthTest, scissorTest;
1222
1223 if (firstCall) {
1224 /* Convert pointerImage into pointerBitmap */
1225 GLint i, j;
1226 for (i = 0; i < POINTER_HEIGHT; i++) {
1227 for (j = 0; j < POINTER_WIDTH; j++) {
1228 if (pointerImage[POINTER_HEIGHT - i - 1][j] == 'X') {
1229 GLubyte bit = 128 >> (j & 0x7);
1230 pointerBitmap[i][j / 8] |= bit;
1231 }
1232 }
1233 }
1234 firstCall = GL_FALSE;
1235 }
1236
1237 render_spu.self.GetBooleanv(GL_LIGHTING, &lighting);
1238 render_spu.self.GetBooleanv(GL_DEPTH_TEST, &depthTest);
1239 render_spu.self.GetBooleanv(GL_SCISSOR_TEST, &scissorTest);
1240 render_spu.self.Disable(GL_LIGHTING);
1241 render_spu.self.Disable(GL_DEPTH_TEST);
1242 render_spu.self.Disable(GL_SCISSOR_TEST);
1243 render_spu.self.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1244
1245 render_spu.self.Color3f(1, 1, 1);
1246
1247 /* save current raster pos */
1248 render_spu.self.PushAttrib(GL_CURRENT_BIT);
1249 SetRasterPos(x, y);
1250 render_spu.self.Bitmap(POINTER_WIDTH, POINTER_HEIGHT, 1.0, 31.0, 0, 0,
1251 (const GLubyte *) pointerBitmap);
1252 /* restore current raster pos */
1253 render_spu.self.PopAttrib();
1254
1255 if (lighting)
1256 render_spu.self.Enable(GL_LIGHTING);
1257 if (depthTest)
1258 render_spu.self.Enable(GL_DEPTH_TEST);
1259 if (scissorTest)
1260 render_spu.self.Enable(GL_SCISSOR_TEST);
1261}
1262
1263void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags )
1264{
1265 WindowInfo *w = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1266
1267 if (!w)
1268 {
1269 crDebug("Render SPU: SwapBuffers invalid window id: %d", window);
1270 return;
1271 }
1272
1273 if (flags & CR_SUPPRESS_SWAP_BIT)
1274 {
1275 render_spu.self.Finish();
1276 return;
1277 }
1278
1279 if (render_spu.drawCursor)
1280 DrawCursor( render_spu.cursorX, render_spu.cursorY );
1281
1282 if (render_spu.swap_master_url)
1283 DoSync();
1284
1285 renderspu_SystemSwapBuffers( w, flags );
1286}
1287
1288
1289/*
1290 * Barrier functions
1291 * Normally, we'll have a crserver somewhere that handles the barrier calls.
1292 * However, if we're running the render SPU on the client node, then we
1293 * should handle barriers here. The threadtest demo illustrates this.
1294 * If we have N threads calling using this SPU we need these barrier
1295 * functions to synchronize them.
1296 */
1297
1298static void RENDER_APIENTRY renderspuBarrierCreateCR( GLuint name, GLuint count )
1299{
1300 Barrier *b;
1301
1302 if (render_spu.ignore_papi)
1303 return;
1304
1305 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1306 if (b) {
1307 /* HACK -- this allows everybody to create a barrier, and all
1308 but the first creation are ignored, assuming the count
1309 match. */
1310 if ( b->count != count ) {
1311 crError( "Render SPU: Barrier name=%u created with count=%u, but already "
1312 "exists with count=%u", name, count, b->count );
1313 }
1314 }
1315 else {
1316 b = (Barrier *) crAlloc( sizeof(Barrier) );
1317 b->count = count;
1318 crInitBarrier( &b->barrier, count );
1319 crHashtableAdd( render_spu.barrierHash, name, b );
1320 }
1321}
1322
1323static void RENDER_APIENTRY renderspuBarrierDestroyCR( GLuint name )
1324{
1325 if (render_spu.ignore_papi)
1326 return;
1327 crHashtableDelete( render_spu.barrierHash, name, crFree );
1328}
1329
1330static void RENDER_APIENTRY renderspuBarrierExecCR( GLuint name )
1331{
1332 Barrier *b;
1333
1334 if (render_spu.ignore_papi)
1335 return;
1336
1337 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1338 if (b) {
1339 crWaitBarrier( &(b->barrier) );
1340 }
1341 else {
1342 crWarning("Render SPU: Bad barrier name %d in BarrierExec()", name);
1343 }
1344}
1345
1346
1347/*
1348 * Semaphore functions
1349 * XXX we should probably implement these too, for the same reason as
1350 * barriers (see above).
1351 */
1352
1353static void RENDER_APIENTRY renderspuSemaphoreCreateCR( GLuint name, GLuint count )
1354{
1355 (void) name;
1356 (void) count;
1357}
1358
1359static void RENDER_APIENTRY renderspuSemaphoreDestroyCR( GLuint name )
1360{
1361 (void) name;
1362}
1363
1364static void RENDER_APIENTRY renderspuSemaphorePCR( GLuint name )
1365{
1366 (void) name;
1367}
1368
1369static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
1370{
1371 (void) name;
1372}
1373
1374
1375/*
1376 * Misc functions
1377 */
1378void renderspuSetDefaultSharedContext(ContextInfo *pCtx)
1379{
1380 if (pCtx == render_spu.defaultSharedContext)
1381 return;
1382
1383 renderspu_SystemDefaultSharedContextChanged(render_spu.defaultSharedContext, pCtx);
1384
1385 if (render_spu.defaultSharedContext)
1386 renderspuContextRelease(render_spu.defaultSharedContext);
1387
1388 if (pCtx)
1389 renderspuContextRetain(pCtx);
1390 render_spu.defaultSharedContext = pCtx;
1391}
1392
1393static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
1394{
1395 switch (target)
1396 {
1397 case GL_HH_SET_DEFAULT_SHARED_CTX:
1398 {
1399 ContextInfo * pCtx = NULL;
1400 if (value)
1401 pCtx = (ContextInfo *)crHashtableSearch(render_spu.contextTable, value);
1402 else
1403 crWarning("invalid default shared context id %d", value);
1404
1405 renderspuSetDefaultSharedContext(pCtx);
1406 break;
1407 }
1408 case GL_HH_RENDERTHREAD_INFORM:
1409 {
1410 if (value)
1411 {
1412 int rc = renderspuDefaultCtxInit();
1413 if (RT_FAILURE(rc))
1414 {
1415 WARN(("renderspuDefaultCtxInit failed"));
1416 break;
1417 }
1418 }
1419 else
1420 {
1421 renderspuCleanupBase(false);
1422 }
1423 break;
1424 }
1425 default:
1426// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
1427 break;
1428 }
1429}
1430
1431static void RENDER_APIENTRY
1432renderspuChromiumParameterfCR(GLenum target, GLfloat value)
1433{
1434 (void) target;
1435 (void) value;
1436
1437#if 0
1438 switch (target) {
1439 default:
1440 crWarning("Unhandled target in renderspuChromiumParameterfCR()");
1441 break;
1442 }
1443#endif
1444}
1445
1446bool renderspuCalloutAvailable()
1447{
1448 return render_spu.pfnClientCallout != NULL;
1449}
1450
1451bool renderspuCalloutClient(PFNVCRSERVER_CLIENT_CALLOUT_CB pfnCb, void *pvCb)
1452{
1453 if (render_spu.pfnClientCallout)
1454 {
1455 render_spu.pfnClientCallout(pfnCb, pvCb);
1456 return true;
1457 }
1458 return false;
1459}
1460
1461static void RENDER_APIENTRY
1462renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
1463 const GLvoid *values)
1464{
1465 int client_num;
1466 unsigned short port;
1467 CRMessage *msg, pingback;
1468 unsigned char *privbuf = NULL;
1469
1470 switch (target) {
1471 case GL_HH_SET_CLIENT_CALLOUT:
1472 render_spu.pfnClientCallout = (PFNVCRSERVER_CLIENT_CALLOUT)values;
1473 break;
1474 case GL_GATHER_CONNECT_CR:
1475 if (render_spu.gather_userbuf_size)
1476 privbuf = (unsigned char *)crAlloc(1024*768*4);
1477
1478 port = ((GLint *) values)[0];
1479
1480 if (render_spu.gather_conns == NULL)
1481 render_spu.gather_conns = crAlloc(render_spu.server->numClients*sizeof(CRConnection *));
1482 else
1483 {
1484 crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
1485 }
1486
1487 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1488 {
1489 switch (render_spu.server->clients[client_num]->conn->type)
1490 {
1491 case CR_TCPIP:
1492 crDebug("Render SPU: AcceptClient from %s on %d",
1493 render_spu.server->clients[client_num]->conn->hostname, render_spu.gather_port);
1494 render_spu.gather_conns[client_num] =
1495 crNetAcceptClient("tcpip", NULL, port, 1024*1024, 1);
1496 break;
1497
1498 case CR_GM:
1499 render_spu.gather_conns[client_num] =
1500 crNetAcceptClient("gm", NULL, port, 1024*1024, 1);
1501 break;
1502
1503 default:
1504 crError("Render SPU: Unknown Network Type to Open Gather Connection");
1505 }
1506
1507
1508 if (render_spu.gather_userbuf_size)
1509 {
1510 render_spu.gather_conns[client_num]->userbuf = privbuf;
1511 render_spu.gather_conns[client_num]->userbuf_len = render_spu.gather_userbuf_size;
1512 }
1513 else
1514 {
1515 render_spu.gather_conns[client_num]->userbuf = NULL;
1516 render_spu.gather_conns[client_num]->userbuf_len = 0;
1517 }
1518
1519 if (render_spu.gather_conns[client_num])
1520 {
1521 crDebug("Render SPU: success! from %s", render_spu.gather_conns[client_num]->hostname);
1522 }
1523 }
1524
1525 break;
1526
1527 case GL_GATHER_DRAWPIXELS_CR:
1528 pingback.header.type = CR_MESSAGE_OOB;
1529
1530 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1531 {
1532 crNetGetMessage(render_spu.gather_conns[client_num], &msg);
1533 if (msg->header.type == CR_MESSAGE_GATHER)
1534 {
1535 crNetFree(render_spu.gather_conns[client_num], msg);
1536 }
1537 else
1538 {
1539 crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
1540 client_num, render_spu.server->numClients-1);
1541 }
1542 }
1543
1544 /*
1545 * We're only hitting the case if we're not actually calling
1546 * child.SwapBuffers from readback, so a switch about which
1547 * call to DoSync() we really want [this one, or the one
1548 * in SwapBuffers above] is not necessary -- karl
1549 */
1550
1551 if (render_spu.swap_master_url)
1552 DoSync();
1553
1554 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1555 crNetSend(render_spu.gather_conns[client_num], NULL, &pingback,
1556 sizeof(CRMessageHeader));
1557
1558 render_spu.self.RasterPos2i(((GLint *)values)[0], ((GLint *)values)[1]);
1559 render_spu.self.DrawPixels( ((GLint *)values)[2], ((GLint *)values)[3],
1560 ((GLint *)values)[4], ((GLint *)values)[5],
1561 render_spu.gather_conns[0]->userbuf);
1562
1563
1564 render_spu.self.SwapBuffers(((GLint *)values)[6], 0);
1565 break;
1566
1567 case GL_CURSOR_POSITION_CR:
1568 if (type == GL_INT && count == 2) {
1569 render_spu.cursorX = ((GLint *) values)[0];
1570 render_spu.cursorY = ((GLint *) values)[1];
1571 crDebug("Render SPU: GL_CURSOR_POSITION_CR (%d, %d)", render_spu.cursorX, render_spu.cursorY);
1572 }
1573 else {
1574 crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
1575 }
1576 break;
1577
1578 case GL_WINDOW_SIZE_CR:
1579 /* XXX this is old code that should be removed.
1580 * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
1581 */
1582 {
1583 GLint w, h;
1584 WindowInfo *window;
1585 CRASSERT(type == GL_INT);
1586 CRASSERT(count == 2);
1587 CRASSERT(values);
1588 w = ((GLint*)values)[0];
1589 h = ((GLint*)values)[1];
1590 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
1591 if (window)
1592 {
1593 renderspu_SystemWindowSize(window, w, h);
1594 }
1595 }
1596 break;
1597
1598 case GL_HH_SET_TMPCTX_MAKE_CURRENT:
1599 if (type == GL_BYTE && count == sizeof (void*))
1600 memcpy(&render_spu.blitterDispatch.MakeCurrent, values, count);
1601 else
1602 WARN(("unexpected type(%#x) - count(%d) pair", type, count));
1603 break;
1604
1605 default:
1606#if 0
1607 WARN(("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target));
1608#endif
1609 break;
1610 }
1611}
1612
1613
1614static void RENDER_APIENTRY
1615renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
1616 GLsizei count, GLvoid *values)
1617{
1618 switch (target) {
1619 case GL_WINDOW_SIZE_CR:
1620 {
1621 GLint x, y, w, h, *size = (GLint *) values;
1622 WindowInfo *window;
1623 CRASSERT(type == GL_INT);
1624 CRASSERT(count == 2);
1625 CRASSERT(values);
1626 size[0] = size[1] = 0; /* default */
1627 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1628 if (window)
1629 {
1630 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1631 size[0] = w;
1632 size[1] = h;
1633 }
1634 }
1635 break;
1636 case GL_WINDOW_POSITION_CR:
1637 /* return window position, as a screen coordinate */
1638 {
1639 GLint *pos = (GLint *) values;
1640 GLint x, y, w, h;
1641 WindowInfo *window;
1642 CRASSERT(type == GL_INT);
1643 CRASSERT(count == 2);
1644 CRASSERT(values);
1645 pos[0] = pos[1] = 0; /* default */
1646 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1647 if (window)
1648 {
1649 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1650 pos[0] = x;/*window->x;*/
1651 pos[1] = y;/*window->y;*/
1652 }
1653 }
1654 break;
1655 case GL_MAX_WINDOW_SIZE_CR:
1656 {
1657 GLint *maxSize = (GLint *) values;
1658 WindowInfo *window;
1659 CRASSERT(type == GL_INT);
1660 CRASSERT(count == 2);
1661 CRASSERT(values);
1662 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1663 if (window)
1664 {
1665 renderspu_SystemGetMaxWindowSize(window, maxSize + 0, maxSize + 1);
1666 }
1667 }
1668 break;
1669 case GL_WINDOW_VISIBILITY_CR:
1670 {
1671 GLint *vis = (GLint *) values;
1672 WindowInfo *window;
1673 CRASSERT(type == GL_INT);
1674 CRASSERT(count == 1);
1675 CRASSERT(values);
1676 vis[0] = 0; /* default */
1677 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1678 if (window)
1679 {
1680 vis[0] = window->visible;
1681 }
1682 }
1683 break;
1684 default:
1685 ; /* nothing - silence compiler */
1686 }
1687}
1688
1689
1690static void RENDER_APIENTRY
1691renderspuBoundsInfoCR( CRrecti *bounds, GLbyte *payload, GLint len,
1692 GLint num_opcodes )
1693{
1694 (void) bounds;
1695 (void) payload;
1696 (void) len;
1697 (void) num_opcodes;
1698 /* draw the bounding box */
1699 if (render_spu.draw_bbox) {
1700 GET_CONTEXT(context);
1701 WindowInfo *window = context->currentWindow;
1702 GLint x, y, w, h;
1703
1704 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1705
1706 render_spu.self.PushMatrix();
1707 render_spu.self.LoadIdentity();
1708 render_spu.self.MatrixMode(GL_PROJECTION);
1709 render_spu.self.PushMatrix();
1710 render_spu.self.LoadIdentity();
1711 render_spu.self.Ortho(0, w, 0, h, -1, 1);
1712 render_spu.self.Color3f(1, 1, 1);
1713 render_spu.self.Begin(GL_LINE_LOOP);
1714 render_spu.self.Vertex2i(bounds->x1, bounds->y1);
1715 render_spu.self.Vertex2i(bounds->x2, bounds->y1);
1716 render_spu.self.Vertex2i(bounds->x2, bounds->y2);
1717 render_spu.self.Vertex2i(bounds->x1, bounds->y2);
1718 render_spu.self.End();
1719 render_spu.self.PopMatrix();
1720 render_spu.self.MatrixMode(GL_MODELVIEW);
1721 render_spu.self.PopMatrix();
1722 }
1723}
1724
1725
1726static void RENDER_APIENTRY
1727renderspuWriteback( GLint *writeback )
1728{
1729 (void) writeback;
1730}
1731
1732
1733static void
1734remove_trailing_space(char *s)
1735{
1736 int k = crStrlen(s);
1737 while (k > 0 && s[k-1] == ' ')
1738 k--;
1739 s[k] = 0;
1740}
1741
1742static const GLubyte * RENDER_APIENTRY
1743renderspuGetString(GLenum pname)
1744{
1745 static char tempStr[1000];
1746 GET_CONTEXT(context);
1747
1748 if (pname == GL_EXTENSIONS)
1749 {
1750 const char *nativeExt;
1751 char *crExt, *s1, *s2;
1752
1753 if (!render_spu.ws.glGetString)
1754 return NULL;
1755
1756 nativeExt = (const char *) render_spu.ws.glGetString(GL_EXTENSIONS);
1757 if (!nativeExt) {
1758 /* maybe called w/out current context. */
1759 return NULL;
1760 }
1761
1762 if (!context)
1763 return (const GLubyte *)nativeExt;
1764
1765 crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
1766 s1 = crStrIntersect(nativeExt, crExt);
1767 remove_trailing_space(s1);
1768 s2 = crStrjoin3(s1, " ", crChromiumExtensions);
1769 remove_trailing_space(s2);
1770 crFree(crExt);
1771 crFree(s1);
1772 if (context->extensionString)
1773 crFree(context->extensionString);
1774 context->extensionString = s2;
1775 return (const GLubyte *) s2;
1776 }
1777 else if (pname == GL_VENDOR)
1778 return (const GLubyte *) CR_VENDOR;
1779 else if (pname == GL_VERSION)
1780 return render_spu.ws.glGetString(GL_VERSION);
1781 else if (pname == GL_RENDERER) {
1782#ifdef VBOX
1783 snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1784#else
1785 sprintf(tempStr, "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1786#endif
1787 return (const GLubyte *) tempStr;
1788 }
1789#ifdef CR_OPENGL_VERSION_2_0
1790 else if (pname == GL_SHADING_LANGUAGE_VERSION)
1791 return render_spu.ws.glGetString(GL_SHADING_LANGUAGE_VERSION);
1792#endif
1793#ifdef GL_CR_real_vendor_strings
1794 else if (pname == GL_REAL_VENDOR)
1795 return render_spu.ws.glGetString(GL_VENDOR);
1796 else if (pname == GL_REAL_VERSION)
1797 return render_spu.ws.glGetString(GL_VERSION);
1798 else if (pname == GL_REAL_RENDERER)
1799 return render_spu.ws.glGetString(GL_RENDERER);
1800 else if (pname == GL_REAL_EXTENSIONS)
1801 return render_spu.ws.glGetString(GL_EXTENSIONS);
1802#endif
1803 else
1804 return NULL;
1805}
1806
1807static void renderspuReparentWindowCB(unsigned long key, void *data1, void *data2)
1808{
1809 WindowInfo *pWindow = (WindowInfo *)data1;
1810
1811 renderspu_SystemReparentWindow(pWindow);
1812}
1813
1814DECLEXPORT(void) renderspuReparentWindow(GLint window)
1815{
1816 WindowInfo *pWindow;
1817 CRASSERT(window >= 0);
1818
1819 pWindow = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1820
1821 if (!pWindow)
1822 {
1823 crDebug("Render SPU: Attempt to reparent invalid window (%d)", window);
1824 return;
1825 }
1826
1827 renderspu_SystemReparentWindow(pWindow);
1828
1829 /* special case: reparent all internal windows as well */
1830 if (window == CR_RENDER_DEFAULT_WINDOW_ID)
1831 {
1832 crHashtableWalk(render_spu.dummyWindowTable, renderspuReparentWindowCB, NULL);
1833 }
1834}
1835
1836#define FILLIN( NAME, FUNC ) \
1837 table[i].name = crStrdup(NAME); \
1838 table[i].fn = (SPUGenericFunction) FUNC; \
1839 i++;
1840
1841
1842/* These are the functions which the render SPU implements, not OpenGL.
1843 */
1844int
1845renderspuCreateFunctions(SPUNamedFunctionTable table[])
1846{
1847 int i = 0;
1848 FILLIN( "SwapBuffers", renderspuSwapBuffers );
1849 FILLIN( "CreateContext", renderspuCreateContext );
1850 FILLIN( "DestroyContext", renderspuDestroyContext );
1851 FILLIN( "MakeCurrent", renderspuMakeCurrent );
1852 FILLIN( "WindowCreate", renderspuWindowCreate );
1853 FILLIN( "WindowDestroy", renderspuWindowDestroy );
1854 FILLIN( "WindowSize", renderspuWindowSize );
1855 FILLIN( "WindowPosition", renderspuWindowPosition );
1856 FILLIN( "WindowVisibleRegion", renderspuWindowVisibleRegion );
1857 FILLIN( "WindowShow", renderspuWindowShow );
1858 FILLIN( "BarrierCreateCR", renderspuBarrierCreateCR );
1859 FILLIN( "BarrierDestroyCR", renderspuBarrierDestroyCR );
1860 FILLIN( "BarrierExecCR", renderspuBarrierExecCR );
1861 FILLIN( "BoundsInfoCR", renderspuBoundsInfoCR );
1862 FILLIN( "SemaphoreCreateCR", renderspuSemaphoreCreateCR );
1863 FILLIN( "SemaphoreDestroyCR", renderspuSemaphoreDestroyCR );
1864 FILLIN( "SemaphorePCR", renderspuSemaphorePCR );
1865 FILLIN( "SemaphoreVCR", renderspuSemaphoreVCR );
1866 FILLIN( "Writeback", renderspuWriteback );
1867 FILLIN( "ChromiumParameteriCR", renderspuChromiumParameteriCR );
1868 FILLIN( "ChromiumParameterfCR", renderspuChromiumParameterfCR );
1869 FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
1870 FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
1871 FILLIN( "GetString", renderspuGetString );
1872 FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
1873 return i;
1874}
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