VirtualBox

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

Last change on this file since 45039 was 45039, checked in by vboxsync, 12 years ago

crOpenGL/glx: additional fixes

  • 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 = renderspuWindowInit(&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("renderspuWindowInit 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 /* enable multi-threading */
649 XInitThreads();
650
651 /* setup communication display connection */
652 dpyName = renderspuGetDisplayName();
653 if (!dpyName)
654 {
655 crWarning("no display name, aborting");
656 return VERR_GENERAL_FAILURE;
657 }
658
659 render_spu.pCommunicationDisplay = XOpenDisplay(dpyName);
660 if (!render_spu.pCommunicationDisplay)
661 {
662 crWarning( "Couldn't open X display named '%s'", dpyName );
663 return VERR_GENERAL_FAILURE;
664 }
665
666 if ( !render_spu.ws.glXQueryExtension( render_spu.pCommunicationDisplay, NULL, NULL ) )
667 {
668 crWarning( "Render SPU: Display %s doesn't support GLX", dpyName );
669 return VERR_GENERAL_FAILURE;
670 }
671
672 rc = RTSemEventCreate(&render_spu.hWinCmdCompleteEvent);
673 if (RT_SUCCESS(rc))
674 {
675 rc = RTThreadCreate(&render_spu.hWinCmdThread, renderspuWinCmdThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBoxCrWinCmd");
676 if (RT_SUCCESS(rc))
677 {
678 rc = RTSemEventWait(render_spu.hWinCmdCompleteEvent, RT_INDEFINITE_WAIT);
679 if (RT_SUCCESS(rc))
680 {
681 return VINF_SUCCESS;
682 }
683 else
684 {
685 crWarning("RTSemEventWait failed rc %d", rc);
686 }
687
688 RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
689 }
690 else
691 {
692 crWarning("RTThreadCreate failed rc %d", rc);
693 }
694 RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
695 }
696 else
697 {
698 crWarning("RTSemEventCreate failed rc %d", rc);
699 }
700
701 return rc;
702}
703
704int renderspu_SystemTerm()
705{
706 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_EXIT, NULL);
707 if (!RT_SUCCESS(rc))
708 {
709 crWarning("renderspuWinCmdSubmit EXIT failed rc %d", rc);
710 return rc;
711 }
712
713 RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
714 RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
715 return VINF_SUCCESS;
716}
717
718GLboolean
719renderspu_SystemInitVisual( VisualInfo *visual )
720{
721 const char *dpyName;
722 int screen;
723
724 CRASSERT(visual);
725
726#ifdef USE_OSMESA
727 if (render_spu.use_osmesa) {
728 /* A dummy visual - being non null is enough. */
729 visual->visual =(XVisualInfo *) "os";
730 return GL_TRUE;
731 }
732#endif
733
734 dpyName = renderspuGetDisplayName();
735 if (!dpyName)
736 {
737 crWarning("Render SPU: no display, aborting");
738 return GL_FALSE;
739 }
740
741
742 crInfo("Render SPU: Opening display %s", dpyName);
743
744 if (dpyName &&
745 (crStrncmp(dpyName, "localhost:11", 12) == 0 ||
746 crStrncmp(dpyName, "localhost:12", 12) == 0 ||
747 crStrncmp(dpyName, "localhost:13", 12) == 0)) {
748 /* Issue both debug and warning messages to make sure the
749 * message gets noticed!
750 */
751 crDebug("Render SPU: display string looks like a proxy X server!");
752 crDebug("Render SPU: This is usually a problem!");
753 crWarning("Render SPU: display string looks like a proxy X server!");
754 crWarning("Render SPU: This is usually a problem!");
755 }
756
757 visual->dpy = XOpenDisplay(dpyName);
758 if (!visual->dpy)
759 {
760 crWarning( "Couldn't open X display named '%s'", dpyName );
761 return GL_FALSE;
762 }
763
764 if ( !render_spu.ws.glXQueryExtension( visual->dpy, NULL, NULL ) )
765 {
766 crWarning( "Render SPU: Display %s doesn't support GLX", visual->displayName );
767 return GL_FALSE;
768 }
769
770 screen = DefaultScreen(visual->dpy);
771
772#ifdef GLX_VERSION_1_3
773 if (visual->visAttribs & CR_PBUFFER_BIT)
774 {
775 visual->fbconfig = chooseFBConfig(visual->dpy, screen, visual->visAttribs);
776 if (!visual->fbconfig) {
777 char s[1000];
778 renderspuMakeVisString( visual->visAttribs, s );
779 crWarning( "Render SPU: Display %s doesn't have the necessary fbconfig: %s",
780 dpyName, s );
781 XCloseDisplay(visual->dpy);
782 return GL_FALSE;
783 }
784 }
785 else
786#endif /* GLX_VERSION_1_3 */
787 {
788 visual->visual = chooseVisualRetry(visual->dpy, screen, visual->visAttribs);
789 if (!visual->visual) {
790 char s[1000];
791 renderspuMakeVisString( visual->visAttribs, s );
792 crWarning("Render SPU: Display %s doesn't have the necessary visual: %s",
793 dpyName, s );
794 XCloseDisplay(visual->dpy);
795 return GL_FALSE;
796 }
797 }
798
799 if ( render_spu.sync )
800 {
801 crDebug( "Render SPU: Turning on XSynchronize" );
802 XSynchronize( visual->dpy, True );
803 }
804
805 if (visual->visual) {
806 crDebug( "Render SPU: Choose visual id=0x%x: RGBA=(%d,%d,%d,%d) Z=%d"
807 " stencil=%d double=%d stereo=%d accum=(%d,%d,%d,%d)",
808 (int) visual->visual->visualid,
809 Attrib( visual, GLX_RED_SIZE ),
810 Attrib( visual, GLX_GREEN_SIZE ),
811 Attrib( visual, GLX_BLUE_SIZE ),
812 Attrib( visual, GLX_ALPHA_SIZE ),
813 Attrib( visual, GLX_DEPTH_SIZE ),
814 Attrib( visual, GLX_STENCIL_SIZE ),
815 Attrib( visual, GLX_DOUBLEBUFFER ),
816 Attrib( visual, GLX_STEREO ),
817 Attrib( visual, GLX_ACCUM_RED_SIZE ),
818 Attrib( visual, GLX_ACCUM_GREEN_SIZE ),
819 Attrib( visual, GLX_ACCUM_BLUE_SIZE ),
820 Attrib( visual, GLX_ACCUM_ALPHA_SIZE )
821 );
822 }
823 else if (visual->fbconfig) {
824 int id;
825 render_spu.ws.glXGetFBConfigAttrib(visual->dpy, visual->fbconfig,
826 GLX_FBCONFIG_ID, &id);
827 crDebug("Render SPU: Chose FBConfig 0x%x, visBits=0x%x",
828 id, visual->visAttribs);
829 }
830
831 return GL_TRUE;
832}
833
834
835/*
836 * Add a GLX window to a swap group for inter-machine SwapBuffer
837 * synchronization.
838 * Only supported on NVIDIA Quadro 3000G hardware.
839 */
840static void
841JoinSwapGroup(Display *dpy, int screen, Window window,
842 GLuint group, GLuint barrier)
843{
844 GLuint maxGroups, maxBarriers;
845 const char *ext;
846 Bool b;
847
848 /*
849 * XXX maybe query glXGetClientString() instead???
850 */
851 ext = render_spu.ws.glXQueryExtensionsString(dpy, screen);
852
853 if (!crStrstr(ext, "GLX_NV_swap_group") ||
854 !render_spu.ws.glXQueryMaxSwapGroupsNV ||
855 !render_spu.ws.glXJoinSwapGroupNV ||
856 !render_spu.ws.glXBindSwapBarrierNV) {
857 crWarning("Render SPU: nv_swap_group is set but GLX_NV_swap_group is not supported on this system!");
858 return;
859 }
860
861 b = render_spu.ws.glXQueryMaxSwapGroupsNV(dpy, screen,
862 &maxGroups, &maxBarriers);
863 if (!b)
864 crWarning("Render SPU: call to glXQueryMaxSwapGroupsNV() failed!");
865
866 if (group >= maxGroups) {
867 crWarning("Render SPU: nv_swap_group too large (%d > %d)",
868 group, (int) maxGroups);
869 return;
870 }
871 crDebug("Render SPU: max swap groups = %d, max barriers = %d",
872 maxGroups, maxBarriers);
873
874 /* add this window to the swap group */
875 b = render_spu.ws.glXJoinSwapGroupNV(dpy, window, group);
876 if (!b) {
877 crWarning("Render SPU: call to glXJoinSwapGroupNV() failed!");
878 return;
879 }
880 else {
881 crDebug("Render SPU: call to glXJoinSwapGroupNV() worked!");
882 }
883
884 /* ... and bind window to barrier of same ID */
885 b = render_spu.ws.glXBindSwapBarrierNV(dpy, group, barrier);
886 if (!b) {
887 crWarning("Render SPU: call to glXBindSwapBarrierNV(group=%d barrier=%d) failed!", group, barrier);
888 return;
889 }
890 else {
891 crDebug("Render SPU: call to glXBindSwapBarrierNV(group=%d barrier=%d) worked!", group, barrier);
892 }
893
894 crDebug("Render SPU: window has joined swap group %d", group);
895}
896
897
898
899static GLboolean
900createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
901{
902 Display *dpy;
903 Colormap cmap;
904 XSetWindowAttributes swa;
905 XSizeHints hints = {0};
906 XEvent event;
907 XTextProperty text_prop;
908 XClassHint *class_hints = NULL;
909 Window parent;
910 char *name;
911 unsigned long flags;
912 unsigned int vncWin;
913
914 CRASSERT(visual);
915 window->visual = visual;
916 window->nativeWindow = 0;
917
918#ifdef USE_OSMESA
919 if (render_spu.use_osmesa)
920 return GL_TRUE;
921#endif
922
923 dpy = visual->dpy;
924
925 if ( render_spu.use_L2 )
926 {
927 crWarning( "Render SPU: Going fullscreen because we think we're using Lightning-2." );
928 render_spu.fullscreen = 1;
929 }
930
931 /*
932 * Query screen size if we're going full-screen
933 */
934 if ( render_spu.fullscreen )
935 {
936 XWindowAttributes xwa;
937 Window root_window;
938
939 /* disable the screensaver */
940 XSetScreenSaver( dpy, 0, 0, PreferBlanking, AllowExposures );
941 crDebug( "Render SPU: Just turned off the screensaver" );
942
943 /* Figure out how big the screen is, and make the window that size */
944 root_window = DefaultRootWindow( dpy );
945 XGetWindowAttributes( dpy, root_window, &xwa );
946
947 crDebug( "Render SPU: root window size: %d x %d", xwa.width, xwa.height );
948
949 window->x = 0;
950 window->y = 0;
951 window->BltInfo.width = xwa.width;
952 window->BltInfo.height = xwa.height;
953 }
954
955 /* i've changed default window size to be 0,0 but X doesn't like it */
956 /*CRASSERT(window->BltInfo.width >= 1);
957 CRASSERT(window->BltInfo.height >= 1);*/
958 if (window->BltInfo.width < 1) window->BltInfo.width = 1;
959 if (window->BltInfo.height < 1) window->BltInfo.height = 1;
960
961 /*
962 * Get a colormap.
963 */
964 if (render_spu.use_lut8)
965 cmap = GetLUTColormap( dpy, visual->visual );
966 else
967 cmap = GetShareableColormap( dpy, visual->visual );
968 if ( !cmap ) {
969 crError( "Render SPU: Unable to get a colormap!" );
970 return GL_FALSE;
971 }
972
973 /* destroy existing window if there is one */
974 if (window->window) {
975 XDestroyWindow(dpy, window->window);
976 }
977
978 /*
979 * Create the window
980 *
981 * POSSIBLE OPTIMIZATION:
982 * If we're using the render_to_app_window or render_to_crut_window option
983 * (or DMX) we may never actually use this X window. So we could perhaps
984 * delay its creation until glXMakeCurrent is called. With NVIDIA's OpenGL
985 * driver, creating a lot of GLX windows can eat up a lot of VRAM and lead
986 * to slow, software-fallback rendering. Apps that use render_to_app_window,
987 * etc should set the default window size very small to avoid this.
988 * See dmx.conf for example.
989 */
990 swa.colormap = cmap;
991 swa.border_pixel = 0;
992 swa.event_mask = ExposureMask | StructureNotifyMask;
993 swa.override_redirect = 1;
994
995 flags = CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect;
996
997 /*
998 * We pass the VNC's desktop windowID via an environment variable.
999 * If we don't find one, we're not on a 3D-capable vncviewer, or
1000 * if we do find one, then create the renderspu subwindow as a
1001 * child of the vncviewer's desktop window.
1002 *
1003 * This is purely for the replicateSPU.
1004 *
1005 * NOTE: This is crufty, and will do for now. FIXME.
1006 */
1007 vncWin = crStrToInt( crGetenv("CRVNCWINDOW") );
1008 if (vncWin)
1009 parent = (Window) vncWin;
1010 else
1011 parent = RootWindow(dpy, visual->visual->screen);
1012
1013 if (render_spu_parent_window_id>0)
1014 {
1015 crDebug("Render SPU: VBox parent window_id is: %x", render_spu_parent_window_id);
1016 window->window = XCreateWindow(dpy, render_spu_parent_window_id,
1017 window->x, window->y,
1018 window->BltInfo.width, window->BltInfo.height,
1019 0, visual->visual->depth, InputOutput,
1020 visual->visual->visual, flags, &swa);
1021 }
1022 else
1023 {
1024 /* This should happen only at the call from crVBoxServerInit. At this point we don't
1025 * know render_spu_parent_window_id yet, nor we need it for default window which is hidden.
1026 */
1027
1028 crDebug("Render SPU: Creating global window, parent: %x", RootWindow(dpy, visual->visual->screen));
1029 window->window = XCreateWindow(dpy, RootWindow(dpy, visual->visual->screen),
1030 window->x, window->y,
1031 window->BltInfo.width, window->BltInfo.height,
1032 0, visual->visual->depth, InputOutput,
1033 visual->visual->visual, flags, &swa);
1034 }
1035
1036 if (!window->window) {
1037 crWarning( "Render SPU: unable to create window" );
1038 return GL_FALSE;
1039 }
1040
1041 crDebug( "Render SPU: Created window 0x%x on display %s, Xvisual 0x%x",
1042 (int) window->window,
1043 DisplayString(visual->dpy),
1044 (int) visual->visual->visual->visualid /* yikes */
1045 );
1046
1047 if (render_spu.fullscreen || render_spu.borderless)
1048 {
1049 /* Disable border/decorations with an MWM property (observed by most
1050 * modern window managers.
1051 */
1052 PropMotifWmHints motif_hints;
1053 Atom prop, proptype;
1054
1055 /* setup the property */
1056 motif_hints.flags = MWM_HINTS_DECORATIONS;
1057 motif_hints.decorations = 0; /* Turn off all decorations */
1058
1059 /* get the atom for the property */
1060 prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True );
1061 if (prop) {
1062 /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */
1063 proptype = prop;
1064 XChangeProperty( dpy, window->window, /* display, window */
1065 prop, proptype, /* property, type */
1066 32, /* format: 32-bit datums */
1067 PropModeReplace, /* mode */
1068 (unsigned char *) &motif_hints, /* data */
1069 PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */
1070 );
1071 }
1072 }
1073
1074 /* Make a clear cursor to get rid of the monitor cursor */
1075 if ( render_spu.fullscreen )
1076 {
1077 Pixmap pixmap;
1078 Cursor cursor;
1079 XColor colour;
1080 char clearByte = 0;
1081
1082 /* AdB - Only bother to create a 1x1 cursor (byte) */
1083 pixmap = XCreatePixmapFromBitmapData(dpy, window->window, &clearByte,
1084 1, 1, 1, 0, 1);
1085 if(!pixmap){
1086 crWarning("Unable to create clear cursor pixmap");
1087 return GL_FALSE;
1088 }
1089
1090 cursor = XCreatePixmapCursor(dpy, pixmap, pixmap, &colour, &colour, 0, 0);
1091 if(!cursor){
1092 crWarning("Unable to create clear cursor from zero byte pixmap");
1093 return GL_FALSE;
1094 }
1095 XDefineCursor(dpy, window->window, cursor);
1096 XFreePixmap(dpy, pixmap);
1097 }
1098
1099 hints.x = window->x;
1100 hints.y = window->y;
1101 hints.width = window->BltInfo.width;
1102 hints.height = window->BltInfo.height;
1103 hints.min_width = hints.width;
1104 hints.min_height = hints.height;
1105 hints.max_width = hints.width;
1106 hints.max_height = hints.height;
1107 if (render_spu.resizable)
1108 hints.flags = USPosition | USSize;
1109 else
1110 hints.flags = USPosition | USSize | PMinSize | PMaxSize;
1111 XSetStandardProperties( dpy, window->window,
1112 WINDOW_NAME, WINDOW_NAME,
1113 None, NULL, 0, &hints );
1114
1115 /* New item! This is needed so that the sgimouse server can find
1116 * the crDebug window.
1117 */
1118 name = WINDOW_NAME;
1119 XStringListToTextProperty( &name, 1, &text_prop );
1120 XSetWMName( dpy, window->window, &text_prop );
1121
1122 /* Set window name, resource class */
1123 class_hints = XAllocClassHint( );
1124 class_hints->res_name = crStrdup( "foo" );
1125 class_hints->res_class = crStrdup( "Chromium" );
1126 XSetClassHint( dpy, window->window, class_hints );
1127 crFree( class_hints->res_name );
1128 crFree( class_hints->res_class );
1129 XFree( class_hints );
1130
1131 if (showIt) {
1132 XMapWindow( dpy, window->window );
1133 XIfEvent( dpy, &event, WaitForMapNotify,
1134 (char *) window->window );
1135 }
1136
1137 if ((window->visual->visAttribs & CR_DOUBLE_BIT) && render_spu.nvSwapGroup) {
1138 /* NOTE:
1139 * If this SPU creates N windows we don't want to gang the N windows
1140 * together!
1141 * By adding the window ID to the nvSwapGroup ID we can be sure each
1142 * app window is in a separate swap group while all the back-end windows
1143 * which form a mural are in the same swap group.
1144 */
1145 GLuint group = 0; /*render_spu.nvSwapGroup + window->BltInfo.Base.id;*/
1146 GLuint barrier = 0;
1147 JoinSwapGroup(dpy, visual->visual->screen, window->window, group, barrier);
1148 }
1149
1150 /*
1151 * End GLX code
1152 */
1153 crDebug( "Render SPU: actual window x, y, width, height: %d, %d, %d, %d",
1154 window->x, window->y, window->BltInfo.width, window->BltInfo.height );
1155
1156 XSync(dpy, 0);
1157
1158 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1159 {
1160 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE, window);
1161 AssertRC(rc);
1162 }
1163
1164 return GL_TRUE;
1165}
1166
1167
1168static GLboolean
1169createPBuffer( VisualInfo *visual, WindowInfo *window )
1170{
1171 window->visual = visual;
1172 window->x = 0;
1173 window->y = 0;
1174 window->nativeWindow = 0;
1175
1176 CRASSERT(window->BltInfo.width > 0);
1177 CRASSERT(window->BltInfo.height > 0);
1178
1179#ifdef GLX_VERSION_1_3
1180 {
1181 int attribs[100], i = 0, w, h;
1182 CRASSERT(visual->fbconfig);
1183 w = window->BltInfo.width;
1184 h = window->BltInfo.height;
1185 attribs[i++] = GLX_PRESERVED_CONTENTS;
1186 attribs[i++] = True;
1187 attribs[i++] = GLX_PBUFFER_WIDTH;
1188 attribs[i++] = w;
1189 attribs[i++] = GLX_PBUFFER_HEIGHT;
1190 attribs[i++] = h;
1191 attribs[i++] = 0; /* terminator */
1192 window->window = render_spu.ws.glXCreatePbuffer(visual->dpy,
1193 visual->fbconfig, attribs);
1194 if (window->window) {
1195 crDebug("Render SPU: Allocated %d x %d pbuffer", w, h);
1196 return GL_TRUE;
1197 }
1198 else {
1199 crWarning("Render SPU: Failed to allocate %d x %d pbuffer", w, h);
1200 return GL_FALSE;
1201 }
1202 }
1203#endif /* GLX_VERSION_1_3 */
1204 return GL_FALSE;
1205}
1206
1207
1208GLboolean
1209renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1210{
1211 if (visual->visAttribs & CR_PBUFFER_BIT) {
1212 window->BltInfo.width = render_spu.defaultWidth;
1213 window->BltInfo.height = render_spu.defaultHeight;
1214 return createPBuffer(visual, window);
1215 }
1216 else {
1217 return createWindow(visual, showIt, window);
1218 }
1219}
1220
1221GLboolean
1222renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1223{
1224 return renderspu_SystemCreateWindow(visual, showIt, window);
1225}
1226
1227void
1228renderspu_SystemDestroyWindow( WindowInfo *window )
1229{
1230 CRASSERT(window);
1231 CRASSERT(window->visual);
1232
1233#ifdef USE_OSMESA
1234 if (render_spu.use_osmesa)
1235 {
1236 crFree(window->buffer);
1237 window->buffer = NULL;
1238 }
1239 else
1240#endif
1241 {
1242 if (window->visual->visAttribs & CR_PBUFFER_BIT) {
1243#ifdef GLX_VERSION_1_3
1244 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1245#endif
1246 }
1247 else {
1248 /* The value window->nativeWindow will only be non-NULL if the
1249 * render_to_app_window option is set to true. In this case, we
1250 * don't want to do anything, since we're not responsible for this
1251 * window. I know...personal responsibility and all...
1252 */
1253 if (!window->nativeWindow) {
1254 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1255 {
1256 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY, window);
1257 AssertRC(rc);
1258 }
1259 XDestroyWindow(window->visual->dpy, window->window);
1260 XSync(window->visual->dpy, 0);
1261 }
1262 }
1263 }
1264 window->visual = NULL;
1265 window->window = 0;
1266}
1267
1268
1269GLboolean
1270renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
1271{
1272 Bool is_direct;
1273 GLXContext sharedSystemContext = NULL;
1274
1275 CRASSERT(visual);
1276 CRASSERT(context);
1277
1278 context->visual = visual;
1279
1280 if (sharedContext != NULL) {
1281 sharedSystemContext = sharedContext->context;
1282 }
1283
1284
1285
1286#ifdef USE_OSMESA
1287 if (render_spu.use_osmesa) {
1288 context->context = (GLXContext) render_spu.OSMesaCreateContext(OSMESA_RGB, 0);
1289 if (context->context)
1290 return GL_TRUE;
1291 else
1292 return GL_FALSE;
1293 }
1294#endif
1295
1296#ifdef GLX_VERSION_1_3
1297 if (visual->visAttribs & CR_PBUFFER_BIT) {
1298 context->context = render_spu.ws.glXCreateNewContext( visual->dpy,
1299 visual->fbconfig,
1300 GLX_RGBA_TYPE,
1301 sharedSystemContext,
1302 render_spu.try_direct);
1303 }
1304 else
1305#endif
1306 {
1307 context->context = render_spu.ws.glXCreateContext( visual->dpy,
1308 visual->visual,
1309 sharedSystemContext,
1310 render_spu.try_direct);
1311 }
1312 if (!context->context) {
1313 crError( "Render SPU: Couldn't create rendering context" );
1314 return GL_FALSE;
1315 }
1316
1317 is_direct = render_spu.ws.glXIsDirect( visual->dpy, context->context );
1318 if (visual->visual)
1319 crDebug("Render SPU: Created %s context (%d) on display %s for visAttribs 0x%x",
1320 is_direct ? "DIRECT" : "INDIRECT",
1321 context->BltInfo.Base.id,
1322 DisplayString(visual->dpy),
1323 visual->visAttribs);
1324
1325 if ( render_spu.force_direct && !is_direct )
1326 {
1327 crError( "Render SPU: Direct rendering not possible." );
1328 return GL_FALSE;
1329 }
1330
1331 return GL_TRUE;
1332}
1333
1334
1335#define USE_GLX_COPYCONTEXT 0
1336
1337#if !USE_GLX_COPYCONTEXT
1338
1339/**
1340 * Unfortunately, glXCopyContext() is broken sometimes (NVIDIA 76.76 driver).
1341 * This bit of code gets and sets GL state we need to copy between contexts.
1342 */
1343struct saved_state
1344{
1345 /* XXX depending on the app, more state may be needed here */
1346 GLboolean Lighting;
1347 GLboolean LightEnabled[8];
1348 GLfloat LightPos[8][4];
1349 GLfloat LightAmbient[8][4];
1350 GLfloat LightDiffuse[8][4];
1351 GLfloat LightSpecular[8][4];
1352 GLboolean DepthTest;
1353};
1354
1355static struct saved_state SavedState;
1356
1357static void
1358get_state(struct saved_state *s)
1359{
1360 int i;
1361
1362 s->Lighting = render_spu.self.IsEnabled(GL_LIGHTING);
1363 for (i = 0; i < 8; i++) {
1364 s->LightEnabled[i] = render_spu.self.IsEnabled(GL_LIGHT0 + i);
1365 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1366 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1367 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1368 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1369 }
1370
1371 s->DepthTest = render_spu.self.IsEnabled(GL_DEPTH_TEST);
1372}
1373
1374static void
1375set_state(const struct saved_state *s)
1376{
1377 int i;
1378
1379 if (s->Lighting) {
1380 render_spu.self.Enable(GL_LIGHTING);
1381 }
1382 else {
1383 render_spu.self.Disable(GL_LIGHTING);
1384 }
1385
1386 for (i = 0; i < 8; i++) {
1387 if (s->LightEnabled[i]) {
1388 render_spu.self.Enable(GL_LIGHT0 + i);
1389 }
1390 else {
1391 render_spu.self.Disable(GL_LIGHT0 + i);
1392 }
1393 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1394 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1395 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1396 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1397 }
1398
1399 if (s->DepthTest)
1400 render_spu.self.Enable(GL_DEPTH_TEST);
1401 else
1402 render_spu.self.Disable(GL_DEPTH_TEST);
1403}
1404
1405#endif /* !USE_GLX_COPYCONTEXT */
1406
1407/**
1408 * Recreate the GLX context for ContextInfo. The new context will use the
1409 * visual specified by newVisualID.
1410 */
1411static void
1412renderspu_RecreateContext( ContextInfo *context, int newVisualID )
1413{
1414 XVisualInfo templateVis, *vis;
1415 long templateFlags;
1416 int screen = 0, count;
1417 GLXContext oldContext = context->context;
1418
1419 templateFlags = VisualScreenMask | VisualIDMask;
1420 templateVis.screen = screen;
1421 templateVis.visualid = newVisualID;
1422 vis = XGetVisualInfo(context->visual->dpy, templateFlags, &templateVis, &count);
1423 CRASSERT(vis);
1424 if (!vis)
1425 return;
1426
1427 /* create new context */
1428 crDebug("Render SPU: Creating new GLX context with visual 0x%x", newVisualID);
1429 context->context = render_spu.ws.glXCreateContext(context->visual->dpy,
1430 vis, NULL,
1431 render_spu.try_direct);
1432 CRASSERT(context->context);
1433
1434#if USE_GLX_COPYCONTEXT
1435 /* copy old context state to new context */
1436 render_spu.ws.glXCopyContext(context->visual->dpy,
1437 oldContext, context->context, ~0);
1438 crDebug("Render SPU: Done copying context state");
1439#endif
1440
1441 /* destroy old context */
1442 render_spu.ws.glXDestroyContext(context->visual->dpy, oldContext);
1443
1444 context->visual->visual = vis;
1445}
1446
1447
1448void
1449renderspu_SystemDestroyContext( ContextInfo *context )
1450{
1451#ifdef USE_OSMESA
1452 if (render_spu.use_osmesa)
1453 {
1454 render_spu.OSMesaDestroyContext( (OSMesaContext) context->context );
1455 }
1456 else
1457#endif
1458 {
1459#if 0
1460 /* XXX disable for now - causes segfaults w/ NVIDIA's driver */
1461 render_spu.ws.glXDestroyContext( context->visual->dpy, context->context );
1462#endif
1463 }
1464 context->visual = NULL;
1465 context->context = 0;
1466}
1467
1468
1469#ifdef USE_OSMESA
1470static void
1471check_buffer_size( WindowInfo *window )
1472{
1473 if (window->BltInfo.width != window->in_buffer_width
1474 || window->BltInfo.height != window->in_buffer_height
1475 || ! window->buffer) {
1476 crFree(window->buffer);
1477
1478 window->buffer = crCalloc(window->BltInfo.width * window->BltInfo.height
1479 * 4 * sizeof (GLubyte));
1480
1481 window->in_buffer_width = window->BltInfo.width;
1482 window->in_buffer_height = window->BltInfo.height;
1483
1484 crDebug("Render SPU: dimensions changed to %d x %d", window->BltInfo.width, window->BltInfo.height);
1485 }
1486}
1487#endif
1488
1489
1490void
1491renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
1492 ContextInfo *context )
1493{
1494 Bool b;
1495
1496 CRASSERT(render_spu.ws.glXMakeCurrent);
1497
1498 /*crDebug("%s nativeWindow=0x%x", __FUNCTION__, (int) nativeWindow);*/
1499
1500#ifdef USE_OSMESA
1501 if (render_spu.use_osmesa) {
1502 check_buffer_size(window);
1503 render_spu.OSMesaMakeCurrent( (OSMesaContext) context->context,
1504 window->buffer, GL_UNSIGNED_BYTE,
1505 window->BltInfo.width, window->BltInfo.height);
1506 return;
1507 }
1508#endif
1509
1510 nativeWindow = 0;
1511
1512 if (window && context) {
1513 window->appWindow = nativeWindow;
1514
1515 if (window->visual != context->visual) {
1516 crDebug("Render SPU: MakeCurrent visual mismatch (win(%d) bits:0x%x != ctx(%d) bits:0x%x); remaking window.",
1517 window->BltInfo.Base.id, window->visual->visAttribs,
1518 context->BltInfo.Base.id, context->visual->visAttribs);
1519 /*
1520 * XXX have to revisit this issue!!!
1521 *
1522 * But for now we destroy the current window
1523 * and re-create it with the context's visual abilities
1524 */
1525#ifndef SOLARIS_9_X_BUG
1526 /*
1527 I'm having some really weird issues if I destroy this window
1528 when I'm using the version of sunX that comes with Solaris 9.
1529 Subsiquent glX calls return GLXBadCurrentWindow error.
1530
1531 This is an issue even when running Linux version and using
1532 the Solaris 9 sunX as a display.
1533 -- jw
1534
1535 jw: we might have to call glXMakeCurrent(dpy, 0, 0) to unbind
1536 the context from the window before destroying it. -Brian
1537 */
1538 render_spu.ws.glXMakeCurrent(window->visual->dpy, 0, 0);
1539 renderspu_SystemDestroyWindow( window );
1540#endif
1541 renderspu_SystemCreateWindow( context->visual, window->visible, window );
1542 /*
1543 crError("In renderspu_SystemMakeCurrent() window and context"
1544 " weren't created with same visual!");
1545 */
1546 }
1547
1548 CRASSERT(context->context);
1549
1550#if 0
1551 if (render_spu.render_to_crut_window) {
1552 if (render_spu.crut_drawable == 0) {
1553 /* We don't know the X drawable ID yet. Ask mothership for it. */
1554 char response[8096];
1555 CRConnection *conn = crMothershipConnect();
1556 if (!conn)
1557 {
1558 crError("Couldn't connect to the mothership to get CRUT drawable-- "
1559 "I have no idea what to do!");
1560 }
1561 crMothershipGetParam( conn, "crut_drawable", response );
1562 render_spu.crut_drawable = crStrToInt(response);
1563 crMothershipDisconnect(conn);
1564
1565 crDebug("Render SPU: using CRUT drawable: 0x%x",
1566 render_spu.crut_drawable);
1567 if (!render_spu.crut_drawable) {
1568 crDebug("Render SPU: Crut drawable 0 is invalid");
1569 /* Continue with nativeWindow = 0; we'll render to the window that
1570 * we (the Render SPU) previously created.
1571 */
1572 }
1573 }
1574
1575 nativeWindow = render_spu.crut_drawable;
1576 }
1577#endif
1578
1579 if ((render_spu.render_to_crut_window || render_spu.render_to_app_window)
1580 && nativeWindow)
1581 {
1582 /* We're about to bind the rendering context to a window that we
1583 * (the Render SPU) did not create. The window was created by the
1584 * application or the CRUT server.
1585 * Make sure the window ID is valid and that the window's X visual is
1586 * the same as the rendering context's.
1587 */
1588 if (WindowExists(window->visual->dpy, nativeWindow))
1589 {
1590 int vid = GetWindowVisualID(window->visual->dpy, nativeWindow);
1591 GLboolean recreated = GL_FALSE;
1592
1593 /* check that the window's visual and context's visual match */
1594 if (vid != (int) context->visual->visual->visualid) {
1595 crWarning("Render SPU: Can't bind context %d to CRUT/native window "
1596 "0x%x because of different X visuals (0x%x != 0x%x)!",
1597 context->BltInfo.Base.id, (int) nativeWindow,
1598 vid, (int) context->visual->visual->visualid);
1599 crWarning("Render SPU: Trying to recreate GLX context to match.");
1600 /* Try to recreate the GLX context so that it uses the same
1601 * GLX visual as the window.
1602 */
1603#if !USE_GLX_COPYCONTEXT
1604 if (context->everCurrent) {
1605 get_state(&SavedState);
1606 }
1607#endif
1608 renderspu_RecreateContext(context, vid);
1609 recreated = GL_TRUE;
1610 }
1611
1612 /* OK, this should work */
1613 window->nativeWindow = (Window) nativeWindow;
1614 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1615 window->nativeWindow,
1616 context->context );
1617 CRASSERT(b);
1618#if !USE_GLX_COPYCONTEXT
1619 if (recreated) {
1620 set_state(&SavedState);
1621 }
1622#endif
1623 }
1624 else
1625 {
1626 crWarning("Render SPU: render_to_app/crut_window option is set but "
1627 "the window ID 0x%x is invalid on the display named %s",
1628 (unsigned int) nativeWindow,
1629 DisplayString(window->visual->dpy));
1630 CRASSERT(window->window);
1631 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1632 window->window, context->context );
1633 CRASSERT(b);
1634 }
1635 }
1636 else
1637 {
1638 /* This is the normal case - rendering to the render SPU's own window */
1639 CRASSERT(window->window);
1640#if 0
1641 crDebug("calling glXMakecurrent(%p, 0x%x, 0x%x)",
1642 window->visual->dpy,
1643 (int) window->window, (int) context->context );
1644#endif
1645 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1646 window->window, context->context );
1647 if (!b) {
1648 crWarning("glXMakeCurrent(%p, 0x%x, %p) failed! (winId %d, ctxId %d)",
1649 window->visual->dpy,
1650 (int) window->window, (void *) context->context,
1651 window->BltInfo.Base.id, context->BltInfo.Base.id );
1652 }
1653 /*CRASSERT(b);*/
1654 }
1655
1656 /* XXX this is a total hack to work around an NVIDIA driver bug */
1657#if 0
1658 if (render_spu.self.GetFloatv && context->haveWindowPosARB) {
1659 GLfloat f[4];
1660 render_spu.self.GetFloatv(GL_CURRENT_RASTER_POSITION, f);
1661 if (!window->everCurrent || f[1] < 0.0) {
1662 crDebug("Render SPU: Resetting raster pos");
1663 render_spu.self.WindowPos2iARB(0, 0);
1664 }
1665 }
1666#endif
1667 }
1668 else
1669 {
1670 GET_CONTEXT(pCurCtx);
1671 if (pCurCtx)
1672 {
1673 b = render_spu.ws.glXMakeCurrent( pCurCtx->currentWindow->visual->dpy, None, NULL);
1674 if (!b) {
1675 crWarning("glXMakeCurrent(%p, None, NULL) failed!", pCurCtx->currentWindow->visual->dpy);
1676 }
1677 }
1678
1679 }
1680
1681#if 0
1682 /* XXX disabled for now due to problem with threadtest.conf */
1683 renderspu_GCWindow();
1684#endif
1685}
1686
1687
1688/**
1689 * Set window (or pbuffer) size.
1690 */
1691void
1692renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
1693{
1694#ifdef USE_OSMESA
1695 if (render_spu.use_osmesa) {
1696 window->BltInfo.width = w;
1697 window->BltInfo.height = h;
1698 check_buffer_size(window);
1699 return;
1700 }
1701#endif
1702
1703 CRASSERT(window);
1704 CRASSERT(window->visual);
1705 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1706 {
1707 /* resizing a pbuffer */
1708 if (render_spu.pbufferWidth != 0 || render_spu.pbufferHeight != 0) {
1709 /* size limit check */
1710 if (w > render_spu.pbufferWidth || h > render_spu.pbufferHeight) {
1711 crWarning("Render SPU: Request for %d x %d pbuffer is larger than "
1712 "the configured size of %d x %d. ('pbuffer_size')",
1713 w, h, render_spu.pbufferWidth, render_spu.pbufferHeight);
1714 return;
1715 }
1716 /*
1717 * If the requested new pbuffer size is greater than 1/2 the size of
1718 * the max pbuffer, just use the max pbuffer size. This helps avoid
1719 * problems with VRAM memory fragmentation. If we run out of VRAM
1720 * for pbuffers, some drivers revert to software rendering. We want
1721 * to avoid that!
1722 */
1723 if (w * h >= render_spu.pbufferWidth * render_spu.pbufferHeight / 2) {
1724 /* increase the dimensions to the max pbuffer size now */
1725 w = render_spu.pbufferWidth;
1726 h = render_spu.pbufferHeight;
1727 }
1728 }
1729
1730 if (window->BltInfo.width != w || window->BltInfo.height != h) {
1731 /* Only resize if the new dimensions really are different */
1732#ifdef CHROMIUM_THREADSAFE
1733 ContextInfo *currentContext = (ContextInfo *) crGetTSD(&_RenderTSD);
1734#else
1735 ContextInfo *currentContext = render_spu.currentContext;
1736#endif
1737 /* Can't resize pbuffers, so destroy it and make a new one */
1738 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1739 window->BltInfo.width = w;
1740 window->BltInfo.height = h;
1741 crDebug("Render SPU: Creating new %d x %d PBuffer (id=%d)",
1742 w, h, window->BltInfo.Base.id);
1743 if (!createPBuffer(window->visual, window)) {
1744 crWarning("Render SPU: Unable to create PBuffer (out of VRAM?)!");
1745 }
1746 else if (currentContext && currentContext->currentWindow == window) {
1747 /* Determine if we need to bind the current context to new pbuffer */
1748 render_spu.ws.glXMakeCurrent(window->visual->dpy,
1749 window->window,
1750 currentContext->context );
1751 }
1752 }
1753 }
1754 else {
1755 if (!w || !h)
1756 {
1757 /* X can not handle zero sizes */
1758 if (window->visible)
1759 {
1760 renderspu_SystemShowWindow( window, GL_FALSE );
1761 return;
1762 }
1763 }
1764 /* Resize ordinary X window */
1765 /*
1766 * This is ugly, but it seems to be the only thing that works.
1767 * Basically, XResizeWindow() doesn't seem to always take effect
1768 * immediately.
1769 * Even after an XSync(), the GetWindowAttributes() call will sometimes
1770 * return the old window size. So, we use a loop to repeat the window
1771 * resize until it seems to take effect.
1772 */
1773 int attempt;
1774 crDebug("Render SPU: XResizeWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, w, h);
1775 XResizeWindow(window->visual->dpy, window->window, w, h);
1776 XSync(window->visual->dpy, 0);
1777
1778 if (!window->BltInfo.width || !window->BltInfo.height)
1779 {
1780 /* we have hidden the window instead of sizing it to (0;0) since X is unable to handle zero sizes */
1781 if (window->visible)
1782 {
1783 renderspu_SystemShowWindow( window, GL_TRUE );
1784 return;
1785 }
1786 }
1787#if 0
1788 for (attempt = 0; attempt < 3; attempt++) { /* try three times max */
1789 XWindowAttributes attribs;
1790 /* Now, query the window size */
1791 XGetWindowAttributes(window->visual->dpy, window->window, &attribs);
1792 if (attribs.width == w && attribs.height == h)
1793 break;
1794 /* sleep for a millisecond and try again */
1795 crMsleep(1);
1796 }
1797#endif
1798 }
1799}
1800
1801
1802void
1803renderspu_SystemGetWindowGeometry( WindowInfo *window,
1804 GLint *x, GLint *y, GLint *w, GLint *h )
1805{
1806#ifdef USE_OSMESA
1807 if (render_spu.use_osmesa) {
1808 *w = window->BltInfo.width;
1809 *h = window->BltInfo.height;
1810 return;
1811 }
1812#endif
1813
1814 CRASSERT(window);
1815 CRASSERT(window->visual);
1816 CRASSERT(window->window);
1817 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1818 {
1819 *x = 0;
1820 *y = 0;
1821 *w = window->BltInfo.width;
1822 *h = window->BltInfo.height;
1823 }
1824 else
1825 {
1826 Window xw, child, root;
1827 unsigned int width, height, bw, d;
1828 int rx, ry;
1829
1830 if ((render_spu.render_to_app_window || render_spu.render_to_crut_window)
1831 && window->nativeWindow) {
1832 xw = window->nativeWindow;
1833 }
1834 else {
1835 xw = window->window;
1836 }
1837
1838 XGetGeometry(window->visual->dpy, xw, &root,
1839 x, y, &width, &height, &bw, &d);
1840
1841 /* translate x/y to screen coords */
1842 if (!XTranslateCoordinates(window->visual->dpy, xw, root,
1843 0, 0, &rx, &ry, &child)) {
1844 rx = ry = 0;
1845 }
1846 *x = rx;
1847 *y = ry;
1848 *w = (int) width;
1849 *h = (int) height;
1850 }
1851}
1852
1853
1854void
1855renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h )
1856{
1857 int scrn;
1858#ifdef USE_OSMESA
1859 if (render_spu.use_osmesa) {
1860 *w = 2048;
1861 *h = 2048;
1862 return;
1863 }
1864#endif
1865
1866 CRASSERT(window);
1867 CRASSERT(window->visual);
1868 CRASSERT(window->window);
1869
1870 scrn = DefaultScreen(window->visual->dpy);
1871 *w = DisplayWidth(window->visual->dpy, scrn);
1872 *h = DisplayHeight(window->visual->dpy, scrn);
1873}
1874
1875
1876void
1877renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
1878{
1879#ifdef USE_OSMESA
1880 if (render_spu.use_osmesa)
1881 return;
1882#endif
1883
1884 CRASSERT(window);
1885 CRASSERT(window->visual);
1886 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1887 {
1888 crDebug("Render SPU: XMoveWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, x, y);
1889 XMoveWindow(window->visual->dpy, window->window, x, y);
1890 XSync(window->visual->dpy, 0);
1891 }
1892}
1893
1894void
1895renderspu_SystemWindowVisibleRegion( WindowInfo *window, GLint cRects, GLint *pRects )
1896{
1897#ifdef USE_OSMESA
1898 if (render_spu.use_osmesa)
1899 return;
1900#endif
1901
1902 CRASSERT(window);
1903 CRASSERT(window->visual);
1904 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1905 {
1906 int evb, erb, i;
1907 XRectangle *pXRects;
1908
1909 if (!XShapeQueryExtension(window->visual->dpy, &evb, &erb))
1910 {
1911 crWarning("Render SPU: Display %s doesn't support SHAPE extension", window->visual->displayName);
1912 return;
1913 }
1914
1915 if (cRects>0)
1916 {
1917 pXRects = (XRectangle *) crAlloc(cRects * sizeof(XRectangle));
1918
1919 for (i=0; i<cRects; ++i)
1920 {
1921 pXRects[i].x = (short) pRects[4*i];
1922 pXRects[i].y = (short) pRects[4*i+1];
1923 pXRects[i].width = (unsigned short) (pRects[4*i+2]-pRects[4*i]);
1924 pXRects[i].height = (unsigned short) (pRects[4*i+3]-pRects[4*i+1]);
1925 }
1926 }
1927 else
1928 {
1929 pXRects = (XRectangle *) crAlloc(sizeof(XRectangle));
1930 pXRects[0].x = 0;
1931 pXRects[0].y = 0;
1932 pXRects[0].width = 0;
1933 pXRects[0].height = 0;
1934 cRects = 1;
1935 }
1936
1937 crDebug("Render SPU: XShapeCombineRectangles (%x, %x, cRects=%i)", window->visual->dpy, window->window, cRects);
1938
1939 XShapeCombineRectangles(window->visual->dpy, window->window, ShapeBounding, 0, 0,
1940 pXRects, cRects, ShapeSet, YXBanded);
1941 XSync(window->visual->dpy, 0);
1942 crFree(pXRects);
1943 }
1944}
1945
1946/* Either show or hide the render SPU's window. */
1947void
1948renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
1949{
1950#ifdef USE_OSMESA
1951 if (render_spu.use_osmesa)
1952 return;
1953#endif
1954
1955 if (window->visual->dpy && window->window &&
1956 (window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1957 {
1958 if (showIt)
1959 {
1960 if (window->BltInfo.width && window->BltInfo.height)
1961 {
1962 XMapWindow( window->visual->dpy, window->window );
1963 XSync(window->visual->dpy, 0);
1964 }
1965 }
1966 else
1967 {
1968 XUnmapWindow( window->visual->dpy, window->window );
1969 XSync(window->visual->dpy, 0);
1970 }
1971 }
1972}
1973
1974void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
1975{
1976 /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
1977 * here it forces rendering in WinCmd thread rather than a Main thread.
1978 * it is used for debugging only in any way actually.
1979 * @todo: change to some more generic macro name */
1980#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
1981 struct VBOXVR_SCR_COMPOSITOR *pCurCompositor;
1982 /* 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 */
1983 int rc = renderspuVBoxCompositorTryAcquire(window, &pCurCompositor);
1984 if (RT_SUCCESS(rc))
1985 {
1986 Assert(pCurCompositor == pCompositor);
1987 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
1988 renderspuVBoxCompositorRelease(window);
1989 }
1990 else if (rc == VERR_SEM_BUSY)
1991#endif
1992 {
1993 Status status;
1994 XEvent event;
1995 render_spu.self.Flush();
1996 renderspuVBoxPresentBlitterEnsureCreated(window, 0);
1997
1998 crMemset(&event, 0, sizeof (event));
1999 event.type = Expose;
2000 event.xexpose.window = window->window;
2001 event.xexpose.width = window->BltInfo.width;
2002 event.xexpose.height = window->BltInfo.height;
2003 status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, 0, &event);
2004 if (!status)
2005 {
2006 Assert(0);
2007 crWarning("XSendEvent returned null");
2008 }
2009 XFlush(render_spu.pCommunicationDisplay);
2010 }
2011#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
2012 else
2013 {
2014 /* this is somewhat we do not expect */
2015 crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
2016 }
2017#endif
2018}
2019
2020static void
2021MarkWindow(WindowInfo *w)
2022{
2023 static GC gc = 0; /* XXX per-window??? */
2024 if (!gc) {
2025 /* Create a GC for drawing invisible lines */
2026 XGCValues gcValues;
2027 gcValues.function = GXnoop;
2028 gc = XCreateGC(w->visual->dpy, w->nativeWindow, GCFunction, &gcValues);
2029 }
2030 XDrawLine(w->visual->dpy, w->nativeWindow, gc, 0, 0, w->BltInfo.width, w->BltInfo.height);
2031}
2032
2033
2034void
2035renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
2036{
2037 CRASSERT(w);
2038
2039#if 00 /*TEMPORARY - FOR TESTING SWAP LOCK*/
2040 if (1) {
2041 /* random delay */
2042 int k = crRandInt(1000 * 100, 750*1000);
2043 static int first = 1;
2044 if (first) {
2045 crRandAutoSeed();
2046 first = 0;
2047 }
2048 usleep(k);
2049 }
2050#endif
2051
2052 /* render_to_app_window:
2053 * w->nativeWindow will only be non-zero if the
2054 * render_spu.render_to_app_window option is true and
2055 * MakeCurrent() recorded the nativeWindow handle in the WindowInfo
2056 * structure.
2057 */
2058 if (w->nativeWindow) {
2059 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->nativeWindow );
2060#if 0
2061 MarkWindow(w);
2062#else
2063 (void) MarkWindow;
2064#endif
2065 }
2066 else {
2067 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->window );
2068 }
2069}
2070
2071void renderspu_SystemReparentWindow(WindowInfo *window)
2072{
2073 Window parent;
2074
2075 parent = render_spu_parent_window_id>0 ? render_spu_parent_window_id :
2076 RootWindow(window->visual->dpy, window->visual->visual->screen);
2077
2078 XReparentWindow(window->visual->dpy, window->window, parent, window->x, window->y);
2079 XSync(window->visual->dpy, False);
2080}
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