VirtualBox

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

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

crOpenGL/OSX: bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 55.1 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 )
949{
950 PCR_BLITTER 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, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
1004{
1005 PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
1006 if (!pBlitter)
1007 return;
1008
1009 renderspuVBoxCompositorBlit(pCompositor, pBlitter);
1010
1011 renderspu_SystemSwapBuffers(window, 0);
1012
1013 CrBltLeave(pBlitter);
1014}
1015
1016void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
1017{
1018 int rc;
1019 /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
1020 * no need to synch here
1021 * the lock is actually needed to ensure we're in synch with the redraw thread */
1022 if (window->pCompositor == pCompositor)
1023 return;
1024 rc = RTCritSectEnter(&window->CompositorLock);
1025 if (RT_SUCCESS(rc))
1026 {
1027 window->pCompositor = pCompositor;
1028 RTCritSectLeave(&window->CompositorLock);
1029 return;
1030 }
1031 else
1032 {
1033 crWarning("RTCritSectEnter failed rc %d", rc);
1034 }
1035}
1036
1037static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
1038{
1039 WindowInfo *window = (WindowInfo *) data1;
1040 renderspuVBoxCompositorSet(window, NULL);
1041}
1042
1043void renderspuVBoxCompositorClearAll()
1044{
1045 /* we need to clear window compositor, which is not that trivial though,
1046 * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
1047 * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
1048 * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
1049 * and the table can be modified from that thread only as well */
1050 crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
1051}
1052
1053const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
1054{
1055 int rc = RTCritSectEnter(&window->CompositorLock);
1056 if (RT_SUCCESS(rc))
1057 {
1058 const VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
1059 if (pCompositor)
1060 return pCompositor;
1061
1062 /* if no compositor is set, release the lock and return */
1063 RTCritSectLeave(&window->CompositorLock);
1064 }
1065 else
1066 {
1067 crWarning("RTCritSectEnter failed rc %d", rc);
1068 }
1069 return NULL;
1070}
1071
1072int renderspuVBoxCompositorLock(WindowInfo *window)
1073{
1074 int rc = RTCritSectEnter(&window->CompositorLock);
1075 AssertRC(rc);
1076 return rc;
1077}
1078
1079int renderspuVBoxCompositorUnlock(WindowInfo *window)
1080{
1081 int rc = RTCritSectLeave(&window->CompositorLock);
1082 AssertRC(rc);
1083 return rc;
1084}
1085
1086int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
1087{
1088 int rc = RTCritSectTryEnter(&window->CompositorLock);
1089 if (RT_SUCCESS(rc))
1090 {
1091 *ppCompositor = window->pCompositor;
1092 if (*ppCompositor)
1093 return VINF_SUCCESS;
1094
1095 /* if no compositor is set, release the lock and return */
1096 RTCritSectLeave(&window->CompositorLock);
1097 rc = VERR_INVALID_STATE;
1098 }
1099 else
1100 {
1101 *ppCompositor = NULL;
1102 }
1103 return rc;
1104}
1105
1106void renderspuVBoxCompositorRelease( WindowInfo *window)
1107{
1108 int rc;
1109 Assert(window->pCompositor);
1110 if (CrVrScrCompositorIsEmpty(window->pCompositor) && RTCritSectGetRecursion(&window->CompositorLock) == 1)
1111 window->pCompositor = NULL;
1112 rc = RTCritSectLeave(&window->CompositorLock);
1113 if (!RT_SUCCESS(rc))
1114 {
1115 crWarning("RTCritSectLeave failed rc %d", rc);
1116 }
1117}
1118
1119
1120/*
1121 * Set the current raster position to the given window coordinate.
1122 */
1123static void
1124SetRasterPos( GLint winX, GLint winY )
1125{
1126 GLfloat fx, fy;
1127
1128 /* Push current matrix mode and viewport attributes */
1129 render_spu.self.PushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT );
1130
1131 /* Setup projection parameters */
1132 render_spu.self.MatrixMode( GL_PROJECTION );
1133 render_spu.self.PushMatrix();
1134 render_spu.self.LoadIdentity();
1135 render_spu.self.MatrixMode( GL_MODELVIEW );
1136 render_spu.self.PushMatrix();
1137 render_spu.self.LoadIdentity();
1138
1139 render_spu.self.Viewport( winX - 1, winY - 1, 2, 2 );
1140
1141 /* set the raster (window) position */
1142 /* huh ? */
1143 fx = (GLfloat) (winX - (int) winX);
1144 fy = (GLfloat) (winY - (int) winY);
1145 render_spu.self.RasterPos4f( fx, fy, 0.0, 1.0 );
1146
1147 /* restore matrices, viewport and matrix mode */
1148 render_spu.self.PopMatrix();
1149 render_spu.self.MatrixMode( GL_PROJECTION );
1150 render_spu.self.PopMatrix();
1151
1152 render_spu.self.PopAttrib();
1153}
1154
1155
1156/*
1157 * Draw the mouse pointer bitmap at (x,y) in window coords.
1158 */
1159static void DrawCursor( GLint x, GLint y )
1160{
1161#define POINTER_WIDTH 32
1162#define POINTER_HEIGHT 32
1163 /* Somebody artistic could probably do better here */
1164 static const char *pointerImage[POINTER_HEIGHT] =
1165 {
1166 "XX..............................",
1167 "XXXX............................",
1168 ".XXXXX..........................",
1169 ".XXXXXXX........................",
1170 "..XXXXXXXX......................",
1171 "..XXXXXXXXXX....................",
1172 "...XXXXXXXXXXX..................",
1173 "...XXXXXXXXXXXXX................",
1174 "....XXXXXXXXXXXXXX..............",
1175 "....XXXXXXXXXXXXXXXX............",
1176 ".....XXXXXXXXXXXXXXXXX..........",
1177 ".....XXXXXXXXXXXXXXXXXXX........",
1178 "......XXXXXXXXXXXXXXXXXXXX......",
1179 "......XXXXXXXXXXXXXXXXXXXXXX....",
1180 ".......XXXXXXXXXXXXXXXXXXXXXXX..",
1181 ".......XXXXXXXXXXXXXXXXXXXXXXXX.",
1182 "........XXXXXXXXXXXXX...........",
1183 "........XXXXXXXX.XXXXX..........",
1184 ".........XXXXXX...XXXXX.........",
1185 ".........XXXXX.....XXXXX........",
1186 "..........XXX.......XXXXX.......",
1187 "..........XX.........XXXXX......",
1188 "......................XXXXX.....",
1189 ".......................XXXXX....",
1190 "........................XXX.....",
1191 ".........................X......",
1192 "................................",
1193 "................................",
1194 "................................",
1195 "................................",
1196 "................................",
1197 "................................"
1198
1199 };
1200 static GLubyte pointerBitmap[POINTER_HEIGHT][POINTER_WIDTH / 8];
1201 static GLboolean firstCall = GL_TRUE;
1202 GLboolean lighting, depthTest, scissorTest;
1203
1204 if (firstCall) {
1205 /* Convert pointerImage into pointerBitmap */
1206 GLint i, j;
1207 for (i = 0; i < POINTER_HEIGHT; i++) {
1208 for (j = 0; j < POINTER_WIDTH; j++) {
1209 if (pointerImage[POINTER_HEIGHT - i - 1][j] == 'X') {
1210 GLubyte bit = 128 >> (j & 0x7);
1211 pointerBitmap[i][j / 8] |= bit;
1212 }
1213 }
1214 }
1215 firstCall = GL_FALSE;
1216 }
1217
1218 render_spu.self.GetBooleanv(GL_LIGHTING, &lighting);
1219 render_spu.self.GetBooleanv(GL_DEPTH_TEST, &depthTest);
1220 render_spu.self.GetBooleanv(GL_SCISSOR_TEST, &scissorTest);
1221 render_spu.self.Disable(GL_LIGHTING);
1222 render_spu.self.Disable(GL_DEPTH_TEST);
1223 render_spu.self.Disable(GL_SCISSOR_TEST);
1224 render_spu.self.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
1225
1226 render_spu.self.Color3f(1, 1, 1);
1227
1228 /* save current raster pos */
1229 render_spu.self.PushAttrib(GL_CURRENT_BIT);
1230 SetRasterPos(x, y);
1231 render_spu.self.Bitmap(POINTER_WIDTH, POINTER_HEIGHT, 1.0, 31.0, 0, 0,
1232 (const GLubyte *) pointerBitmap);
1233 /* restore current raster pos */
1234 render_spu.self.PopAttrib();
1235
1236 if (lighting)
1237 render_spu.self.Enable(GL_LIGHTING);
1238 if (depthTest)
1239 render_spu.self.Enable(GL_DEPTH_TEST);
1240 if (scissorTest)
1241 render_spu.self.Enable(GL_SCISSOR_TEST);
1242}
1243
1244void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags )
1245{
1246 WindowInfo *w = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1247
1248 if (!w)
1249 {
1250 crDebug("Render SPU: SwapBuffers invalid window id: %d", window);
1251 return;
1252 }
1253
1254 if (flags & CR_SUPPRESS_SWAP_BIT)
1255 {
1256 render_spu.self.Finish();
1257 return;
1258 }
1259
1260 if (render_spu.drawCursor)
1261 DrawCursor( render_spu.cursorX, render_spu.cursorY );
1262
1263 if (render_spu.swap_master_url)
1264 DoSync();
1265
1266 renderspu_SystemSwapBuffers( w, flags );
1267}
1268
1269
1270/*
1271 * Barrier functions
1272 * Normally, we'll have a crserver somewhere that handles the barrier calls.
1273 * However, if we're running the render SPU on the client node, then we
1274 * should handle barriers here. The threadtest demo illustrates this.
1275 * If we have N threads calling using this SPU we need these barrier
1276 * functions to synchronize them.
1277 */
1278
1279static void RENDER_APIENTRY renderspuBarrierCreateCR( GLuint name, GLuint count )
1280{
1281 Barrier *b;
1282
1283 if (render_spu.ignore_papi)
1284 return;
1285
1286 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1287 if (b) {
1288 /* HACK -- this allows everybody to create a barrier, and all
1289 but the first creation are ignored, assuming the count
1290 match. */
1291 if ( b->count != count ) {
1292 crError( "Render SPU: Barrier name=%u created with count=%u, but already "
1293 "exists with count=%u", name, count, b->count );
1294 }
1295 }
1296 else {
1297 b = (Barrier *) crAlloc( sizeof(Barrier) );
1298 b->count = count;
1299 crInitBarrier( &b->barrier, count );
1300 crHashtableAdd( render_spu.barrierHash, name, b );
1301 }
1302}
1303
1304static void RENDER_APIENTRY renderspuBarrierDestroyCR( GLuint name )
1305{
1306 if (render_spu.ignore_papi)
1307 return;
1308 crHashtableDelete( render_spu.barrierHash, name, crFree );
1309}
1310
1311static void RENDER_APIENTRY renderspuBarrierExecCR( GLuint name )
1312{
1313 Barrier *b;
1314
1315 if (render_spu.ignore_papi)
1316 return;
1317
1318 b = (Barrier *) crHashtableSearch( render_spu.barrierHash, name );
1319 if (b) {
1320 crWaitBarrier( &(b->barrier) );
1321 }
1322 else {
1323 crWarning("Render SPU: Bad barrier name %d in BarrierExec()", name);
1324 }
1325}
1326
1327
1328/*
1329 * Semaphore functions
1330 * XXX we should probably implement these too, for the same reason as
1331 * barriers (see above).
1332 */
1333
1334static void RENDER_APIENTRY renderspuSemaphoreCreateCR( GLuint name, GLuint count )
1335{
1336 (void) name;
1337 (void) count;
1338}
1339
1340static void RENDER_APIENTRY renderspuSemaphoreDestroyCR( GLuint name )
1341{
1342 (void) name;
1343}
1344
1345static void RENDER_APIENTRY renderspuSemaphorePCR( GLuint name )
1346{
1347 (void) name;
1348}
1349
1350static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
1351{
1352 (void) name;
1353}
1354
1355
1356/*
1357 * Misc functions
1358 */
1359void renderspuSetDefaultSharedContext(ContextInfo *pCtx)
1360{
1361 if (pCtx == render_spu.defaultSharedContext)
1362 return;
1363
1364 renderspu_SystemDefaultSharedContextChanged(render_spu.defaultSharedContext, pCtx);
1365
1366 if (render_spu.defaultSharedContext)
1367 renderspuContextRelease(render_spu.defaultSharedContext);
1368
1369 if (pCtx)
1370 renderspuContextRetain(pCtx);
1371 render_spu.defaultSharedContext = pCtx;
1372}
1373
1374static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
1375{
1376 switch (target)
1377 {
1378 case GL_HH_SET_DEFAULT_SHARED_CTX:
1379 {
1380 ContextInfo * pCtx = NULL;
1381 if (value)
1382 pCtx = (ContextInfo *)crHashtableSearch(render_spu.contextTable, value);
1383 else
1384 crWarning("invalid default shared context id %d", value);
1385
1386 renderspuSetDefaultSharedContext(pCtx);
1387 break;
1388 }
1389 case GL_HH_RENDERTHREAD_INFORM:
1390 {
1391 if (value)
1392 {
1393 int rc = renderspuDefaultCtxInit();
1394 if (RT_FAILURE(rc))
1395 {
1396 WARN(("renderspuDefaultCtxInit failed"));
1397 break;
1398 }
1399 }
1400 else
1401 {
1402 renderspuCleanupBase(false);
1403 }
1404 break;
1405 }
1406 default:
1407// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
1408 break;
1409 }
1410}
1411
1412static void RENDER_APIENTRY
1413renderspuChromiumParameterfCR(GLenum target, GLfloat value)
1414{
1415 (void) target;
1416 (void) value;
1417
1418#if 0
1419 switch (target) {
1420 default:
1421 crWarning("Unhandled target in renderspuChromiumParameterfCR()");
1422 break;
1423 }
1424#endif
1425}
1426
1427
1428static void RENDER_APIENTRY
1429renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
1430 const GLvoid *values)
1431{
1432 int client_num;
1433 unsigned short port;
1434 CRMessage *msg, pingback;
1435 unsigned char *privbuf = NULL;
1436
1437 switch (target) {
1438
1439 case GL_GATHER_CONNECT_CR:
1440 if (render_spu.gather_userbuf_size)
1441 privbuf = (unsigned char *)crAlloc(1024*768*4);
1442
1443 port = ((GLint *) values)[0];
1444
1445 if (render_spu.gather_conns == NULL)
1446 render_spu.gather_conns = crAlloc(render_spu.server->numClients*sizeof(CRConnection *));
1447 else
1448 {
1449 crError("Oh bother! duplicate GL_GATHER_CONNECT_CR getting through");
1450 }
1451
1452 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1453 {
1454 switch (render_spu.server->clients[client_num]->conn->type)
1455 {
1456 case CR_TCPIP:
1457 crDebug("Render SPU: AcceptClient from %s on %d",
1458 render_spu.server->clients[client_num]->conn->hostname, render_spu.gather_port);
1459 render_spu.gather_conns[client_num] =
1460 crNetAcceptClient("tcpip", NULL, port, 1024*1024, 1);
1461 break;
1462
1463 case CR_GM:
1464 render_spu.gather_conns[client_num] =
1465 crNetAcceptClient("gm", NULL, port, 1024*1024, 1);
1466 break;
1467
1468 default:
1469 crError("Render SPU: Unknown Network Type to Open Gather Connection");
1470 }
1471
1472
1473 if (render_spu.gather_userbuf_size)
1474 {
1475 render_spu.gather_conns[client_num]->userbuf = privbuf;
1476 render_spu.gather_conns[client_num]->userbuf_len = render_spu.gather_userbuf_size;
1477 }
1478 else
1479 {
1480 render_spu.gather_conns[client_num]->userbuf = NULL;
1481 render_spu.gather_conns[client_num]->userbuf_len = 0;
1482 }
1483
1484 if (render_spu.gather_conns[client_num])
1485 {
1486 crDebug("Render SPU: success! from %s", render_spu.gather_conns[client_num]->hostname);
1487 }
1488 }
1489
1490 break;
1491
1492 case GL_GATHER_DRAWPIXELS_CR:
1493 pingback.header.type = CR_MESSAGE_OOB;
1494
1495 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1496 {
1497 crNetGetMessage(render_spu.gather_conns[client_num], &msg);
1498 if (msg->header.type == CR_MESSAGE_GATHER)
1499 {
1500 crNetFree(render_spu.gather_conns[client_num], msg);
1501 }
1502 else
1503 {
1504 crError("Render SPU: expecting MESSAGE_GATHER. got crap! (%d of %d)",
1505 client_num, render_spu.server->numClients-1);
1506 }
1507 }
1508
1509 /*
1510 * We're only hitting the case if we're not actually calling
1511 * child.SwapBuffers from readback, so a switch about which
1512 * call to DoSync() we really want [this one, or the one
1513 * in SwapBuffers above] is not necessary -- karl
1514 */
1515
1516 if (render_spu.swap_master_url)
1517 DoSync();
1518
1519 for (client_num=0; client_num< render_spu.server->numClients; client_num++)
1520 crNetSend(render_spu.gather_conns[client_num], NULL, &pingback,
1521 sizeof(CRMessageHeader));
1522
1523 render_spu.self.RasterPos2i(((GLint *)values)[0], ((GLint *)values)[1]);
1524 render_spu.self.DrawPixels( ((GLint *)values)[2], ((GLint *)values)[3],
1525 ((GLint *)values)[4], ((GLint *)values)[5],
1526 render_spu.gather_conns[0]->userbuf);
1527
1528
1529 render_spu.self.SwapBuffers(((GLint *)values)[6], 0);
1530 break;
1531
1532 case GL_CURSOR_POSITION_CR:
1533 if (type == GL_INT && count == 2) {
1534 render_spu.cursorX = ((GLint *) values)[0];
1535 render_spu.cursorY = ((GLint *) values)[1];
1536 crDebug("Render SPU: GL_CURSOR_POSITION_CR (%d, %d)", render_spu.cursorX, render_spu.cursorY);
1537 }
1538 else {
1539 crWarning("Render SPU: Bad type or count for ChromiumParametervCR(GL_CURSOR_POSITION_CR)");
1540 }
1541 break;
1542
1543 case GL_WINDOW_SIZE_CR:
1544 /* XXX this is old code that should be removed.
1545 * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
1546 */
1547 {
1548 GLint w, h;
1549 WindowInfo *window;
1550 CRASSERT(type == GL_INT);
1551 CRASSERT(count == 2);
1552 CRASSERT(values);
1553 w = ((GLint*)values)[0];
1554 h = ((GLint*)values)[1];
1555 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
1556 if (window)
1557 {
1558 renderspu_SystemWindowSize(window, w, h);
1559 }
1560 }
1561 break;
1562
1563 case GL_HH_SET_TMPCTX_MAKE_CURRENT:
1564 if (type == GL_BYTE && count == sizeof (void*))
1565 memcpy(&render_spu.blitterDispatch.MakeCurrent, values, count);
1566 else
1567 WARN(("unexpected type(%#x) - count(%d) pair", type, count));
1568 break;
1569
1570 default:
1571#if 0
1572 WARN(("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target));
1573#endif
1574 break;
1575 }
1576}
1577
1578
1579static void RENDER_APIENTRY
1580renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
1581 GLsizei count, GLvoid *values)
1582{
1583 switch (target) {
1584 case GL_WINDOW_SIZE_CR:
1585 {
1586 GLint x, y, w, h, *size = (GLint *) values;
1587 WindowInfo *window;
1588 CRASSERT(type == GL_INT);
1589 CRASSERT(count == 2);
1590 CRASSERT(values);
1591 size[0] = size[1] = 0; /* default */
1592 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1593 if (window)
1594 {
1595 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1596 size[0] = w;
1597 size[1] = h;
1598 }
1599 }
1600 break;
1601 case GL_WINDOW_POSITION_CR:
1602 /* return window position, as a screen coordinate */
1603 {
1604 GLint *pos = (GLint *) values;
1605 GLint x, y, w, h;
1606 WindowInfo *window;
1607 CRASSERT(type == GL_INT);
1608 CRASSERT(count == 2);
1609 CRASSERT(values);
1610 pos[0] = pos[1] = 0; /* default */
1611 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1612 if (window)
1613 {
1614 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1615 pos[0] = x;/*window->x;*/
1616 pos[1] = y;/*window->y;*/
1617 }
1618 }
1619 break;
1620 case GL_MAX_WINDOW_SIZE_CR:
1621 {
1622 GLint *maxSize = (GLint *) values;
1623 WindowInfo *window;
1624 CRASSERT(type == GL_INT);
1625 CRASSERT(count == 2);
1626 CRASSERT(values);
1627 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1628 if (window)
1629 {
1630 renderspu_SystemGetMaxWindowSize(window, maxSize + 0, maxSize + 1);
1631 }
1632 }
1633 break;
1634 case GL_WINDOW_VISIBILITY_CR:
1635 {
1636 GLint *vis = (GLint *) values;
1637 WindowInfo *window;
1638 CRASSERT(type == GL_INT);
1639 CRASSERT(count == 1);
1640 CRASSERT(values);
1641 vis[0] = 0; /* default */
1642 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
1643 if (window)
1644 {
1645 vis[0] = window->visible;
1646 }
1647 }
1648 break;
1649 default:
1650 ; /* nothing - silence compiler */
1651 }
1652}
1653
1654
1655static void RENDER_APIENTRY
1656renderspuBoundsInfoCR( CRrecti *bounds, GLbyte *payload, GLint len,
1657 GLint num_opcodes )
1658{
1659 (void) bounds;
1660 (void) payload;
1661 (void) len;
1662 (void) num_opcodes;
1663 /* draw the bounding box */
1664 if (render_spu.draw_bbox) {
1665 GET_CONTEXT(context);
1666 WindowInfo *window = context->currentWindow;
1667 GLint x, y, w, h;
1668
1669 renderspu_SystemGetWindowGeometry(window, &x, &y, &w, &h);
1670
1671 render_spu.self.PushMatrix();
1672 render_spu.self.LoadIdentity();
1673 render_spu.self.MatrixMode(GL_PROJECTION);
1674 render_spu.self.PushMatrix();
1675 render_spu.self.LoadIdentity();
1676 render_spu.self.Ortho(0, w, 0, h, -1, 1);
1677 render_spu.self.Color3f(1, 1, 1);
1678 render_spu.self.Begin(GL_LINE_LOOP);
1679 render_spu.self.Vertex2i(bounds->x1, bounds->y1);
1680 render_spu.self.Vertex2i(bounds->x2, bounds->y1);
1681 render_spu.self.Vertex2i(bounds->x2, bounds->y2);
1682 render_spu.self.Vertex2i(bounds->x1, bounds->y2);
1683 render_spu.self.End();
1684 render_spu.self.PopMatrix();
1685 render_spu.self.MatrixMode(GL_MODELVIEW);
1686 render_spu.self.PopMatrix();
1687 }
1688}
1689
1690
1691static void RENDER_APIENTRY
1692renderspuWriteback( GLint *writeback )
1693{
1694 (void) writeback;
1695}
1696
1697
1698static void
1699remove_trailing_space(char *s)
1700{
1701 int k = crStrlen(s);
1702 while (k > 0 && s[k-1] == ' ')
1703 k--;
1704 s[k] = 0;
1705}
1706
1707static const GLubyte * RENDER_APIENTRY
1708renderspuGetString(GLenum pname)
1709{
1710 static char tempStr[1000];
1711 GET_CONTEXT(context);
1712
1713 if (pname == GL_EXTENSIONS)
1714 {
1715 const char *nativeExt;
1716 char *crExt, *s1, *s2;
1717
1718 if (!render_spu.ws.glGetString)
1719 return NULL;
1720
1721 nativeExt = (const char *) render_spu.ws.glGetString(GL_EXTENSIONS);
1722 if (!nativeExt) {
1723 /* maybe called w/out current context. */
1724 return NULL;
1725 }
1726
1727 if (!context)
1728 return (const GLubyte *)nativeExt;
1729
1730 crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
1731 s1 = crStrIntersect(nativeExt, crExt);
1732 remove_trailing_space(s1);
1733 s2 = crStrjoin3(s1, " ", crChromiumExtensions);
1734 remove_trailing_space(s2);
1735 crFree(crExt);
1736 crFree(s1);
1737 if (context->extensionString)
1738 crFree(context->extensionString);
1739 context->extensionString = s2;
1740 return (const GLubyte *) s2;
1741 }
1742 else if (pname == GL_VENDOR)
1743 return (const GLubyte *) CR_VENDOR;
1744 else if (pname == GL_VERSION)
1745 return render_spu.ws.glGetString(GL_VERSION);
1746 else if (pname == GL_RENDERER) {
1747#ifdef VBOX
1748 snprintf(tempStr, sizeof(tempStr), "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1749#else
1750 sprintf(tempStr, "Chromium (%s)", (char *) render_spu.ws.glGetString(GL_RENDERER));
1751#endif
1752 return (const GLubyte *) tempStr;
1753 }
1754#ifdef CR_OPENGL_VERSION_2_0
1755 else if (pname == GL_SHADING_LANGUAGE_VERSION)
1756 return render_spu.ws.glGetString(GL_SHADING_LANGUAGE_VERSION);
1757#endif
1758#ifdef GL_CR_real_vendor_strings
1759 else if (pname == GL_REAL_VENDOR)
1760 return render_spu.ws.glGetString(GL_VENDOR);
1761 else if (pname == GL_REAL_VERSION)
1762 return render_spu.ws.glGetString(GL_VERSION);
1763 else if (pname == GL_REAL_RENDERER)
1764 return render_spu.ws.glGetString(GL_RENDERER);
1765 else if (pname == GL_REAL_EXTENSIONS)
1766 return render_spu.ws.glGetString(GL_EXTENSIONS);
1767#endif
1768 else
1769 return NULL;
1770}
1771
1772static void renderspuReparentWindowCB(unsigned long key, void *data1, void *data2)
1773{
1774 WindowInfo *pWindow = (WindowInfo *)data1;
1775
1776 renderspu_SystemReparentWindow(pWindow);
1777}
1778
1779DECLEXPORT(void) renderspuReparentWindow(GLint window)
1780{
1781 WindowInfo *pWindow;
1782 CRASSERT(window >= 0);
1783
1784 pWindow = (WindowInfo *) crHashtableSearch(render_spu.windowTable, window);
1785
1786 if (!pWindow)
1787 {
1788 crDebug("Render SPU: Attempt to reparent invalid window (%d)", window);
1789 return;
1790 }
1791
1792 renderspu_SystemReparentWindow(pWindow);
1793
1794 /* special case: reparent all internal windows as well */
1795 if (window == CR_RENDER_DEFAULT_WINDOW_ID)
1796 {
1797 crHashtableWalk(render_spu.dummyWindowTable, renderspuReparentWindowCB, NULL);
1798 }
1799}
1800
1801#define FILLIN( NAME, FUNC ) \
1802 table[i].name = crStrdup(NAME); \
1803 table[i].fn = (SPUGenericFunction) FUNC; \
1804 i++;
1805
1806
1807/* These are the functions which the render SPU implements, not OpenGL.
1808 */
1809int
1810renderspuCreateFunctions(SPUNamedFunctionTable table[])
1811{
1812 int i = 0;
1813 FILLIN( "SwapBuffers", renderspuSwapBuffers );
1814 FILLIN( "CreateContext", renderspuCreateContext );
1815 FILLIN( "DestroyContext", renderspuDestroyContext );
1816 FILLIN( "MakeCurrent", renderspuMakeCurrent );
1817 FILLIN( "WindowCreate", renderspuWindowCreate );
1818 FILLIN( "WindowDestroy", renderspuWindowDestroy );
1819 FILLIN( "WindowSize", renderspuWindowSize );
1820 FILLIN( "WindowPosition", renderspuWindowPosition );
1821 FILLIN( "WindowVisibleRegion", renderspuWindowVisibleRegion );
1822 FILLIN( "WindowShow", renderspuWindowShow );
1823 FILLIN( "BarrierCreateCR", renderspuBarrierCreateCR );
1824 FILLIN( "BarrierDestroyCR", renderspuBarrierDestroyCR );
1825 FILLIN( "BarrierExecCR", renderspuBarrierExecCR );
1826 FILLIN( "BoundsInfoCR", renderspuBoundsInfoCR );
1827 FILLIN( "SemaphoreCreateCR", renderspuSemaphoreCreateCR );
1828 FILLIN( "SemaphoreDestroyCR", renderspuSemaphoreDestroyCR );
1829 FILLIN( "SemaphorePCR", renderspuSemaphorePCR );
1830 FILLIN( "SemaphoreVCR", renderspuSemaphoreVCR );
1831 FILLIN( "Writeback", renderspuWriteback );
1832 FILLIN( "ChromiumParameteriCR", renderspuChromiumParameteriCR );
1833 FILLIN( "ChromiumParameterfCR", renderspuChromiumParameterfCR );
1834 FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
1835 FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
1836 FILLIN( "GetString", renderspuGetString );
1837 FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
1838 return i;
1839}
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