VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c@ 44860

最後變更 在這個檔案從44860是 44860,由 vboxsync 提交於 12 年 前

crOpenGL: redraw impl for X11/glx hosts; enable offscreen rendering for X11/glx hosts

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 17.2 KB
 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_spu.h"
9#include "cr_error.h"
10#include "cr_string.h"
11#include "cr_url.h"
12#include "cr_environment.h"
13#include "renderspu.h"
14#include <stdio.h>
15
16#ifdef RT_OS_DARWIN
17# include <iprt/semaphore.h>
18#endif /* RT_OS_DARWIN */
19
20static SPUNamedFunctionTable _cr_render_table[1000];
21
22SPUFunctions render_functions = {
23 NULL, /* CHILD COPY */
24 NULL, /* DATA */
25 _cr_render_table /* THE ACTUAL FUNCTIONS */
26};
27
28RenderSPU render_spu;
29uint64_t render_spu_parent_window_id = 0;
30
31#ifdef CHROMIUM_THREADSAFE
32CRtsd _RenderTSD;
33#endif
34
35static void swapsyncConnect(void)
36{
37 char hostname[4096], protocol[4096];
38 unsigned short port;
39
40 crNetInit(NULL, NULL);
41
42 if (!crParseURL( render_spu.swap_master_url, protocol, hostname,
43 &port, 9876))
44 crError( "Bad URL: %s", render_spu.swap_master_url );
45
46 if (render_spu.is_swap_master)
47 {
48 int a;
49
50 render_spu.swap_conns = (CRConnection **)crAlloc(
51 render_spu.num_swap_clients*sizeof(CRConnection *));
52 for (a=0; a<render_spu.num_swap_clients; a++)
53 {
54 render_spu.swap_conns[a] = crNetAcceptClient( protocol, hostname, port,
55 render_spu.swap_mtu, 1);
56 }
57 }
58 else
59 {
60 render_spu.swap_conns = (CRConnection **)crAlloc(sizeof(CRConnection *));
61
62 render_spu.swap_conns[0] = crNetConnectToServer(render_spu.swap_master_url,
63 port, render_spu.swap_mtu, 1);
64 if (!render_spu.swap_conns[0])
65 crError("Failed connection");
66 }
67}
68
69#ifdef RT_OS_WINDOWS
70static DWORD WINAPI renderSPUWindowThreadProc(void* unused)
71{
72 MSG msg;
73 bool bRet;
74
75 (void) unused;
76
77 /* Force system to create the message queue.
78 * Else, there's a chance that render spu will issue PostThreadMessage
79 * before this thread calls GetMessage for first time.
80 */
81 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
82
83 crDebug("RenderSPU: Window thread started (%x)", crThreadID());
84 SetEvent(render_spu.hWinThreadReadyEvent);
85
86 while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
87 {
88 if (bRet == -1)
89 {
90 crError("RenderSPU: Window thread GetMessage failed (%x)", GetLastError());
91 break;
92 }
93 else
94 {
95 if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW)
96 {
97 LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam;
98 HWND hWnd;
99 WindowInfo *pWindow = (WindowInfo *)pCS->lpCreateParams;
100
101 CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams);
102
103 hWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style,
104 pCS->x, pCS->y, pCS->cx, pCS->cy,
105 pCS->hwndParent, pCS->hMenu, pCS->hInstance, &render_spu);
106
107 pWindow->hWnd = hWnd;
108
109 SetEvent(render_spu.hWinThreadReadyEvent);
110 }
111 else if (msg.message == WM_VBOX_RENDERSPU_DESTROY_WINDOW)
112 {
113 CRASSERT(msg.lParam && !msg.wParam);
114
115 DestroyWindow(((VBOX_RENDERSPU_DESTROY_WINDOW*) msg.lParam)->hWnd);
116
117 SetEvent(render_spu.hWinThreadReadyEvent);
118 }
119 else
120 {
121 TranslateMessage(&msg);
122 DispatchMessage(&msg);
123 }
124 }
125 }
126
127 render_spu.dwWinThreadId = 0;
128
129 crDebug("RenderSPU: Window thread stopped (%x)", crThreadID());
130 SetEvent(render_spu.hWinThreadReadyEvent);
131
132 return 0;
133}
134#endif
135
136static SPUFunctions *
137renderSPUInit( int id, SPU *child, SPU *self,
138 unsigned int context_id, unsigned int num_contexts )
139{
140 int numFuncs, numSpecial;
141 GLint defaultWin, defaultCtx;
142 WindowInfo *windowInfo;
143 const char * pcpwSetting;
144
145 (void) child;
146 (void) context_id;
147 (void) num_contexts;
148
149 self->privatePtr = (void *) &render_spu;
150
151#ifdef CHROMIUM_THREADSAFE
152 crDebug("Render SPU: thread-safe");
153#endif
154
155 crMemZero(&render_spu, sizeof(render_spu));
156
157 render_spu.id = id;
158 renderspuSetVBoxConfiguration(&render_spu);
159
160 if (render_spu.swap_master_url)
161 swapsyncConnect();
162
163
164 /* Get our special functions. */
165 numSpecial = renderspuCreateFunctions( _cr_render_table );
166
167#ifdef RT_OS_WINDOWS
168 /* Start thread to create windows and process window messages */
169 crDebug("RenderSPU: Starting windows serving thread");
170 render_spu.hWinThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
171 if (!render_spu.hWinThreadReadyEvent)
172 {
173 crError("RenderSPU: Failed to create WinThreadReadyEvent! (%x)", GetLastError());
174 return NULL;
175 }
176
177 if (!CreateThread(NULL, 0, renderSPUWindowThreadProc, 0, 0, &render_spu.dwWinThreadId))
178 {
179 crError("RenderSPU: Failed to start windows thread! (%x)", GetLastError());
180 return NULL;
181 }
182 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
183#endif
184
185 /* Get the OpenGL functions. */
186 numFuncs = crLoadOpenGL( &render_spu.ws, _cr_render_table + numSpecial );
187 if (numFuncs == 0) {
188 crError("The render SPU was unable to load the native OpenGL library");
189 return NULL;
190 }
191
192 numFuncs += numSpecial;
193
194 render_spu.contextTable = crAllocHashtableEx(1, INT32_MAX);
195 render_spu.windowTable = crAllocHashtableEx(1, INT32_MAX);
196
197 pcpwSetting = crGetenv("CR_RENDER_ENABLE_PRESENT_CONTEXT_PER_WINDOW");
198 if (pcpwSetting)
199 {
200 if (pcpwSetting[0] == '0')
201 pcpwSetting = NULL;
202 }
203 else
204 {
205 /* default is enable for OSX */
206#if 0 //defined(DARWIN) && defined(VBOX_WITH_COCOA_QT)
207 pcpwSetting = (char*)1;
208#endif
209
210 }
211
212
213 if (pcpwSetting)
214 {
215 render_spu.blitterTable = crAllocHashtable();
216 CRASSERT(render_spu.blitterTable);
217 }
218 else
219 render_spu.blitterTable = NULL;
220
221 CRASSERT(render_spu.default_visual & CR_RGB_BIT);
222
223#ifdef GLX
224 {
225 int rc = renderspu_SystemInit();
226 if (!RT_SUCCESS(rc))
227 {
228 crError("renderspu_SystemInit failed rc %d", rc);
229 return NULL;
230 }
231 }
232#endif
233
234#ifdef USE_OSMESA
235 if (render_spu.use_osmesa) {
236 if (!crLoadOSMesa(&render_spu.OSMesaCreateContext,
237 &render_spu.OSMesaMakeCurrent,
238 &render_spu.OSMesaDestroyContext)) {
239 crError("Unable to load OSMesa library");
240 }
241 }
242#endif
243
244#ifdef DARWIN
245# ifdef VBOX_WITH_COCOA_QT
246# else /* VBOX_WITH_COCOA_QT */
247 render_spu.hRootVisibleRegion = 0;
248 render_spu.currentBufferName = 1;
249 render_spu.uiDockUpdateTS = 0;
250 /* Create a mutex for synchronizing events from the main Qt thread & this
251 thread */
252 RTSemFastMutexCreate(&render_spu.syncMutex);
253 /* Create our window groups */
254 CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pMasterGroup);
255 CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pParentGroup);
256 /* Make the correct z-layering */
257 SendWindowGroupBehind (render_spu.pParentGroup, render_spu.pMasterGroup);
258 /* and set the gParentGroup as parent for gMasterGroup. */
259 SetWindowGroupParent (render_spu.pMasterGroup, render_spu.pParentGroup);
260 /* Install the event handlers */
261 EventTypeSpec eventList[] =
262 {
263 {kEventClassVBox, kEventVBoxUpdateContext}, /* Update the context after show/size/move events */
264 {kEventClassVBox, kEventVBoxBoundsChanged} /* Clip/Pos the OpenGL windows when the main window is changed in pos/size */
265 };
266 /* We need to process events from our main window */
267 render_spu.hParentEventHandler = NewEventHandlerUPP(windowEvtHndlr);
268 InstallApplicationEventHandler (render_spu.hParentEventHandler,
269 GetEventTypeCount(eventList), eventList,
270 NULL, NULL);
271 render_spu.fInit = true;
272# endif /* VBOX_WITH_COCOA_QT */
273#endif /* DARWIN */
274
275 /*
276 * Create the default window and context. Their indexes are zero and
277 * a client can use them without calling CreateContext or WindowCreate.
278 */
279 crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)",
280 render_spu.default_visual);
281 defaultWin = renderspuWindowCreateEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_WINDOW_ID );
282 if (defaultWin != CR_RENDER_DEFAULT_WINDOW_ID) {
283 crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!");
284 return NULL;
285 }
286 crDebug( "Render SPU: WindowCreate returned %d (0=normal)", defaultWin );
287
288 crDebug("Render SPU: Creating default context, visBits=0x%x",
289 render_spu.default_visual );
290 defaultCtx = renderspuCreateContextEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_CONTEXT_ID, 0 );
291 if (defaultCtx != CR_RENDER_DEFAULT_CONTEXT_ID) {
292 crError("Render SPU: failed to create default context!");
293 return NULL;
294 }
295
296 renderspuMakeCurrent( defaultWin, 0, defaultCtx );
297
298 /* Get windowInfo for the default window */
299 windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
300 CRASSERT(windowInfo);
301 windowInfo->mapPending = GL_TRUE;
302
303 /*
304 * Get the OpenGL extension functions.
305 * SIGH -- we have to wait until the very bitter end to load the
306 * extensions, because the context has to be bound before
307 * wglGetProcAddress will work correctly. No such issue with GLX though.
308 */
309 numFuncs += crLoadOpenGLExtensions( &render_spu.ws, _cr_render_table + numFuncs );
310 CRASSERT(numFuncs < 1000);
311
312#ifdef WINDOWS
313 /*
314 * Same problem as above, these are extensions so we need to
315 * load them after a context has been bound. As they're WGL
316 * extensions too, we can't simply tag them into the spu_loader.
317 * So we do them here for now.
318 * Grrr, NVIDIA driver uses EXT for GetExtensionsStringEXT,
319 * but ARB for others. Need further testing here....
320 */
321 render_spu.ws.wglGetExtensionsStringEXT =
322 (wglGetExtensionsStringEXTFunc_t)
323 render_spu.ws.wglGetProcAddress( "wglGetExtensionsStringEXT" );
324 render_spu.ws.wglChoosePixelFormatEXT =
325 (wglChoosePixelFormatEXTFunc_t)
326 render_spu.ws.wglGetProcAddress( "wglChoosePixelFormatARB" );
327 render_spu.ws.wglGetPixelFormatAttribivEXT =
328 (wglGetPixelFormatAttribivEXTFunc_t)
329 render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
330 render_spu.ws.wglGetPixelFormatAttribfvEXT =
331 (wglGetPixelFormatAttribfvEXTFunc_t)
332 render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribfvARB" );
333
334 if (render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D"))
335 {
336 _cr_render_table[numFuncs].name = crStrdup("CopyTexSubImage3D");
337 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D");
338 ++numFuncs;
339 crDebug("Render SPU: Found glCopyTexSubImage3D function");
340 }
341
342 if (render_spu.ws.wglGetProcAddress("glDrawRangeElements"))
343 {
344 _cr_render_table[numFuncs].name = crStrdup("DrawRangeElements");
345 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glDrawRangeElements");
346 ++numFuncs;
347 crDebug("Render SPU: Found glDrawRangeElements function");
348 }
349
350 if (render_spu.ws.wglGetProcAddress("glTexSubImage3D"))
351 {
352 _cr_render_table[numFuncs].name = crStrdup("TexSubImage3D");
353 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexSubImage3D");
354 ++numFuncs;
355 crDebug("Render SPU: Found glTexSubImage3D function");
356 }
357
358 if (render_spu.ws.wglGetProcAddress("glTexImage3D"))
359 {
360 _cr_render_table[numFuncs].name = crStrdup("TexImage3D");
361 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexImage3D");
362 ++numFuncs;
363 crDebug("Render SPU: Found glTexImage3D function");
364 }
365
366 if (render_spu.ws.wglGetExtensionsStringEXT) {
367 crDebug("WGL - found wglGetExtensionsStringEXT\n");
368 }
369 if (render_spu.ws.wglChoosePixelFormatEXT) {
370 crDebug("WGL - found wglChoosePixelFormatEXT\n");
371 }
372#endif
373
374 render_spu.barrierHash = crAllocHashtable();
375
376 render_spu.cursorX = 0;
377 render_spu.cursorY = 0;
378 render_spu.use_L2 = 0;
379
380 render_spu.gather_conns = NULL;
381
382 crDebug("Render SPU: ---------- End of Init -------------");
383
384 return &render_functions;
385}
386
387static void renderSPUSelfDispatch(SPUDispatchTable *self)
388{
389 crSPUInitDispatchTable( &(render_spu.self) );
390 crSPUCopyDispatchTable( &(render_spu.self), self );
391
392 render_spu.blitterDispatch = &(render_spu.self);
393
394 render_spu.server = (CRServer *)(self->server);
395
396 {
397 GLfloat version;
398 version = crStrToFloat((const char *) render_spu.ws.glGetString(GL_VERSION));
399
400 if (version>=2.f || crStrstr((const char*)render_spu.ws.glGetString(GL_EXTENSIONS), "GL_ARB_vertex_shader"))
401 {
402 GLint mu=0;
403 render_spu.self.GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &mu);
404 crInfo("Render SPU: GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB=%i", mu);
405 }
406 }
407}
408
409
410static void DeleteContextCallback( void *data )
411{
412 ContextInfo *context = (ContextInfo *) data;
413 renderspu_SystemDestroyContext(context);
414 crFree(context);
415}
416
417static void DeleteWindowCallback( void *data )
418{
419 WindowInfo *window = (WindowInfo *) data;
420 renderspu_SystemDestroyWindow(window);
421 crFree(window);
422}
423
424static void DeleteBlitterCallback( void *data )
425{
426 PCR_BLITTER pBlitter = (PCR_BLITTER) data;
427 CrBltTerm(pBlitter);
428 crFree(pBlitter);
429}
430
431static int renderSPUCleanup(void)
432{
433 crFreeHashtable(render_spu.contextTable, DeleteContextCallback);
434 render_spu.contextTable = NULL;
435 crFreeHashtable(render_spu.windowTable, DeleteWindowCallback);
436 render_spu.windowTable = NULL;
437 crFreeHashtable(render_spu.barrierHash, crFree);
438 render_spu.barrierHash = NULL;
439
440 if (render_spu.blitterTable)
441 crFreeHashtable(render_spu.blitterTable, DeleteBlitterCallback);
442
443#ifdef RT_OS_DARWIN
444# ifndef VBOX_WITH_COCOA_QT
445 render_spu.fInit = false;
446 DisposeEventHandlerUPP(render_spu.hParentEventHandler);
447 ReleaseWindowGroup(render_spu.pMasterGroup);
448 ReleaseWindowGroup(render_spu.pParentGroup);
449 if (render_spu.hRootVisibleRegion)
450 {
451 DisposeRgn(render_spu.hRootVisibleRegion);
452 render_spu.hRootVisibleRegion = 0;
453 }
454 render_spu.currentBufferName = 1;
455 render_spu.uiDockUpdateTS = 0;
456 RTSemFastMutexDestroy(render_spu.syncMutex);
457# else /* VBOX_WITH_COCOA_QT */
458# endif /* VBOX_WITH_COCOA_QT */
459#endif /* RT_OS_DARWIN */
460
461#ifdef RT_OS_WINDOWS
462 if (render_spu.dwWinThreadId)
463 {
464 HANDLE hNative;
465
466 hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
467 false, render_spu.dwWinThreadId);
468 if (!hNative)
469 {
470 crWarning("Failed to get handle for window thread(%#x)", GetLastError());
471 }
472
473 if (PostThreadMessage(render_spu.dwWinThreadId, WM_QUIT, 0, 0))
474 {
475 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
476
477 /*wait for os thread to actually finish*/
478 if (hNative && WaitForSingleObject(hNative, 3000)==WAIT_TIMEOUT)
479 {
480 crDebug("Wait failed, terminating");
481 if (!TerminateThread(hNative, 1))
482 {
483 crWarning("TerminateThread failed");
484 }
485 }
486 }
487
488 if (hNative)
489 {
490 CloseHandle(hNative);
491 }
492 }
493 CloseHandle(render_spu.hWinThreadReadyEvent);
494 render_spu.hWinThreadReadyEvent = NULL;
495#endif
496
497 crUnloadOpenGL();
498
499#ifdef CHROMIUM_THREADSAFE
500 crFreeTSD(&_RenderTSD);
501#endif
502
503 return 1;
504}
505
506
507extern SPUOptions renderSPUOptions[];
508
509int SPULoad( char **name, char **super, SPUInitFuncPtr *init,
510 SPUSelfDispatchFuncPtr *self, SPUCleanupFuncPtr *cleanup,
511 SPUOptionsPtr *options, int *flags )
512{
513 *name = "render";
514 *super = NULL;
515 *init = renderSPUInit;
516 *self = renderSPUSelfDispatch;
517 *cleanup = renderSPUCleanup;
518 *options = renderSPUOptions;
519 *flags = (SPU_NO_PACKER|SPU_IS_TERMINAL|SPU_MAX_SERVERS_ZERO);
520
521 return 1;
522}
523
524DECLEXPORT(void) renderspuSetWindowId(uint64_t winId)
525{
526 render_spu_parent_window_id = winId;
527}
528
529static void renderspuWindowVisibleRegionCB(unsigned long key, void *data1, void *data2)
530{
531 WindowInfo *window = (WindowInfo *) data1;
532 CRASSERT(window);
533
534 renderspu_SystemWindowApplyVisibleRegion(window);
535}
536
537DECLEXPORT(void) renderspuSetRootVisibleRegion(GLint cRects, GLint *pRects)
538{
539#ifdef RT_OS_DARWIN
540 renderspu_SystemSetRootVisibleRegion(cRects, pRects);
541
542 crHashtableWalk(render_spu.windowTable, renderspuWindowVisibleRegionCB, NULL);
543#endif
544}
545
546#ifndef RT_OS_DARWIN
547void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
548{
549}
550#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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