VirtualBox

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

最後變更 在這個檔案從80334是 78911,由 vboxsync 提交於 6 年 前

SharedOpenGL/renderspu.c: Fix small memory leak

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

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