VirtualBox

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

最後變更 在這個檔案從57946是 57946,由 vboxsync 提交於 9 年 前

SharedOpenGL: log OpenGL extensions which are enabled in Chromium but not supported by the host

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

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