VirtualBox

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

Last change on this file since 51975 was 51975, checked in by vboxsync, 10 years ago

crOpenGL/OSX: fix garbage on resize

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