VirtualBox

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

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

crOpenGL: fix window mgmt

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