VirtualBox

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

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

crOpenGL: more window attr handling fixes

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