VirtualBox

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

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

Host 3D unscaled HiDPI output: privide notifyHiDPIOutputPolicyChange() IDisplay interface to GUI in ouder to notify 3D about corresponding user option value change.

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