VirtualBox

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

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

crOpenGL: basics for BlitFramebuffer driver bugs work around

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette