VirtualBox

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

Last change on this file since 78425 was 78408, checked in by vboxsync, 6 years ago

Additions,GuestHost/OpenGL,HostServices/SharedOpenGL: Get rid of the individual SPU shared libraries and merge them into the VBoxSharedCrOpenGL shared libraries on the host and VBoxOGL{,-x86} shared libraries for the guest additions, bugref:9435

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.7 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_mem.h"
8#include "cr_spu.h"
9#include "cr_error.h"
10#include "cr_string.h"
11#include "renderspu.h"
12#include <stdio.h>
13
14#include <iprt/env.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;
30CRtsd _RenderTSD;
31
32#ifdef RT_OS_WINDOWS
33static DWORD WINAPI renderSPUWindowThreadProc(void* unused)
34{
35 MSG msg;
36 BOOL bRet;
37
38 (void) unused;
39
40 /* Force system to create the message queue.
41 * Else, there's a chance that render spu will issue PostThreadMessage
42 * before this thread calls GetMessage for first time.
43 */
44 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
45
46 crDebug("RenderSPU: Window thread started (%x)", crThreadID());
47 SetEvent(render_spu.hWinThreadReadyEvent);
48
49 while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
50 {
51 if (bRet == -1)
52 {
53 crError("RenderSPU: Window thread GetMessage failed (%x)", GetLastError());
54 break;
55 }
56 else
57 {
58 if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW)
59 {
60 LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam;
61 HWND hWnd;
62 WindowInfo *pWindow = (WindowInfo *)pCS->lpCreateParams;
63
64 CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams);
65
66 hWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style,
67 pCS->x, pCS->y, pCS->cx, pCS->cy,
68 pCS->hwndParent, pCS->hMenu, pCS->hInstance, &render_spu);
69
70 pWindow->hWnd = hWnd;
71
72 SetEvent(render_spu.hWinThreadReadyEvent);
73 }
74 else if (msg.message == WM_VBOX_RENDERSPU_DESTROY_WINDOW)
75 {
76 CRASSERT(msg.lParam && !msg.wParam);
77
78 DestroyWindow(((VBOX_RENDERSPU_DESTROY_WINDOW*) msg.lParam)->hWnd);
79
80 SetEvent(render_spu.hWinThreadReadyEvent);
81 }
82 else
83 {
84 TranslateMessage(&msg);
85 DispatchMessage(&msg);
86 }
87 }
88 }
89
90 render_spu.dwWinThreadId = 0;
91
92 crDebug("RenderSPU: Window thread stopped (%x)", crThreadID());
93 SetEvent(render_spu.hWinThreadReadyEvent);
94
95 return 0;
96}
97#endif
98
99int renderspuDefaultCtxInit(void)
100{
101 GLint defaultWin, defaultCtx;
102 WindowInfo *windowInfo;
103
104 /*
105 * Create the default window and context. Their indexes are zero and
106 * a client can use them without calling CreateContext or WindowCreate.
107 */
108 crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)",
109 render_spu.default_visual);
110 defaultWin = renderspuWindowCreateEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_WINDOW_ID );
111 if (defaultWin != CR_RENDER_DEFAULT_WINDOW_ID) {
112 crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!");
113 return VERR_GENERAL_FAILURE;
114 }
115 crDebug( "Render SPU: WindowCreate returned %d (0=normal)", defaultWin );
116
117 crDebug("Render SPU: Creating default context, visBits=0x%x",
118 render_spu.default_visual );
119 defaultCtx = renderspuCreateContextEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_CONTEXT_ID, 0 );
120 if (defaultCtx != CR_RENDER_DEFAULT_CONTEXT_ID) {
121 crError("Render SPU: failed to create default context!");
122 return VERR_GENERAL_FAILURE;
123 }
124
125 renderspuMakeCurrent( defaultWin, 0, defaultCtx );
126
127 /* Get windowInfo for the default window */
128 windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
129 CRASSERT(windowInfo);
130 windowInfo->mapPending = GL_TRUE;
131
132 return VINF_SUCCESS;
133}
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
141 const char * pcpwSetting;
142 int rc;
143
144 (void) child;
145 (void) context_id;
146 (void) num_contexts;
147
148 self->privatePtr = (void *) &render_spu;
149
150 crDebug("Render SPU: thread-safe");
151 crInitTSD(&_RenderTSD);
152
153 crMemZero(&render_spu, sizeof(render_spu));
154
155 render_spu.id = id;
156 renderspuSetVBoxConfiguration(&render_spu);
157
158 /* Get our special functions. */
159 numSpecial = renderspuCreateFunctions( _cr_render_table );
160
161#ifdef RT_OS_WINDOWS
162 /* Start thread to create windows and process window messages */
163 crDebug("RenderSPU: Starting windows serving thread");
164 render_spu.hWinThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
165 if (!render_spu.hWinThreadReadyEvent)
166 {
167 crError("RenderSPU: Failed to create WinThreadReadyEvent! (%x)", GetLastError());
168 return NULL;
169 }
170
171 if (!CreateThread(NULL, 0, renderSPUWindowThreadProc, 0, 0, &render_spu.dwWinThreadId))
172 {
173 crError("RenderSPU: Failed to start windows thread! (%x)", GetLastError());
174 return NULL;
175 }
176 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
177#endif
178
179 /* Get the OpenGL functions. */
180 numFuncs = crLoadOpenGL( &render_spu.ws, _cr_render_table + numSpecial );
181 if (numFuncs == 0) {
182 crError("The render SPU was unable to load the native OpenGL library");
183 return NULL;
184 }
185
186 numFuncs += numSpecial;
187
188 render_spu.contextTable = crAllocHashtableEx(1, INT32_MAX);
189 render_spu.windowTable = crAllocHashtableEx(1, INT32_MAX);
190
191 render_spu.dummyWindowTable = crAllocHashtable();
192
193 pcpwSetting = RTEnvGet("CR_RENDER_ENABLE_SINGLE_PRESENT_CONTEXT");
194 if (pcpwSetting)
195 {
196 if (pcpwSetting[0] == '0')
197 pcpwSetting = NULL;
198 }
199
200 if (pcpwSetting)
201 {
202 /** @todo need proper blitter synchronization, do not use so far!
203 * the problem is that rendering can be done in multiple thread: the main command (hgcm) thread and the redraw thread
204 * we currently use per-window synchronization, while we'll need a per-blitter synchronization if one blitter is used for multiple windows
205 * this is not done currently */
206 crWarning("TODO: need proper blitter synchronization, do not use so far!");
207 render_spu.blitterTable = crAllocHashtable();
208 CRASSERT(render_spu.blitterTable);
209 }
210 else
211 render_spu.blitterTable = NULL;
212
213 CRASSERT(render_spu.default_visual & CR_RGB_BIT);
214
215 rc = renderspu_SystemInit();
216 if (!RT_SUCCESS(rc))
217 {
218 crError("renderspu_SystemInit failed rc %d", rc);
219 return NULL;
220 }
221
222 rc = renderspuDefaultCtxInit();
223 if (!RT_SUCCESS(rc))
224 {
225 WARN(("renderspuDefaultCtxInit failed %d", rc));
226 return NULL;
227 }
228
229 /*
230 * Get the OpenGL extension functions.
231 * SIGH -- we have to wait until the very bitter end to load the
232 * extensions, because the context has to be bound before
233 * wglGetProcAddress will work correctly. No such issue with GLX though.
234 */
235 numFuncs += crLoadOpenGLExtensions( &render_spu.ws, _cr_render_table + numFuncs );
236 CRASSERT(numFuncs < 1000);
237
238#ifdef WINDOWS
239 /*
240 * Same problem as above, these are extensions so we need to
241 * load them after a context has been bound. As they're WGL
242 * extensions too, we can't simply tag them into the spu_loader.
243 * So we do them here for now.
244 * Grrr, NVIDIA driver uses EXT for GetExtensionsStringEXT,
245 * but ARB for others. Need further testing here....
246 */
247 render_spu.ws.wglGetExtensionsStringEXT =
248 (wglGetExtensionsStringEXTFunc_t)
249 render_spu.ws.wglGetProcAddress( "wglGetExtensionsStringEXT" );
250 render_spu.ws.wglChoosePixelFormatEXT =
251 (wglChoosePixelFormatEXTFunc_t)
252 render_spu.ws.wglGetProcAddress( "wglChoosePixelFormatARB" );
253 render_spu.ws.wglGetPixelFormatAttribivEXT =
254 (wglGetPixelFormatAttribivEXTFunc_t)
255 render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
256 render_spu.ws.wglGetPixelFormatAttribfvEXT =
257 (wglGetPixelFormatAttribfvEXTFunc_t)
258 render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribfvARB" );
259
260 if (render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D"))
261 {
262 _cr_render_table[numFuncs].name = crStrdup("CopyTexSubImage3D");
263 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D");
264 ++numFuncs;
265 crDebug("Render SPU: Found glCopyTexSubImage3D function");
266 }
267
268 if (render_spu.ws.wglGetProcAddress("glDrawRangeElements"))
269 {
270 _cr_render_table[numFuncs].name = crStrdup("DrawRangeElements");
271 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glDrawRangeElements");
272 ++numFuncs;
273 crDebug("Render SPU: Found glDrawRangeElements function");
274 }
275
276 if (render_spu.ws.wglGetProcAddress("glTexSubImage3D"))
277 {
278 _cr_render_table[numFuncs].name = crStrdup("TexSubImage3D");
279 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexSubImage3D");
280 ++numFuncs;
281 crDebug("Render SPU: Found glTexSubImage3D function");
282 }
283
284 if (render_spu.ws.wglGetProcAddress("glTexImage3D"))
285 {
286 _cr_render_table[numFuncs].name = crStrdup("TexImage3D");
287 _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexImage3D");
288 ++numFuncs;
289 crDebug("Render SPU: Found glTexImage3D function");
290 }
291
292 if (render_spu.ws.wglGetExtensionsStringEXT) {
293 crDebug("WGL - found wglGetExtensionsStringEXT\n");
294 }
295 if (render_spu.ws.wglChoosePixelFormatEXT) {
296 crDebug("WGL - found wglChoosePixelFormatEXT\n");
297 }
298#endif
299
300 render_spu.barrierHash = crAllocHashtable();
301
302 render_spu.cursorX = 0;
303 render_spu.cursorY = 0;
304 render_spu.use_L2 = 0;
305
306 render_spu.gather_conns = NULL;
307
308 numFuncs = renderspu_SystemPostprocessFunctions(_cr_render_table, numFuncs, RT_ELEMENTS(_cr_render_table));
309
310 crDebug("Render SPU: ---------- End of Init -------------");
311
312 return &render_functions;
313}
314
315static void renderSPUSelfDispatch(SPUDispatchTable *self)
316{
317 crSPUInitDispatchTable( &(render_spu.self) );
318 crSPUCopyDispatchTable( &(render_spu.self), self );
319
320 crSPUInitDispatchTable( &(render_spu.blitterDispatch) );
321 crSPUCopyDispatchTable( &(render_spu.blitterDispatch), self );
322
323 render_spu.server = (CRServer *)(self->server);
324
325 {
326 GLfloat version;
327 version = crStrToFloat((const char *) render_spu.ws.glGetString(GL_VERSION));
328
329 if (version>=2.f || crStrstr((const char*)render_spu.ws.glGetString(GL_EXTENSIONS), "GL_ARB_vertex_shader"))
330 {
331 GLint mu=0;
332 render_spu.self.GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &mu);
333 crInfo("Render SPU: GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB=%i", mu);
334 }
335 }
336}
337
338
339static void DeleteContextCallback( void *data )
340{
341 ContextInfo *context = (ContextInfo *) data;
342 renderspuContextMarkDeletedAndRelease(context);
343}
344
345static void DeleteWindowCallback( void *data )
346{
347 WindowInfo *window = (WindowInfo *) data;
348 renderspuWinTermOnShutdown(window);
349 renderspuWinRelease(window);
350}
351
352static void DeleteBlitterCallback( void *data )
353{
354 PCR_BLITTER pBlitter = (PCR_BLITTER) data;
355 CrBltTerm(pBlitter);
356 crFree(pBlitter);
357}
358
359static void renderspuBlitterCleanupCB(unsigned long key, void *data1, void *data2)
360{
361 WindowInfo *window = (WindowInfo *) data1;
362 CRASSERT(window);
363
364 RT_NOREF(key, data2);
365
366 renderspuVBoxPresentBlitterCleanup( window );
367}
368
369
370static void renderspuDeleteBlitterCB(unsigned long key, void *data1, void *data2)
371{
372 CRHashTable *pTbl = (CRHashTable*)data2;
373
374 crHashtableDelete( pTbl, key, NULL );
375
376 DeleteBlitterCallback(data1);
377}
378
379
380static void renderspuDeleteWindowCB(unsigned long key, void *data1, void *data2)
381{
382 CRHashTable *pTbl = (CRHashTable*)data2;
383
384 crHashtableDelete( pTbl, key, NULL );
385
386 DeleteWindowCallback(data1);
387}
388
389static void renderspuDeleteBarierCB(unsigned long key, void *data1, void *data2)
390{
391 CRHashTable *pTbl = (CRHashTable*)data2;
392
393 crHashtableDelete( pTbl, key, NULL );
394
395 crFree(data1);
396}
397
398
399static void renderspuDeleteContextCB(unsigned long key, void *data1, void *data2)
400{
401 CRHashTable *pTbl = (CRHashTable*)data2;
402
403 crHashtableDelete( pTbl, key, NULL );
404
405 DeleteContextCallback(data1);
406}
407
408void renderspuCleanupBase(bool fDeleteTables)
409{
410 renderspuVBoxCompositorClearAll();
411
412 if (render_spu.blitterTable)
413 {
414 if (fDeleteTables)
415 {
416 crFreeHashtable(render_spu.blitterTable, DeleteBlitterCallback);
417 render_spu.blitterTable = NULL;
418 }
419 else
420 {
421 crHashtableWalk(render_spu.blitterTable, renderspuDeleteBlitterCB, render_spu.contextTable);
422 }
423 }
424 else
425 {
426 crHashtableWalk(render_spu.windowTable, renderspuBlitterCleanupCB, NULL);
427
428 crHashtableWalk(render_spu.dummyWindowTable, renderspuBlitterCleanupCB, NULL);
429 }
430
431 renderspuSetDefaultSharedContext(NULL);
432
433 if (fDeleteTables)
434 {
435 crFreeHashtable(render_spu.contextTable, DeleteContextCallback);
436 render_spu.contextTable = NULL;
437 crFreeHashtable(render_spu.windowTable, DeleteWindowCallback);
438 render_spu.windowTable = NULL;
439 crFreeHashtable(render_spu.dummyWindowTable, DeleteWindowCallback);
440 render_spu.dummyWindowTable = NULL;
441 crFreeHashtable(render_spu.barrierHash, crFree);
442 render_spu.barrierHash = NULL;
443 }
444 else
445 {
446 crHashtableWalk(render_spu.contextTable, renderspuDeleteContextCB, render_spu.contextTable);
447 crHashtableWalk(render_spu.windowTable, renderspuDeleteWindowCB, render_spu.windowTable);
448 crHashtableWalk(render_spu.dummyWindowTable, renderspuDeleteWindowCB, render_spu.dummyWindowTable);
449 crHashtableWalk(render_spu.barrierHash, renderspuDeleteBarierCB, render_spu.barrierHash);
450 }
451}
452
453static int renderSPUCleanup(void)
454{
455 renderspuCleanupBase(true);
456
457#ifdef RT_OS_WINDOWS
458 if (render_spu.dwWinThreadId)
459 {
460 HANDLE hNative;
461
462 hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
463 false, render_spu.dwWinThreadId);
464 if (!hNative)
465 {
466 crWarning("Failed to get handle for window thread(%#x)", GetLastError());
467 }
468
469 if (PostThreadMessage(render_spu.dwWinThreadId, WM_QUIT, 0, 0))
470 {
471 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
472
473 /*wait for os thread to actually finish*/
474 if (hNative && WaitForSingleObject(hNative, 3000)==WAIT_TIMEOUT)
475 {
476 crDebug("Wait failed, terminating");
477 if (!TerminateThread(hNative, 1))
478 {
479 crWarning("TerminateThread failed");
480 }
481 }
482 }
483
484 if (hNative)
485 {
486 CloseHandle(hNative);
487 }
488 }
489 CloseHandle(render_spu.hWinThreadReadyEvent);
490 render_spu.hWinThreadReadyEvent = NULL;
491#endif
492
493 crUnloadOpenGL();
494
495 crFreeTSD(&_RenderTSD);
496 return 1;
497}
498
499
500DECLHIDDEN(void) renderspuSetWindowId(uint64_t winId)
501{
502 render_spu_parent_window_id = winId;
503 crDebug("Set new parent window %p (no actual reparent performed)", winId);
504}
505
506DECLHIDDEN(const SPUREG) g_RenderSpuReg =
507{
508 /** pszName. */
509 "render",
510 /** pszSuperName. */
511 NULL,
512 /** fFlags. */
513 SPU_NO_PACKER | SPU_IS_TERMINAL | SPU_MAX_SERVERS_ZERO,
514 /** pfnInit. */
515 renderSPUInit,
516 /** pfnDispatch. */
517 renderSPUSelfDispatch,
518 /** pfnCleanup. */
519 renderSPUCleanup
520};
Note: See TracBrowser for help on using the repository browser.

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