VirtualBox

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

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

crOpenGL: window reference

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