VirtualBox

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

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

crOpenGL: saved state fixes, misc fixes

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