VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/OpenGL/VBoxOGL.cpp@ 3464

Last change on this file since 3464 was 3464, checked in by vboxsync, 18 years ago

wrong string

File size: 14.8 KB
Line 
1/** @file
2 *
3 * VBoxDisp -- Windows Guest OpenGL ICD
4 *
5 * Copyright (C) 2006-2007 innotek GmbH
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation,
11 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
12 * distribution. VirtualBox OSE is distributed in the hope that it will
13 * be useful, but WITHOUT ANY WARRANTY of any kind.
14 *
15 * If you received this file as part of a commercial VirtualBox
16 * distribution, then only the terms of your commercial VirtualBox
17 * license agreement apply instead of the previous paragraph.
18 *
19 */
20#include "VBoxOGL.h"
21#include <VBox/version.h>
22#include <VBox/VBoxGuest.h>
23#include <stdarg.h>
24#include <stdio.h>
25
26#define VBOX_INIT_CALL(a, b, c) \
27 (a)->result = VINF_SUCCESS; \
28 (a)->u32ClientID = (c)->u32ClientID; \
29 (a)->u32Function = VBOXOGL_FN_##b; \
30 (a)->cParms = VBOXOGL_CPARMS_##b
31
32
33 HINSTANCE hDllVBoxOGL = 0;
34static DWORD dwOGLTlsIndex = TLS_OUT_OF_INDEXES;
35static VBOX_OGL_CTX vboxOGLCtx = {0};
36static char szOpenGLVersion[256] = "";
37static char szOpenGLExtensions[8192] = ""; /* this one can be rather long */
38
39
40/**
41 * Set the thread local OpenGL context
42 *
43 * @param pCtx thread local OpenGL context ptr
44 */
45void VBoxOGLSetThreadCtx(PVBOX_OGL_THREAD_CTX pCtx)
46{
47 BOOL ret;
48
49 ret = TlsSetValue(dwOGLTlsIndex, pCtx);
50 Assert(ret);
51}
52
53
54/**
55 * Return the thread local OpenGL context
56 *
57 * @return thread local OpenGL context ptr or NULL if failure
58 */
59PVBOX_OGL_THREAD_CTX VBoxOGLGetThreadCtx()
60{
61 PVBOX_OGL_THREAD_CTX pCtx;
62
63 pCtx = (PVBOX_OGL_THREAD_CTX)TlsGetValue(dwOGLTlsIndex);
64 if (!pCtx)
65 {
66 /* lazy init */
67 VBoxOGLThreadAttach();
68 pCtx = (PVBOX_OGL_THREAD_CTX)TlsGetValue(dwOGLTlsIndex);
69 }
70 Assert(pCtx);
71 return pCtx;
72}
73
74/**
75 * Initialize the OpenGL guest-host communication channel
76 *
77 * @return success or failure (boolean)
78 * @param hDllInst Dll instance handle
79 */
80BOOL VBoxOGLInit(HINSTANCE hDllInst)
81{
82 dwOGLTlsIndex = TlsAlloc();
83 if (dwOGLTlsIndex == TLS_OUT_OF_INDEXES)
84 {
85 DbgPrintf(("TlsAlloc failed with %d\n", GetLastError()));
86 return FALSE;
87 }
88 DbgPrintf(("VBoxOGLInit TLS index=%d\n", dwOGLTlsIndex));
89
90 /* open VBox guest driver */
91 vboxOGLCtx.hGuestDrv = CreateFile(VBOXGUEST_DEVICE_NAME,
92 GENERIC_READ | GENERIC_WRITE,
93 FILE_SHARE_READ | FILE_SHARE_WRITE,
94 NULL,
95 OPEN_EXISTING,
96 FILE_ATTRIBUTE_NORMAL,
97 NULL);
98 if (vboxOGLCtx.hGuestDrv == INVALID_HANDLE_VALUE)
99 {
100 DbgPrintf(("VBoxService: could not open VBox Guest Additions driver! rc = %d\n", GetLastError()));
101 return FALSE;
102 }
103
104 VBoxOGLThreadAttach();
105 hDllVBoxOGL = hDllInst;
106 return TRUE;
107}
108
109/**
110 * Destroy the OpenGL guest-host communication channel
111 *
112 * @return success or failure (boolean)
113 */
114BOOL VBoxOGLExit()
115{
116 DbgPrintf(("VBoxOGLExit\n"));
117 VBoxOGLThreadDetach();
118 CloseHandle(vboxOGLCtx.hGuestDrv);
119
120 hDllVBoxOGL = 0;
121 return TRUE;
122}
123
124
125/**
126 * Initialize new thread
127 *
128 * @return success or failure (boolean)
129 */
130BOOL VBoxOGLThreadAttach()
131{
132 PVBOX_OGL_THREAD_CTX pCtx;
133
134 DbgPrintf(("VBoxOGLThreadAttach id=%x\n", GetCurrentThreadId()));
135
136 pCtx = (PVBOX_OGL_THREAD_CTX)malloc(sizeof(*pCtx));
137 AssertReturn(pCtx, FALSE);
138 if (!pCtx)
139 return FALSE;
140
141 pCtx->pCmdBuffer = (uint8_t *)VirtualAlloc(NULL, VBOX_OGL_MAX_CMD_BUFFER, MEM_COMMIT, PAGE_READWRITE);
142 pCtx->pCmdBufferEnd = pCtx->pCmdBuffer + VBOX_OGL_MAX_CMD_BUFFER;
143 pCtx->pCurrentCmd = pCtx->pCmdBuffer;
144 pCtx->cCommands = 0;
145 Assert(pCtx->pCmdBuffer);
146 if (!pCtx->pCmdBuffer)
147 return FALSE;
148
149 VBoxOGLSetThreadCtx(pCtx);
150
151 VBoxGuestHGCMConnectInfo info;
152 memset (&info, 0, sizeof (info));
153
154 info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
155
156 strcpy (info.Loc.u.host.achName, "VBoxSharedOpenGL");
157
158 DWORD cbReturned;
159
160 if (DeviceIoControl(vboxOGLCtx.hGuestDrv,
161 IOCTL_VBOXGUEST_HGCM_CONNECT,
162 &info, sizeof (info),
163 &info, sizeof (info),
164 &cbReturned,
165 NULL))
166 {
167 if (info.result == VINF_SUCCESS)
168 {
169 pCtx->u32ClientID = info.u32ClientID;
170 DbgPrintf(("HGCM connect was successful: client id =%x\n", pCtx->u32ClientID));
171 }
172 }
173 else
174 {
175 DbgPrintf(("HGCM connect failed with rc=%x\n", GetLastError()));
176 return FALSE;
177 }
178
179 VBoxOGLglGetString parms;
180 memset(&parms, 0, sizeof(parms));
181
182 VBOX_INIT_CALL(&parms.hdr, GLGETSTRING, pCtx);
183
184 parms.name.type = VMMDevHGCMParmType_32bit;
185 parms.name.u.value32 = GL_VERSION;
186 parms.pString.type = VMMDevHGCMParmType_LinAddr;
187 parms.pString.u.Pointer.size = sizeof(szOpenGLVersion);
188 parms.pString.u.Pointer.u.linearAddr = (vmmDevHypPtr)szOpenGLVersion;
189
190 int rc = vboxHGCMCall(vboxOGLCtx.hGuestDrv, &parms, sizeof (parms));
191
192 if ( VBOX_FAILURE(rc)
193 || VBOX_FAILURE(parms.hdr.result))
194 {
195 DbgPrintf(("GL_VERSION failed with %x %x\n", rc, parms.hdr.result));
196 return FALSE;
197 }
198 DbgPrintf(("GL_VERSION=%s\n", szOpenGLVersion));
199
200 memset(&parms, 0, sizeof(parms));
201 VBOX_INIT_CALL(&parms.hdr, GLGETSTRING, pCtx);
202
203 parms.name.type = VMMDevHGCMParmType_32bit;
204 parms.name.u.value32 = GL_EXTENSIONS;
205 parms.pString.type = VMMDevHGCMParmType_LinAddr;
206 parms.pString.u.Pointer.size = sizeof(szOpenGLExtensions);
207 parms.pString.u.Pointer.u.linearAddr = (vmmDevHypPtr)szOpenGLExtensions;
208
209 rc = vboxHGCMCall(vboxOGLCtx.hGuestDrv, &parms, sizeof (parms));
210
211 if ( VBOX_FAILURE(rc)
212 || VBOX_FAILURE(parms.hdr.result))
213 {
214 DbgPrintf(("GL_EXTENSIONS failed with %x %x\n", rc, parms.hdr.result));
215 return FALSE;
216 }
217 DbgPrintf(("GL_EXTENSIONS=%s\n\n", szOpenGLExtensions));
218
219 /* Initialize OpenGL extensions */
220 vboxInitOpenGLExtensions();
221
222 return TRUE;
223}
224
225/**
226 * Clean up for terminating thread
227 *
228 * @return success or failure (boolean)
229 */
230BOOL VBoxOGLThreadDetach()
231{
232 PVBOX_OGL_THREAD_CTX pCtx;
233
234 DbgPrintf(("VBoxOGLThreadDetach id=%x\n", GetCurrentThreadId()));
235
236 pCtx = VBoxOGLGetThreadCtx();
237 if (pCtx && pCtx->u32ClientID)
238 {
239 VBoxGuestHGCMDisconnectInfo info;
240
241 memset (&info, 0, sizeof (info));
242
243 info.u32ClientID = pCtx->u32ClientID;
244
245 DWORD cbReturned;
246
247 BOOL bRet = DeviceIoControl(vboxOGLCtx.hGuestDrv,
248 IOCTL_VBOXGUEST_HGCM_DISCONNECT,
249 &info, sizeof (info),
250 &info, sizeof (info),
251 &cbReturned,
252 NULL);
253
254 if (!bRet)
255 {
256 DbgPrintf(("Disconnect failed with %x\n", GetLastError()));
257 }
258 }
259 if (pCtx)
260 {
261 if (pCtx->pCmdBuffer)
262 VirtualFree(pCtx->pCmdBuffer, 0, MEM_RELEASE);
263
264 free(pCtx);
265 VBoxOGLSetThreadCtx(NULL);
266 }
267
268 return TRUE;
269}
270
271
272
273/**
274 * Send an HGCM request
275 *
276 * @return VBox status code
277 * @param hDriver Driver handle
278 * @param pvData Data pointer
279 * @param cbData Data size
280 */
281int vboxHGCMCall(HANDLE hDriver, void *pvData, unsigned cbData)
282{
283 DWORD cbReturned;
284
285 if (DeviceIoControl (hDriver,
286 IOCTL_VBOXGUEST_HGCM_CALL,
287 pvData, cbData,
288 pvData, cbData,
289 &cbReturned,
290 NULL))
291 {
292 return VINF_SUCCESS;
293 }
294 DbgPrintf(("vboxCall failed with %x\n", GetLastError()));
295 return VERR_NOT_SUPPORTED;
296}
297
298#ifdef DEBUG
299/**
300 * Log to the debug output device
301 *
302 * @param pszFormat Format string
303 * @param ... Variable parameters
304 */
305void VBoxDbgLog(char *pszFormat, ...)
306{
307 va_list va;
308
309 va_start(va, pszFormat);
310 CHAR Buffer[10240];
311 if (strlen(pszFormat) < 512)
312 {
313 vsprintf (Buffer, pszFormat, va);
314
315 printf(Buffer);
316// OutputDebugStringA(Buffer);
317 }
318
319 va_end (va);
320}
321#endif
322
323
324GLenum APIENTRY glGetError (void)
325{
326 PVBOX_OGL_THREAD_CTX pCtx = VBoxOGLGetThreadCtx();
327
328 /** @todo if fetch error flag set -> flush buffer */
329 return pCtx->glLastError;
330}
331
332void APIENTRY glSetError(GLenum glNewError)
333{
334 PVBOX_OGL_THREAD_CTX pCtx = VBoxOGLGetThreadCtx();
335
336 pCtx->glLastError = glNewError;
337}
338
339/**
340 * Query OpenGL strings
341 *
342 * @returns OpenGL string pointer
343 * @param name string type
344 */
345const GLubyte * APIENTRY glGetString (GLenum name)
346{
347 DbgPrintf(("glGetString %x\n", name));
348 switch (name)
349 {
350 /* Note: We hide the host vendor and renderer to avoid exposing potential critical information (exploits) */
351 case GL_VENDOR:
352 return (const GLubyte *)VBOX_VENDOR;
353
354 case GL_RENDERER:
355 return (const GLubyte *)"VirtualBox OpenGL Renderer";
356
357 case GL_VERSION:
358 return (const GLubyte *)szOpenGLVersion;
359
360 case GL_EXTENSIONS:
361 return (const GLubyte *)szOpenGLExtensions;
362
363 default:
364 glLogError(GL_INVALID_ENUM);
365 return NULL;
366 }
367}
368
369/**
370 * Flush the OpenGL command queue and return the return val of the last command
371 *
372 * @returns return val of last command
373 */
374uint64_t VBoxOGLFlush()
375{
376 PVBOX_OGL_THREAD_CTX pCtx = VBoxOGLGetThreadCtx();
377 VBoxOGLglFlush parms;
378
379 AssertReturn(pCtx->pCurrentCmd > pCtx->pCmdBuffer, 0);
380
381 VBOX_INIT_CALL(&parms.hdr, GLFLUSH, pCtx);
382
383 parms.pCmdBuffer.type = VMMDevHGCMParmType_LinAddr_In;
384 parms.pCmdBuffer.u.Pointer.size = pCtx->pCurrentCmd - pCtx->pCmdBuffer;
385 parms.pCmdBuffer.u.Pointer.u.linearAddr = (vmmDevHypPtr)pCtx->pCmdBuffer;
386 parms.cCommands.type = VMMDevHGCMParmType_32bit;
387 parms.cCommands.u.value32 = pCtx->cCommands;
388 parms.retval.type = VMMDevHGCMParmType_64bit;
389 parms.retval.u.value64 = 0;
390 parms.lasterror.type = VMMDevHGCMParmType_32bit;
391 parms.lasterror.u.value32 = 0;
392
393 int rc = vboxHGCMCall(vboxOGLCtx.hGuestDrv, &parms, sizeof (parms));
394
395 /* reset command buffer */
396 pCtx->pCurrentCmd = pCtx->pCmdBuffer;
397 pCtx->cCommands = 0;
398
399 if ( VBOX_FAILURE(rc)
400 || VBOX_FAILURE(parms.hdr.result))
401 {
402 DbgPrintf(("GL_FLUSH failed with %x %x\n", rc, parms.hdr.result));
403 return 0;
404 }
405
406 glSetError(parms.lasterror.u.value32);
407#ifdef DEBUG
408 if (parms.lasterror.u.value32)
409 DbgPrintf(("Last command returned error %x\n", parms.lasterror.u.value32));
410#endif
411 return parms.retval.u.value64;
412}
413
414/**
415 * Flush the OpenGL command queue and return the return val of the last command
416 * The last command's final parameter is a pointer where its result is stored
417 *
418 * @returns return val of last command
419 * @param pLastParam Last parameter's address
420 * @param cbParam Last parameter's size
421 */
422uint64_t VBoxOGLFlushPtr(void *pLastParam, uint32_t cbParam)
423{
424 PVBOX_OGL_THREAD_CTX pCtx = VBoxOGLGetThreadCtx();
425 VBoxOGLglFlushPtr parms;
426
427 AssertReturn(pCtx->pCurrentCmd > pCtx->pCmdBuffer, 0);
428
429 VBOX_INIT_CALL(&parms.hdr, GLFLUSHPTR, pCtx);
430
431 parms.pCmdBuffer.type = VMMDevHGCMParmType_LinAddr_In;
432 parms.pCmdBuffer.u.Pointer.size = pCtx->pCurrentCmd - pCtx->pCmdBuffer;
433 parms.pCmdBuffer.u.Pointer.u.linearAddr = (vmmDevHypPtr)pCtx->pCmdBuffer;
434 parms.cCommands.type = VMMDevHGCMParmType_32bit;
435 parms.cCommands.u.value32 = pCtx->cCommands;
436 parms.retval.type = VMMDevHGCMParmType_64bit;
437 parms.retval.u.value64 = 0;
438 parms.lasterror.type = VMMDevHGCMParmType_32bit;
439 parms.lasterror.u.value32 = 0;
440 if (cbParam)
441 {
442 Assert(pLastParam);
443 parms.pLastParam.type = VMMDevHGCMParmType_LinAddr;
444 parms.pLastParam.u.Pointer.size = cbParam;
445 parms.pLastParam.u.Pointer.u.linearAddr = (vmmDevHypPtr)pLastParam;
446 }
447 else
448 {
449 /* Placeholder as HGCM doesn't like NULL pointers */
450 Assert(!cbParam && !pLastParam);
451 parms.pLastParam.type = VMMDevHGCMParmType_32bit;
452 parms.pLastParam.u.value32 = 0;
453 }
454
455 int rc = vboxHGCMCall(vboxOGLCtx.hGuestDrv, &parms, sizeof (parms));
456
457 /* reset command buffer */
458 pCtx->pCurrentCmd = pCtx->pCmdBuffer;
459 pCtx->cCommands = 0;
460
461 if ( VBOX_FAILURE(rc)
462 || VBOX_FAILURE(parms.hdr.result))
463 {
464 DbgPrintf(("GL_FLUSH failed with %x %x\n", rc, parms.hdr.result));
465 return 0;
466 }
467
468 glSetError(parms.lasterror.u.value32);
469#ifdef DEBUG
470 if (parms.lasterror.u.value32)
471 DbgPrintf(("Last command returned error %x\n", parms.lasterror.u.value32));
472#endif
473 return parms.retval.u.value64;
474}
475
476/**
477 * Check if an OpenGL extension is available on the host
478 *
479 * @returns available or not
480 * @param pszExtFunctionName
481 */
482bool VBoxIsExtensionAvailable(const char *pszExtFunctionName)
483{
484 PVBOX_OGL_THREAD_CTX pCtx = VBoxOGLGetThreadCtx();
485 VBoxOGLglCheckExt parms;
486
487 AssertReturn(pCtx->pCurrentCmd > pCtx->pCmdBuffer, 0);
488
489 VBOX_INIT_CALL(&parms.hdr, GLCHECKEXT, pCtx);
490
491 parms.pszExtFnName.type = VMMDevHGCMParmType_LinAddr_In;
492 parms.pszExtFnName.u.Pointer.size = strlen(pszExtFunctionName)+1;
493 parms.pszExtFnName.u.Pointer.u.linearAddr = (vmmDevHypPtr)pszExtFunctionName;
494
495 int rc = vboxHGCMCall(vboxOGLCtx.hGuestDrv, &parms, sizeof (parms));
496
497 if ( VBOX_FAILURE(rc)
498 || VBOX_FAILURE(parms.hdr.result))
499 {
500 DbgPrintf(("GLCHECKEXT failed with %x %x\n", rc, parms.hdr.result));
501 return false;
502 }
503
504 return true;
505}
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