VirtualBox

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

最後變更 在這個檔案從49960是 48726,由 vboxsync 提交於 11 年 前

crOpenGL: seamless fixes

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette