VirtualBox

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

Last change on this file since 78263 was 78263, checked in by vboxsync, 6 years ago

Config.kmk,GuestHost\OpenGL,HostServices\SharedOpenGL: Fix a bunch of compiler warnings and enable them again

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