VirtualBox

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

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

Merge first stage of the Chromium cleanup from the branch:

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

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