VirtualBox

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

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

crOpenGL: OSX backend rework; oddscreen rendering generalization

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