VirtualBox

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

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

crOpenGL: basics for no-alpha blits

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