VirtualBox

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

Last change on this file since 67663 was 58617, checked in by vboxsync, 9 years ago

GuestHost: indent missing host features by 2 space for cosmetical reasons

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