VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c@ 48798

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

Additions and HostServices: remove unneeded calls to XInitThreads().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 64.9 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6#if 00 /*TEMPORARY*/
7#include <unistd.h>
8#include "cr_rand.h"
9#endif
10
11#include <GL/glx.h>
12#include <X11/Xlib.h>
13#include <X11/Xutil.h>
14#include <X11/Xmu/StdCmap.h>
15#include <X11/Xatom.h>
16#include <X11/extensions/shape.h>
17#include <sys/time.h>
18#include <stdio.h>
19
20#include "cr_environment.h"
21#include "cr_error.h"
22#include "cr_string.h"
23#include "cr_mem.h"
24#include "cr_process.h"
25#include "renderspu.h"
26
27
28/*
29 * Stuff from MwmUtils.h
30 */
31typedef struct
32{
33 unsigned long flags;
34 unsigned long functions;
35 unsigned long decorations;
36 long inputMode;
37 unsigned long status;
38} PropMotifWmHints;
39
40#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
41#define MWM_HINTS_DECORATIONS (1L << 1)
42
43
44#define WINDOW_NAME window->title
45
46static Bool WindowExistsFlag;
47
48static int
49WindowExistsErrorHandler( Display *dpy, XErrorEvent *xerr )
50{
51 if (xerr->error_code == BadWindow)
52 {
53 WindowExistsFlag = GL_FALSE;
54 }
55 return 0;
56}
57
58static GLboolean
59WindowExists( Display *dpy, Window w )
60{
61 XWindowAttributes xwa;
62 int (*oldXErrorHandler)(Display *, XErrorEvent *);
63
64 WindowExistsFlag = GL_TRUE;
65 oldXErrorHandler = XSetErrorHandler(WindowExistsErrorHandler);
66 XGetWindowAttributes(dpy, w, &xwa); /* dummy request */
67 XSetErrorHandler(oldXErrorHandler);
68 return WindowExistsFlag;
69}
70
71static GLboolean
72renderDestroyWindow( Display *dpy, Window w )
73{
74 XWindowAttributes xwa;
75 int (*oldXErrorHandler)(Display *, XErrorEvent *);
76
77 WindowExistsFlag = GL_TRUE;
78 oldXErrorHandler = XSetErrorHandler(WindowExistsErrorHandler);
79 XGetWindowAttributes(dpy, w, &xwa); /* dummy request */
80 if (xwa.map_state == IsViewable) {
81 XDestroyWindow (dpy, w); /* dummy request */
82 XSync (dpy,0);
83 }
84 XSetErrorHandler(oldXErrorHandler);
85 return WindowExistsFlag;
86}
87
88#if 0
89/*
90 * Garbage collection function.
91 * Loop over all known windows and check if corresponding X window still
92 * exists. If it doesn't, destroy the render SPU window.
93 * XXX seems to blow up with threadtest.conf tests.
94 */
95void
96renderspu_GCWindow(void)
97{
98 int i;
99 WindowInfo *window;
100
101 for (i = 0; i < (int)render_spu.window_id - 1; i++) {
102 window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, i);
103 if (window->visual->dpy) {
104 if (!WindowExists (window->visual->dpy, window->appWindow) ) {
105 XSync(window->visual->dpy,0);
106 if(WindowExists(window->visual->dpy, window->window)) {
107 renderDestroyWindow(window->visual->dpy, window->window);
108 }
109 }
110 }
111 }
112}
113#endif
114
115static Colormap
116GetLUTColormap( Display *dpy, XVisualInfo *vi )
117{
118 int a;
119 XColor col;
120 Colormap cmap;
121
122#if defined(__cplusplus) || defined(c_plusplus)
123 int localclass = vi->c_class; /* C++ */
124#else
125 int localclass = vi->class; /* C */
126#endif
127
128 if ( localclass != DirectColor )
129 {
130 crError( "No support for non-DirectColor visuals with LUTs" );
131 }
132
133 cmap = XCreateColormap( dpy, RootWindow(dpy, vi->screen),
134 vi->visual, AllocAll );
135
136 for (a=0; a<256; a++)
137 {
138 col.red = render_spu.lut8[0][a]<<8;
139 col.green = col.blue = 0;
140 col.pixel = a<<16;
141 col.flags = DoRed;
142 XStoreColor(dpy, cmap, &col);
143 }
144
145 for (a=0; a<256; a++)
146 {
147 col.green = render_spu.lut8[1][a]<<8;
148 col.red = col.blue = 0;
149 col.pixel = a<<8;
150 col.flags = DoGreen;
151 XStoreColor(dpy, cmap, &col);
152 }
153
154 for (a=0; a<256; a++)
155 {
156 col.blue = render_spu.lut8[2][a]<<8;
157 col.red = col.green= 0;
158 col.pixel = a;
159 col.flags = DoBlue;
160 XStoreColor(dpy, cmap, &col);
161 }
162
163 return cmap;
164}
165
166static Colormap
167GetShareableColormap( Display *dpy, XVisualInfo *vi )
168{
169 Status status;
170 XStandardColormap *standardCmaps;
171 Colormap cmap;
172 int i, numCmaps;
173
174#if defined(__cplusplus) || defined(c_plusplus)
175 int localclass = vi->c_class; /* C++ */
176#else
177 int localclass = vi->class; /* C */
178#endif
179
180 if ( localclass != TrueColor )
181 {
182 crError( "No support for non-TrueColor visuals." );
183 }
184
185 status = XmuLookupStandardColormap( dpy, vi->screen, vi->visualid,
186 vi->depth, XA_RGB_DEFAULT_MAP,
187 False, True );
188
189 if ( status == 1 )
190 {
191 status = XGetRGBColormaps( dpy, RootWindow( dpy, vi->screen),
192 &standardCmaps, &numCmaps,
193 XA_RGB_DEFAULT_MAP );
194 if ( status == 1 )
195 {
196 for (i = 0 ; i < numCmaps ; i++)
197 {
198 if (standardCmaps[i].visualid == vi->visualid)
199 {
200 cmap = standardCmaps[i].colormap;
201 XFree( standardCmaps);
202 return cmap;
203 }
204 }
205 }
206 }
207
208 cmap = XCreateColormap( dpy, RootWindow(dpy, vi->screen),
209 vi->visual, AllocNone );
210 return cmap;
211}
212
213
214static int
215WaitForMapNotify( Display *display, XEvent *event, char *arg )
216{
217 (void)display;
218 return ( event->type == MapNotify && event->xmap.window == (Window)arg );
219}
220
221
222/**
223 * Return the X Visual ID of the given window
224 */
225static int
226GetWindowVisualID( Display *dpy, Window w )
227{
228 XWindowAttributes attr;
229 int k = XGetWindowAttributes(dpy, w, &attr);
230 if (!k)
231 return -1;
232 return attr.visual->visualid;
233}
234
235
236/**
237 * Wrapper for glXGetConfig().
238 */
239static int
240Attrib( const VisualInfo *visual, int attrib )
241{
242 int value = 0;
243 render_spu.ws.glXGetConfig( visual->dpy, visual->visual, attrib, &value );
244 return value;
245}
246
247
248
249/**
250 * Find a visual with the specified attributes. If we fail, turn off an
251 * attribute (like multisample or stereo) and try again.
252 */
253static XVisualInfo *
254chooseVisualRetry( Display *dpy, int screen, GLbitfield visAttribs )
255{
256 while (1) {
257 XVisualInfo *vis = crChooseVisual(&render_spu.ws, dpy, screen,
258 (GLboolean) render_spu.use_lut8,
259 visAttribs);
260 if (vis)
261 return vis;
262
263 if (visAttribs & CR_MULTISAMPLE_BIT)
264 visAttribs &= ~CR_MULTISAMPLE_BIT;
265 else if (visAttribs & CR_OVERLAY_BIT)
266 visAttribs &= ~CR_OVERLAY_BIT;
267 else if (visAttribs & CR_STEREO_BIT)
268 visAttribs &= ~CR_STEREO_BIT;
269 else if (visAttribs & CR_ACCUM_BIT)
270 visAttribs &= ~CR_ACCUM_BIT;
271 else if (visAttribs & CR_ALPHA_BIT)
272 visAttribs &= ~CR_ALPHA_BIT;
273 else
274 return NULL;
275 }
276}
277
278
279/**
280 * Get an FBconfig for the specified attributes
281 */
282#ifdef GLX_VERSION_1_3
283static GLXFBConfig
284chooseFBConfig( Display *dpy, int screen, GLbitfield visAttribs )
285{
286 GLXFBConfig *fbconfig;
287 int attribs[1000], attrCount = 0, numConfigs;
288 int major, minor;
289
290 CRASSERT(visAttribs & CR_PBUFFER_BIT);
291
292 /* Make sure pbuffers are supported */
293 render_spu.ws.glXQueryVersion(dpy, &major, &minor);
294 if (major * 100 + minor < 103) {
295 crWarning("Render SPU: GLX %d.%d doesn't support pbuffers", major, minor);
296 return 0;
297 }
298
299 attribs[attrCount++] = GLX_DRAWABLE_TYPE;
300 attribs[attrCount++] = GLX_PBUFFER_BIT;
301
302 if (visAttribs & CR_RGB_BIT) {
303 attribs[attrCount++] = GLX_RENDER_TYPE;
304 attribs[attrCount++] = GLX_RGBA_BIT;
305 attribs[attrCount++] = GLX_RED_SIZE;
306 attribs[attrCount++] = 1;
307 attribs[attrCount++] = GLX_GREEN_SIZE;
308 attribs[attrCount++] = 1;
309 attribs[attrCount++] = GLX_BLUE_SIZE;
310 attribs[attrCount++] = 1;
311 if (visAttribs & CR_ALPHA_BIT) {
312 attribs[attrCount++] = GLX_ALPHA_SIZE;
313 attribs[attrCount++] = 1;
314 }
315 }
316
317 if (visAttribs & CR_DEPTH_BIT) {
318 attribs[attrCount++] = GLX_DEPTH_SIZE;
319 attribs[attrCount++] = 1;
320 }
321
322 if (visAttribs & CR_DOUBLE_BIT) {
323 attribs[attrCount++] = GLX_DOUBLEBUFFER;
324 attribs[attrCount++] = True;
325 }
326 else {
327 /* don't care */
328 }
329
330 if (visAttribs & CR_STENCIL_BIT) {
331 attribs[attrCount++] = GLX_STENCIL_SIZE;
332 attribs[attrCount++] = 1;
333 }
334
335 if (visAttribs & CR_ACCUM_BIT) {
336 attribs[attrCount++] = GLX_ACCUM_RED_SIZE;
337 attribs[attrCount++] = 1;
338 attribs[attrCount++] = GLX_ACCUM_GREEN_SIZE;
339 attribs[attrCount++] = 1;
340 attribs[attrCount++] = GLX_ACCUM_BLUE_SIZE;
341 attribs[attrCount++] = 1;
342 if (visAttribs & CR_ALPHA_BIT) {
343 attribs[attrCount++] = GLX_ACCUM_ALPHA_SIZE;
344 attribs[attrCount++] = 1;
345 }
346 }
347
348 if (visAttribs & CR_MULTISAMPLE_BIT) {
349 attribs[attrCount++] = GLX_SAMPLE_BUFFERS_SGIS;
350 attribs[attrCount++] = 1;
351 attribs[attrCount++] = GLX_SAMPLES_SGIS;
352 attribs[attrCount++] = 4;
353 }
354
355 if (visAttribs & CR_STEREO_BIT) {
356 attribs[attrCount++] = GLX_STEREO;
357 attribs[attrCount++] = 1;
358 }
359
360 /* terminate */
361 attribs[attrCount++] = 0;
362
363 fbconfig = render_spu.ws.glXChooseFBConfig(dpy, screen, attribs, &numConfigs);
364 if (!fbconfig || numConfigs == 0) {
365 /* no matches! */
366 return 0;
367 }
368 if (numConfigs == 1) {
369 /* one match */
370 return fbconfig[0];
371 }
372 else {
373 /* found several matches - try to find best one */
374 int i;
375
376 crDebug("Render SPU: glXChooseFBConfig found %d matches for visBits 0x%x",
377 numConfigs, visAttribs);
378 /* Skip/omit configs that have unneeded Z buffer or unneeded double
379 * buffering. Possible add other tests in the future.
380 */
381 for (i = 0; i < numConfigs; i++) {
382 int zBits, db;
383 render_spu.ws.glXGetFBConfigAttrib(dpy, fbconfig[i],
384 GLX_DEPTH_SIZE, &zBits);
385 if ((visAttribs & CR_DEPTH_BIT) == 0 && zBits > 0) {
386 /* omit fbconfig with unneeded Z */
387 continue;
388 }
389 render_spu.ws.glXGetFBConfigAttrib(dpy, fbconfig[i],
390 GLX_DOUBLEBUFFER, &db);
391 if ((visAttribs & CR_DOUBLE_BIT) == 0 && db) {
392 /* omit fbconfig with unneeded DB */
393 continue;
394 }
395
396 /* if we get here, use this config */
397 return fbconfig[i];
398 }
399
400 /* if we get here, we didn't find a better fbconfig */
401 return fbconfig[0];
402 }
403}
404#endif /* GLX_VERSION_1_3 */
405
406static const char * renderspuGetDisplayName()
407{
408 const char *dpyName;
409
410 if (render_spu.display_string[0])
411 dpyName = render_spu.display_string;
412 else
413 {
414 crWarning("Render SPU: no display..");
415 dpyName = NULL;
416 }
417 return dpyName;
418}
419
420static int renderspuWinCmdWinCreate(WindowInfo *pWindow)
421{
422 return VERR_NOT_IMPLEMENTED;
423}
424
425static int renderspuWinCmdWinDestroy(WindowInfo *pWindow)
426{
427 return VERR_NOT_IMPLEMENTED;
428}
429
430static int renderspuWinCmdInit()
431{
432 const char * dpyName;
433 int rc = VERR_GENERAL_FAILURE;
434
435 if (!crHashtableAllocRegisterKey(render_spu.windowTable, CR_RENDER_WINCMD_ID))
436 {
437 crError("CR_RENDER_WINCMD_ID %d is occupied already", CR_RENDER_WINCMD_ID);
438 return VERR_INVALID_STATE;
439 }
440
441 render_spu.pWinToInfoTable = crAllocHashtable();
442 if (render_spu.pWinToInfoTable)
443 {
444 dpyName = renderspuGetDisplayName();
445 if (dpyName)
446 {
447 GLboolean bRc = renderspuInitVisual(&render_spu.WinCmdVisual, dpyName, render_spu.default_visual);
448 if (bRc)
449 {
450 bRc = renderspuWindowInitWithVisual(&render_spu.WinCmdWindow, &render_spu.WinCmdVisual, GL_FALSE, CR_RENDER_WINCMD_ID);
451 if (bRc)
452 {
453 XSelectInput(render_spu.WinCmdVisual.dpy, render_spu.WinCmdWindow.window, StructureNotifyMask);
454 render_spu.WinCmdAtom = XInternAtom(render_spu.WinCmdVisual.dpy, "VBoxWinCmd", False);
455 CRASSERT(render_spu.WinCmdAtom != None);
456 return VINF_SUCCESS;
457 }
458 else
459 {
460 crError("renderspuWindowInitWithVisual failed");
461 }
462 /* there is no visual destroy impl currently
463 * @todo: implement */
464 }
465 else
466 {
467 crError("renderspuInitVisual failed");
468 }
469 }
470 else
471 {
472 crError("Render SPU: no display, aborting");
473 }
474 crFreeHashtable(render_spu.pWinToInfoTable, NULL);
475 render_spu.pWinToInfoTable = NULL;
476 }
477 else
478 {
479 crError("crAllocHashtable failed");
480 }
481 return rc;
482}
483
484static void renderspuWinCmdTerm()
485{
486 /* the window is not in the table, this will just ensure the key is freed */
487 crHashtableDelete(render_spu.windowTable, CR_RENDER_WINCMD_ID, NULL);
488 renderspuWindowTerm(&render_spu.WinCmdWindow);
489 crFreeHashtable(render_spu.pWinToInfoTable, NULL);
490 /* we do not have visual destroy functionality
491 * @todo implement */
492}
493
494
495static bool renderspuWinCmdProcess(CR_RENDER_WINCMD* pWinCmd)
496{
497 bool fExit = false;
498 /* process commands */
499 switch (pWinCmd->enmCmd)
500 {
501 case CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE:
502 crHashtableAdd(render_spu.pWinToInfoTable, pWinCmd->pWindow->window, pWinCmd->pWindow);
503 XSelectInput(render_spu.WinCmdVisual.dpy, pWinCmd->pWindow->window, ExposureMask);
504 pWinCmd->rc = VINF_SUCCESS;
505 break;
506 case CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY:
507 crHashtableDelete(render_spu.pWinToInfoTable, pWinCmd->pWindow->window, NULL);
508 pWinCmd->rc = VINF_SUCCESS;
509 break;
510 case CR_RENDER_WINCMD_TYPE_NOP:
511 pWinCmd->rc = VINF_SUCCESS;
512 break;
513 case CR_RENDER_WINCMD_TYPE_EXIT:
514 renderspuWinCmdTerm();
515 pWinCmd->rc = VINF_SUCCESS;
516 fExit = true;
517 pWinCmd->rc = VINF_SUCCESS;
518 break;
519 case CR_RENDER_WINCMD_TYPE_WIN_CREATE:
520 pWinCmd->rc = renderspuWinCmdWinCreate(pWinCmd->pWindow);
521 break;
522 case CR_RENDER_WINCMD_TYPE_WIN_DESTROY:
523 pWinCmd->rc = renderspuWinCmdWinDestroy(pWinCmd->pWindow);
524 break;
525 default:
526 crError("unknown WinCmd command! %d", pWinCmd->enmCmd);
527 pWinCmd->rc = VERR_INVALID_PARAMETER;
528 break;
529 }
530
531 RTSemEventSignal(render_spu.hWinCmdCompleteEvent);
532 return fExit;
533}
534
535static DECLCALLBACK(int) renderspuWinCmdThreadProc(RTTHREAD ThreadSelf, void *pvUser)
536{
537 int rc;
538 bool fExit = false;
539 crDebug("RenderSPU: Window thread started (%x)", crThreadID());
540
541 rc = renderspuWinCmdInit();
542
543 /* notify the main cmd thread that we have started */
544 RTSemEventSignal(render_spu.hWinCmdCompleteEvent);
545
546 if (!RT_SUCCESS(rc))
547 {
548 CRASSERT(!render_spu.pWinToInfoTable);
549 return rc;
550 }
551
552 do
553 {
554 XEvent event;
555 XNextEvent(render_spu.WinCmdVisual.dpy, &event);
556
557 switch (event.type)
558 {
559 case ClientMessage:
560 {
561 CRASSERT(event.xclient.window == render_spu.WinCmdWindow.window);
562 if (event.xclient.window == render_spu.WinCmdWindow.window)
563 {
564 if (render_spu.WinCmdAtom == event.xclient.message_type)
565 {
566 CR_RENDER_WINCMD *pWinCmd;
567 memcpy(&pWinCmd, event.xclient.data.b, sizeof (pWinCmd));
568 fExit = renderspuWinCmdProcess(pWinCmd);
569 }
570 }
571
572 break;
573 }
574 case Expose:
575 {
576 if (!event.xexpose.count)
577 {
578 WindowInfo *pWindow = (WindowInfo*)crHashtableSearch(render_spu.pWinToInfoTable, event.xexpose.window);
579 if (pWindow)
580 {
581 struct VBOXVR_SCR_COMPOSITOR * pCompositor;
582
583 pCompositor = renderspuVBoxCompositorAcquire(pWindow);
584 if (pCompositor)
585 {
586 renderspuVBoxPresentCompositionGeneric(pWindow, pCompositor, NULL, 0);
587 renderspuVBoxCompositorRelease(pWindow);
588 }
589 }
590 }
591 break;
592 }
593 default:
594 break;
595 }
596 } while (!fExit);
597
598 return 0;
599}
600
601static int renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE enmCmd, WindowInfo *pWindow)
602{
603 Status status;
604 XEvent event;
605 CR_RENDER_WINCMD WinCmd, *pWinCmd;
606 int rc;
607
608 pWinCmd = &WinCmd;
609 pWinCmd->enmCmd = enmCmd;
610 pWinCmd->rc = VERR_GENERAL_FAILURE;
611 pWinCmd->pWindow = pWindow;
612
613 memset(&event, 0, sizeof (event));
614 event.type = ClientMessage;
615 event.xclient.window = render_spu.WinCmdWindow.window;
616 event.xclient.message_type = render_spu.WinCmdAtom;
617 event.xclient.format = 8;
618 memcpy(event.xclient.data.b, &pWinCmd, sizeof (pWinCmd));
619
620 status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, StructureNotifyMask, &event);
621 if (!status)
622 {
623 Assert(0);
624 crWarning("XSendEvent returned null");
625 return VERR_GENERAL_FAILURE;
626 }
627
628 XFlush(render_spu.pCommunicationDisplay);
629 rc = RTSemEventWaitNoResume(render_spu.hWinCmdCompleteEvent, RT_INDEFINITE_WAIT);
630 if (!RT_SUCCESS(rc))
631 {
632 crWarning("RTSemEventWaitNoResume failed rc %d", rc);
633 return rc;
634 }
635 return pWinCmd->rc;
636}
637
638int renderspu_SystemInit()
639{
640 const char * dpyName;
641 int rc = VERR_GENERAL_FAILURE;
642
643 if (!render_spu.use_glxchoosevisual) {
644 /* sometimes want to set this option with ATI drivers */
645 render_spu.ws.glXChooseVisual = NULL;
646 }
647
648 /* setup communication display connection */
649 dpyName = renderspuGetDisplayName();
650 if (!dpyName)
651 {
652 crWarning("no display name, aborting");
653 return VERR_GENERAL_FAILURE;
654 }
655
656 render_spu.pCommunicationDisplay = XOpenDisplay(dpyName);
657 if (!render_spu.pCommunicationDisplay)
658 {
659 crWarning( "Couldn't open X display named '%s'", dpyName );
660 return VERR_GENERAL_FAILURE;
661 }
662
663 if ( !render_spu.ws.glXQueryExtension( render_spu.pCommunicationDisplay, NULL, NULL ) )
664 {
665 crWarning( "Render SPU: Display %s doesn't support GLX", dpyName );
666 return VERR_GENERAL_FAILURE;
667 }
668
669 rc = RTSemEventCreate(&render_spu.hWinCmdCompleteEvent);
670 if (RT_SUCCESS(rc))
671 {
672 rc = RTThreadCreate(&render_spu.hWinCmdThread, renderspuWinCmdThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBoxCrWinCmd");
673 if (RT_SUCCESS(rc))
674 {
675 rc = RTSemEventWait(render_spu.hWinCmdCompleteEvent, RT_INDEFINITE_WAIT);
676 if (RT_SUCCESS(rc))
677 {
678 return VINF_SUCCESS;
679 }
680 else
681 {
682 crWarning("RTSemEventWait failed rc %d", rc);
683 }
684
685 RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
686 }
687 else
688 {
689 crWarning("RTThreadCreate failed rc %d", rc);
690 }
691 RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
692 }
693 else
694 {
695 crWarning("RTSemEventCreate failed rc %d", rc);
696 }
697
698 return rc;
699}
700
701int renderspu_SystemTerm()
702{
703 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_EXIT, NULL);
704 if (!RT_SUCCESS(rc))
705 {
706 crWarning("renderspuWinCmdSubmit EXIT failed rc %d", rc);
707 return rc;
708 }
709
710 RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
711 RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
712 return VINF_SUCCESS;
713}
714
715GLboolean
716renderspu_SystemInitVisual( VisualInfo *visual )
717{
718 const char *dpyName;
719 int screen;
720
721 CRASSERT(visual);
722
723#ifdef USE_OSMESA
724 if (render_spu.use_osmesa) {
725 /* A dummy visual - being non null is enough. */
726 visual->visual =(XVisualInfo *) "os";
727 return GL_TRUE;
728 }
729#endif
730
731 dpyName = renderspuGetDisplayName();
732 if (!dpyName)
733 {
734 crWarning("Render SPU: no display, aborting");
735 return GL_FALSE;
736 }
737
738
739 crInfo("Render SPU: Opening display %s", dpyName);
740
741 if (dpyName &&
742 (crStrncmp(dpyName, "localhost:11", 12) == 0 ||
743 crStrncmp(dpyName, "localhost:12", 12) == 0 ||
744 crStrncmp(dpyName, "localhost:13", 12) == 0)) {
745 /* Issue both debug and warning messages to make sure the
746 * message gets noticed!
747 */
748 crDebug("Render SPU: display string looks like a proxy X server!");
749 crDebug("Render SPU: This is usually a problem!");
750 crWarning("Render SPU: display string looks like a proxy X server!");
751 crWarning("Render SPU: This is usually a problem!");
752 }
753
754 visual->dpy = XOpenDisplay(dpyName);
755 if (!visual->dpy)
756 {
757 crWarning( "Couldn't open X display named '%s'", dpyName );
758 return GL_FALSE;
759 }
760
761 if ( !render_spu.ws.glXQueryExtension( visual->dpy, NULL, NULL ) )
762 {
763 crWarning( "Render SPU: Display %s doesn't support GLX", visual->displayName );
764 return GL_FALSE;
765 }
766
767 screen = DefaultScreen(visual->dpy);
768
769#ifdef GLX_VERSION_1_3
770 if (visual->visAttribs & CR_PBUFFER_BIT)
771 {
772 visual->fbconfig = chooseFBConfig(visual->dpy, screen, visual->visAttribs);
773 if (!visual->fbconfig) {
774 char s[1000];
775 renderspuMakeVisString( visual->visAttribs, s );
776 crWarning( "Render SPU: Display %s doesn't have the necessary fbconfig: %s",
777 dpyName, s );
778 XCloseDisplay(visual->dpy);
779 return GL_FALSE;
780 }
781 }
782 else
783#endif /* GLX_VERSION_1_3 */
784 {
785 visual->visual = chooseVisualRetry(visual->dpy, screen, visual->visAttribs);
786 if (!visual->visual) {
787 char s[1000];
788 renderspuMakeVisString( visual->visAttribs, s );
789 crWarning("Render SPU: Display %s doesn't have the necessary visual: %s",
790 dpyName, s );
791 XCloseDisplay(visual->dpy);
792 return GL_FALSE;
793 }
794 }
795
796 if ( render_spu.sync )
797 {
798 crDebug( "Render SPU: Turning on XSynchronize" );
799 XSynchronize( visual->dpy, True );
800 }
801
802 if (visual->visual) {
803 crDebug( "Render SPU: Choose visual id=0x%x: RGBA=(%d,%d,%d,%d) Z=%d"
804 " stencil=%d double=%d stereo=%d accum=(%d,%d,%d,%d)",
805 (int) visual->visual->visualid,
806 Attrib( visual, GLX_RED_SIZE ),
807 Attrib( visual, GLX_GREEN_SIZE ),
808 Attrib( visual, GLX_BLUE_SIZE ),
809 Attrib( visual, GLX_ALPHA_SIZE ),
810 Attrib( visual, GLX_DEPTH_SIZE ),
811 Attrib( visual, GLX_STENCIL_SIZE ),
812 Attrib( visual, GLX_DOUBLEBUFFER ),
813 Attrib( visual, GLX_STEREO ),
814 Attrib( visual, GLX_ACCUM_RED_SIZE ),
815 Attrib( visual, GLX_ACCUM_GREEN_SIZE ),
816 Attrib( visual, GLX_ACCUM_BLUE_SIZE ),
817 Attrib( visual, GLX_ACCUM_ALPHA_SIZE )
818 );
819 }
820 else if (visual->fbconfig) {
821 int id;
822 render_spu.ws.glXGetFBConfigAttrib(visual->dpy, visual->fbconfig,
823 GLX_FBCONFIG_ID, &id);
824 crDebug("Render SPU: Chose FBConfig 0x%x, visBits=0x%x",
825 id, visual->visAttribs);
826 }
827
828 return GL_TRUE;
829}
830
831
832/*
833 * Add a GLX window to a swap group for inter-machine SwapBuffer
834 * synchronization.
835 * Only supported on NVIDIA Quadro 3000G hardware.
836 */
837static void
838JoinSwapGroup(Display *dpy, int screen, Window window,
839 GLuint group, GLuint barrier)
840{
841 GLuint maxGroups, maxBarriers;
842 const char *ext;
843 Bool b;
844
845 /*
846 * XXX maybe query glXGetClientString() instead???
847 */
848 ext = render_spu.ws.glXQueryExtensionsString(dpy, screen);
849
850 if (!crStrstr(ext, "GLX_NV_swap_group") ||
851 !render_spu.ws.glXQueryMaxSwapGroupsNV ||
852 !render_spu.ws.glXJoinSwapGroupNV ||
853 !render_spu.ws.glXBindSwapBarrierNV) {
854 crWarning("Render SPU: nv_swap_group is set but GLX_NV_swap_group is not supported on this system!");
855 return;
856 }
857
858 b = render_spu.ws.glXQueryMaxSwapGroupsNV(dpy, screen,
859 &maxGroups, &maxBarriers);
860 if (!b)
861 crWarning("Render SPU: call to glXQueryMaxSwapGroupsNV() failed!");
862
863 if (group >= maxGroups) {
864 crWarning("Render SPU: nv_swap_group too large (%d > %d)",
865 group, (int) maxGroups);
866 return;
867 }
868 crDebug("Render SPU: max swap groups = %d, max barriers = %d",
869 maxGroups, maxBarriers);
870
871 /* add this window to the swap group */
872 b = render_spu.ws.glXJoinSwapGroupNV(dpy, window, group);
873 if (!b) {
874 crWarning("Render SPU: call to glXJoinSwapGroupNV() failed!");
875 return;
876 }
877 else {
878 crDebug("Render SPU: call to glXJoinSwapGroupNV() worked!");
879 }
880
881 /* ... and bind window to barrier of same ID */
882 b = render_spu.ws.glXBindSwapBarrierNV(dpy, group, barrier);
883 if (!b) {
884 crWarning("Render SPU: call to glXBindSwapBarrierNV(group=%d barrier=%d) failed!", group, barrier);
885 return;
886 }
887 else {
888 crDebug("Render SPU: call to glXBindSwapBarrierNV(group=%d barrier=%d) worked!", group, barrier);
889 }
890
891 crDebug("Render SPU: window has joined swap group %d", group);
892}
893
894
895
896static GLboolean
897createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
898{
899 Display *dpy;
900 Colormap cmap;
901 XSetWindowAttributes swa;
902 XSizeHints hints = {0};
903 XEvent event;
904 XTextProperty text_prop;
905 XClassHint *class_hints = NULL;
906 Window parent;
907 char *name;
908 unsigned long flags;
909 unsigned int vncWin;
910
911 CRASSERT(visual);
912 window->visual = visual;
913 window->nativeWindow = 0;
914
915#ifdef USE_OSMESA
916 if (render_spu.use_osmesa)
917 return GL_TRUE;
918#endif
919
920 dpy = visual->dpy;
921
922 if ( render_spu.use_L2 )
923 {
924 crWarning( "Render SPU: Going fullscreen because we think we're using Lightning-2." );
925 render_spu.fullscreen = 1;
926 }
927
928 /*
929 * Query screen size if we're going full-screen
930 */
931 if ( render_spu.fullscreen )
932 {
933 XWindowAttributes xwa;
934 Window root_window;
935
936 /* disable the screensaver */
937 XSetScreenSaver( dpy, 0, 0, PreferBlanking, AllowExposures );
938 crDebug( "Render SPU: Just turned off the screensaver" );
939
940 /* Figure out how big the screen is, and make the window that size */
941 root_window = DefaultRootWindow( dpy );
942 XGetWindowAttributes( dpy, root_window, &xwa );
943
944 crDebug( "Render SPU: root window size: %d x %d", xwa.width, xwa.height );
945
946 window->x = 0;
947 window->y = 0;
948 window->BltInfo.width = xwa.width;
949 window->BltInfo.height = xwa.height;
950 }
951
952 /* i've changed default window size to be 0,0 but X doesn't like it */
953 /*CRASSERT(window->BltInfo.width >= 1);
954 CRASSERT(window->BltInfo.height >= 1);*/
955 if (window->BltInfo.width < 1) window->BltInfo.width = 1;
956 if (window->BltInfo.height < 1) window->BltInfo.height = 1;
957
958 /*
959 * Get a colormap.
960 */
961 if (render_spu.use_lut8)
962 cmap = GetLUTColormap( dpy, visual->visual );
963 else
964 cmap = GetShareableColormap( dpy, visual->visual );
965 if ( !cmap ) {
966 crError( "Render SPU: Unable to get a colormap!" );
967 return GL_FALSE;
968 }
969
970 /* destroy existing window if there is one */
971 if (window->window) {
972 XDestroyWindow(dpy, window->window);
973 }
974
975 /*
976 * Create the window
977 *
978 * POSSIBLE OPTIMIZATION:
979 * If we're using the render_to_app_window or render_to_crut_window option
980 * (or DMX) we may never actually use this X window. So we could perhaps
981 * delay its creation until glXMakeCurrent is called. With NVIDIA's OpenGL
982 * driver, creating a lot of GLX windows can eat up a lot of VRAM and lead
983 * to slow, software-fallback rendering. Apps that use render_to_app_window,
984 * etc should set the default window size very small to avoid this.
985 * See dmx.conf for example.
986 */
987 swa.colormap = cmap;
988 swa.border_pixel = 0;
989 swa.event_mask = ExposureMask | StructureNotifyMask;
990 swa.override_redirect = 1;
991
992 flags = CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
993
994 /*
995 * We pass the VNC's desktop windowID via an environment variable.
996 * If we don't find one, we're not on a 3D-capable vncviewer, or
997 * if we do find one, then create the renderspu subwindow as a
998 * child of the vncviewer's desktop window.
999 *
1000 * This is purely for the replicateSPU.
1001 *
1002 * NOTE: This is crufty, and will do for now. FIXME.
1003 */
1004 vncWin = crStrToInt( crGetenv("CRVNCWINDOW") );
1005 if (vncWin)
1006 parent = (Window) vncWin;
1007 else
1008 parent = RootWindow(dpy, visual->visual->screen);
1009
1010 if (render_spu_parent_window_id>0)
1011 {
1012 crDebug("Render SPU: VBox parent window_id is: %x", render_spu_parent_window_id);
1013 window->window = XCreateWindow(dpy, render_spu_parent_window_id,
1014 window->x, window->y,
1015 window->BltInfo.width, window->BltInfo.height,
1016 0, visual->visual->depth, InputOutput,
1017 visual->visual->visual, flags, &swa);
1018 }
1019 else
1020 {
1021 /* This should happen only at the call from crVBoxServerInit. At this point we don't
1022 * know render_spu_parent_window_id yet, nor we need it for default window which is hidden.
1023 */
1024
1025 crDebug("Render SPU: Creating global window, parent: %x", RootWindow(dpy, visual->visual->screen));
1026 window->window = XCreateWindow(dpy, RootWindow(dpy, visual->visual->screen),
1027 window->x, window->y,
1028 window->BltInfo.width, window->BltInfo.height,
1029 0, visual->visual->depth, InputOutput,
1030 visual->visual->visual, flags, &swa);
1031 }
1032
1033 if (!window->window) {
1034 crWarning( "Render SPU: unable to create window" );
1035 return GL_FALSE;
1036 }
1037
1038 crDebug( "Render SPU: Created window 0x%x on display %s, Xvisual 0x%x",
1039 (int) window->window,
1040 DisplayString(visual->dpy),
1041 (int) visual->visual->visual->visualid /* yikes */
1042 );
1043
1044 if (render_spu.fullscreen || render_spu.borderless)
1045 {
1046 /* Disable border/decorations with an MWM property (observed by most
1047 * modern window managers.
1048 */
1049 PropMotifWmHints motif_hints;
1050 Atom prop, proptype;
1051
1052 /* setup the property */
1053 motif_hints.flags = MWM_HINTS_DECORATIONS;
1054 motif_hints.decorations = 0; /* Turn off all decorations */
1055
1056 /* get the atom for the property */
1057 prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
1058 if (prop) {
1059 /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
1060 proptype = prop;
1061 XChangeProperty( dpy, window->window, /* display, window */
1062 prop, proptype, /* property, type */
1063 32, /* format: 32-bit datums */
1064 PropModeReplace, /* mode */
1065 (unsigned char *) &motif_hints, /* data */
1066 PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */
1067 );
1068 }
1069 }
1070
1071 /* Make a clear cursor to get rid of the monitor cursor */
1072 if ( render_spu.fullscreen )
1073 {
1074 Pixmap pixmap;
1075 Cursor cursor;
1076 XColor colour;
1077 char clearByte = 0;
1078
1079 /* AdB - Only bother to create a 1x1 cursor (byte) */
1080 pixmap = XCreatePixmapFromBitmapData(dpy, window->window, &clearByte,
1081 1, 1, 1, 0, 1);
1082 if(!pixmap){
1083 crWarning("Unable to create clear cursor pixmap");
1084 return GL_FALSE;
1085 }
1086
1087 cursor = XCreatePixmapCursor(dpy, pixmap, pixmap, &colour, &colour, 0, 0);
1088 if(!cursor){
1089 crWarning("Unable to create clear cursor from zero byte pixmap");
1090 return GL_FALSE;
1091 }
1092 XDefineCursor(dpy, window->window, cursor);
1093 XFreePixmap(dpy, pixmap);
1094 }
1095
1096 hints.x = window->x;
1097 hints.y = window->y;
1098 hints.width = window->BltInfo.width;
1099 hints.height = window->BltInfo.height;
1100 hints.min_width = hints.width;
1101 hints.min_height = hints.height;
1102 hints.max_width = hints.width;
1103 hints.max_height = hints.height;
1104 if (render_spu.resizable)
1105 hints.flags = USPosition | USSize;
1106 else
1107 hints.flags = USPosition | USSize | PMinSize | PMaxSize;
1108 XSetStandardProperties( dpy, window->window,
1109 WINDOW_NAME, WINDOW_NAME,
1110 None, NULL, 0, &hints );
1111
1112 /* New item! This is needed so that the sgimouse server can find
1113 * the crDebug window.
1114 */
1115 name = WINDOW_NAME;
1116 XStringListToTextProperty( &name, 1, &text_prop );
1117 XSetWMName( dpy, window->window, &text_prop );
1118
1119 /* Set window name, resource class */
1120 class_hints = XAllocClassHint( );
1121 class_hints->res_name = crStrdup( "foo" );
1122 class_hints->res_class = crStrdup( "Chromium" );
1123 XSetClassHint( dpy, window->window, class_hints );
1124 crFree( class_hints->res_name );
1125 crFree( class_hints->res_class );
1126 XFree( class_hints );
1127
1128 if (showIt) {
1129 XMapWindow( dpy, window->window );
1130 XIfEvent( dpy, &event, WaitForMapNotify,
1131 (char *) window->window );
1132 }
1133
1134 if ((window->visual->visAttribs & CR_DOUBLE_BIT) && render_spu.nvSwapGroup) {
1135 /* NOTE:
1136 * If this SPU creates N windows we don't want to gang the N windows
1137 * together!
1138 * By adding the window ID to the nvSwapGroup ID we can be sure each
1139 * app window is in a separate swap group while all the back-end windows
1140 * which form a mural are in the same swap group.
1141 */
1142 GLuint group = 0; /*render_spu.nvSwapGroup + window->BltInfo.Base.id;*/
1143 GLuint barrier = 0;
1144 JoinSwapGroup(dpy, visual->visual->screen, window->window, group, barrier);
1145 }
1146
1147 /*
1148 * End GLX code
1149 */
1150 crDebug( "Render SPU: actual window x, y, width, height: %d, %d, %d, %d",
1151 window->x, window->y, window->BltInfo.width, window->BltInfo.height );
1152
1153 XSync(dpy, 0);
1154
1155 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1156 {
1157 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE, window);
1158 AssertRC(rc);
1159 }
1160
1161 return GL_TRUE;
1162}
1163
1164
1165static GLboolean
1166createPBuffer( VisualInfo *visual, WindowInfo *window )
1167{
1168 window->visual = visual;
1169 window->x = 0;
1170 window->y = 0;
1171 window->nativeWindow = 0;
1172
1173 CRASSERT(window->BltInfo.width > 0);
1174 CRASSERT(window->BltInfo.height > 0);
1175
1176#ifdef GLX_VERSION_1_3
1177 {
1178 int attribs[100], i = 0, w, h;
1179 CRASSERT(visual->fbconfig);
1180 w = window->BltInfo.width;
1181 h = window->BltInfo.height;
1182 attribs[i++] = GLX_PRESERVED_CONTENTS;
1183 attribs[i++] = True;
1184 attribs[i++] = GLX_PBUFFER_WIDTH;
1185 attribs[i++] = w;
1186 attribs[i++] = GLX_PBUFFER_HEIGHT;
1187 attribs[i++] = h;
1188 attribs[i++] = 0; /* terminator */
1189 window->window = render_spu.ws.glXCreatePbuffer(visual->dpy,
1190 visual->fbconfig, attribs);
1191 if (window->window) {
1192 crDebug("Render SPU: Allocated %d x %d pbuffer", w, h);
1193 return GL_TRUE;
1194 }
1195 else {
1196 crWarning("Render SPU: Failed to allocate %d x %d pbuffer", w, h);
1197 return GL_FALSE;
1198 }
1199 }
1200#endif /* GLX_VERSION_1_3 */
1201 return GL_FALSE;
1202}
1203
1204
1205GLboolean
1206renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1207{
1208 if (visual->visAttribs & CR_PBUFFER_BIT) {
1209 window->BltInfo.width = render_spu.defaultWidth;
1210 window->BltInfo.height = render_spu.defaultHeight;
1211 return createPBuffer(visual, window);
1212 }
1213 else {
1214 return createWindow(visual, showIt, window);
1215 }
1216}
1217
1218GLboolean
1219renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1220{
1221 return renderspu_SystemCreateWindow(visual, showIt, window);
1222}
1223
1224void
1225renderspu_SystemDestroyWindow( WindowInfo *window )
1226{
1227 CRASSERT(window);
1228 CRASSERT(window->visual);
1229
1230#ifdef USE_OSMESA
1231 if (render_spu.use_osmesa)
1232 {
1233 crFree(window->buffer);
1234 window->buffer = NULL;
1235 }
1236 else
1237#endif
1238 {
1239 if (window->visual->visAttribs & CR_PBUFFER_BIT) {
1240#ifdef GLX_VERSION_1_3
1241 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1242#endif
1243 }
1244 else {
1245 /* The value window->nativeWindow will only be non-NULL if the
1246 * render_to_app_window option is set to true. In this case, we
1247 * don't want to do anything, since we're not responsible for this
1248 * window. I know...personal responsibility and all...
1249 */
1250 if (!window->nativeWindow) {
1251 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1252 {
1253 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY, window);
1254 AssertRC(rc);
1255 }
1256 XDestroyWindow(window->visual->dpy, window->window);
1257 XSync(window->visual->dpy, 0);
1258 }
1259 }
1260 }
1261 window->visual = NULL;
1262 window->window = 0;
1263}
1264
1265
1266GLboolean
1267renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
1268{
1269 Bool is_direct;
1270 GLXContext sharedSystemContext = NULL;
1271
1272 CRASSERT(visual);
1273 CRASSERT(context);
1274
1275 context->visual = visual;
1276
1277 if (sharedContext != NULL) {
1278 sharedSystemContext = sharedContext->context;
1279 }
1280
1281
1282
1283#ifdef USE_OSMESA
1284 if (render_spu.use_osmesa) {
1285 context->context = (GLXContext) render_spu.OSMesaCreateContext(OSMESA_RGB, 0);
1286 if (context->context)
1287 return GL_TRUE;
1288 else
1289 return GL_FALSE;
1290 }
1291#endif
1292
1293#ifdef GLX_VERSION_1_3
1294 if (visual->visAttribs & CR_PBUFFER_BIT) {
1295 context->context = render_spu.ws.glXCreateNewContext( visual->dpy,
1296 visual->fbconfig,
1297 GLX_RGBA_TYPE,
1298 sharedSystemContext,
1299 render_spu.try_direct);
1300 }
1301 else
1302#endif
1303 {
1304 context->context = render_spu.ws.glXCreateContext( visual->dpy,
1305 visual->visual,
1306 sharedSystemContext,
1307 render_spu.try_direct);
1308 }
1309 if (!context->context) {
1310 crError( "Render SPU: Couldn't create rendering context" );
1311 return GL_FALSE;
1312 }
1313
1314 is_direct = render_spu.ws.glXIsDirect( visual->dpy, context->context );
1315 if (visual->visual)
1316 crDebug("Render SPU: Created %s context (%d) on display %s for visAttribs 0x%x",
1317 is_direct ? "DIRECT" : "INDIRECT",
1318 context->BltInfo.Base.id,
1319 DisplayString(visual->dpy),
1320 visual->visAttribs);
1321
1322 if ( render_spu.force_direct && !is_direct )
1323 {
1324 crError( "Render SPU: Direct rendering not possible." );
1325 return GL_FALSE;
1326 }
1327
1328 return GL_TRUE;
1329}
1330
1331
1332#define USE_GLX_COPYCONTEXT 0
1333
1334#if !USE_GLX_COPYCONTEXT
1335
1336/**
1337 * Unfortunately, glXCopyContext() is broken sometimes (NVIDIA 76.76 driver).
1338 * This bit of code gets and sets GL state we need to copy between contexts.
1339 */
1340struct saved_state
1341{
1342 /* XXX depending on the app, more state may be needed here */
1343 GLboolean Lighting;
1344 GLboolean LightEnabled[8];
1345 GLfloat LightPos[8][4];
1346 GLfloat LightAmbient[8][4];
1347 GLfloat LightDiffuse[8][4];
1348 GLfloat LightSpecular[8][4];
1349 GLboolean DepthTest;
1350};
1351
1352static struct saved_state SavedState;
1353
1354static void
1355get_state(struct saved_state *s)
1356{
1357 int i;
1358
1359 s->Lighting = render_spu.self.IsEnabled(GL_LIGHTING);
1360 for (i = 0; i < 8; i++) {
1361 s->LightEnabled[i] = render_spu.self.IsEnabled(GL_LIGHT0 + i);
1362 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1363 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1364 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1365 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1366 }
1367
1368 s->DepthTest = render_spu.self.IsEnabled(GL_DEPTH_TEST);
1369}
1370
1371static void
1372set_state(const struct saved_state *s)
1373{
1374 int i;
1375
1376 if (s->Lighting) {
1377 render_spu.self.Enable(GL_LIGHTING);
1378 }
1379 else {
1380 render_spu.self.Disable(GL_LIGHTING);
1381 }
1382
1383 for (i = 0; i < 8; i++) {
1384 if (s->LightEnabled[i]) {
1385 render_spu.self.Enable(GL_LIGHT0 + i);
1386 }
1387 else {
1388 render_spu.self.Disable(GL_LIGHT0 + i);
1389 }
1390 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1391 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1392 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1393 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1394 }
1395
1396 if (s->DepthTest)
1397 render_spu.self.Enable(GL_DEPTH_TEST);
1398 else
1399 render_spu.self.Disable(GL_DEPTH_TEST);
1400}
1401
1402#endif /* !USE_GLX_COPYCONTEXT */
1403
1404/**
1405 * Recreate the GLX context for ContextInfo. The new context will use the
1406 * visual specified by newVisualID.
1407 */
1408static void
1409renderspu_RecreateContext( ContextInfo *context, int newVisualID )
1410{
1411 XVisualInfo templateVis, *vis;
1412 long templateFlags;
1413 int screen = 0, count;
1414 GLXContext oldContext = context->context;
1415
1416 templateFlags = VisualScreenMask | VisualIDMask;
1417 templateVis.screen = screen;
1418 templateVis.visualid = newVisualID;
1419 vis = XGetVisualInfo(context->visual->dpy, templateFlags, &templateVis, &count);
1420 CRASSERT(vis);
1421 if (!vis)
1422 return;
1423
1424 /* create new context */
1425 crDebug("Render SPU: Creating new GLX context with visual 0x%x", newVisualID);
1426 context->context = render_spu.ws.glXCreateContext(context->visual->dpy,
1427 vis, NULL,
1428 render_spu.try_direct);
1429 CRASSERT(context->context);
1430
1431#if USE_GLX_COPYCONTEXT
1432 /* copy old context state to new context */
1433 render_spu.ws.glXCopyContext(context->visual->dpy,
1434 oldContext, context->context, ~0);
1435 crDebug("Render SPU: Done copying context state");
1436#endif
1437
1438 /* destroy old context */
1439 render_spu.ws.glXDestroyContext(context->visual->dpy, oldContext);
1440
1441 context->visual->visual = vis;
1442}
1443
1444
1445void
1446renderspu_SystemDestroyContext( ContextInfo *context )
1447{
1448#ifdef USE_OSMESA
1449 if (render_spu.use_osmesa)
1450 {
1451 render_spu.OSMesaDestroyContext( (OSMesaContext) context->context );
1452 }
1453 else
1454#endif
1455 {
1456#if 0
1457 /* XXX disable for now - causes segfaults w/ NVIDIA's driver */
1458 render_spu.ws.glXDestroyContext( context->visual->dpy, context->context );
1459#endif
1460 }
1461 context->visual = NULL;
1462 context->context = 0;
1463}
1464
1465
1466#ifdef USE_OSMESA
1467static void
1468check_buffer_size( WindowInfo *window )
1469{
1470 if (window->BltInfo.width != window->in_buffer_width
1471 || window->BltInfo.height != window->in_buffer_height
1472 || ! window->buffer) {
1473 crFree(window->buffer);
1474
1475 window->buffer = crCalloc(window->BltInfo.width * window->BltInfo.height
1476 * 4 * sizeof (GLubyte));
1477
1478 window->in_buffer_width = window->BltInfo.width;
1479 window->in_buffer_height = window->BltInfo.height;
1480
1481 crDebug("Render SPU: dimensions changed to %d x %d", window->BltInfo.width, window->BltInfo.height);
1482 }
1483}
1484#endif
1485
1486
1487void
1488renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
1489 ContextInfo *context )
1490{
1491 Bool b;
1492
1493 CRASSERT(render_spu.ws.glXMakeCurrent);
1494
1495 /*crDebug("%s nativeWindow=0x%x", __FUNCTION__, (int) nativeWindow);*/
1496
1497#ifdef USE_OSMESA
1498 if (render_spu.use_osmesa) {
1499 check_buffer_size(window);
1500 render_spu.OSMesaMakeCurrent( (OSMesaContext) context->context,
1501 window->buffer, GL_UNSIGNED_BYTE,
1502 window->BltInfo.width, window->BltInfo.height);
1503 return;
1504 }
1505#endif
1506
1507 nativeWindow = 0;
1508
1509 if (window && context) {
1510 window->appWindow = nativeWindow;
1511
1512 if (window->visual != context->visual) {
1513 crDebug("Render SPU: MakeCurrent visual mismatch (win(%d) bits:0x%x != ctx(%d) bits:0x%x); remaking window.",
1514 window->BltInfo.Base.id, window->visual->visAttribs,
1515 context->BltInfo.Base.id, context->visual->visAttribs);
1516 /*
1517 * XXX have to revisit this issue!!!
1518 *
1519 * But for now we destroy the current window
1520 * and re-create it with the context's visual abilities
1521 */
1522#ifndef SOLARIS_9_X_BUG
1523 /*
1524 I'm having some really weird issues if I destroy this window
1525 when I'm using the version of sunX that comes with Solaris 9.
1526 Subsiquent glX calls return GLXBadCurrentWindow error.
1527
1528 This is an issue even when running Linux version and using
1529 the Solaris 9 sunX as a display.
1530 -- jw
1531
1532 jw: we might have to call glXMakeCurrent(dpy, 0, 0) to unbind
1533 the context from the window before destroying it. -Brian
1534 */
1535 render_spu.ws.glXMakeCurrent(window->visual->dpy, 0, 0);
1536 renderspu_SystemDestroyWindow( window );
1537#endif
1538 renderspu_SystemCreateWindow( context->visual, window->visible, window );
1539 /*
1540 crError("In renderspu_SystemMakeCurrent() window and context"
1541 " weren't created with same visual!");
1542 */
1543 }
1544
1545 CRASSERT(context->context);
1546
1547#if 0
1548 if (render_spu.render_to_crut_window) {
1549 if (render_spu.crut_drawable == 0) {
1550 /* We don't know the X drawable ID yet. Ask mothership for it. */
1551 char response[8096];
1552 CRConnection *conn = crMothershipConnect();
1553 if (!conn)
1554 {
1555 crError("Couldn't connect to the mothership to get CRUT drawable-- "
1556 "I have no idea what to do!");
1557 }
1558 crMothershipGetParam( conn, "crut_drawable", response );
1559 render_spu.crut_drawable = crStrToInt(response);
1560 crMothershipDisconnect(conn);
1561
1562 crDebug("Render SPU: using CRUT drawable: 0x%x",
1563 render_spu.crut_drawable);
1564 if (!render_spu.crut_drawable) {
1565 crDebug("Render SPU: Crut drawable 0 is invalid");
1566 /* Continue with nativeWindow = 0; we'll render to the window that
1567 * we (the Render SPU) previously created.
1568 */
1569 }
1570 }
1571
1572 nativeWindow = render_spu.crut_drawable;
1573 }
1574#endif
1575
1576 if ((render_spu.render_to_crut_window || render_spu.render_to_app_window)
1577 && nativeWindow)
1578 {
1579 /* We're about to bind the rendering context to a window that we
1580 * (the Render SPU) did not create. The window was created by the
1581 * application or the CRUT server.
1582 * Make sure the window ID is valid and that the window's X visual is
1583 * the same as the rendering context's.
1584 */
1585 if (WindowExists(window->visual->dpy, nativeWindow))
1586 {
1587 int vid = GetWindowVisualID(window->visual->dpy, nativeWindow);
1588 GLboolean recreated = GL_FALSE;
1589
1590 /* check that the window's visual and context's visual match */
1591 if (vid != (int) context->visual->visual->visualid) {
1592 crWarning("Render SPU: Can't bind context %d to CRUT/native window "
1593 "0x%x because of different X visuals (0x%x != 0x%x)!",
1594 context->BltInfo.Base.id, (int) nativeWindow,
1595 vid, (int) context->visual->visual->visualid);
1596 crWarning("Render SPU: Trying to recreate GLX context to match.");
1597 /* Try to recreate the GLX context so that it uses the same
1598 * GLX visual as the window.
1599 */
1600#if !USE_GLX_COPYCONTEXT
1601 if (context->everCurrent) {
1602 get_state(&SavedState);
1603 }
1604#endif
1605 renderspu_RecreateContext(context, vid);
1606 recreated = GL_TRUE;
1607 }
1608
1609 /* OK, this should work */
1610 window->nativeWindow = (Window) nativeWindow;
1611 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1612 window->nativeWindow,
1613 context->context );
1614 CRASSERT(b);
1615#if !USE_GLX_COPYCONTEXT
1616 if (recreated) {
1617 set_state(&SavedState);
1618 }
1619#endif
1620 }
1621 else
1622 {
1623 crWarning("Render SPU: render_to_app/crut_window option is set but "
1624 "the window ID 0x%x is invalid on the display named %s",
1625 (unsigned int) nativeWindow,
1626 DisplayString(window->visual->dpy));
1627 CRASSERT(window->window);
1628 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1629 window->window, context->context );
1630 CRASSERT(b);
1631 }
1632 }
1633 else
1634 {
1635 /* This is the normal case - rendering to the render SPU's own window */
1636 CRASSERT(window->window);
1637#if 0
1638 crDebug("calling glXMakecurrent(%p, 0x%x, 0x%x)",
1639 window->visual->dpy,
1640 (int) window->window, (int) context->context );
1641#endif
1642 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1643 window->window, context->context );
1644 if (!b) {
1645 crWarning("glXMakeCurrent(%p, 0x%x, %p) failed! (winId %d, ctxId %d)",
1646 window->visual->dpy,
1647 (int) window->window, (void *) context->context,
1648 window->BltInfo.Base.id, context->BltInfo.Base.id );
1649 }
1650 /*CRASSERT(b);*/
1651 }
1652
1653 /* XXX this is a total hack to work around an NVIDIA driver bug */
1654#if 0
1655 if (render_spu.self.GetFloatv && context->haveWindowPosARB) {
1656 GLfloat f[4];
1657 render_spu.self.GetFloatv(GL_CURRENT_RASTER_POSITION, f);
1658 if (!window->everCurrent || f[1] < 0.0) {
1659 crDebug("Render SPU: Resetting raster pos");
1660 render_spu.self.WindowPos2iARB(0, 0);
1661 }
1662 }
1663#endif
1664 }
1665 else
1666 {
1667 GET_CONTEXT(pCurCtx);
1668 if (pCurCtx)
1669 {
1670 b = render_spu.ws.glXMakeCurrent( pCurCtx->currentWindow->visual->dpy, None, NULL);
1671 if (!b) {
1672 crWarning("glXMakeCurrent(%p, None, NULL) failed!", pCurCtx->currentWindow->visual->dpy);
1673 }
1674 }
1675
1676 }
1677
1678#if 0
1679 /* XXX disabled for now due to problem with threadtest.conf */
1680 renderspu_GCWindow();
1681#endif
1682}
1683
1684
1685/**
1686 * Set window (or pbuffer) size.
1687 */
1688void
1689renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
1690{
1691#ifdef USE_OSMESA
1692 if (render_spu.use_osmesa) {
1693 window->BltInfo.width = w;
1694 window->BltInfo.height = h;
1695 check_buffer_size(window);
1696 return;
1697 }
1698#endif
1699
1700 CRASSERT(window);
1701 CRASSERT(window->visual);
1702 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1703 {
1704 /* resizing a pbuffer */
1705 if (render_spu.pbufferWidth != 0 || render_spu.pbufferHeight != 0) {
1706 /* size limit check */
1707 if (w > render_spu.pbufferWidth || h > render_spu.pbufferHeight) {
1708 crWarning("Render SPU: Request for %d x %d pbuffer is larger than "
1709 "the configured size of %d x %d. ('pbuffer_size')",
1710 w, h, render_spu.pbufferWidth, render_spu.pbufferHeight);
1711 return;
1712 }
1713 /*
1714 * If the requested new pbuffer size is greater than 1/2 the size of
1715 * the max pbuffer, just use the max pbuffer size. This helps avoid
1716 * problems with VRAM memory fragmentation. If we run out of VRAM
1717 * for pbuffers, some drivers revert to software rendering. We want
1718 * to avoid that!
1719 */
1720 if (w * h >= render_spu.pbufferWidth * render_spu.pbufferHeight / 2) {
1721 /* increase the dimensions to the max pbuffer size now */
1722 w = render_spu.pbufferWidth;
1723 h = render_spu.pbufferHeight;
1724 }
1725 }
1726
1727 if (window->BltInfo.width != w || window->BltInfo.height != h) {
1728 /* Only resize if the new dimensions really are different */
1729#ifdef CHROMIUM_THREADSAFE
1730 ContextInfo *currentContext = (ContextInfo *) crGetTSD(&_RenderTSD);
1731#else
1732 ContextInfo *currentContext = render_spu.currentContext;
1733#endif
1734 /* Can't resize pbuffers, so destroy it and make a new one */
1735 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1736 window->BltInfo.width = w;
1737 window->BltInfo.height = h;
1738 crDebug("Render SPU: Creating new %d x %d PBuffer (id=%d)",
1739 w, h, window->BltInfo.Base.id);
1740 if (!createPBuffer(window->visual, window)) {
1741 crWarning("Render SPU: Unable to create PBuffer (out of VRAM?)!");
1742 }
1743 else if (currentContext && currentContext->currentWindow == window) {
1744 /* Determine if we need to bind the current context to new pbuffer */
1745 render_spu.ws.glXMakeCurrent(window->visual->dpy,
1746 window->window,
1747 currentContext->context );
1748 }
1749 }
1750 }
1751 else {
1752 if (!w || !h)
1753 {
1754 /* X can not handle zero sizes */
1755 if (window->visible)
1756 {
1757 renderspu_SystemShowWindow( window, GL_FALSE );
1758 }
1759 return;
1760 }
1761 /* Resize ordinary X window */
1762 /*
1763 * This is ugly, but it seems to be the only thing that works.
1764 * Basically, XResizeWindow() doesn't seem to always take effect
1765 * immediately.
1766 * Even after an XSync(), the GetWindowAttributes() call will sometimes
1767 * return the old window size. So, we use a loop to repeat the window
1768 * resize until it seems to take effect.
1769 */
1770 int attempt;
1771 crDebug("Render SPU: XResizeWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, w, h);
1772 XResizeWindow(window->visual->dpy, window->window, w, h);
1773 XSync(window->visual->dpy, 0);
1774
1775 if (!window->BltInfo.width || !window->BltInfo.height)
1776 {
1777 /* we have hidden the window instead of sizing it to (0;0) since X is unable to handle zero sizes */
1778 if (window->visible)
1779 {
1780 renderspu_SystemShowWindow( window, GL_TRUE );
1781 return;
1782 }
1783 }
1784#if 0
1785 for (attempt = 0; attempt < 3; attempt++) { /* try three times max */
1786 XWindowAttributes attribs;
1787 /* Now, query the window size */
1788 XGetWindowAttributes(window->visual->dpy, window->window, &attribs);
1789 if (attribs.width == w && attribs.height == h)
1790 break;
1791 /* sleep for a millisecond and try again */
1792 crMsleep(1);
1793 }
1794#endif
1795 }
1796}
1797
1798
1799void
1800renderspu_SystemGetWindowGeometry( WindowInfo *window,
1801 GLint *x, GLint *y, GLint *w, GLint *h )
1802{
1803#ifdef USE_OSMESA
1804 if (render_spu.use_osmesa) {
1805 *w = window->BltInfo.width;
1806 *h = window->BltInfo.height;
1807 return;
1808 }
1809#endif
1810
1811 CRASSERT(window);
1812 CRASSERT(window->visual);
1813 CRASSERT(window->window);
1814 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1815 {
1816 *x = 0;
1817 *y = 0;
1818 *w = window->BltInfo.width;
1819 *h = window->BltInfo.height;
1820 }
1821 else
1822 {
1823 Window xw, child, root;
1824 unsigned int width, height, bw, d;
1825 int rx, ry;
1826
1827 if ((render_spu.render_to_app_window || render_spu.render_to_crut_window)
1828 && window->nativeWindow) {
1829 xw = window->nativeWindow;
1830 }
1831 else {
1832 xw = window->window;
1833 }
1834
1835 XGetGeometry(window->visual->dpy, xw, &root,
1836 x, y, &width, &height, &bw, &d);
1837
1838 /* translate x/y to screen coords */
1839 if (!XTranslateCoordinates(window->visual->dpy, xw, root,
1840 0, 0, &rx, &ry, &child)) {
1841 rx = ry = 0;
1842 }
1843 *x = rx;
1844 *y = ry;
1845 *w = (int) width;
1846 *h = (int) height;
1847 }
1848}
1849
1850
1851void
1852renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h )
1853{
1854 int scrn;
1855#ifdef USE_OSMESA
1856 if (render_spu.use_osmesa) {
1857 *w = 2048;
1858 *h = 2048;
1859 return;
1860 }
1861#endif
1862
1863 CRASSERT(window);
1864 CRASSERT(window->visual);
1865 CRASSERT(window->window);
1866
1867 scrn = DefaultScreen(window->visual->dpy);
1868 *w = DisplayWidth(window->visual->dpy, scrn);
1869 *h = DisplayHeight(window->visual->dpy, scrn);
1870}
1871
1872
1873void
1874renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
1875{
1876#ifdef USE_OSMESA
1877 if (render_spu.use_osmesa)
1878 return;
1879#endif
1880
1881 CRASSERT(window);
1882 CRASSERT(window->visual);
1883 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1884 {
1885 crDebug("Render SPU: XMoveWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, x, y);
1886 XMoveWindow(window->visual->dpy, window->window, x, y);
1887 XSync(window->visual->dpy, 0);
1888 }
1889}
1890
1891void
1892renderspu_SystemWindowVisibleRegion( WindowInfo *window, GLint cRects, const GLint *pRects )
1893{
1894#ifdef USE_OSMESA
1895 if (render_spu.use_osmesa)
1896 return;
1897#endif
1898
1899 CRASSERT(window);
1900 CRASSERT(window->visual);
1901 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1902 {
1903 int evb, erb, i;
1904 XRectangle *pXRects;
1905
1906 if (!XShapeQueryExtension(window->visual->dpy, &evb, &erb))
1907 {
1908 crWarning("Render SPU: Display %s doesn't support SHAPE extension", window->visual->displayName);
1909 return;
1910 }
1911
1912 if (cRects>0)
1913 {
1914 pXRects = (XRectangle *) crAlloc(cRects * sizeof(XRectangle));
1915
1916 for (i=0; i<cRects; ++i)
1917 {
1918 pXRects[i].x = (short) pRects[4*i];
1919 pXRects[i].y = (short) pRects[4*i+1];
1920 pXRects[i].width = (unsigned short) (pRects[4*i+2]-pRects[4*i]);
1921 pXRects[i].height = (unsigned short) (pRects[4*i+3]-pRects[4*i+1]);
1922 }
1923 }
1924 else
1925 {
1926 pXRects = (XRectangle *) crAlloc(sizeof(XRectangle));
1927 pXRects[0].x = 0;
1928 pXRects[0].y = 0;
1929 pXRects[0].width = 0;
1930 pXRects[0].height = 0;
1931 cRects = 1;
1932 }
1933
1934 crDebug("Render SPU: XShapeCombineRectangles (%x, %x, cRects=%i)", window->visual->dpy, window->window, cRects);
1935
1936 XShapeCombineRectangles(window->visual->dpy, window->window, ShapeBounding, 0, 0,
1937 pXRects, cRects, ShapeSet, YXBanded);
1938 XSync(window->visual->dpy, 0);
1939 crFree(pXRects);
1940 }
1941}
1942
1943/* Either show or hide the render SPU's window. */
1944void
1945renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
1946{
1947#ifdef USE_OSMESA
1948 if (render_spu.use_osmesa)
1949 return;
1950#endif
1951
1952 if (window->visual->dpy && window->window &&
1953 (window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1954 {
1955 if (showIt)
1956 {
1957 if (window->BltInfo.width && window->BltInfo.height)
1958 {
1959 XMapWindow( window->visual->dpy, window->window );
1960 XSync(window->visual->dpy, 0);
1961 }
1962 }
1963 else
1964 {
1965 XUnmapWindow( window->visual->dpy, window->window );
1966 XSync(window->visual->dpy, 0);
1967 }
1968 }
1969}
1970
1971void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
1972{
1973 /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
1974 * here it forces rendering in WinCmd thread rather than a Main thread.
1975 * it is used for debugging only in any way actually.
1976 * @todo: change to some more generic macro name */
1977#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
1978 struct VBOXVR_SCR_COMPOSITOR *pCompositor;
1979 /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
1980 int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
1981 if (RT_SUCCESS(rc))
1982 {
1983 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
1984 renderspuVBoxCompositorRelease(window);
1985 }
1986 else if (rc == VERR_SEM_BUSY)
1987#endif
1988 {
1989 Status status;
1990 XEvent event;
1991 render_spu.self.Flush();
1992 renderspuVBoxPresentBlitterEnsureCreated(window, 0);
1993
1994 crMemset(&event, 0, sizeof (event));
1995 event.type = Expose;
1996 event.xexpose.window = window->window;
1997 event.xexpose.width = window->BltInfo.width;
1998 event.xexpose.height = window->BltInfo.height;
1999 status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, 0, &event);
2000 if (!status)
2001 {
2002 Assert(0);
2003 crWarning("XSendEvent returned null");
2004 }
2005 XFlush(render_spu.pCommunicationDisplay);
2006 }
2007#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
2008 else
2009 {
2010 /* this is somewhat we do not expect */
2011 crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
2012 }
2013#endif
2014}
2015
2016static void
2017MarkWindow(WindowInfo *w)
2018{
2019 static GC gc = 0; /* XXX per-window??? */
2020 if (!gc) {
2021 /* Create a GC for drawing invisible lines */
2022 XGCValues gcValues;
2023 gcValues.function = GXnoop;
2024 gc = XCreateGC(w->visual->dpy, w->nativeWindow, GCFunction, &gcValues);
2025 }
2026 XDrawLine(w->visual->dpy, w->nativeWindow, gc, 0, 0, w->BltInfo.width, w->BltInfo.height);
2027}
2028
2029
2030void
2031renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
2032{
2033 CRASSERT(w);
2034
2035#if 00 /*TEMPORARY - FOR TESTING SWAP LOCK*/
2036 if (1) {
2037 /* random delay */
2038 int k = crRandInt(1000 * 100, 750*1000);
2039 static int first = 1;
2040 if (first) {
2041 crRandAutoSeed();
2042 first = 0;
2043 }
2044 usleep(k);
2045 }
2046#endif
2047
2048 /* render_to_app_window:
2049 * w->nativeWindow will only be non-zero if the
2050 * render_spu.render_to_app_window option is true and
2051 * MakeCurrent() recorded the nativeWindow handle in the WindowInfo
2052 * structure.
2053 */
2054 if (w->nativeWindow) {
2055 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->nativeWindow );
2056#if 0
2057 MarkWindow(w);
2058#else
2059 (void) MarkWindow;
2060#endif
2061 }
2062 else {
2063 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->window );
2064 }
2065}
2066
2067void renderspu_SystemReparentWindow(WindowInfo *window)
2068{
2069 Window parent;
2070
2071 parent = render_spu_parent_window_id>0 ? render_spu_parent_window_id :
2072 RootWindow(window->visual->dpy, window->visual->visual->screen);
2073
2074 XReparentWindow(window->visual->dpy, window->window, parent, window->x, window->y);
2075 XSync(window->visual->dpy, False);
2076}
2077
2078void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
2079{
2080
2081}
Note: See TracBrowser for help on using the repository browser.

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