VirtualBox

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

Last change on this file since 50184 was 50184, checked in by vboxsync, 11 years ago

crOpenGL: misc bugfixes, Vrdp+3D working with the new framework

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 54.6 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_environment.h"
8#include "cr_string.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_spu.h"
12#include "cr_environment.h"
13#include "renderspu.h"
14#include "cr_extstring.h"
15
16#include <iprt/asm.h>
17
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 renderspuSetDefaultSharedContext(NULL);
301 }
302
303 curCtx = GET_CONTEXT_VAL();
304 CRASSERT(curCtx);
305 if (curCtx == context)
306 {
307 renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID );
308 curCtx = GET_CONTEXT_VAL();
309 Assert(curCtx);
310 Assert(curCtx != context);
311 }
312
313 crHashtableDelete(render_spu.contextTable, ctx, NULL);
314
315 renderspuContextMarkDeletedAndRelease(context);
316}
317
318WindowInfo* renderspuGetDummyWindow(GLint visBits)
319{
320 WindowInfo *window = (WindowInfo *) crHashtableSearch(render_spu.dummyWindowTable, visBits);
321 if (!window)
322 {
323 window = (WindowInfo *)crAlloc(sizeof (*window));
324 if (!window)
325 {
326 crWarning("crAlloc failed");
327 return NULL;
328 }
329
330 if (!renderspuWindowInit(window, NULL, visBits, -1))
331 {
332 crWarning("renderspuWindowInit failed");
333 crFree(window);
334 return NULL;
335 }
336
337 crHashtableAdd(render_spu.dummyWindowTable, visBits, window);
338 }
339
340 return window;
341}
342
343void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow, ContextInfo *context)
344{
345 if (window && context)
346 {
347#ifdef CHROMIUM_THREADSAFE
348 crSetTSD(&_RenderTSD, context);
349#else
350 render_spu.currentContext = context;
351#endif
352 context->currentWindow = window;
353 if (!window)
354 {
355 crDebug("Render SPU: MakeCurrent invalid window id: %d", window->BltInfo.Base.id);
356 return;
357 }
358 if (!context)
359 {
360 crDebug("Render SPU: MakeCurrent invalid context id: %d", context->BltInfo.Base.id);
361 return;
362 }
363
364 renderspu_SystemMakeCurrent( window, nativeWindow, context );
365 if (!context->everCurrent) {
366 /* print OpenGL info */
367 const char *extString = (const char *) render_spu.ws.glGetString( GL_EXTENSIONS );
368 /*
369 crDebug( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) );
370 */
371 crInfo( "Render SPU: GL_VENDOR: %s", render_spu.ws.glGetString( GL_VENDOR ) );
372 crInfo( "Render SPU: GL_RENDERER: %s", render_spu.ws.glGetString( GL_RENDERER ) );
373 crInfo( "Render SPU: GL_VERSION: %s", render_spu.ws.glGetString( GL_VERSION ) );
374 crInfo( "Render SPU: GL_EXTENSIONS: %s", render_spu.ws.glGetString( GL_EXTENSIONS ) );
375 if (crStrstr(extString, "GL_ARB_window_pos"))
376 context->haveWindowPosARB = GL_TRUE;
377 else
378 context->haveWindowPosARB = GL_FALSE;
379 context->everCurrent = GL_TRUE;
380 }
381 if (window->BltInfo.Base.id == CR_RENDER_DEFAULT_WINDOW_ID && window->mapPending &&
382 !render_spu.render_to_app_window && !render_spu.render_to_crut_window) {
383 /* Window[CR_RENDER_DEFAULT_CONTEXT_ID] is special, it's the default window and normally hidden.
384 * If the mapPending flag is set, then we should now make the window
385 * visible.
386 */
387 /*renderspu_SystemShowWindow( window, GL_TRUE );*/
388 window->mapPending = GL_FALSE;
389 }
390 window->everCurrent = GL_TRUE;
391 }
392 else if (!window && !context)
393 {
394 renderspu_SystemMakeCurrent( NULL, 0, NULL );
395#ifdef CHROMIUM_THREADSAFE
396 crSetTSD(&_RenderTSD, NULL);
397#else
398 render_spu.currentContext = NULL;
399#endif
400 }
401 else
402 {
403 crError("renderspuMakeCurrent invalid ids: crWindow(%d), ctx(%d)",
404 window ? window->BltInfo.Base.id : 0,
405 context ? context->BltInfo.Base.id : 0);
406 }
407}
408
409void RENDER_APIENTRY
410renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
411{
412 WindowInfo *window = NULL;
413 ContextInfo *context = NULL;
414
415 /*
416 crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx);
417 */
418
419 if (crWindow)
420 {
421 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow);
422 if (!window)
423 {
424 crWarning("invalid window %d specified", crWindow);
425 return;
426 }
427 }
428
429 if (ctx)
430 {
431 context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
432 if (!context)
433 {
434 crWarning("invalid context %d specified", ctx);
435 return;
436 }
437 }
438
439 if (!context != !window)
440 {
441 crWarning("either window %d or context %d are zero", crWindow, ctx);
442 return;
443 }
444
445 renderspuPerformMakeCurrent(window, nativeWindow, context);
446}
447
448GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id )
449{
450 crMemset(window, 0, sizeof (*window));
451 RTCritSectInit(&window->CompositorLock);
452 window->fCompositorPresentEmpty = GL_FALSE;
453 window->pCompositor = NULL;
454
455 window->BltInfo.Base.id = id;
456
457 window->x = render_spu.defaultX;
458 window->y = render_spu.defaultY;
459 window->BltInfo.width = render_spu.defaultWidth;
460 window->BltInfo.height = render_spu.defaultHeight;
461
462 /* Set window->title, replacing %i with the window ID number */
463 {
464 const char *s = crStrstr(render_spu.window_title, "%i");
465 if (s) {
466 int i, j, k;
467 window->title = crAlloc(crStrlen(render_spu.window_title) + 10);
468 for (i = 0; render_spu.window_title[i] != '%'; i++)
469 window->title[i] = render_spu.window_title[i];
470 k = sprintf(window->title + i, "%d", window->BltInfo.Base.id);
471 CRASSERT(k < 10);
472 i++; /* skip the 'i' after the '%' */
473 j = i + k;
474 for (; (window->title[j] = s[i]) != 0; i++, j++)
475 ;
476 }
477 else {
478 window->title = crStrdup(render_spu.window_title);
479 }
480 }
481
482 window->BltInfo.Base.visualBits = visual->visAttribs;
483
484
485 /*
486 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
487 */
488 /* Have GLX/WGL/AGL create the window */
489 if (!renderspu_SystemVBoxCreateWindow( visual, showIt, window ))
490 {
491 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
492 return GL_FALSE;
493 }
494
495 window->visible = !!showIt;
496
497 CRASSERT(window->visual == visual);
498 return GL_TRUE;
499}
500
501/*
502 * Window functions
503 */
504GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
505{
506 VisualInfo *visual;
507
508 crMemset(pWindow, 0, sizeof (*pWindow));
509
510 if (!dpyName || crStrlen(render_spu.display_string) > 0)
511 dpyName = render_spu.display_string;
512
513 visual = renderspuFindVisual( dpyName, visBits );
514 if (!visual)
515 {
516 crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
517 return GL_FALSE;
518 }
519
520 /*
521 crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
522 */
523 /* Have GLX/WGL/AGL create the window */
524 if (!renderspuWindowInitWithVisual( pWindow, visual, 0, id ))
525 {
526 crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
527 return GL_FALSE;
528 }
529
530 return GL_TRUE;
531}
532
533GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id )
534{
535 WindowInfo *window;
536
537 if (id <= 0)
538 {
539 id = (GLint)crHashtableAllocKeys(render_spu.windowTable, 1);
540 if (id <= 0)
541 {
542 crWarning("failed to allocate window id");
543 return -1;
544 }
545 }
546 else
547 {
548 if (crHashtableIsKeyUsed(render_spu.windowTable, id))
549 {
550 crWarning("the specified window key %d is in use", id);
551 return -1;
552 }
553 }
554
555 /* Allocate WindowInfo */
556 window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
557 if (!window)
558 {
559 crWarning( "Render SPU: Couldn't create a window" );
560 return -1;
561 }
562
563 if (!renderspuWindowInit(window, dpyName, visBits, id))
564 {
565 crWarning("renderspuWindowInit failed");
566 crFree(window);
567 return -1;
568 }
569
570 crHashtableAdd(render_spu.windowTable, id, window);
571 return window->BltInfo.Base.id;
572}
573
574GLint RENDER_APIENTRY
575renderspuWindowCreate( const char *dpyName, GLint visBits )
576{
577 return renderspuWindowCreateEx( dpyName, visBits, 0 );
578}
579
580static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
581{
582 ContextInfo *pCtx = (ContextInfo *) data1;
583 WindowInfo *pWindow = data2;
584 (void) key;
585
586 if (pCtx->currentWindow==pWindow)
587 {
588 WindowInfo* pDummy = renderspuGetDummyWindow(pCtx->BltInfo.Base.visualBits);
589 if (pDummy)
590 {
591 renderspuPerformMakeCurrent(pDummy, 0, pCtx);
592 }
593 else
594 {
595 crWarning("failed to get dummy window");
596 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
597 }
598 }
599}
600
601void renderspuWindowTerm( WindowInfo *window )
602{
603 GET_CONTEXT(pOldCtx);
604 WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
605 CRASSERT(!pOldCtx == !pOldWindow);
606 /* ensure no concurrent draws can take place */
607 renderspuVBoxCompositorSet(window, NULL);
608 renderspuVBoxPresentBlitterCleanup(window);
609 renderspu_SystemDestroyWindow( window );
610 RTCritSectDelete(&window->CompositorLock);
611 /* check if this window is bound to some ctx. Note: window pointer is already freed here */
612 crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
613 /* restore current context */
614 {
615 GET_CONTEXT(pNewCtx);
616 WindowInfo * pNewWindow = pNewCtx ? pNewCtx->currentWindow : NULL;
617 CRASSERT(!pNewCtx == !pNewWindow);
618
619 if (pOldWindow == window)
620 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
621 else if (pNewCtx != pOldCtx || pOldWindow != pNewWindow)
622 {
623 if (pOldCtx)
624 renderspuPerformMakeCurrent(pOldWindow, 0, pOldCtx);
625 else
626 renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
627 }
628 }
629}
630
631void
632RENDER_APIENTRY renderspuWindowDestroy( GLint win )
633{
634 WindowInfo *window;
635
636 CRASSERT(win >= 0);
637 if (win == CR_RENDER_DEFAULT_WINDOW_ID)
638 {
639 crWarning("request to destroy a default mural, ignoring");
640 return;
641 }
642 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
643 if (window) {
644 crDebug("Render SPU: Destroy window (%d)", win);
645 renderspuWindowTerm( window );
646
647 /* remove window info from hash table, and free it */
648 crHashtableDelete(render_spu.windowTable, win, crFree);
649
650 }
651 else {
652 crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
653 }
654}
655
656
657static void RENDER_APIENTRY
658renderspuWindowSize( GLint win, GLint w, GLint h )
659{
660 WindowInfo *window;
661 CRASSERT(win >= 0);
662 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
663 if (window) {
664 if (w != window->BltInfo.width
665 || h != window->BltInfo.height)
666 {
667 /* window is resized, compositor data is no longer valid
668 * this set also ensures all redraw operations are done in the redraw thread
669 * and that no redraw is started until new Present request comes containing a valid presentation data */
670 renderspuVBoxCompositorSet( window, NULL);
671 renderspu_SystemWindowSize( window, w, h );
672 window->BltInfo.width = w;
673 window->BltInfo.height = h;
674 }
675 }
676 else {
677 crDebug("Render SPU: Attempt to resize invalid window (%d)", win);
678 }
679}
680
681
682static void RENDER_APIENTRY
683renderspuWindowPosition( GLint win, GLint x, GLint y )
684{
685 if (!render_spu.ignore_window_moves) {
686 WindowInfo *window;
687 CRASSERT(win >= 0);
688 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
689 if (window) {
690 renderspu_SystemWindowPosition( window, x, y );
691 window->x = x;
692 window->y = y;
693 }
694 else {
695 crDebug("Render SPU: Attempt to move invalid window (%d)", win);
696 }
697 }
698}
699
700#ifdef DEBUG_misha
701# define CR_DBG_DUMP_VISIBLE_REGIONS
702#endif
703
704#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
705static void renderspuDbgDumpVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
706{
707 GLint i;
708 const RTRECT *pRtRects = (const RTRECT *)((const void*)pRects);
709
710 crInfo("Window %d, Vidible Regions%d", win, cRects);
711 for (i = 0; i < cRects; ++i)
712 {
713 crInfo("%d: (%d,%d), (%d,%d)", i, pRtRects[i].xLeft, pRtRects[i].yTop, pRtRects[i].xRight, pRtRects[i].yBottom);
714 }
715 crInfo("======");
716}
717#endif
718
719static void RENDER_APIENTRY
720renderspuWindowVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
721{
722 WindowInfo *window;
723 CRASSERT(win >= 0);
724
725#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
726 renderspuDbgDumpVisibleRegion(win, cRects, pRects);
727#endif
728
729 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
730 if (window) {
731 renderspu_SystemWindowVisibleRegion( window, cRects, pRects );
732 }
733 else {
734 crWarning("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
735 }
736}
737
738static void RENDER_APIENTRY
739renderspuWindowShow( GLint win, GLint flag )
740{
741 WindowInfo *window;
742 CRASSERT(win >= 0);
743 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
744 if (window) {
745 GLboolean visible;
746 if (window->nativeWindow) {
747 /* We're rendering back to the native app window instead of the
748 * new window which we (the Render SPU) created earlier.
749 * So, we never want to show the Render SPU's window.
750 */
751 flag = 0;
752 }
753
754 visible = !!flag;
755
756 if (window->visible != visible)
757 {
758 renderspu_SystemShowWindow( window, visible );
759 window->visible = visible;
760 }
761 }
762 else {
763 crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win);
764 }
765}
766
767static void RENDER_APIENTRY
768renderspuVBoxPresentComposition( GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
769{
770 WindowInfo *window;
771 CRASSERT(win >= 0);
772 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
773 if (window) {
774 if (pCompositor && CrVrScrCompositorIsEmpty(pCompositor) && !window->fCompositorPresentEmpty)
775 pCompositor = NULL;
776
777 if (pCompositor)
778 window->fCompositorPresentEmpty = GL_FALSE;
779
780 renderspuVBoxCompositorSet( window, pCompositor);
781 if (pCompositor)
782 {
783 renderspu_SystemVBoxPresentComposition(window, pChangedEntry);
784 }
785 }
786 else {
787 crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win);
788 }
789}
790
791void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
792{
793 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
794 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
795 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
796 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
797 {
798 uint32_t cRegions;
799 const RTRECT *paSrcRegions, *paDstRegions;
800 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
801 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
802 if (RT_SUCCESS(rc))
803 {
804 uint32_t i;
805 for (i = 0; i < cRegions; ++i)
806 {
807 RTRECT DstRect;
808 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
809 DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
810 DstRect.yTop = paDstRegions[i].yTop * scaleY;
811 DstRect.xRight = paDstRegions[i].xRight * scaleX;
812 DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
813 CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), &paSrcRegions[i], &DstRect, 1, fFlags);
814 }
815 }
816 else
817 {
818 crWarning("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
819 }
820 }
821}
822
823void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
824{
825 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
826 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
827 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
828 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
829 {
830 uint32_t cRegions;
831 const RTRECT *paSrcRegions, *paDstRegions;
832 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
833 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
834 if (RT_SUCCESS(rc))
835 {
836 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
837 CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), paSrcRegions, paDstRegions, cRegions, fFlags);
838 }
839 else
840 {
841 crWarning("Blit: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
842 }
843 }
844}
845
846void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
847{
848 if (!window->pBlitter)
849 return;
850
851 if (render_spu.blitterTable)
852 {
853 const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
854 if (pBltInfo && pBltInfo->Base.id == window->BltInfo.Base.id)
855 {
856 CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
857 }
858 }
859 else
860 {
861 CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
862 CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
863 CrBltTerm(window->pBlitter);
864 }
865 window->pBlitter = NULL;
866}
867
868PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
869{
870 PCR_BLITTER pBlitter = window->pBlitter;
871 if (!pBlitter)
872 {
873 if (render_spu.blitterTable)
874 {
875 crHashtableLock(render_spu.blitterTable);
876 pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
877 }
878
879 if (!pBlitter)
880 {
881 int rc;
882 ContextInfo * pDefaultCtxInfo;
883
884 pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
885 if (!pBlitter)
886 {
887 crWarning("failed to allocate blitter");
888 return NULL;
889 }
890
891 pDefaultCtxInfo = renderspuDefaultSharedContextAcquire();
892 if (!pDefaultCtxInfo)
893 {
894 crWarning("no default ctx info!");
895 crFree(pBlitter);
896 return NULL;
897 }
898
899 rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, &render_spu.blitterDispatch);
900
901 /* we can release it either way, since it will be retained when used as a shared context */
902 renderspuDefaultSharedContextRelease(pDefaultCtxInfo);
903
904 if (!RT_SUCCESS(rc))
905 {
906 crWarning("CrBltInit failed, rc %d", rc);
907 crFree(pBlitter);
908 return NULL;
909 }
910
911 if (render_spu.blitterTable)
912 {
913 crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
914 }
915 }
916
917 if (render_spu.blitterTable)
918 crHashtableUnlock(render_spu.blitterTable);
919
920 Assert(pBlitter);
921 window->pBlitter = pBlitter;
922 }
923
924 CrBltMuralSetCurrentInfo(pBlitter, &window->BltInfo);
925 return pBlitter;
926}
927
928int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
929{
930 int rc;
931
932 CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
933
934 rc = CrBltEnter(pBlitter);
935 if (!RT_SUCCESS(rc))
936 {
937 crWarning("CrBltEnter failed, rc %d", rc);
938 return rc;
939 }
940 return VINF_SUCCESS;
941}
942
943PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData )
944{
945 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet(window);
946 if (pBlitter)
947 {
948 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
949 if (RT_SUCCESS(rc))
950 {
951 return pBlitter;
952 }
953 }
954 return NULL;
955}
956
957PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
958{
959 if (!window->pBlitter)
960 {
961 const struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
962 /* just use compositor lock to synchronize */
963 pTmpCompositor = renderspuVBoxCompositorAcquire(window);
964 CRASSERT(pTmpCompositor);
965 if (pTmpCompositor)
966 {
967 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet( window );
968 if (pBlitter)
969 {
970 if (!CrBltIsEverEntered(pBlitter))
971 {
972 int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
973 if (RT_SUCCESS(rc))
974 {
975 CrBltLeave(pBlitter);
976 }
977 else
978 {
979 crWarning("renderspuVBoxPresentBlitterEnter failed rc %d", rc);
980 }
981 }
982 }
983 else
984 {
985 crWarning("renderspuVBoxPresentBlitterGet failed");
986 }
987
988 renderspuVBoxCompositorRelease(window);
989 }
990 else
991 {
992 crWarning("renderspuVBoxCompositorAcquire failed");
993 }
994 }
995 return window->pBlitter;
996}
997
998void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
999{
1000 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
1001 if (!pBlitter)
1002 return;
1003
1004 renderspuVBoxCompositorBlit(pCompositor, pBlitter);
1005
1006 renderspu_SystemSwapBuffers(window, 0);
1007
1008 CrBltLeave(pBlitter);
1009}
1010
1011void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
1012{
1013 int rc;
1014 /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
1015 * no need to synch here
1016 * the lock is actually needed to ensure we're in synch with the redraw thread */
1017 if (window->pCompositor == pCompositor)
1018 return;
1019 rc = RTCritSectEnter(&window->CompositorLock);
1020 if (RT_SUCCESS(rc))
1021 {
1022 window->pCompositor = pCompositor;
1023 RTCritSectLeave(&window->CompositorLock);
1024 return;
1025 }
1026 else
1027 {
1028 crWarning("RTCritSectEnter failed rc %d", rc);
1029 }
1030}
1031
1032static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
1033{
1034 WindowInfo *window = (WindowInfo *) data1;
1035 renderspuVBoxCompositorSet(window, NULL);
1036}
1037
1038void renderspuVBoxCompositorClearAll()
1039{
1040 /* we need to clear window compositor, which is not that trivial though,
1041 * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
1042 * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
1043 * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
1044 * and the table can be modified from that thread only as well */
1045 crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
1046}
1047
1048const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
1049{
1050 int rc = RTCritSectEnter(&window->CompositorLock);
1051 if (RT_SUCCESS(rc))
1052 {
1053 const VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
1054 if (pCompositor)
1055 return pCompositor;
1056
1057 /* if no compositor is set, release the lock and return */
1058 RTCritSectLeave(&window->CompositorLock);
1059 }
1060 else
1061 {
1062 crWarning("RTCritSectEnter failed rc %d", rc);
1063 }
1064 return NULL;
1065}
1066
1067int renderspuVBoxCompositorLock(WindowInfo *window)
1068{
1069 int rc = RTCritSectEnter(&window->CompositorLock);
1070 AssertRC(rc);
1071 return rc;
1072}
1073
1074int renderspuVBoxCompositorUnlock(WindowInfo *window)
1075{
1076 int rc = RTCritSectLeave(&window->CompositorLock);
1077 AssertRC(rc);
1078 return rc;
1079}
1080
1081int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
1082{
1083 int rc = RTCritSectTryEnter(&window->CompositorLock);
1084 if (RT_SUCCESS(rc))
1085 {
1086 *ppCompositor = window->pCompositor;
1087 if (*ppCompositor)
1088 return VINF_SUCCESS;
1089
1090 /* if no compositor is set, release the lock and return */
1091 RTCritSectLeave(&window->CompositorLock);
1092 rc = VERR_INVALID_STATE;
1093 }
1094 else
1095 {
1096 *ppCompositor = NULL;
1097 }
1098 return rc;
1099}
1100
1101void renderspuVBoxCompositorRelease( WindowInfo *window)
1102{
1103 int rc;
1104 Assert(window->pCompositor);
1105 if (CrVrScrCompositorIsEmpty(window->pCompositor) && RTCritSectGetRecursion(&window->CompositorLock) == 1)
1106 window->pCompositor = NULL;
1107 rc = RTCritSectLeave(&window->CompositorLock);
1108 if (!RT_SUCCESS(rc))
1109 {
1110 crWarning("RTCritSectLeave failed rc %d", rc);
1111 }
1112}
1113
1114
1115/*
1116 * Set the current raster position to the given window coordinate.
1117 */
1118static void
1119SetRasterPos( GLint winX, GLint winY )
1120{
1121 GLfloat fx, fy;
1122
1123 /* Push current matrix mode and viewport attributes */
1124 render_spu.self.PushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
1125
1126 /* Setup projection parameters */
1127 render_spu.self.MatrixMode( GL_PROJECTION );
1128 render_spu.self.PushMatrix();
1129 render_spu.self.LoadIdentity();
1130 render_spu.self.MatrixMode( GL_MODELVIEW );
1131 render_spu.self.PushMatrix();
1132 render_spu.self.LoadIdentity();
1133
1134 render_spu.self.Viewport( winX - 1, winY - 1, 2, 2 );
1135
1136 /* set the raster (window) position */
1137 /* huh ? */
1138 fx = (GLfloat) (winX - (int) winX);
1139 fy = (GLfloat) (winY - (int) winY);
1140 render_spu.self.RasterPos4f( fx, fy, 0.0, 1.0 );
1141
1142 /* restore matrices, viewport and matrix mode */
1143 render_spu.self.PopMatrix();
1144 render_spu.self.MatrixMode( GL_PROJECTION );
1145 render_spu.self.PopMatrix();
1146
1147 render_spu.self.PopAttrib();
1148}
1149
1150
1151/*
1152 * Draw the mouse pointer bitmap at (x,y) in window coords.
1153 */
1154static void DrawCursor( GLint x, GLint y )
1155{
1156#define POINTER_WIDTH 32
1157#define POINTER_HEIGHT 32
1158 /* Somebody artistic could probably do better here */
1159 static const char *pointerImage[POINTER_HEIGHT] =
1160 {
1161 "XX..............................",
1162 "XXXX............................",
1163 ".XXXXX..........................",
1164 ".XXXXXXX........................",
1165 "..XXXXXXXX......................",
1166 "..XXXXXXXXXX....................",
1167 "...XXXXXXXXXXX..................",
1168 "...XXXXXXXXXXXXX................",
1169 "....XXXXXXXXXXXXXX..............",
1170 "....XXXXXXXXXXXXXXXX............",
1171 ".....XXXXXXXXXXXXXXXXX..........",
1172 ".....XXXXXXXXXXXXXXXXXXX........",
1173 "......XXXXXXXXXXXXXXXXXXXX......",
1174 "......XXXXXXXXXXXXXXXXXXXXXX....",
1175 ".......XXXXXXXXXXXXXXXXXXXXXXX..",
1176 ".......XXXXXXXXXXXXXXXXXXXXXXXX.",
1177 "........XXXXXXXXXXXXX...........",
1178 "........XXXXXXXX.XXXXX..........",
1179 ".........XXXXXX...XXXXX.........",
1180 ".........XXXXX.....XXXXX........",
1181 "..........XXX.......XXXXX.......",
1182 "..........XX.........XXXXX......",
1183 "......................XXXXX.....",
1184 ".......................XXXXX....",
1185 "........................XXX.....",
1186 ".........................X......",
1187 "................................",
1188 "................................",
1189 "................................",
1190 "................................",
1191 "................................",
1192 "................................"
1193
1194 };
1195 static GLubyte pointerBitmap[POINTER_HEIGHT][POINTER_WIDTH / 8];
1196 static GLboolean firstCall = GL_TRUE;
1197 GLboolean lighting, depthTest, scissorTest;
1198
1199 if (firstCall) {
1200 /* Convert pointerImage into pointerBitmap */
1201 GLint i, j;
1202 for (i = 0; i < POINTER_HEIGHT; i++) {
1203 for (j = 0; j < POINTER_WIDTH; j++) {
1204 if (pointerImage[POINTER_HEIGHT - i - 1][j] == 'X') {
1205 GLubyte bit = 128 >> (j & 0x7);
1206 pointerBitmap[i][j / 8] |= bit;
1207 }
1208 }
1209 }
1210 firstCall = GL_FALSE;
1211 }
1212
1213 render_spu.self.GetBooleanv(GL_LIGHTING, &lighting);
1214 render_spu.self.GetBooleanv(GL_DEPTH_TEST, &depthTest);
1215 render_spu.self.GetBooleanv(GL_SCISSOR_TEST, &scissorTest);
1216 render_spu.self.Disable(GL_LIGHTING);
1217 render_spu.self.Disable(GL_DEPTH_TEST);
1218 render_spu.self.Disable(GL_SCISSOR_TEST);
1219 render_spu.self.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1220
1221 render_spu.self.Color3f(1, 1, 1);
1222
1223 /* save current raster pos */
1224 render_spu.self.PushAttrib(GL_CURRENT_BIT);
1225 SetRasterPos(x, y);
1226 render_spu.self.Bitmap(POINTER_WIDTH, POINTER_HEIGHT, 1.0, 31.0, 0, 0,
1227 (const GLubyte *) pointerBitmap);
1228 /* restore current raster pos */
1229 render_spu.self.PopAttrib();
1230
1231 if (lighting)
1232 render_spu.self.Enable(GL_LIGHTING);
1233 if (depthTest)
1234 render_spu.self.Enable(GL_DEPTH_TEST);
1235 if (scissorTest)
1236 render_spu.self.Enable(GL_SCISSOR_TEST);
1237}
1238
1239void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags )
1240{
1241 WindowInfo *w = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1242
1243 if (!w)
1244 {
1245 crDebug("Render SPU: SwapBuffers invalid window id: %d", window);
1246 return;
1247 }
1248
1249 if (flags & CR_SUPPRESS_SWAP_BIT)
1250 {
1251 render_spu.self.Finish();
1252 return;
1253 }
1254
1255 if (render_spu.drawCursor)
1256 DrawCursor( render_spu.cursorX, render_spu.cursorY );
1257
1258 if (render_spu.swap_master_url)
1259 DoSync();
1260
1261 renderspu_SystemSwapBuffers( w, flags );
1262}
1263
1264
1265/*
1266 * Barrier functions
1267 * Normally, we'll have a crserver somewhere that handles the barrier calls.
1268 * However, if we're running the render SPU on the client node, then we
1269 * should handle barriers here. The threadtest demo illustrates this.
1270 * If we have N threads calling using this SPU we need these barrier
1271 * functions to synchronize them.
1272 */
1273
1274static void RENDER_APIENTRY renderspuBarrierCreateCR( GLuint name, GLuint count )
1275{
1276 Barrier *b;
1277
1278 if (render_spu.ignore_papi)
1279 return;
1280
1281 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1282 if (b) {
1283 /* HACK -- this allows everybody to create a barrier, and all
1284 but the first creation are ignored, assuming the count
1285 match. */
1286 if ( b->count != count ) {
1287 crError( "Render SPU: Barrier name=%u created with count=%u, but already "
1288 "exists with count=%u", name, count, b->count );
1289 }
1290 }
1291 else {
1292 b = (Barrier *) crAlloc( sizeof(Barrier) );
1293 b->count = count;
1294 crInitBarrier( &b->barrier, count );
1295 crHashtableAdd( render_spu.barrierHash, name, b );
1296 }
1297}
1298
1299static void RENDER_APIENTRY renderspuBarrierDestroyCR( GLuint name )
1300{
1301 if (render_spu.ignore_papi)
1302 return;
1303 crHashtableDelete( render_spu.barrierHash, name, crFree );
1304}
1305
1306static void RENDER_APIENTRY renderspuBarrierExecCR( GLuint name )
1307{
1308 Barrier *b;
1309
1310 if (render_spu.ignore_papi)
1311 return;
1312
1313 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1314 if (b) {
1315 crWaitBarrier( &(b->barrier) );
1316 }
1317 else {
1318 crWarning("Render SPU: Bad barrier name %d in BarrierExec()", name);
1319 }
1320}
1321
1322
1323/*
1324 * Semaphore functions
1325 * XXX we should probably implement these too, for the same reason as
1326 * barriers (see above).
1327 */
1328
1329static void RENDER_APIENTRY renderspuSemaphoreCreateCR( GLuint name, GLuint count )
1330{
1331 (void) name;
1332 (void) count;
1333}
1334
1335static void RENDER_APIENTRY renderspuSemaphoreDestroyCR( GLuint name )
1336{
1337 (void) name;
1338}
1339
1340static void RENDER_APIENTRY renderspuSemaphorePCR( GLuint name )
1341{
1342 (void) name;
1343}
1344
1345static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
1346{
1347 (void) name;
1348}
1349
1350
1351/*
1352 * Misc functions
1353 */
1354void renderspuSetDefaultSharedContext(ContextInfo *pCtx)
1355{
1356 if (pCtx == render_spu.defaultSharedContext)
1357 return;
1358
1359 renderspu_SystemDefaultSharedContextChanged(render_spu.defaultSharedContext, pCtx);
1360
1361 if (render_spu.defaultSharedContext)
1362 renderspuContextRelease(render_spu.defaultSharedContext);
1363
1364 if (pCtx)
1365 renderspuContextRetain(pCtx);
1366 render_spu.defaultSharedContext = pCtx;
1367}
1368
1369
1370static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
1371{
1372
1373 switch (target)
1374 {
1375 case GL_HH_SET_DEFAULT_SHARED_CTX:
1376 {
1377 ContextInfo * pCtx = NULL;
1378 if (value)
1379 pCtx = (ContextInfo *)crHashtableSearch(render_spu.contextTable, value);
1380 else
1381 crWarning("invalid default shared context id %d", value);
1382
1383 renderspuSetDefaultSharedContext(pCtx);
1384 break;
1385 }
1386 default:
1387// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
1388 break;
1389 }
1390}
1391
1392static void RENDER_APIENTRY
1393renderspuChromiumParameterfCR(GLenum target, GLfloat value)
1394{
1395 (void) target;
1396 (void) value;
1397
1398#if 0
1399 switch (target) {
1400 default:
1401 crWarning("Unhandled target in renderspuChromiumParameterfCR()");
1402 break;
1403 }
1404#endif
1405}
1406
1407
1408static void RENDER_APIENTRY
1409renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
1410 const GLvoid *values)
1411{
1412 int client_num;
1413 unsigned short port;
1414 CRMessage *msg, pingback;
1415 unsigned char *privbuf = NULL;
1416
1417 switch (target) {
1418
1419 case GL_GATHER_CONNECT_CR:
1420 if (render_spu.gather_userbuf_size)
1421 privbuf = (unsigned char *)crAlloc(1024*768*4);
1422
1423 port = ((GLint *) values)[0];
1424
1425 if (render_spu.gather_conns == NULL)
1426 render_spu.gather_conns = crAlloc(render_spu.server->numClients*sizeof(CRConnection *));
1427 else
1428 {
1429 crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
1430 }
1431
1432 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1433 {
1434 switch (render_spu.server->clients[client_num]->conn->type)
1435 {
1436 case CR_TCPIP:
1437 crDebug("Render SPU: AcceptClient from %s on %d",
1438 render_spu.server->clients[client_num]->conn->hostname, render_spu.gather_port);
1439 render_spu.gather_conns[client_num] =
1440 crNetAcceptClient("tcpip", NULL, port, 1024*1024, 1);
1441 break;
1442
1443 case CR_GM:
1444 render_spu.gather_conns[client_num] =
1445 crNetAcceptClient("gm", NULL, port, 1024*1024, 1);
1446 break;
1447
1448 default:
1449 crError("Render SPU: Unknown Network Type to Open Gather Connection");
1450 }
1451
1452
1453 if (render_spu.gather_userbuf_size)
1454 {
1455 render_spu.gather_conns[client_num]->userbuf = privbuf;
1456 render_spu.gather_conns[client_num]->userbuf_len = render_spu.gather_userbuf_size;
1457 }
1458 else
1459 {
1460 render_spu.gather_conns[client_num]->userbuf = NULL;
1461 render_spu.gather_conns[client_num]->userbuf_len = 0;
1462 }
1463
1464 if (render_spu.gather_conns[client_num])
1465 {
1466 crDebug("Render SPU: success! from %s", render_spu.gather_conns[client_num]->hostname);
1467 }
1468 }
1469
1470 break;
1471
1472 case GL_GATHER_DRAWPIXELS_CR:
1473 pingback.header.type = CR_MESSAGE_OOB;
1474
1475 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1476 {
1477 crNetGetMessage(render_spu.gather_conns[client_num], &msg);
1478 if (msg->header.type == CR_MESSAGE_GATHER)
1479 {
1480 crNetFree(render_spu.gather_conns[client_num], msg);
1481 }
1482 else
1483 {
1484 crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
1485 client_num, render_spu.server->numClients-1);
1486 }
1487 }
1488
1489 /*
1490 * We're only hitting the case if we're not actually calling
1491 * child.SwapBuffers from readback, so a switch about which
1492 * call to DoSync() we really want [this one, or the one
1493 * in SwapBuffers above] is not necessary -- karl
1494 */
1495
1496 if (render_spu.swap_master_url)
1497 DoSync();
1498
1499 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1500 crNetSend(render_spu.gather_conns[client_num], NULL, &pingback,
1501 sizeof(CRMessageHeader));
1502
1503 render_spu.self.RasterPos2i(((GLint *)values)[0], ((GLint *)values)[1]);
1504 render_spu.self.DrawPixels( ((GLint *)values)[2], ((GLint *)values)[3],
1505 ((GLint *)values)[4], ((GLint *)values)[5],
1506 render_spu.gather_conns[0]->userbuf);
1507
1508
1509 render_spu.self.SwapBuffers(((GLint *)values)[6], 0);
1510 break;
1511
1512 case GL_CURSOR_POSITION_CR:
1513 if (type == GL_INT && count == 2) {
1514 render_spu.cursorX = ((GLint *) values)[0];
1515 render_spu.cursorY = ((GLint *) values)[1];
1516 crDebug("Render SPU: GL_CURSOR_POSITION_CR (%d, %d)", render_spu.cursorX, render_spu.cursorY);
1517 }
1518 else {
1519 crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
1520 }
1521 break;
1522
1523 case GL_WINDOW_SIZE_CR:
1524 /* XXX this is old code that should be removed.
1525 * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
1526 */
1527 {
1528 GLint w, h;
1529 WindowInfo *window;
1530 CRASSERT(type == GL_INT);
1531 CRASSERT(count == 2);
1532 CRASSERT(values);
1533 w = ((GLint*)values)[0];
1534 h = ((GLint*)values)[1];
1535 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
1536 if (window)
1537 {
1538 renderspu_SystemWindowSize(window, w, h);
1539 }
1540 }
1541 break;
1542
1543 case GL_HH_SET_TMPCTX_MAKE_CURRENT:
1544 if (type == GL_BYTE && count == sizeof (void*))
1545 memcpy(&render_spu.blitterDispatch.MakeCurrent, values, count);
1546 else
1547 WARN(("unexpected type(%#x) - count(%d) pair", type, count));
1548 break;
1549
1550 default:
1551#if 0
1552 WARN(("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target));
1553#endif
1554 break;
1555 }
1556}
1557
1558
1559static void RENDER_APIENTRY
1560renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
1561 GLsizei count, GLvoid *values)
1562{
1563 switch (target) {
1564 case GL_WINDOW_SIZE_CR:
1565 {
1566 GLint x, y, w, h, *size = (GLint *) values;
1567 WindowInfo *window;
1568 CRASSERT(type == GL_INT);
1569 CRASSERT(count == 2);
1570 CRASSERT(values);
1571 size[0] = size[1] = 0; /* default */
1572 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1573 if (window)
1574 {
1575 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1576 size[0] = w;
1577 size[1] = h;
1578 }
1579 }
1580 break;
1581 case GL_WINDOW_POSITION_CR:
1582 /* return window position, as a screen coordinate */
1583 {
1584 GLint *pos = (GLint *) values;
1585 GLint x, y, w, h;
1586 WindowInfo *window;
1587 CRASSERT(type == GL_INT);
1588 CRASSERT(count == 2);
1589 CRASSERT(values);
1590 pos[0] = pos[1] = 0; /* default */
1591 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1592 if (window)
1593 {
1594 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1595 pos[0] = x;/*window->x;*/
1596 pos[1] = y;/*window->y;*/
1597 }
1598 }
1599 break;
1600 case GL_MAX_WINDOW_SIZE_CR:
1601 {
1602 GLint *maxSize = (GLint *) values;
1603 WindowInfo *window;
1604 CRASSERT(type == GL_INT);
1605 CRASSERT(count == 2);
1606 CRASSERT(values);
1607 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1608 if (window)
1609 {
1610 renderspu_SystemGetMaxWindowSize(window, maxSize + 0, maxSize + 1);
1611 }
1612 }
1613 break;
1614 case GL_WINDOW_VISIBILITY_CR:
1615 {
1616 GLint *vis = (GLint *) values;
1617 WindowInfo *window;
1618 CRASSERT(type == GL_INT);
1619 CRASSERT(count == 1);
1620 CRASSERT(values);
1621 vis[0] = 0; /* default */
1622 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1623 if (window)
1624 {
1625 vis[0] = window->visible;
1626 }
1627 }
1628 break;
1629 default:
1630 ; /* nothing - silence compiler */
1631 }
1632}
1633
1634
1635static void RENDER_APIENTRY
1636renderspuBoundsInfoCR( CRrecti *bounds, GLbyte *payload, GLint len,
1637 GLint num_opcodes )
1638{
1639 (void) bounds;
1640 (void) payload;
1641 (void) len;
1642 (void) num_opcodes;
1643 /* draw the bounding box */
1644 if (render_spu.draw_bbox) {
1645 GET_CONTEXT(context);
1646 WindowInfo *window = context->currentWindow;
1647 GLint x, y, w, h;
1648
1649 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1650
1651 render_spu.self.PushMatrix();
1652 render_spu.self.LoadIdentity();
1653 render_spu.self.MatrixMode(GL_PROJECTION);
1654 render_spu.self.PushMatrix();
1655 render_spu.self.LoadIdentity();
1656 render_spu.self.Ortho(0, w, 0, h, -1, 1);
1657 render_spu.self.Color3f(1, 1, 1);
1658 render_spu.self.Begin(GL_LINE_LOOP);
1659 render_spu.self.Vertex2i(bounds->x1, bounds->y1);
1660 render_spu.self.Vertex2i(bounds->x2, bounds->y1);
1661 render_spu.self.Vertex2i(bounds->x2, bounds->y2);
1662 render_spu.self.Vertex2i(bounds->x1, bounds->y2);
1663 render_spu.self.End();
1664 render_spu.self.PopMatrix();
1665 render_spu.self.MatrixMode(GL_MODELVIEW);
1666 render_spu.self.PopMatrix();
1667 }
1668}
1669
1670
1671static void RENDER_APIENTRY
1672renderspuWriteback( GLint *writeback )
1673{
1674 (void) writeback;
1675}
1676
1677
1678static void
1679remove_trailing_space(char *s)
1680{
1681 int k = crStrlen(s);
1682 while (k > 0 && s[k-1] == ' ')
1683 k--;
1684 s[k] = 0;
1685}
1686
1687static const GLubyte * RENDER_APIENTRY
1688renderspuGetString(GLenum pname)
1689{
1690 static char tempStr[1000];
1691 GET_CONTEXT(context);
1692
1693 if (pname == GL_EXTENSIONS)
1694 {
1695 const char *nativeExt;
1696 char *crExt, *s1, *s2;
1697
1698 if (!render_spu.ws.glGetString)
1699 return NULL;
1700
1701 nativeExt = (const char *) render_spu.ws.glGetString(GL_EXTENSIONS);
1702 if (!nativeExt) {
1703 /* maybe called w/out current context. */
1704 return NULL;
1705 }
1706
1707 crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
1708 s1 = crStrIntersect(nativeExt, crExt);
1709 remove_trailing_space(s1);
1710 s2 = crStrjoin3(s1, " ", crChromiumExtensions);
1711 remove_trailing_space(s2);
1712 crFree(crExt);
1713 crFree(s1);
1714 if (context->extensionString)
1715 crFree(context->extensionString);
1716 context->extensionString = s2;
1717 return (const GLubyte *) s2;
1718 }
1719 else if (pname == GL_VENDOR)
1720 return (const GLubyte *) CR_VENDOR;
1721 else if (pname == GL_VERSION)
1722 return render_spu.ws.glGetString(GL_VERSION);
1723 else if (pname == GL_RENDERER) {
1724#ifdef VBOX
1725 snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1726#else
1727 sprintf(tempStr, "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1728#endif
1729 return (const GLubyte *) tempStr;
1730 }
1731#ifdef CR_OPENGL_VERSION_2_0
1732 else if (pname == GL_SHADING_LANGUAGE_VERSION)
1733 return render_spu.ws.glGetString(GL_SHADING_LANGUAGE_VERSION);
1734#endif
1735#ifdef GL_CR_real_vendor_strings
1736 else if (pname == GL_REAL_VENDOR)
1737 return render_spu.ws.glGetString(GL_VENDOR);
1738 else if (pname == GL_REAL_VERSION)
1739 return render_spu.ws.glGetString(GL_VERSION);
1740 else if (pname == GL_REAL_RENDERER)
1741 return render_spu.ws.glGetString(GL_RENDERER);
1742 else if (pname == GL_REAL_EXTENSIONS)
1743 return render_spu.ws.glGetString(GL_EXTENSIONS);
1744#endif
1745 else
1746 return NULL;
1747}
1748
1749static void renderspuReparentWindowCB(unsigned long key, void *data1, void *data2)
1750{
1751 WindowInfo *pWindow = (WindowInfo *)data1;
1752
1753 renderspu_SystemReparentWindow(pWindow);
1754}
1755
1756DECLEXPORT(void) renderspuReparentWindow(GLint window)
1757{
1758 WindowInfo *pWindow;
1759 CRASSERT(window >= 0);
1760
1761 pWindow = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1762
1763 if (!pWindow)
1764 {
1765 crDebug("Render SPU: Attempt to reparent invalid window (%d)", window);
1766 return;
1767 }
1768
1769 renderspu_SystemReparentWindow(pWindow);
1770
1771 /* special case: reparent all internal windows as well */
1772 if (window == CR_RENDER_DEFAULT_WINDOW_ID)
1773 {
1774 crHashtableWalk(render_spu.dummyWindowTable, renderspuReparentWindowCB, NULL);
1775 }
1776}
1777
1778#define FILLIN( NAME, FUNC ) \
1779 table[i].name = crStrdup(NAME); \
1780 table[i].fn = (SPUGenericFunction) FUNC; \
1781 i++;
1782
1783
1784/* These are the functions which the render SPU implements, not OpenGL.
1785 */
1786int
1787renderspuCreateFunctions(SPUNamedFunctionTable table[])
1788{
1789 int i = 0;
1790 FILLIN( "SwapBuffers", renderspuSwapBuffers );
1791 FILLIN( "CreateContext", renderspuCreateContext );
1792 FILLIN( "DestroyContext", renderspuDestroyContext );
1793 FILLIN( "MakeCurrent", renderspuMakeCurrent );
1794 FILLIN( "WindowCreate", renderspuWindowCreate );
1795 FILLIN( "WindowDestroy", renderspuWindowDestroy );
1796 FILLIN( "WindowSize", renderspuWindowSize );
1797 FILLIN( "WindowPosition", renderspuWindowPosition );
1798 FILLIN( "WindowVisibleRegion", renderspuWindowVisibleRegion );
1799 FILLIN( "WindowShow", renderspuWindowShow );
1800 FILLIN( "BarrierCreateCR", renderspuBarrierCreateCR );
1801 FILLIN( "BarrierDestroyCR", renderspuBarrierDestroyCR );
1802 FILLIN( "BarrierExecCR", renderspuBarrierExecCR );
1803 FILLIN( "BoundsInfoCR", renderspuBoundsInfoCR );
1804 FILLIN( "SemaphoreCreateCR", renderspuSemaphoreCreateCR );
1805 FILLIN( "SemaphoreDestroyCR", renderspuSemaphoreDestroyCR );
1806 FILLIN( "SemaphorePCR", renderspuSemaphorePCR );
1807 FILLIN( "SemaphoreVCR", renderspuSemaphoreVCR );
1808 FILLIN( "Writeback", renderspuWriteback );
1809 FILLIN( "ChromiumParameteriCR", renderspuChromiumParameteriCR );
1810 FILLIN( "ChromiumParameterfCR", renderspuChromiumParameterfCR );
1811 FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
1812 FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
1813 FILLIN( "GetString", renderspuGetString );
1814 FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
1815 return i;
1816}
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