VirtualBox

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

Last change on this file since 45132 was 45132, checked in by vboxsync, 12 years ago

crOpenGL: seamles mode support impl; bugfizes & cleanup

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