VirtualBox

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

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

crOpenGL/glx: do not allow zero window sizes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 64.8 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 window->visible = showIt;
1137
1138 if ((window->visual->visAttribs & CR_DOUBLE_BIT) && render_spu.nvSwapGroup) {
1139 /* NOTE:
1140 * If this SPU creates N windows we don't want to gang the N windows
1141 * together!
1142 * By adding the window ID to the nvSwapGroup ID we can be sure each
1143 * app window is in a separate swap group while all the back-end windows
1144 * which form a mural are in the same swap group.
1145 */
1146 GLuint group = 0; /*render_spu.nvSwapGroup + window->BltInfo.Base.id;*/
1147 GLuint barrier = 0;
1148 JoinSwapGroup(dpy, visual->visual->screen, window->window, group, barrier);
1149 }
1150
1151 /*
1152 * End GLX code
1153 */
1154 crDebug( "Render SPU: actual window x, y, width, height: %d, %d, %d, %d",
1155 window->x, window->y, window->BltInfo.width, window->BltInfo.height );
1156
1157 XSync(dpy, 0);
1158
1159 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1160 {
1161 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE, window);
1162 AssertRC(rc);
1163 }
1164
1165 return GL_TRUE;
1166}
1167
1168
1169static GLboolean
1170createPBuffer( VisualInfo *visual, WindowInfo *window )
1171{
1172 window->visual = visual;
1173 window->x = 0;
1174 window->y = 0;
1175 window->nativeWindow = 0;
1176
1177 CRASSERT(window->BltInfo.width > 0);
1178 CRASSERT(window->BltInfo.height > 0);
1179
1180#ifdef GLX_VERSION_1_3
1181 {
1182 int attribs[100], i = 0, w, h;
1183 CRASSERT(visual->fbconfig);
1184 w = window->BltInfo.width;
1185 h = window->BltInfo.height;
1186 attribs[i++] = GLX_PRESERVED_CONTENTS;
1187 attribs[i++] = True;
1188 attribs[i++] = GLX_PBUFFER_WIDTH;
1189 attribs[i++] = w;
1190 attribs[i++] = GLX_PBUFFER_HEIGHT;
1191 attribs[i++] = h;
1192 attribs[i++] = 0; /* terminator */
1193 window->window = render_spu.ws.glXCreatePbuffer(visual->dpy,
1194 visual->fbconfig, attribs);
1195 if (window->window) {
1196 crDebug("Render SPU: Allocated %d x %d pbuffer", w, h);
1197 return GL_TRUE;
1198 }
1199 else {
1200 crWarning("Render SPU: Failed to allocate %d x %d pbuffer", w, h);
1201 return GL_FALSE;
1202 }
1203 }
1204#endif /* GLX_VERSION_1_3 */
1205 return GL_FALSE;
1206}
1207
1208
1209GLboolean
1210renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1211{
1212 if (visual->visAttribs & CR_PBUFFER_BIT) {
1213 window->BltInfo.width = render_spu.defaultWidth;
1214 window->BltInfo.height = render_spu.defaultHeight;
1215 return createPBuffer(visual, window);
1216 }
1217 else {
1218 return createWindow(visual, showIt, window);
1219 }
1220}
1221
1222GLboolean
1223renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
1224{
1225 return renderspu_SystemCreateWindow(visual, showIt, window);
1226}
1227
1228void
1229renderspu_SystemDestroyWindow( WindowInfo *window )
1230{
1231 CRASSERT(window);
1232 CRASSERT(window->visual);
1233
1234#ifdef USE_OSMESA
1235 if (render_spu.use_osmesa)
1236 {
1237 crFree(window->buffer);
1238 window->buffer = NULL;
1239 }
1240 else
1241#endif
1242 {
1243 if (window->visual->visAttribs & CR_PBUFFER_BIT) {
1244#ifdef GLX_VERSION_1_3
1245 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1246#endif
1247 }
1248 else {
1249 /* The value window->nativeWindow will only be non-NULL if the
1250 * render_to_app_window option is set to true. In this case, we
1251 * don't want to do anything, since we're not responsible for this
1252 * window. I know...personal responsibility and all...
1253 */
1254 if (!window->nativeWindow) {
1255 if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
1256 {
1257 int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY, window);
1258 AssertRC(rc);
1259 }
1260 XDestroyWindow(window->visual->dpy, window->window);
1261 XSync(window->visual->dpy, 0);
1262 }
1263 }
1264 }
1265 window->visual = NULL;
1266 window->window = 0;
1267}
1268
1269
1270GLboolean
1271renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
1272{
1273 Bool is_direct;
1274 GLXContext sharedSystemContext = NULL;
1275
1276 CRASSERT(visual);
1277 CRASSERT(context);
1278
1279 context->visual = visual;
1280
1281 if (sharedContext != NULL) {
1282 sharedSystemContext = sharedContext->context;
1283 }
1284
1285
1286
1287#ifdef USE_OSMESA
1288 if (render_spu.use_osmesa) {
1289 context->context = (GLXContext) render_spu.OSMesaCreateContext(OSMESA_RGB, 0);
1290 if (context->context)
1291 return GL_TRUE;
1292 else
1293 return GL_FALSE;
1294 }
1295#endif
1296
1297#ifdef GLX_VERSION_1_3
1298 if (visual->visAttribs & CR_PBUFFER_BIT) {
1299 context->context = render_spu.ws.glXCreateNewContext( visual->dpy,
1300 visual->fbconfig,
1301 GLX_RGBA_TYPE,
1302 sharedSystemContext,
1303 render_spu.try_direct);
1304 }
1305 else
1306#endif
1307 {
1308 context->context = render_spu.ws.glXCreateContext( visual->dpy,
1309 visual->visual,
1310 sharedSystemContext,
1311 render_spu.try_direct);
1312 }
1313 if (!context->context) {
1314 crError( "Render SPU: Couldn't create rendering context" );
1315 return GL_FALSE;
1316 }
1317
1318 is_direct = render_spu.ws.glXIsDirect( visual->dpy, context->context );
1319 if (visual->visual)
1320 crDebug("Render SPU: Created %s context (%d) on display %s for visAttribs 0x%x",
1321 is_direct ? "DIRECT" : "INDIRECT",
1322 context->BltInfo.Base.id,
1323 DisplayString(visual->dpy),
1324 visual->visAttribs);
1325
1326 if ( render_spu.force_direct && !is_direct )
1327 {
1328 crError( "Render SPU: Direct rendering not possible." );
1329 return GL_FALSE;
1330 }
1331
1332 return GL_TRUE;
1333}
1334
1335
1336#define USE_GLX_COPYCONTEXT 0
1337
1338#if !USE_GLX_COPYCONTEXT
1339
1340/**
1341 * Unfortunately, glXCopyContext() is broken sometimes (NVIDIA 76.76 driver).
1342 * This bit of code gets and sets GL state we need to copy between contexts.
1343 */
1344struct saved_state
1345{
1346 /* XXX depending on the app, more state may be needed here */
1347 GLboolean Lighting;
1348 GLboolean LightEnabled[8];
1349 GLfloat LightPos[8][4];
1350 GLfloat LightAmbient[8][4];
1351 GLfloat LightDiffuse[8][4];
1352 GLfloat LightSpecular[8][4];
1353 GLboolean DepthTest;
1354};
1355
1356static struct saved_state SavedState;
1357
1358static void
1359get_state(struct saved_state *s)
1360{
1361 int i;
1362
1363 s->Lighting = render_spu.self.IsEnabled(GL_LIGHTING);
1364 for (i = 0; i < 8; i++) {
1365 s->LightEnabled[i] = render_spu.self.IsEnabled(GL_LIGHT0 + i);
1366 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1367 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1368 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1369 render_spu.self.GetLightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1370 }
1371
1372 s->DepthTest = render_spu.self.IsEnabled(GL_DEPTH_TEST);
1373}
1374
1375static void
1376set_state(const struct saved_state *s)
1377{
1378 int i;
1379
1380 if (s->Lighting) {
1381 render_spu.self.Enable(GL_LIGHTING);
1382 }
1383 else {
1384 render_spu.self.Disable(GL_LIGHTING);
1385 }
1386
1387 for (i = 0; i < 8; i++) {
1388 if (s->LightEnabled[i]) {
1389 render_spu.self.Enable(GL_LIGHT0 + i);
1390 }
1391 else {
1392 render_spu.self.Disable(GL_LIGHT0 + i);
1393 }
1394 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_POSITION, s->LightPos[i]);
1395 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_AMBIENT, s->LightAmbient[i]);
1396 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_DIFFUSE, s->LightDiffuse[i]);
1397 render_spu.self.Lightfv(GL_LIGHT0 + i, GL_SPECULAR, s->LightSpecular[i]);
1398 }
1399
1400 if (s->DepthTest)
1401 render_spu.self.Enable(GL_DEPTH_TEST);
1402 else
1403 render_spu.self.Disable(GL_DEPTH_TEST);
1404}
1405
1406#endif /* !USE_GLX_COPYCONTEXT */
1407
1408/**
1409 * Recreate the GLX context for ContextInfo. The new context will use the
1410 * visual specified by newVisualID.
1411 */
1412static void
1413renderspu_RecreateContext( ContextInfo *context, int newVisualID )
1414{
1415 XVisualInfo templateVis, *vis;
1416 long templateFlags;
1417 int screen = 0, count;
1418 GLXContext oldContext = context->context;
1419
1420 templateFlags = VisualScreenMask | VisualIDMask;
1421 templateVis.screen = screen;
1422 templateVis.visualid = newVisualID;
1423 vis = XGetVisualInfo(context->visual->dpy, templateFlags, &templateVis, &count);
1424 CRASSERT(vis);
1425 if (!vis)
1426 return;
1427
1428 /* create new context */
1429 crDebug("Render SPU: Creating new GLX context with visual 0x%x", newVisualID);
1430 context->context = render_spu.ws.glXCreateContext(context->visual->dpy,
1431 vis, NULL,
1432 render_spu.try_direct);
1433 CRASSERT(context->context);
1434
1435#if USE_GLX_COPYCONTEXT
1436 /* copy old context state to new context */
1437 render_spu.ws.glXCopyContext(context->visual->dpy,
1438 oldContext, context->context, ~0);
1439 crDebug("Render SPU: Done copying context state");
1440#endif
1441
1442 /* destroy old context */
1443 render_spu.ws.glXDestroyContext(context->visual->dpy, oldContext);
1444
1445 context->visual->visual = vis;
1446}
1447
1448
1449void
1450renderspu_SystemDestroyContext( ContextInfo *context )
1451{
1452#ifdef USE_OSMESA
1453 if (render_spu.use_osmesa)
1454 {
1455 render_spu.OSMesaDestroyContext( (OSMesaContext) context->context );
1456 }
1457 else
1458#endif
1459 {
1460#if 0
1461 /* XXX disable for now - causes segfaults w/ NVIDIA's driver */
1462 render_spu.ws.glXDestroyContext( context->visual->dpy, context->context );
1463#endif
1464 }
1465 context->visual = NULL;
1466 context->context = 0;
1467}
1468
1469
1470#ifdef USE_OSMESA
1471static void
1472check_buffer_size( WindowInfo *window )
1473{
1474 if (window->BltInfo.width != window->in_buffer_width
1475 || window->BltInfo.height != window->in_buffer_height
1476 || ! window->buffer) {
1477 crFree(window->buffer);
1478
1479 window->buffer = crCalloc(window->BltInfo.width * window->BltInfo.height
1480 * 4 * sizeof (GLubyte));
1481
1482 window->in_buffer_width = window->BltInfo.width;
1483 window->in_buffer_height = window->BltInfo.height;
1484
1485 crDebug("Render SPU: dimensions changed to %d x %d", window->BltInfo.width, window->BltInfo.height);
1486 }
1487}
1488#endif
1489
1490
1491void
1492renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
1493 ContextInfo *context )
1494{
1495 Bool b;
1496
1497 CRASSERT(render_spu.ws.glXMakeCurrent);
1498
1499 /*crDebug("%s nativeWindow=0x%x", __FUNCTION__, (int) nativeWindow);*/
1500
1501#ifdef USE_OSMESA
1502 if (render_spu.use_osmesa) {
1503 check_buffer_size(window);
1504 render_spu.OSMesaMakeCurrent( (OSMesaContext) context->context,
1505 window->buffer, GL_UNSIGNED_BYTE,
1506 window->BltInfo.width, window->BltInfo.height);
1507 return;
1508 }
1509#endif
1510
1511 nativeWindow = 0;
1512
1513 if (window && context) {
1514 window->appWindow = nativeWindow;
1515
1516 if (window->visual != context->visual) {
1517 crDebug("Render SPU: MakeCurrent visual mismatch (win(%d) bits:0x%x != ctx(%d) bits:0x%x); remaking window.",
1518 window->BltInfo.Base.id, window->visual->visAttribs,
1519 context->BltInfo.Base.id, context->visual->visAttribs);
1520 /*
1521 * XXX have to revisit this issue!!!
1522 *
1523 * But for now we destroy the current window
1524 * and re-create it with the context's visual abilities
1525 */
1526#ifndef SOLARIS_9_X_BUG
1527 /*
1528 I'm having some really weird issues if I destroy this window
1529 when I'm using the version of sunX that comes with Solaris 9.
1530 Subsiquent glX calls return GLXBadCurrentWindow error.
1531
1532 This is an issue even when running Linux version and using
1533 the Solaris 9 sunX as a display.
1534 -- jw
1535
1536 jw: we might have to call glXMakeCurrent(dpy, 0, 0) to unbind
1537 the context from the window before destroying it. -Brian
1538 */
1539 render_spu.ws.glXMakeCurrent(window->visual->dpy, 0, 0);
1540 renderspu_SystemDestroyWindow( window );
1541#endif
1542 renderspu_SystemCreateWindow( context->visual, window->visible, window );
1543 /*
1544 crError("In renderspu_SystemMakeCurrent() window and context"
1545 " weren't created with same visual!");
1546 */
1547 }
1548
1549 CRASSERT(context->context);
1550
1551#if 0
1552 if (render_spu.render_to_crut_window) {
1553 if (render_spu.crut_drawable == 0) {
1554 /* We don't know the X drawable ID yet. Ask mothership for it. */
1555 char response[8096];
1556 CRConnection *conn = crMothershipConnect();
1557 if (!conn)
1558 {
1559 crError("Couldn't connect to the mothership to get CRUT drawable-- "
1560 "I have no idea what to do!");
1561 }
1562 crMothershipGetParam( conn, "crut_drawable", response );
1563 render_spu.crut_drawable = crStrToInt(response);
1564 crMothershipDisconnect(conn);
1565
1566 crDebug("Render SPU: using CRUT drawable: 0x%x",
1567 render_spu.crut_drawable);
1568 if (!render_spu.crut_drawable) {
1569 crDebug("Render SPU: Crut drawable 0 is invalid");
1570 /* Continue with nativeWindow = 0; we'll render to the window that
1571 * we (the Render SPU) previously created.
1572 */
1573 }
1574 }
1575
1576 nativeWindow = render_spu.crut_drawable;
1577 }
1578#endif
1579
1580 if ((render_spu.render_to_crut_window || render_spu.render_to_app_window)
1581 && nativeWindow)
1582 {
1583 /* We're about to bind the rendering context to a window that we
1584 * (the Render SPU) did not create. The window was created by the
1585 * application or the CRUT server.
1586 * Make sure the window ID is valid and that the window's X visual is
1587 * the same as the rendering context's.
1588 */
1589 if (WindowExists(window->visual->dpy, nativeWindow))
1590 {
1591 int vid = GetWindowVisualID(window->visual->dpy, nativeWindow);
1592 GLboolean recreated = GL_FALSE;
1593
1594 /* check that the window's visual and context's visual match */
1595 if (vid != (int) context->visual->visual->visualid) {
1596 crWarning("Render SPU: Can't bind context %d to CRUT/native window "
1597 "0x%x because of different X visuals (0x%x != 0x%x)!",
1598 context->BltInfo.Base.id, (int) nativeWindow,
1599 vid, (int) context->visual->visual->visualid);
1600 crWarning("Render SPU: Trying to recreate GLX context to match.");
1601 /* Try to recreate the GLX context so that it uses the same
1602 * GLX visual as the window.
1603 */
1604#if !USE_GLX_COPYCONTEXT
1605 if (context->everCurrent) {
1606 get_state(&SavedState);
1607 }
1608#endif
1609 renderspu_RecreateContext(context, vid);
1610 recreated = GL_TRUE;
1611 }
1612
1613 /* OK, this should work */
1614 window->nativeWindow = (Window) nativeWindow;
1615 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1616 window->nativeWindow,
1617 context->context );
1618 CRASSERT(b);
1619#if !USE_GLX_COPYCONTEXT
1620 if (recreated) {
1621 set_state(&SavedState);
1622 }
1623#endif
1624 }
1625 else
1626 {
1627 crWarning("Render SPU: render_to_app/crut_window option is set but "
1628 "the window ID 0x%x is invalid on the display named %s",
1629 (unsigned int) nativeWindow,
1630 DisplayString(window->visual->dpy));
1631 CRASSERT(window->window);
1632 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1633 window->window, context->context );
1634 CRASSERT(b);
1635 }
1636 }
1637 else
1638 {
1639 /* This is the normal case - rendering to the render SPU's own window */
1640 CRASSERT(window->window);
1641#if 0
1642 crDebug("calling glXMakecurrent(%p, 0x%x, 0x%x)",
1643 window->visual->dpy,
1644 (int) window->window, (int) context->context );
1645#endif
1646 b = render_spu.ws.glXMakeCurrent( window->visual->dpy,
1647 window->window, context->context );
1648 if (!b) {
1649 crWarning("glXMakeCurrent(%p, 0x%x, %p) failed! (winId %d, ctxId %d)",
1650 window->visual->dpy,
1651 (int) window->window, (void *) context->context,
1652 window->BltInfo.Base.id, context->BltInfo.Base.id );
1653 }
1654 /*CRASSERT(b);*/
1655 }
1656
1657 /* XXX this is a total hack to work around an NVIDIA driver bug */
1658#if 0
1659 if (render_spu.self.GetFloatv && context->haveWindowPosARB) {
1660 GLfloat f[4];
1661 render_spu.self.GetFloatv(GL_CURRENT_RASTER_POSITION, f);
1662 if (!window->everCurrent || f[1] < 0.0) {
1663 crDebug("Render SPU: Resetting raster pos");
1664 render_spu.self.WindowPos2iARB(0, 0);
1665 }
1666 }
1667#endif
1668 }
1669 else
1670 {
1671 GET_CONTEXT(pCurCtx);
1672 if (pCurCtx)
1673 {
1674 b = render_spu.ws.glXMakeCurrent( pCurCtx->currentWindow->visual->dpy, None, NULL);
1675 if (!b) {
1676 crWarning("glXMakeCurrent(%p, None, NULL) failed!", pCurCtx->currentWindow->visual->dpy);
1677 }
1678 }
1679
1680 }
1681
1682#if 0
1683 /* XXX disabled for now due to problem with threadtest.conf */
1684 renderspu_GCWindow();
1685#endif
1686}
1687
1688
1689/**
1690 * Set window (or pbuffer) size.
1691 */
1692void
1693renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
1694{
1695#ifdef USE_OSMESA
1696 if (render_spu.use_osmesa) {
1697 window->BltInfo.width = w;
1698 window->BltInfo.height = h;
1699 check_buffer_size(window);
1700 return;
1701 }
1702#endif
1703
1704 CRASSERT(window);
1705 CRASSERT(window->visual);
1706 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1707 {
1708 /* resizing a pbuffer */
1709 if (render_spu.pbufferWidth != 0 || render_spu.pbufferHeight != 0) {
1710 /* size limit check */
1711 if (w > render_spu.pbufferWidth || h > render_spu.pbufferHeight) {
1712 crWarning("Render SPU: Request for %d x %d pbuffer is larger than "
1713 "the configured size of %d x %d. ('pbuffer_size')",
1714 w, h, render_spu.pbufferWidth, render_spu.pbufferHeight);
1715 return;
1716 }
1717 /*
1718 * If the requested new pbuffer size is greater than 1/2 the size of
1719 * the max pbuffer, just use the max pbuffer size. This helps avoid
1720 * problems with VRAM memory fragmentation. If we run out of VRAM
1721 * for pbuffers, some drivers revert to software rendering. We want
1722 * to avoid that!
1723 */
1724 if (w * h >= render_spu.pbufferWidth * render_spu.pbufferHeight / 2) {
1725 /* increase the dimensions to the max pbuffer size now */
1726 w = render_spu.pbufferWidth;
1727 h = render_spu.pbufferHeight;
1728 }
1729 }
1730
1731 if (window->BltInfo.width != w || window->BltInfo.height != h) {
1732 /* Only resize if the new dimensions really are different */
1733#ifdef CHROMIUM_THREADSAFE
1734 ContextInfo *currentContext = (ContextInfo *) crGetTSD(&_RenderTSD);
1735#else
1736 ContextInfo *currentContext = render_spu.currentContext;
1737#endif
1738 /* Can't resize pbuffers, so destroy it and make a new one */
1739 render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
1740 window->BltInfo.width = w;
1741 window->BltInfo.height = h;
1742 crDebug("Render SPU: Creating new %d x %d PBuffer (id=%d)",
1743 w, h, window->BltInfo.Base.id);
1744 if (!createPBuffer(window->visual, window)) {
1745 crWarning("Render SPU: Unable to create PBuffer (out of VRAM?)!");
1746 }
1747 else if (currentContext && currentContext->currentWindow == window) {
1748 /* Determine if we need to bind the current context to new pbuffer */
1749 render_spu.ws.glXMakeCurrent(window->visual->dpy,
1750 window->window,
1751 currentContext->context );
1752 }
1753 }
1754 }
1755 else {
1756 if (!w || !h)
1757 {
1758 /* X can not handle zero sizes */
1759 if (window->visible)
1760 {
1761 renderspu_SystemShowWindow( window, GL_FALSE );
1762 return;
1763 }
1764 }
1765 /* Resize ordinary X window */
1766 /*
1767 * This is ugly, but it seems to be the only thing that works.
1768 * Basically, XResizeWindow() doesn't seem to always take effect
1769 * immediately.
1770 * Even after an XSync(), the GetWindowAttributes() call will sometimes
1771 * return the old window size. So, we use a loop to repeat the window
1772 * resize until it seems to take effect.
1773 */
1774 int attempt;
1775 crDebug("Render SPU: XResizeWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, w, h);
1776 XResizeWindow(window->visual->dpy, window->window, w, h);
1777 XSync(window->visual->dpy, 0);
1778
1779 if (!window->BltInfo.width || !window->BltInfo.height)
1780 {
1781 /* we have hidden the window instead of sizing it to (0;0) since X is unable to handle zero sizes */
1782 if (window->visible)
1783 {
1784 renderspu_SystemShowWindow( window, GL_TRUE );
1785 return;
1786 }
1787 }
1788#if 0
1789 for (attempt = 0; attempt < 3; attempt++) { /* try three times max */
1790 XWindowAttributes attribs;
1791 /* Now, query the window size */
1792 XGetWindowAttributes(window->visual->dpy, window->window, &attribs);
1793 if (attribs.width == w && attribs.height == h)
1794 break;
1795 /* sleep for a millisecond and try again */
1796 crMsleep(1);
1797 }
1798#endif
1799 }
1800}
1801
1802
1803void
1804renderspu_SystemGetWindowGeometry( WindowInfo *window,
1805 GLint *x, GLint *y, GLint *w, GLint *h )
1806{
1807#ifdef USE_OSMESA
1808 if (render_spu.use_osmesa) {
1809 *w = window->BltInfo.width;
1810 *h = window->BltInfo.height;
1811 return;
1812 }
1813#endif
1814
1815 CRASSERT(window);
1816 CRASSERT(window->visual);
1817 CRASSERT(window->window);
1818 if (window->visual->visAttribs & CR_PBUFFER_BIT)
1819 {
1820 *x = 0;
1821 *y = 0;
1822 *w = window->BltInfo.width;
1823 *h = window->BltInfo.height;
1824 }
1825 else
1826 {
1827 Window xw, child, root;
1828 unsigned int width, height, bw, d;
1829 int rx, ry;
1830
1831 if ((render_spu.render_to_app_window || render_spu.render_to_crut_window)
1832 && window->nativeWindow) {
1833 xw = window->nativeWindow;
1834 }
1835 else {
1836 xw = window->window;
1837 }
1838
1839 XGetGeometry(window->visual->dpy, xw, &root,
1840 x, y, &width, &height, &bw, &d);
1841
1842 /* translate x/y to screen coords */
1843 if (!XTranslateCoordinates(window->visual->dpy, xw, root,
1844 0, 0, &rx, &ry, &child)) {
1845 rx = ry = 0;
1846 }
1847 *x = rx;
1848 *y = ry;
1849 *w = (int) width;
1850 *h = (int) height;
1851 }
1852}
1853
1854
1855void
1856renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h )
1857{
1858 int scrn;
1859#ifdef USE_OSMESA
1860 if (render_spu.use_osmesa) {
1861 *w = 2048;
1862 *h = 2048;
1863 return;
1864 }
1865#endif
1866
1867 CRASSERT(window);
1868 CRASSERT(window->visual);
1869 CRASSERT(window->window);
1870
1871 scrn = DefaultScreen(window->visual->dpy);
1872 *w = DisplayWidth(window->visual->dpy, scrn);
1873 *h = DisplayHeight(window->visual->dpy, scrn);
1874}
1875
1876
1877void
1878renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
1879{
1880#ifdef USE_OSMESA
1881 if (render_spu.use_osmesa)
1882 return;
1883#endif
1884
1885 CRASSERT(window);
1886 CRASSERT(window->visual);
1887 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1888 {
1889 crDebug("Render SPU: XMoveWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, x, y);
1890 XMoveWindow(window->visual->dpy, window->window, x, y);
1891 XSync(window->visual->dpy, 0);
1892 }
1893}
1894
1895void
1896renderspu_SystemWindowVisibleRegion( WindowInfo *window, GLint cRects, GLint *pRects )
1897{
1898#ifdef USE_OSMESA
1899 if (render_spu.use_osmesa)
1900 return;
1901#endif
1902
1903 CRASSERT(window);
1904 CRASSERT(window->visual);
1905 if ((window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1906 {
1907 int evb, erb, i;
1908 XRectangle *pXRects;
1909
1910 if (!XShapeQueryExtension(window->visual->dpy, &evb, &erb))
1911 {
1912 crWarning("Render SPU: Display %s doesn't support SHAPE extension", window->visual->displayName);
1913 return;
1914 }
1915
1916 if (cRects>0)
1917 {
1918 pXRects = (XRectangle *) crAlloc(cRects * sizeof(XRectangle));
1919
1920 for (i=0; i<cRects; ++i)
1921 {
1922 pXRects[i].x = (short) pRects[4*i];
1923 pXRects[i].y = (short) pRects[4*i+1];
1924 pXRects[i].width = (unsigned short) (pRects[4*i+2]-pRects[4*i]);
1925 pXRects[i].height = (unsigned short) (pRects[4*i+3]-pRects[4*i+1]);
1926 }
1927 }
1928 else
1929 {
1930 pXRects = (XRectangle *) crAlloc(sizeof(XRectangle));
1931 pXRects[0].x = 0;
1932 pXRects[0].y = 0;
1933 pXRects[0].width = 0;
1934 pXRects[0].height = 0;
1935 cRects = 1;
1936 }
1937
1938 crDebug("Render SPU: XShapeCombineRectangles (%x, %x, cRects=%i)", window->visual->dpy, window->window, cRects);
1939
1940 XShapeCombineRectangles(window->visual->dpy, window->window, ShapeBounding, 0, 0,
1941 pXRects, cRects, ShapeSet, YXBanded);
1942 XSync(window->visual->dpy, 0);
1943 crFree(pXRects);
1944 }
1945}
1946
1947/* Either show or hide the render SPU's window. */
1948void
1949renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
1950{
1951#ifdef USE_OSMESA
1952 if (render_spu.use_osmesa)
1953 return;
1954#endif
1955
1956 if (window->visual->dpy && window->window &&
1957 (window->visual->visAttribs & CR_PBUFFER_BIT) == 0)
1958 {
1959 if (showIt)
1960 {
1961 XMapWindow( window->visual->dpy, window->window );
1962 XSync(window->visual->dpy, 0);
1963 }
1964 else
1965 {
1966 XUnmapWindow( window->visual->dpy, window->window );
1967 XSync(window->visual->dpy, 0);
1968 }
1969 }
1970}
1971
1972void renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
1973{
1974 /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
1975 * here it forces rendering in WinCmd thread rather than a Main thread.
1976 * it is used for debugging only in any way actually.
1977 * @todo: change to some more generic macro name */
1978#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
1979 struct VBOXVR_SCR_COMPOSITOR *pCurCompositor;
1980 /* 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 */
1981 int rc = renderspuVBoxCompositorTryAcquire(window, &pCurCompositor);
1982 if (RT_SUCCESS(rc))
1983 {
1984 Assert(pCurCompositor == pCompositor);
1985 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
1986 renderspuVBoxCompositorRelease(window);
1987 }
1988 else if (rc == VERR_SEM_BUSY)
1989#endif
1990 {
1991 Status status;
1992 XEvent event;
1993 render_spu.self.Flush();
1994 renderspuVBoxPresentBlitterEnsureCreated(window, 0);
1995
1996 crMemset(&event, 0, sizeof (event));
1997 event.type = Expose;
1998 event.xexpose.window = window->window;
1999 event.xexpose.width = window->BltInfo.width;
2000 event.xexpose.height = window->BltInfo.height;
2001 status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, 0, &event);
2002 if (!status)
2003 {
2004 Assert(0);
2005 crWarning("XSendEvent returned null");
2006 }
2007 XFlush(render_spu.pCommunicationDisplay);
2008 }
2009#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
2010 else
2011 {
2012 /* this is somewhat we do not expect */
2013 crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
2014 }
2015#endif
2016}
2017
2018static void
2019MarkWindow(WindowInfo *w)
2020{
2021 static GC gc = 0; /* XXX per-window??? */
2022 if (!gc) {
2023 /* Create a GC for drawing invisible lines */
2024 XGCValues gcValues;
2025 gcValues.function = GXnoop;
2026 gc = XCreateGC(w->visual->dpy, w->nativeWindow, GCFunction, &gcValues);
2027 }
2028 XDrawLine(w->visual->dpy, w->nativeWindow, gc, 0, 0, w->BltInfo.width, w->BltInfo.height);
2029}
2030
2031
2032void
2033renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
2034{
2035 CRASSERT(w);
2036
2037#if 00 /*TEMPORARY - FOR TESTING SWAP LOCK*/
2038 if (1) {
2039 /* random delay */
2040 int k = crRandInt(1000 * 100, 750*1000);
2041 static int first = 1;
2042 if (first) {
2043 crRandAutoSeed();
2044 first = 0;
2045 }
2046 usleep(k);
2047 }
2048#endif
2049
2050 /* render_to_app_window:
2051 * w->nativeWindow will only be non-zero if the
2052 * render_spu.render_to_app_window option is true and
2053 * MakeCurrent() recorded the nativeWindow handle in the WindowInfo
2054 * structure.
2055 */
2056 if (w->nativeWindow) {
2057 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->nativeWindow );
2058#if 0
2059 MarkWindow(w);
2060#else
2061 (void) MarkWindow;
2062#endif
2063 }
2064 else {
2065 render_spu.ws.glXSwapBuffers( w->visual->dpy, w->window );
2066 }
2067}
2068
2069void renderspu_SystemReparentWindow(WindowInfo *window)
2070{
2071 Window parent;
2072
2073 parent = render_spu_parent_window_id>0 ? render_spu_parent_window_id :
2074 RootWindow(window->visual->dpy, window->visual->visual->screen);
2075
2076 XReparentWindow(window->visual->dpy, window->window, parent, window->x, window->y);
2077 XSync(window->visual->dpy, False);
2078}
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