VirtualBox

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

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

crOpenGL: OSX backend rework; oddscreen rendering generalization

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

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