VirtualBox

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

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

Config.kmk,Additions/common/crOpenGL,VBox/GuestHost/OpenGL,HostServices/SharedOpenGL: Remove CHROMIUM_THREADSAFE define and apply the current default

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