VirtualBox

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

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

crOpenGL: TexPresent fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 49.5 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 renderspu_SystemMakeCurrent( NULL, 0, NULL );
355#ifdef CHROMIUM_THREADSAFE
356 crSetTSD(&_RenderTSD, NULL);
357#else
358 render_spu.currentContext = NULL;
359#endif
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 showIt = 0;
470
471 /*
472 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
473 */
474 /* Have GLX/WGL/AGL create the window */
475 if (!renderspuWindowInit( window, visual, showIt, id ))
476 {
477 crFree(window);
478 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
479 return -1;
480 }
481
482 return window->BltInfo.Base.id;
483}
484
485GLint RENDER_APIENTRY
486renderspuWindowCreate( const char *dpyName, GLint visBits )
487{
488 return renderspuWindowCreateEx( dpyName, visBits, 0 );
489}
490
491static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
492{
493 ContextInfo *pCtx = (ContextInfo *) data1;
494 WindowInfo *pWindow = data2;
495 (void) key;
496
497 if (pCtx->currentWindow==pWindow)
498 {
499 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
500 pCtx->currentWindow=0;
501 }
502}
503
504void renderspuWindowTerm( WindowInfo *window )
505{
506 GET_CONTEXT(pOldCtx);
507 /* ensure no concurrent draws can take place */
508 renderspuVBoxCompositorSet(window, NULL);
509 renderspuVBoxPresentBlitterCleanup(window);
510 renderspu_SystemDestroyWindow( window );
511 RTCritSectDelete(&window->CompositorLock);
512 /* check if this window is bound to some ctx. Note: window pointer is already freed here */
513 crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
514 /* restore current context */
515 {
516 GET_CONTEXT(pNewCtx);
517 if (pNewCtx!=pOldCtx)
518 {
519 renderspuMakeCurrent(pOldCtx&&pOldCtx->currentWindow ? pOldCtx->currentWindow->BltInfo.Base.id:CR_RENDER_DEFAULT_WINDOW_ID, 0,
520 pOldCtx ? pOldCtx->BltInfo.Base.id:CR_RENDER_DEFAULT_CONTEXT_ID);
521 }
522 }
523}
524
525void
526RENDER_APIENTRY renderspuWindowDestroy( GLint win )
527{
528 WindowInfo *window;
529
530 CRASSERT(win >= 0);
531 if (win == CR_RENDER_DEFAULT_WINDOW_ID)
532 {
533 crWarning("request to destroy a default mural, ignoring");
534 return;
535 }
536 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
537 if (window) {
538 crDebug("Render SPU: Destroy window (%d)", win);
539 renderspuWindowTerm( window );
540
541 /* remove window info from hash table, and free it */
542 crHashtableDelete(render_spu.windowTable, win, crFree);
543
544 }
545 else {
546 crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
547 }
548}
549
550
551static void RENDER_APIENTRY
552renderspuWindowSize( GLint win, GLint w, GLint h )
553{
554 WindowInfo *window;
555 CRASSERT(win >= 0);
556 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
557 if (window) {
558 if (w != window->BltInfo.width
559 || h != window->BltInfo.height)
560 {
561 /* window is resized, compositor data is no longer valid
562 * this set also ensures all redraw operations are done in the redraw thread
563 * and that no redraw is started until new Present request comes containing a valid presentation data */
564 renderspuVBoxCompositorSet( window, NULL);
565 renderspu_SystemWindowSize( window, w, h );
566 window->BltInfo.width = w;
567 window->BltInfo.height = h;
568 }
569 }
570 else {
571 crDebug("Render SPU: Attempt to resize invalid window (%d)", win);
572 }
573}
574
575
576static void RENDER_APIENTRY
577renderspuWindowPosition( GLint win, GLint x, GLint y )
578{
579 if (!render_spu.ignore_window_moves) {
580 WindowInfo *window;
581 CRASSERT(win >= 0);
582 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
583 if (window) {
584 renderspu_SystemWindowPosition( window, x, y );
585 window->x = x;
586 window->y = y;
587 }
588 else {
589 crDebug("Render SPU: Attempt to move invalid window (%d)", win);
590 }
591 }
592}
593
594static void RENDER_APIENTRY
595renderspuWindowVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
596{
597 WindowInfo *window;
598 CRASSERT(win >= 0);
599 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
600 if (window) {
601 renderspu_SystemWindowVisibleRegion( window, cRects, pRects );
602 }
603 else {
604 crDebug("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
605 }
606}
607
608static void RENDER_APIENTRY
609renderspuWindowShow( GLint win, GLint flag )
610{
611 WindowInfo *window;
612 CRASSERT(win >= 0);
613 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
614 if (window) {
615 GLboolean visible;
616 if (window->nativeWindow) {
617 /* We're rendering back to the native app window instead of the
618 * new window which we (the Render SPU) created earlier.
619 * So, we never want to show the Render SPU's window.
620 */
621 flag = 0;
622 }
623
624 visible = !!flag;
625
626 if (window->visible != visible)
627 {
628 renderspu_SystemShowWindow( window, visible );
629 window->visible = visible;
630 }
631 }
632 else {
633 crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win);
634 }
635}
636
637static void RENDER_APIENTRY
638renderspuVBoxPresentComposition( GLint win, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
639{
640 WindowInfo *window;
641 CRASSERT(win >= 0);
642 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
643 if (window) {
644 if (pCompositor && CrVrScrCompositorIsEmpty(pCompositor) && !window->fCompositorPresentEmpty)
645 pCompositor = NULL;
646
647 if (pCompositor)
648 window->fCompositorPresentEmpty = GL_FALSE;
649
650 renderspuVBoxCompositorSet( window, pCompositor);
651 if (pCompositor)
652 {
653 renderspu_SystemVBoxPresentComposition(window, pChangedEntry);
654 }
655 }
656 else {
657 crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win);
658 }
659}
660
661void renderspuVBoxCompositorBlitStretched ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
662{
663 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
664 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
665 CrVrScrCompositorIterInit(pCompositor, &CIter);
666 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
667 {
668 uint32_t cRegions;
669 const RTRECT *paSrcRegions, *paDstRegions;
670 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
671 uint32_t fFlags = CrVrScrCompositorEntryFlagsGet(pCompositor, pEntry);
672 if (RT_SUCCESS(rc))
673 {
674 uint32_t i;
675 for (i = 0; i < cRegions; ++i)
676 {
677 RTRECT DstRect;
678 DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
679 DstRect.yTop = paDstRegions[i].yTop * scaleY;
680 DstRect.xRight = paDstRegions[i].xRight * scaleX;
681 DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
682 CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, &paSrcRegions[i], &DstRect, 1, fFlags);
683 }
684 }
685 else
686 {
687 crWarning("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
688 }
689 }
690}
691
692void renderspuVBoxCompositorBlit ( struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
693{
694 VBOXVR_SCR_COMPOSITOR_ITERATOR CIter;
695 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
696 CrVrScrCompositorIterInit(pCompositor, &CIter);
697 while ((pEntry = CrVrScrCompositorIterNext(&CIter)) != NULL)
698 {
699 uint32_t cRegions;
700 const RTRECT *paSrcRegions, *paDstRegions;
701 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
702 uint32_t fFlags = CrVrScrCompositorEntryFlagsGet(pCompositor, pEntry);
703 if (RT_SUCCESS(rc))
704 {
705 CrBltBlitTexMural(pBlitter, true, &pEntry->Tex, paSrcRegions, paDstRegions, cRegions, fFlags);
706 }
707 else
708 {
709 crWarning("Blit: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
710 }
711 }
712}
713
714void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
715{
716 if (!window->pBlitter)
717 return;
718
719 if (render_spu.blitterTable)
720 {
721 const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
722 if (pBltInfo->Base.id == window->BltInfo.Base.id)
723 {
724 CrBltMuralSetCurrent(window->pBlitter, NULL);
725 }
726 }
727 else
728 {
729 CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
730 CrBltMuralSetCurrent(window->pBlitter, NULL);
731 CrBltTerm(window->pBlitter);
732 }
733 window->pBlitter = NULL;
734}
735
736PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
737{
738 PCR_BLITTER pBlitter = window->pBlitter;
739 if (!pBlitter)
740 {
741 if (render_spu.blitterTable)
742 {
743 crHashtableLock(render_spu.blitterTable);
744 pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
745 }
746
747 if (!pBlitter)
748 {
749 int rc;
750 CR_BLITTER_CONTEXT ctx;
751 pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
752 if (!pBlitter)
753 {
754 crWarning("failed to allocate blitter");
755 return NULL;
756 }
757
758 /* @todo: this is the assumption that crserverlib uses context 1 as a default one
759 * need to do it in a more proper way */
760 ctx.Base.id = 1;
761 ctx.Base.visualBits = window->visual->visAttribs;
762 rc = CrBltInit(pBlitter, &ctx, true, true, render_spu.blitterDispatch);
763 if (!RT_SUCCESS(rc))
764 {
765 crWarning("CrBltInit failed, rc %d", rc);
766 crFree(pBlitter);
767 return NULL;
768 }
769
770 if (render_spu.blitterTable)
771 {
772 crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
773 }
774 }
775
776 if (render_spu.blitterTable)
777 crHashtableUnlock(render_spu.blitterTable);
778
779 Assert(pBlitter);
780 window->pBlitter = pBlitter;
781 }
782
783 CrBltMuralSetCurrent(pBlitter, &window->BltInfo);
784 return pBlitter;
785}
786
787int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
788{
789 int rc;
790 PCR_BLITTER_CONTEXT pCtxInfo = NULL;
791 PCR_BLITTER_WINDOW pWindowInfo = NULL;
792 GET_CONTEXT(pCtx);
793
794 if (pCtx)
795 {
796 if (pCtx->currentWindow)
797 {
798 pCtxInfo = &pCtx->BltInfo;
799 pWindowInfo = &pCtx->currentWindow->BltInfo;
800 }
801 }
802
803 CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
804
805 rc = CrBltEnter(pBlitter, pCtxInfo, pWindowInfo);
806 if (!RT_SUCCESS(rc))
807 {
808 crWarning("CrBltEnter failed, rc %d", rc);
809 return rc;
810 }
811 return VINF_SUCCESS;
812}
813
814PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData )
815{
816 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet(window);
817 if (pBlitter)
818 {
819 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
820 if (RT_SUCCESS(rc))
821 {
822 return pBlitter;
823 }
824 }
825 return NULL;
826}
827
828PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
829{
830 if (!window->pBlitter)
831 {
832 struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
833 /* just use compositor lock to synchronize */
834 pTmpCompositor = renderspuVBoxCompositorAcquire(window);
835 CRASSERT(pTmpCompositor);
836 if (pTmpCompositor)
837 {
838 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet( window );
839 if (pBlitter)
840 {
841 if (!CrBltIsEverEntered(pBlitter))
842 {
843 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
844 if (RT_SUCCESS(rc))
845 {
846 CrBltLeave(pBlitter);
847 }
848 else
849 {
850 crWarning("renderspuVBoxPresentBlitterEnter failed rc %d", rc);
851 }
852 }
853 }
854 else
855 {
856 crWarning("renderspuVBoxPresentBlitterGet failed");
857 }
858
859 renderspuVBoxCompositorRelease(window);
860 }
861 else
862 {
863 crWarning("renderspuVBoxCompositorAcquire failed");
864 }
865 }
866 return window->pBlitter;
867}
868
869void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
870{
871 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
872 if (!pBlitter)
873 return;
874
875 renderspuVBoxCompositorBlit(pCompositor, pBlitter);
876
877 renderspu_SystemSwapBuffers(window, 0);
878
879 CrBltLeave(pBlitter);
880}
881
882void renderspuVBoxCompositorSet( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor)
883{
884 int rc;
885 /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
886 * no need to synch here
887 * the lock is actually needed to ensure we're in synch with the redraw thread */
888 if (window->pCompositor == pCompositor)
889 return;
890 rc = RTCritSectEnter(&window->CompositorLock);
891 if (RT_SUCCESS(rc))
892 {
893 window->pCompositor = pCompositor;
894 RTCritSectLeave(&window->CompositorLock);
895 return;
896 }
897 else
898 {
899 crWarning("RTCritSectEnter failed rc %d", rc);
900 }
901}
902
903static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
904{
905 WindowInfo *window = (WindowInfo *) data1;
906 renderspuVBoxCompositorSet(window, NULL);
907}
908
909void renderspuVBoxCompositorClearAll()
910{
911 /* we need to clear window compositor, which is not that trivial though,
912 * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
913 * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
914 * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
915 * and the table can be modified from that thread only as well */
916 crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
917}
918
919struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
920{
921 int rc = RTCritSectEnter(&window->CompositorLock);
922 if (RT_SUCCESS(rc))
923 {
924 VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
925 if (pCompositor)
926 return pCompositor;
927
928 /* if no compositor is set, release the lock and return */
929 RTCritSectLeave(&window->CompositorLock);
930 }
931 else
932 {
933 crWarning("RTCritSectEnter failed rc %d", rc);
934 }
935 return NULL;
936}
937
938int renderspuVBoxCompositorLock(WindowInfo *window)
939{
940 int rc = RTCritSectEnter(&window->CompositorLock);
941 AssertRC(rc);
942 return rc;
943}
944
945int renderspuVBoxCompositorUnlock(WindowInfo *window)
946{
947 int rc = RTCritSectLeave(&window->CompositorLock);
948 AssertRC(rc);
949 return rc;
950}
951
952int renderspuVBoxCompositorTryAcquire(WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
953{
954 int rc = RTCritSectTryEnter(&window->CompositorLock);
955 if (RT_SUCCESS(rc))
956 {
957 *ppCompositor = window->pCompositor;
958 if (*ppCompositor)
959 return VINF_SUCCESS;
960
961 /* if no compositor is set, release the lock and return */
962 RTCritSectLeave(&window->CompositorLock);
963 rc = VERR_INVALID_STATE;
964 }
965 else
966 {
967 *ppCompositor = NULL;
968 }
969 return rc;
970}
971
972void renderspuVBoxCompositorRelease( WindowInfo *window)
973{
974 int rc;
975 Assert(window->pCompositor);
976 if (CrVrScrCompositorIsEmpty(window->pCompositor) && RTCritSectGetRecursion(&window->CompositorLock) == 1)
977 window->pCompositor = NULL;
978 rc = RTCritSectLeave(&window->CompositorLock);
979 if (!RT_SUCCESS(rc))
980 {
981 crWarning("RTCritSectLeave failed rc %d", rc);
982 }
983}
984
985
986/*
987 * Set the current raster position to the given window coordinate.
988 */
989static void
990SetRasterPos( GLint winX, GLint winY )
991{
992 GLfloat fx, fy;
993
994 /* Push current matrix mode and viewport attributes */
995 render_spu.self.PushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
996
997 /* Setup projection parameters */
998 render_spu.self.MatrixMode( GL_PROJECTION );
999 render_spu.self.PushMatrix();
1000 render_spu.self.LoadIdentity();
1001 render_spu.self.MatrixMode( GL_MODELVIEW );
1002 render_spu.self.PushMatrix();
1003 render_spu.self.LoadIdentity();
1004
1005 render_spu.self.Viewport( winX - 1, winY - 1, 2, 2 );
1006
1007 /* set the raster (window) position */
1008 /* huh ? */
1009 fx = (GLfloat) (winX - (int) winX);
1010 fy = (GLfloat) (winY - (int) winY);
1011 render_spu.self.RasterPos4f( fx, fy, 0.0, 1.0 );
1012
1013 /* restore matrices, viewport and matrix mode */
1014 render_spu.self.PopMatrix();
1015 render_spu.self.MatrixMode( GL_PROJECTION );
1016 render_spu.self.PopMatrix();
1017
1018 render_spu.self.PopAttrib();
1019}
1020
1021
1022/*
1023 * Draw the mouse pointer bitmap at (x,y) in window coords.
1024 */
1025static void DrawCursor( GLint x, GLint y )
1026{
1027#define POINTER_WIDTH 32
1028#define POINTER_HEIGHT 32
1029 /* Somebody artistic could probably do better here */
1030 static const char *pointerImage[POINTER_HEIGHT] =
1031 {
1032 "XX..............................",
1033 "XXXX............................",
1034 ".XXXXX..........................",
1035 ".XXXXXXX........................",
1036 "..XXXXXXXX......................",
1037 "..XXXXXXXXXX....................",
1038 "...XXXXXXXXXXX..................",
1039 "...XXXXXXXXXXXXX................",
1040 "....XXXXXXXXXXXXXX..............",
1041 "....XXXXXXXXXXXXXXXX............",
1042 ".....XXXXXXXXXXXXXXXXX..........",
1043 ".....XXXXXXXXXXXXXXXXXXX........",
1044 "......XXXXXXXXXXXXXXXXXXXX......",
1045 "......XXXXXXXXXXXXXXXXXXXXXX....",
1046 ".......XXXXXXXXXXXXXXXXXXXXXXX..",
1047 ".......XXXXXXXXXXXXXXXXXXXXXXXX.",
1048 "........XXXXXXXXXXXXX...........",
1049 "........XXXXXXXX.XXXXX..........",
1050 ".........XXXXXX...XXXXX.........",
1051 ".........XXXXX.....XXXXX........",
1052 "..........XXX.......XXXXX.......",
1053 "..........XX.........XXXXX......",
1054 "......................XXXXX.....",
1055 ".......................XXXXX....",
1056 "........................XXX.....",
1057 ".........................X......",
1058 "................................",
1059 "................................",
1060 "................................",
1061 "................................",
1062 "................................",
1063 "................................"
1064
1065 };
1066 static GLubyte pointerBitmap[POINTER_HEIGHT][POINTER_WIDTH / 8];
1067 static GLboolean firstCall = GL_TRUE;
1068 GLboolean lighting, depthTest, scissorTest;
1069
1070 if (firstCall) {
1071 /* Convert pointerImage into pointerBitmap */
1072 GLint i, j;
1073 for (i = 0; i < POINTER_HEIGHT; i++) {
1074 for (j = 0; j < POINTER_WIDTH; j++) {
1075 if (pointerImage[POINTER_HEIGHT - i - 1][j] == 'X') {
1076 GLubyte bit = 128 >> (j & 0x7);
1077 pointerBitmap[i][j / 8] |= bit;
1078 }
1079 }
1080 }
1081 firstCall = GL_FALSE;
1082 }
1083
1084 render_spu.self.GetBooleanv(GL_LIGHTING, &lighting);
1085 render_spu.self.GetBooleanv(GL_DEPTH_TEST, &depthTest);
1086 render_spu.self.GetBooleanv(GL_SCISSOR_TEST, &scissorTest);
1087 render_spu.self.Disable(GL_LIGHTING);
1088 render_spu.self.Disable(GL_DEPTH_TEST);
1089 render_spu.self.Disable(GL_SCISSOR_TEST);
1090 render_spu.self.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1091
1092 render_spu.self.Color3f(1, 1, 1);
1093
1094 /* save current raster pos */
1095 render_spu.self.PushAttrib(GL_CURRENT_BIT);
1096 SetRasterPos(x, y);
1097 render_spu.self.Bitmap(POINTER_WIDTH, POINTER_HEIGHT, 1.0, 31.0, 0, 0,
1098 (const GLubyte *) pointerBitmap);
1099 /* restore current raster pos */
1100 render_spu.self.PopAttrib();
1101
1102 if (lighting)
1103 render_spu.self.Enable(GL_LIGHTING);
1104 if (depthTest)
1105 render_spu.self.Enable(GL_DEPTH_TEST);
1106 if (scissorTest)
1107 render_spu.self.Enable(GL_SCISSOR_TEST);
1108}
1109
1110void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags )
1111{
1112 WindowInfo *w = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1113
1114 if (!w)
1115 {
1116 crDebug("Render SPU: SwapBuffers invalid window id: %d", window);
1117 return;
1118 }
1119
1120 if (flags & CR_SUPPRESS_SWAP_BIT)
1121 {
1122 render_spu.self.Finish();
1123 return;
1124 }
1125
1126 if (render_spu.drawCursor)
1127 DrawCursor( render_spu.cursorX, render_spu.cursorY );
1128
1129 if (render_spu.swap_master_url)
1130 DoSync();
1131
1132 renderspu_SystemSwapBuffers( w, flags );
1133}
1134
1135
1136/*
1137 * Barrier functions
1138 * Normally, we'll have a crserver somewhere that handles the barrier calls.
1139 * However, if we're running the render SPU on the client node, then we
1140 * should handle barriers here. The threadtest demo illustrates this.
1141 * If we have N threads calling using this SPU we need these barrier
1142 * functions to synchronize them.
1143 */
1144
1145static void RENDER_APIENTRY renderspuBarrierCreateCR( GLuint name, GLuint count )
1146{
1147 Barrier *b;
1148
1149 if (render_spu.ignore_papi)
1150 return;
1151
1152 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1153 if (b) {
1154 /* HACK -- this allows everybody to create a barrier, and all
1155 but the first creation are ignored, assuming the count
1156 match. */
1157 if ( b->count != count ) {
1158 crError( "Render SPU: Barrier name=%u created with count=%u, but already "
1159 "exists with count=%u", name, count, b->count );
1160 }
1161 }
1162 else {
1163 b = (Barrier *) crAlloc( sizeof(Barrier) );
1164 b->count = count;
1165 crInitBarrier( &b->barrier, count );
1166 crHashtableAdd( render_spu.barrierHash, name, b );
1167 }
1168}
1169
1170static void RENDER_APIENTRY renderspuBarrierDestroyCR( GLuint name )
1171{
1172 if (render_spu.ignore_papi)
1173 return;
1174 crHashtableDelete( render_spu.barrierHash, name, crFree );
1175}
1176
1177static void RENDER_APIENTRY renderspuBarrierExecCR( GLuint name )
1178{
1179 Barrier *b;
1180
1181 if (render_spu.ignore_papi)
1182 return;
1183
1184 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1185 if (b) {
1186 crWaitBarrier( &(b->barrier) );
1187 }
1188 else {
1189 crWarning("Render SPU: Bad barrier name %d in BarrierExec()", name);
1190 }
1191}
1192
1193
1194/*
1195 * Semaphore functions
1196 * XXX we should probably implement these too, for the same reason as
1197 * barriers (see above).
1198 */
1199
1200static void RENDER_APIENTRY renderspuSemaphoreCreateCR( GLuint name, GLuint count )
1201{
1202 (void) name;
1203 (void) count;
1204}
1205
1206static void RENDER_APIENTRY renderspuSemaphoreDestroyCR( GLuint name )
1207{
1208 (void) name;
1209}
1210
1211static void RENDER_APIENTRY renderspuSemaphorePCR( GLuint name )
1212{
1213 (void) name;
1214}
1215
1216static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
1217{
1218 (void) name;
1219}
1220
1221
1222/*
1223 * Misc functions
1224 */
1225
1226
1227
1228static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
1229{
1230
1231 switch (target)
1232 {
1233 default:
1234// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
1235 break;
1236 }
1237}
1238
1239static void RENDER_APIENTRY
1240renderspuChromiumParameterfCR(GLenum target, GLfloat value)
1241{
1242 (void) target;
1243 (void) value;
1244
1245#if 0
1246 switch (target) {
1247 default:
1248 crWarning("Unhandled target in renderspuChromiumParameterfCR()");
1249 break;
1250 }
1251#endif
1252}
1253
1254
1255static void RENDER_APIENTRY
1256renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
1257 const GLvoid *values)
1258{
1259 int client_num;
1260 unsigned short port;
1261 CRMessage *msg, pingback;
1262 unsigned char *privbuf = NULL;
1263
1264 switch (target) {
1265
1266 case GL_GATHER_CONNECT_CR:
1267 if (render_spu.gather_userbuf_size)
1268 privbuf = (unsigned char *)crAlloc(1024*768*4);
1269
1270 port = ((GLint *) values)[0];
1271
1272 if (render_spu.gather_conns == NULL)
1273 render_spu.gather_conns = crAlloc(render_spu.server->numClients*sizeof(CRConnection *));
1274 else
1275 {
1276 crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
1277 }
1278
1279 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1280 {
1281 switch (render_spu.server->clients[client_num]->conn->type)
1282 {
1283 case CR_TCPIP:
1284 crDebug("Render SPU: AcceptClient from %s on %d",
1285 render_spu.server->clients[client_num]->conn->hostname, render_spu.gather_port);
1286 render_spu.gather_conns[client_num] =
1287 crNetAcceptClient("tcpip", NULL, port, 1024*1024, 1);
1288 break;
1289
1290 case CR_GM:
1291 render_spu.gather_conns[client_num] =
1292 crNetAcceptClient("gm", NULL, port, 1024*1024, 1);
1293 break;
1294
1295 default:
1296 crError("Render SPU: Unknown Network Type to Open Gather Connection");
1297 }
1298
1299
1300 if (render_spu.gather_userbuf_size)
1301 {
1302 render_spu.gather_conns[client_num]->userbuf = privbuf;
1303 render_spu.gather_conns[client_num]->userbuf_len = render_spu.gather_userbuf_size;
1304 }
1305 else
1306 {
1307 render_spu.gather_conns[client_num]->userbuf = NULL;
1308 render_spu.gather_conns[client_num]->userbuf_len = 0;
1309 }
1310
1311 if (render_spu.gather_conns[client_num])
1312 {
1313 crDebug("Render SPU: success! from %s", render_spu.gather_conns[client_num]->hostname);
1314 }
1315 }
1316
1317 break;
1318
1319 case GL_GATHER_DRAWPIXELS_CR:
1320 pingback.header.type = CR_MESSAGE_OOB;
1321
1322 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1323 {
1324 crNetGetMessage(render_spu.gather_conns[client_num], &msg);
1325 if (msg->header.type == CR_MESSAGE_GATHER)
1326 {
1327 crNetFree(render_spu.gather_conns[client_num], msg);
1328 }
1329 else
1330 {
1331 crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
1332 client_num, render_spu.server->numClients-1);
1333 }
1334 }
1335
1336 /*
1337 * We're only hitting the case if we're not actually calling
1338 * child.SwapBuffers from readback, so a switch about which
1339 * call to DoSync() we really want [this one, or the one
1340 * in SwapBuffers above] is not necessary -- karl
1341 */
1342
1343 if (render_spu.swap_master_url)
1344 DoSync();
1345
1346 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1347 crNetSend(render_spu.gather_conns[client_num], NULL, &pingback,
1348 sizeof(CRMessageHeader));
1349
1350 render_spu.self.RasterPos2i(((GLint *)values)[0], ((GLint *)values)[1]);
1351 render_spu.self.DrawPixels( ((GLint *)values)[2], ((GLint *)values)[3],
1352 ((GLint *)values)[4], ((GLint *)values)[5],
1353 render_spu.gather_conns[0]->userbuf);
1354
1355
1356 render_spu.self.SwapBuffers(((GLint *)values)[6], 0);
1357 break;
1358
1359 case GL_CURSOR_POSITION_CR:
1360 if (type == GL_INT && count == 2) {
1361 render_spu.cursorX = ((GLint *) values)[0];
1362 render_spu.cursorY = ((GLint *) values)[1];
1363 crDebug("Render SPU: GL_CURSOR_POSITION_CR (%d, %d)", render_spu.cursorX, render_spu.cursorY);
1364 }
1365 else {
1366 crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
1367 }
1368 break;
1369
1370 case GL_WINDOW_SIZE_CR:
1371 /* XXX this is old code that should be removed.
1372 * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
1373 */
1374 {
1375 GLint w, h;
1376 WindowInfo *window;
1377 CRASSERT(type == GL_INT);
1378 CRASSERT(count == 2);
1379 CRASSERT(values);
1380 w = ((GLint*)values)[0];
1381 h = ((GLint*)values)[1];
1382 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
1383 if (window)
1384 {
1385 renderspu_SystemWindowSize(window, w, h);
1386 }
1387 }
1388 break;
1389
1390 default:
1391#if 0
1392 crWarning("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target);
1393#endif
1394 break;
1395 }
1396}
1397
1398
1399static void RENDER_APIENTRY
1400renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
1401 GLsizei count, GLvoid *values)
1402{
1403 switch (target) {
1404 case GL_WINDOW_SIZE_CR:
1405 {
1406 GLint x, y, w, h, *size = (GLint *) values;
1407 WindowInfo *window;
1408 CRASSERT(type == GL_INT);
1409 CRASSERT(count == 2);
1410 CRASSERT(values);
1411 size[0] = size[1] = 0; /* default */
1412 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1413 if (window)
1414 {
1415 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1416 size[0] = w;
1417 size[1] = h;
1418 }
1419 }
1420 break;
1421 case GL_WINDOW_POSITION_CR:
1422 /* return window position, as a screen coordinate */
1423 {
1424 GLint *pos = (GLint *) values;
1425 GLint x, y, w, h;
1426 WindowInfo *window;
1427 CRASSERT(type == GL_INT);
1428 CRASSERT(count == 2);
1429 CRASSERT(values);
1430 pos[0] = pos[1] = 0; /* default */
1431 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1432 if (window)
1433 {
1434 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1435 pos[0] = x;/*window->x;*/
1436 pos[1] = y;/*window->y;*/
1437 }
1438 }
1439 break;
1440 case GL_MAX_WINDOW_SIZE_CR:
1441 {
1442 GLint *maxSize = (GLint *) values;
1443 WindowInfo *window;
1444 CRASSERT(type == GL_INT);
1445 CRASSERT(count == 2);
1446 CRASSERT(values);
1447 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1448 if (window)
1449 {
1450 renderspu_SystemGetMaxWindowSize(window, maxSize + 0, maxSize + 1);
1451 }
1452 }
1453 break;
1454 case GL_WINDOW_VISIBILITY_CR:
1455 {
1456 GLint *vis = (GLint *) values;
1457 WindowInfo *window;
1458 CRASSERT(type == GL_INT);
1459 CRASSERT(count == 1);
1460 CRASSERT(values);
1461 vis[0] = 0; /* default */
1462 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1463 if (window)
1464 {
1465 vis[0] = window->visible;
1466 }
1467 }
1468 break;
1469 default:
1470 ; /* nothing - silence compiler */
1471 }
1472}
1473
1474
1475static void RENDER_APIENTRY
1476renderspuBoundsInfoCR( CRrecti *bounds, GLbyte *payload, GLint len,
1477 GLint num_opcodes )
1478{
1479 (void) bounds;
1480 (void) payload;
1481 (void) len;
1482 (void) num_opcodes;
1483 /* draw the bounding box */
1484 if (render_spu.draw_bbox) {
1485 GET_CONTEXT(context);
1486 WindowInfo *window = context->currentWindow;
1487 GLint x, y, w, h;
1488
1489 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1490
1491 render_spu.self.PushMatrix();
1492 render_spu.self.LoadIdentity();
1493 render_spu.self.MatrixMode(GL_PROJECTION);
1494 render_spu.self.PushMatrix();
1495 render_spu.self.LoadIdentity();
1496 render_spu.self.Ortho(0, w, 0, h, -1, 1);
1497 render_spu.self.Color3f(1, 1, 1);
1498 render_spu.self.Begin(GL_LINE_LOOP);
1499 render_spu.self.Vertex2i(bounds->x1, bounds->y1);
1500 render_spu.self.Vertex2i(bounds->x2, bounds->y1);
1501 render_spu.self.Vertex2i(bounds->x2, bounds->y2);
1502 render_spu.self.Vertex2i(bounds->x1, bounds->y2);
1503 render_spu.self.End();
1504 render_spu.self.PopMatrix();
1505 render_spu.self.MatrixMode(GL_MODELVIEW);
1506 render_spu.self.PopMatrix();
1507 }
1508}
1509
1510
1511static void RENDER_APIENTRY
1512renderspuWriteback( GLint *writeback )
1513{
1514 (void) writeback;
1515}
1516
1517
1518static void
1519remove_trailing_space(char *s)
1520{
1521 int k = crStrlen(s);
1522 while (k > 0 && s[k-1] == ' ')
1523 k--;
1524 s[k] = 0;
1525}
1526
1527static const GLubyte * RENDER_APIENTRY
1528renderspuGetString(GLenum pname)
1529{
1530 static char tempStr[1000];
1531 GET_CONTEXT(context);
1532
1533 if (pname == GL_EXTENSIONS)
1534 {
1535 const char *nativeExt;
1536 char *crExt, *s1, *s2;
1537
1538 if (!render_spu.ws.glGetString)
1539 return NULL;
1540
1541 nativeExt = (const char *) render_spu.ws.glGetString(GL_EXTENSIONS);
1542 if (!nativeExt) {
1543 /* maybe called w/out current context. */
1544 return NULL;
1545 }
1546
1547 crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
1548 s1 = crStrIntersect(nativeExt, crExt);
1549 remove_trailing_space(s1);
1550 s2 = crStrjoin3(s1, " ", crChromiumExtensions);
1551 remove_trailing_space(s2);
1552 crFree(crExt);
1553 crFree(s1);
1554 if (context->extensionString)
1555 crFree(context->extensionString);
1556 context->extensionString = s2;
1557 return (const GLubyte *) s2;
1558 }
1559 else if (pname == GL_VENDOR)
1560 return (const GLubyte *) CR_VENDOR;
1561 else if (pname == GL_VERSION)
1562 return render_spu.ws.glGetString(GL_VERSION);
1563 else if (pname == GL_RENDERER) {
1564#ifdef VBOX
1565 snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1566#else
1567 sprintf(tempStr, "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1568#endif
1569 return (const GLubyte *) tempStr;
1570 }
1571#ifdef CR_OPENGL_VERSION_2_0
1572 else if (pname == GL_SHADING_LANGUAGE_VERSION)
1573 return render_spu.ws.glGetString(GL_SHADING_LANGUAGE_VERSION);
1574#endif
1575#ifdef GL_CR_real_vendor_strings
1576 else if (pname == GL_REAL_VENDOR)
1577 return render_spu.ws.glGetString(GL_VENDOR);
1578 else if (pname == GL_REAL_VERSION)
1579 return render_spu.ws.glGetString(GL_VERSION);
1580 else if (pname == GL_REAL_RENDERER)
1581 return render_spu.ws.glGetString(GL_RENDERER);
1582 else if (pname == GL_REAL_EXTENSIONS)
1583 return render_spu.ws.glGetString(GL_EXTENSIONS);
1584#endif
1585 else
1586 return NULL;
1587}
1588
1589DECLEXPORT(void) renderspuReparentWindow(GLint window)
1590{
1591 WindowInfo *pWindow;
1592 CRASSERT(window >= 0);
1593
1594 pWindow = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1595
1596 if (!pWindow)
1597 {
1598 crDebug("Render SPU: Attempt to reparent invalid window (%d)", window);
1599 return;
1600 }
1601
1602 renderspu_SystemReparentWindow(pWindow);
1603}
1604
1605#define FILLIN( NAME, FUNC ) \
1606 table[i].name = crStrdup(NAME); \
1607 table[i].fn = (SPUGenericFunction) FUNC; \
1608 i++;
1609
1610
1611/* These are the functions which the render SPU implements, not OpenGL.
1612 */
1613int
1614renderspuCreateFunctions(SPUNamedFunctionTable table[])
1615{
1616 int i = 0;
1617 FILLIN( "SwapBuffers", renderspuSwapBuffers );
1618 FILLIN( "CreateContext", renderspuCreateContext );
1619 FILLIN( "DestroyContext", renderspuDestroyContext );
1620 FILLIN( "MakeCurrent", renderspuMakeCurrent );
1621 FILLIN( "WindowCreate", renderspuWindowCreate );
1622 FILLIN( "WindowDestroy", renderspuWindowDestroy );
1623 FILLIN( "WindowSize", renderspuWindowSize );
1624 FILLIN( "WindowPosition", renderspuWindowPosition );
1625 FILLIN( "WindowVisibleRegion", renderspuWindowVisibleRegion );
1626 FILLIN( "WindowShow", renderspuWindowShow );
1627 FILLIN( "BarrierCreateCR", renderspuBarrierCreateCR );
1628 FILLIN( "BarrierDestroyCR", renderspuBarrierDestroyCR );
1629 FILLIN( "BarrierExecCR", renderspuBarrierExecCR );
1630 FILLIN( "BoundsInfoCR", renderspuBoundsInfoCR );
1631 FILLIN( "SemaphoreCreateCR", renderspuSemaphoreCreateCR );
1632 FILLIN( "SemaphoreDestroyCR", renderspuSemaphoreDestroyCR );
1633 FILLIN( "SemaphorePCR", renderspuSemaphorePCR );
1634 FILLIN( "SemaphoreVCR", renderspuSemaphoreVCR );
1635 FILLIN( "Writeback", renderspuWriteback );
1636 FILLIN( "ChromiumParameteriCR", renderspuChromiumParameteriCR );
1637 FILLIN( "ChromiumParameterfCR", renderspuChromiumParameterfCR );
1638 FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
1639 FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
1640 FILLIN( "GetString", renderspuGetString );
1641 FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
1642
1643 return i;
1644}
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