VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/glwindrv.cpp@ 13026

Last change on this file since 13026 was 11411, checked in by vboxsync, 16 years ago

Fix startup failure and glGetString with NVidia drivers

  • Property svn:eol-style set to native
File size: 15.0 KB
Line 
1/** @file
2 * VBox OpenGL
3 */
4
5/*
6 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
17 * Clara, CA 95054 USA or visit http://www.sun.com if you need
18 * additional information or have any questions.
19 */
20
21
22#include <iprt/alloc.h>
23#include <iprt/string.h>
24#include <iprt/assert.h>
25#include <iprt/thread.h>
26#include <VBox/err.h>
27#include "vboxgl.h"
28
29#define LOG_GROUP LOG_GROUP_SHARED_OPENGL
30#include <VBox/log.h>
31#include "gldrv.h"
32
33#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
34LRESULT CALLBACK VBoxOGLWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
35{
36 switch (message)
37 {
38 case WM_CREATE:
39 return 0;
40
41 case WM_CLOSE:
42 PostQuitMessage( 0 );
43 return 0;
44
45 case WM_DESTROY:
46 return 0;
47
48 default:
49 return DefWindowProc( hWnd, message, wParam, lParam );
50 }
51}
52
53DECLCALLBACK(int) vboxWndThread(RTTHREAD ThreadSelf, void *pvUser)
54{
55 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvUser;
56 HWND hwnd;
57
58 hwnd = pClient->hwnd= CreateWindow("VBoxOGL", "VirtualBox OpenGL",
59 WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE,
60 0, 0, 0, 0,
61 NULL, NULL, 0, NULL);
62 Assert(hwnd);
63 while(true)
64 {
65 MSG msg;
66
67 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
68 {
69 if (msg.message == WM_QUIT)
70 break;
71
72 TranslateMessage(&msg);
73 DispatchMessage(&msg);
74 }
75 }
76 DestroyWindow(hwnd);
77 return VINF_SUCCESS;
78}
79
80#endif
81
82/**
83 * Global init of VBox OpenGL for windows
84 *
85 * @returns VBox error code
86 */
87int vboxglGlobalInit()
88{
89 Log(("vboxglGlobalInit\n"));
90
91 WNDCLASS wc;
92 HWND hWnd;
93
94#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
95 wc.style = CS_OWNDC;
96 wc.lpfnWndProc = VBoxOGLWndProc;
97 wc.cbClsExtra = 0;
98 wc.cbWndExtra = 0;
99 wc.hInstance = 0;
100 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
101 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
102 wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
103 wc.lpszMenuName = NULL;
104 wc.lpszClassName = "VBoxOGL";
105 RegisterClass(&wc);
106#endif
107
108 PIXELFORMATDESCRIPTOR pfd;
109 int iFormat;
110
111 wc.style = CS_OWNDC;
112 wc.lpfnWndProc = DefWindowProc;
113 wc.cbClsExtra = 0;
114 wc.cbWndExtra = 0;
115 wc.hInstance = 0;
116 wc.hIcon = NULL;
117 wc.hCursor = NULL;
118 wc.hbrBackground = NULL;
119 wc.lpszMenuName = NULL;
120 wc.lpszClassName = "VBoxOGLDummy";
121 RegisterClass( &wc );
122
123 /* create dummy window to avoid Intel/Nvidia opengl drivers
124 * problem with DC from desktop window */
125 hWnd = CreateWindow("VBoxOGLDummy", "", WS_POPUPWINDOW,
126 0, 0, 0, 0, NULL, NULL, 0, NULL );
127 Assert(hWnd);
128
129 HDC hdc = GetDC(hWnd);
130
131 ZeroMemory(&pfd, sizeof(pfd));
132 pfd.nSize = sizeof(pfd);
133 pfd.nVersion = 1;
134 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
135 pfd.iPixelType = PFD_TYPE_RGBA;
136 pfd.cColorBits = 24;
137 pfd.cDepthBits = 16;
138 pfd.iLayerType = PFD_MAIN_PLANE;
139 iFormat = ChoosePixelFormat(hdc, &pfd);
140 SetPixelFormat(hdc, iFormat, &pfd);
141
142 HGLRC hRC = wglCreateContext(hdc);
143 wglMakeCurrent(hdc, hRC);
144
145 vboxInitOpenGLExtensions();
146
147 wglMakeCurrent(NULL, NULL);
148 wglDeleteContext(hRC);
149 ReleaseDC(hWnd, hdc);
150 DestroyWindow(hWnd);
151
152 return VINF_SUCCESS;
153}
154
155/**
156 * Global deinit of VBox OpenGL
157 *
158 * @returns VBox error code
159 */
160int vboxglGlobalUnload()
161{
162 Log(("vboxglGlobalUnload\n"));
163
164 return VINF_SUCCESS;
165}
166
167/**
168 * Enable OpenGL
169 *
170 * @returns VBox error code
171 * @param pClient Client context
172 */
173int vboxglEnableOpenGL(PVBOXOGLCTX pClient)
174{
175 PIXELFORMATDESCRIPTOR pfd;
176 int iFormat;
177
178 if (!pClient->enable.hwnd)
179 {
180 pClient->enable.hwnd = CreateWindow("VBoxOGLDummy", "", WS_POPUPWINDOW,
181 0, 0, 0, 0, NULL, NULL, 0, NULL );
182 }
183
184 Assert(pClient->enable.hwnd);
185 pClient->enable.hdc = GetDC(pClient->enable.hwnd);
186
187 ZeroMemory(&pfd, sizeof(pfd));
188 pfd.nSize = sizeof(pfd);
189 pfd.nVersion = 1;
190 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
191 pfd.iPixelType = PFD_TYPE_RGBA;
192 pfd.cColorBits = 24;
193 pfd.cDepthBits = 16;
194 pfd.iLayerType = PFD_MAIN_PLANE;
195 iFormat = ChoosePixelFormat(pClient->enable.hdc, &pfd);
196 SetPixelFormat(pClient->enable.hdc, iFormat, &pfd);
197
198 pClient->enable.hglrc = wglCreateContext(pClient->enable.hdc);
199 wglMakeCurrent(pClient->enable.hdc, pClient->enable.hglrc);
200 return VINF_SUCCESS;
201}
202
203
204/**
205 * Disable OpenGL
206 *
207 * @returns VBox error code
208 * @param pClient Client context
209 */
210int vboxglDisableOpenGL(PVBOXOGLCTX pClient)
211{
212 wglMakeCurrent(NULL, NULL);
213 wglDeleteContext(pClient->enable.hglrc);
214 ReleaseDC(pClient->enable.hwnd, pClient->enable.hdc);
215 if (pClient->enable.hwnd)
216 {
217 DestroyWindow(pClient->enable.hwnd);
218 pClient->enable.hwnd = 0;
219 }
220 return VINF_SUCCESS;
221}
222
223/**
224 * Client connect init
225 *
226 * @returns VBox error code
227 * @param pClient Client context
228 */
229int vboxglConnect(PVBOXOGLCTX pClient)
230{
231 Log(("vboxglConnect\n"));
232 return VINF_SUCCESS;
233}
234
235/**
236 * Client disconnect cleanup
237 *
238 * @returns VBox error code
239 * @param pClient Client context
240 */
241int vboxglDisconnect(PVBOXOGLCTX pClient)
242{
243 Log(("vboxglDisconnect\n"));
244#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
245 if (pClient->hwnd)
246 {
247 if (pClient->hdc)
248 ReleaseDC(pClient->hwnd, pClient->hdc);
249 PostMessage(pClient->hwnd, WM_CLOSE, 0, 0);
250 pClient->hwnd = 0;
251 }
252#endif
253 return VINF_SUCCESS;
254}
255
256
257/* Driver functions */
258void vboxglDrvCreateContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
259{
260 HGLRC glrc = 0;
261
262 OGL_CMD(DrvCreateContext, 1);
263 OGL_PARAM(HDC, hdc);
264
265 Log(("DrvCreateContext %x\n", hdc));
266 Assert(VBOX_OGL_GUEST_TO_HOST_HDC(hdc));
267 glrc = wglCreateContext(pClient->hdc);
268
269 pClient->lastretval = (uint64_t)glrc;
270 pClient->fHasLastError = true;
271 pClient->ulLastError = GetLastError();
272}
273
274void vboxglDrvSetContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
275{
276 OGL_CMD(DrvSetContext, 2);
277 OGL_PARAM(HDC, hdc);
278 OGL_PARAM(HGLRC, hglrc);
279
280 Log(("DrvSetyContext %x %x\n", hdc, hglrc));
281 pClient->lastretval = wglMakeCurrent(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), hglrc);
282 if (!pClient->lastretval)
283 Log(("wglMakeCurrent failed with %d\n", GetLastError()));
284
285 pClient->fHasLastError = true;
286 pClient->ulLastError = GetLastError();
287}
288
289void vboxglDrvCopyContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
290{
291 OGL_CMD(DrvDeleteContext, 3);
292 OGL_PARAM(HGLRC, hglrcSrc);
293 OGL_PARAM(HGLRC, hglrcDst);
294 OGL_PARAM(UINT, mask);
295 Log(("DrvCopyContext %x %x %x\n", hglrcSrc, hglrcDst, mask));
296 pClient->lastretval = wglCopyContext(hglrcSrc, hglrcDst, mask);
297 if (!pClient->lastretval)
298 Log(("wglCopyContext failed with %d\n", GetLastError()));
299
300 pClient->fHasLastError = true;
301 pClient->ulLastError = GetLastError();
302}
303
304void vboxglDrvReleaseContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
305{
306 OGL_CMD(DrvReleaseContext, 1);
307 OGL_PARAM(HGLRC, hglrc);
308
309 Log(("DrvReleaseContext %x\n", hglrc));
310 /* clear current selection */
311 pClient->lastretval = wglMakeCurrent(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), NULL);
312 if (!pClient->lastretval)
313 Log(("wglMakeCurrent failed with %d\n", GetLastError()));
314 pClient->fHasLastError = true;
315 pClient->ulLastError = GetLastError();
316}
317
318void vboxglDrvDeleteContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
319{
320 OGL_CMD(DrvDeleteContext, 1);
321 OGL_PARAM(HGLRC, hglrc);
322
323 Log(("DrvDeleteContext %x\n", hglrc));
324 pClient->lastretval = wglDeleteContext(hglrc);
325 if (!pClient->lastretval)
326 Log(("wglDeleteContext failed with %d\n", GetLastError()));
327 pClient->fHasLastError = true;
328 pClient->ulLastError = GetLastError();
329}
330
331void vboxglDrvCreateLayerContext(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
332{
333 HGLRC glrc = 0;
334
335 OGL_CMD(DrvCreateLayerContext, 2);
336 OGL_PARAM(HDC, hdc);
337 OGL_PARAM(int, iLayerPlane);
338
339 Log(("DrvCreateLayerContext %x %d\n", hdc, iLayerPlane));
340 Assert(VBOX_OGL_GUEST_TO_HOST_HDC(hdc));
341 glrc = wglCreateLayerContext(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iLayerPlane);
342
343 pClient->lastretval = (uint64_t)glrc;
344 pClient->fHasLastError = true;
345 pClient->ulLastError = GetLastError();
346}
347
348void vboxglDrvShareLists(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
349{
350 OGL_CMD(DrvShareLists, 3);
351 OGL_PARAM(HGLRC, hglrc1);
352 OGL_PARAM(HGLRC, hglrc2);
353
354 Log(("DrvShareLists %x %x\n", hglrc1, hglrc2));
355 pClient->lastretval = wglShareLists(hglrc1, hglrc2);
356 pClient->fHasLastError = true;
357 pClient->ulLastError = GetLastError();
358}
359
360
361void vboxglDrvRealizeLayerPalette(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
362{
363 OGL_CMD(DrvRealizeLayerPalette, 3);
364 OGL_PARAM(HDC, hdc);
365 OGL_PARAM(int, iLayerPlane);
366 OGL_PARAM(BOOL, bRealize);
367 Log(("DrvRealizeLayerPalette %x %d %d\n", hdc, iLayerPlane, bRealize));
368 pClient->lastretval = wglRealizeLayerPalette(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iLayerPlane, bRealize);
369 pClient->fHasLastError = true;
370 pClient->ulLastError = GetLastError();
371}
372
373void vboxglDrvSwapLayerBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
374{
375 OGL_CMD(DrvSwapLayerBuffers, 2);
376 OGL_PARAM(HDC, hdc);
377 OGL_PARAM(UINT, fuPlanes);
378 Log(("DrvSwapLayerBuffers %x %d\n", hdc, fuPlanes));
379 pClient->lastretval = wglSwapLayerBuffers(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), fuPlanes);
380 pClient->fHasLastError = true;
381 pClient->ulLastError = GetLastError();
382}
383
384void vboxglDrvSetPixelFormat(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
385{
386 int rc;
387 PIXELFORMATDESCRIPTOR pfd;
388
389 OGL_CMD(DrvSetPixelFormat, 4);
390 OGL_PARAM(HDC, hdc);
391 OGL_PARAM(int, iPixelFormat);
392 OGL_PARAM(uint32_t, cx);
393 OGL_PARAM(uint32_t, cy);
394
395#ifdef VBOX_OGL_DEBUG_WINDOW_OUTPUT
396 if (!pClient->hwnd)
397 {
398 RTThreadCreate(NULL, vboxWndThread, pClient, 0, RTTHREADTYPE_DEFAULT, 0, "OpenGLWnd");
399 while (!pClient->hwnd)
400 RTThreadSleep(100);
401 }
402 SetWindowPos(pClient->hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
403
404 pClient->hdc = GetDC(pClient->hwnd);
405
406 rc = DescribePixelFormat(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iPixelFormat, sizeof(pfd), &pfd);
407 if (rc)
408 {
409 pClient->lastretval = SetPixelFormat(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iPixelFormat, &pfd);
410 }
411 else
412 {
413 Log(("DescribePixelFormat %d failed with 0 (%d)\n", iPixelFormat, GetLastError()));
414 pClient->lastretval = 0;
415 }
416
417#else
418 AssertFailed();
419#endif
420
421 Log(("DrvSetPixelFormat %x %d (%d,%d)\n", hdc, iPixelFormat, cx, cy));
422 pClient->fHasLastError = true;
423 pClient->ulLastError = GetLastError();
424}
425
426void vboxglDrvSwapBuffers(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
427{
428 OGL_CMD(DrvSwapBuffers, 1);
429 OGL_PARAM(HDC, hdc);
430
431 Log(("DrvSwapBuffers %x\n", hdc));
432 pClient->lastretval = SwapBuffers(VBOX_OGL_GUEST_TO_HOST_HDC(hdc));
433 if (!pClient->lastretval)
434 Log(("SwapBuffers failed with %d\n", GetLastError()));
435
436 /** @todo sync bitmap/screen contents */
437 pClient->fHasLastError = true;
438 pClient->ulLastError = GetLastError();
439}
440
441void vboxglDrvDescribeLayerPlane(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
442{
443 PLAYERPLANEDESCRIPTOR plpd;
444
445 OGL_CMD(DrvDescribeLayerPlane, 4);
446 OGL_PARAM(HDC, hdc);
447 OGL_PARAM(int, iPixelFormat);
448 OGL_PARAM(int, iLayerPlane);
449 OGL_PARAM(UINT, nBytes);
450 Assert(pClient->cbLastParam == nBytes);
451 plpd = (PLAYERPLANEDESCRIPTOR)pClient->pLastParam;
452
453 Log(("DrvDescribeLayerPlane %x %d %d %d %x\n", hdc, iPixelFormat, iLayerPlane, nBytes, plpd));
454 pClient->lastretval = wglDescribeLayerPlane(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iPixelFormat, iLayerPlane, nBytes, plpd);
455 if (!pClient->lastretval)
456 Log(("wglDescribeLayerPlane failed with %d\n", GetLastError()));
457 pClient->fHasLastError = true;
458 pClient->ulLastError = GetLastError();
459}
460
461void vboxglDrvSetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
462{
463 OGL_CMD(DrvSetLayerPaletteEntries, 5);
464 OGL_PARAM(HDC, hdc);
465 OGL_PARAM(int, iLayerPlane);
466 OGL_PARAM(int, iStart);
467 OGL_PARAM(int, cEntries);
468 OGL_MEMPARAM(COLORREF, pcr);
469
470 Log(("DrvSetLayerPaletteEntries %x %d %d %d %x\n", hdc, iLayerPlane, iStart, cEntries, pcr));
471 pClient->lastretval = wglSetLayerPaletteEntries(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iLayerPlane, iStart, cEntries, pcr);
472 if (!pClient->lastretval)
473 Log(("wglSetLayerPaletteEntries failed with %d\n", GetLastError()));
474 pClient->fHasLastError = true;
475 pClient->ulLastError = GetLastError();
476}
477
478void vboxglDrvGetLayerPaletteEntries(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
479{
480 COLORREF *pcr;
481
482 OGL_CMD(DrvGetLayerPaletteEntries, 4);
483 OGL_PARAM(HDC, hdc);
484 OGL_PARAM(int, iLayerPlane);
485 OGL_PARAM(int, iStart);
486 OGL_PARAM(int, cEntries);
487
488 Assert(pClient->cbLastParam == sizeof(COLORREF)*cEntries);
489 pcr = (COLORREF *)pClient->pLastParam;
490
491 Log(("DrvGetLayerPaletteEntries %x %d %d %d %x\n", hdc, iLayerPlane, iStart, cEntries, pcr));
492 pClient->lastretval = wglGetLayerPaletteEntries(VBOX_OGL_GUEST_TO_HOST_HDC(hdc), iLayerPlane, iStart, cEntries, pcr);
493 if (!pClient->lastretval)
494 Log(("wglGetLayerPaletteEntries failed with %d\n", GetLastError()));
495 pClient->fHasLastError = true;
496 pClient->ulLastError = GetLastError();
497}
498
499void vboxglDrvDescribePixelFormat(VBOXOGLCTX *pClient, uint8_t *pCmdBuffer)
500{
501 LPPIXELFORMATDESCRIPTOR ppfd;
502
503 OGL_CMD(DrvDescribePixelFormat, 3);
504 OGL_PARAM(HDC, hdc);
505 OGL_PARAM(int, iPixelFormat);
506 OGL_PARAM(UINT, nBytes);
507 Assert(pClient->cbLastParam == nBytes);
508 ppfd = (LPPIXELFORMATDESCRIPTOR)pClient->pLastParam;
509
510 hdc = VBOX_OGL_GUEST_TO_HOST_HDC(hdc);
511 if (!hdc)
512 hdc = GetDC(0);
513
514 Log(("DrvDescribePixelFormat %x %d %d %x\n", hdc, iPixelFormat, nBytes, ppfd));
515 pClient->lastretval = DescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
516 if (!pClient->lastretval)
517 Log(("DescribePixelFormat failed with %d\n", GetLastError()));
518
519 pClient->fHasLastError = true;
520 pClient->ulLastError = GetLastError();
521
522 if (!VBOX_OGL_GUEST_TO_HOST_HDC(hdc))
523 ReleaseDC(0, pClient->hdc);
524}
525
526RTUINTPTR vboxDrvIsExtensionAvailable(char *pszExtFunctionName)
527{
528 RTUINTPTR pfnProc = (RTUINTPTR)wglGetProcAddress(pszExtFunctionName);
529
530 Log(("vboxDrvIsExtensionAvailable %s -> %d\n", pszExtFunctionName, !!pfnProc));
531 return pfnProc;
532}
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