VirtualBox

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

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

crOpenGL/win: fix redraw concurrency

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