VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c@ 73150

最後變更 在這個檔案從73150是 70871,由 vboxsync 提交於 7 年 前

HostServices/SharedOpenGL: bugref:9103: Improved logging of rectangles for 3D window region (Windows hosts only).

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 53.7 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
8#define WIN32_LEAN_AND_MEAN
9#include <iprt/win/windows.h>
10
11#include <stdlib.h>
12#include <stdio.h>
13#include <memory.h>
14
15#include "cr_environment.h"
16#include "cr_error.h"
17#include "cr_string.h"
18#include "renderspu.h"
19#include "cr_mem.h"
20
21
22/* IAT patcher stuff */
23#define RVA2PTR(_t, _base, _off) ((_t*)(((uint8_t*)(_base)) + (_off)))
24
25int renderspuIatPatcherGetImportAddress(HMODULE hModule, LPCSTR pszLib, LPCSTR pszName, void** ppAdr)
26{
27 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hModule;
28 PIMAGE_NT_HEADERS pNtHdr;
29 PIMAGE_IMPORT_DESCRIPTOR pImportDr;
30 DWORD rvaImport;
31
32 crDebug("searching entry %s from %s", pszName, pszLib);
33
34 *ppAdr = 0;
35
36 if (pDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
37 {
38 crWarning("invalid dos signature");
39 return VERR_INVALID_HANDLE;
40 }
41 pNtHdr = RVA2PTR(IMAGE_NT_HEADERS, pDosHdr, pDosHdr->e_lfanew);
42 if (pNtHdr->Signature != IMAGE_NT_SIGNATURE)
43 {
44 crWarning("invalid nt signature");
45 return VERR_INVALID_HANDLE;
46 }
47 rvaImport = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
48 if (!rvaImport)
49 {
50 crWarning("no imports found");
51 return VERR_NOT_FOUND;
52 }
53 pImportDr = RVA2PTR(IMAGE_IMPORT_DESCRIPTOR, pDosHdr, rvaImport);
54
55 for ( ;pImportDr->TimeDateStamp != 0 || pImportDr->Name != 0; ++pImportDr)
56 {
57 DWORD rvaINT, rvaIAT;
58 PIMAGE_THUNK_DATA pINT, pIAT;
59 LPCSTR pszLibCur = RVA2PTR(char, pDosHdr, pImportDr->Name);
60 if (stricmp(pszLibCur, pszLib))
61 continue;
62
63 /* got the necessary lib! */
64 crDebug("got info for lib");
65
66 rvaINT = pImportDr->OriginalFirstThunk;
67 rvaIAT = pImportDr->FirstThunk;
68
69 if (!rvaINT || !rvaIAT)
70 {
71 crWarning("either rvaINT(0x%x) or rvaIAT(0x%x) are NULL, nothing found!", rvaINT, rvaIAT);
72 return VERR_NOT_FOUND;
73 }
74
75 pINT = RVA2PTR(IMAGE_THUNK_DATA, pDosHdr, rvaINT);
76 pIAT = RVA2PTR(IMAGE_THUNK_DATA, pDosHdr, rvaIAT);
77
78 for ( ; pINT->u1.AddressOfData; ++pINT, ++pIAT)
79 {
80 PIMAGE_IMPORT_BY_NAME pIbn;
81
82 if (IMAGE_SNAP_BY_ORDINAL(pINT->u1.Ordinal))
83 continue;
84
85 pIbn = RVA2PTR(IMAGE_IMPORT_BY_NAME, pDosHdr, pINT->u1.AddressOfData);
86
87 if (stricmp(pszName, (char*)pIbn->Name))
88 continue;
89
90 *ppAdr = &pIAT->u1.Function;
91
92 crDebug("search succeeded!");
93 return VINF_SUCCESS;
94 }
95 }
96
97 crDebug("not found");
98 return VERR_NOT_FOUND;
99}
100
101int renderspuIatPatcherPatchEntry(void *pvEntry, void *pvValue, void **ppvOldVal)
102{
103 void **ppfn = (void**)pvEntry;
104 DWORD dwOldProtect = 0;
105
106 if (!VirtualProtect(pvEntry, sizeof (pvEntry), PAGE_READWRITE, &dwOldProtect))
107 {
108 crWarning("VirtualProtect 1 failed, %d", GetLastError());
109 return VERR_ACCESS_DENIED;
110 }
111
112 if (ppvOldVal)
113 *ppvOldVal = *ppfn;
114 *ppfn = pvValue;
115
116 if (!VirtualProtect(pvEntry, sizeof (pvEntry), dwOldProtect, &dwOldProtect))
117 {
118 crWarning("VirtualProtect 2 failed, %d.. ignoring", GetLastError());
119 }
120
121 return VINF_SUCCESS;
122}
123
124
125int renderspuIatPatcherPatchFunction(HMODULE hModule, LPCSTR pszLib, LPCSTR pszName, void* pfn)
126{
127 void* pAdr;
128 int rc = renderspuIatPatcherGetImportAddress(hModule, pszLib, pszName, &pAdr);
129 if (RT_FAILURE(rc))
130 {
131 crDebug("renderspuIatPatcherGetImportAddress failed, %d", rc);
132 return rc;
133 }
134
135 rc = renderspuIatPatcherPatchEntry(pAdr, pfn, NULL);
136 if (RT_FAILURE(rc))
137 {
138 crWarning("renderspuIatPatcherPatchEntry failed, %d", rc);
139 return rc;
140 }
141
142 return VINF_SUCCESS;
143}
144
145/* patch */
146static HWND __stdcall renderspuAtiQuirk_GetForegroundWindow()
147{
148 crDebug("renderspuAtiQuirk_GetForegroundWindow");
149 return NULL;
150}
151
152
153#define CRREG_MAXKEYNAME 8
154static int renderspuAtiQuirk_GetICDDriverList(char *pBuf, DWORD cbBuf, DWORD *pcbResult)
155{
156 static LPCSTR aValueNames[] = {"OpenGLVendorName", "OpenGLDriverName"};
157 char *pBufPos = pBuf;
158 DWORD cbBufRemain = cbBuf, cbTotal = 0;
159 HKEY hKey, hSubkey;
160 DWORD dwIndex = 0;
161 int i;
162 int rc = VINF_SUCCESS;
163 char NameBuf[CRREG_MAXKEYNAME];
164 LONG lRc;
165
166 if (pcbResult)
167 *pcbResult = 0;
168
169 lRc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
170 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}",
171 0, /* reserved*/
172 KEY_READ,
173 &hKey);
174 if (ERROR_SUCCESS != lRc)
175 {
176 crDebug("RegOpenKeyEx 1 failed, %d", lRc);
177 return VERR_OPEN_FAILED;
178 }
179
180 for ( ; ; ++dwIndex)
181 {
182 lRc = RegEnumKeyA(hKey, dwIndex, NameBuf, CRREG_MAXKEYNAME);
183 if (lRc == ERROR_NO_MORE_ITEMS)
184 break;
185 if (lRc == ERROR_MORE_DATA)
186 continue;
187 if (lRc != ERROR_SUCCESS)
188 {
189 crWarning("RegEnumKeyA failed, %d", lRc);
190 continue;
191 }
192
193 lRc = RegOpenKeyEx(hKey,
194 NameBuf,
195 0, /* reserved*/
196 KEY_READ,
197 &hSubkey);
198 if (ERROR_SUCCESS != lRc)
199 {
200 crDebug("RegOpenKeyEx 2 failed, %d", lRc);
201 RegCloseKey(hKey);
202 return VERR_OPEN_FAILED;
203 }
204
205 for (i = 0; i < RT_ELEMENTS(aValueNames); ++i)
206 {
207 DWORD cbCur = cbBufRemain;
208 DWORD type;
209 lRc = RegQueryValueExA(hSubkey, aValueNames[i], NULL, /* reserved*/
210 &type,
211 (PBYTE)pBufPos, &cbCur);
212 /* exclude second null termination */
213 --cbCur;
214
215 if (ERROR_MORE_DATA == lRc)
216 {
217 if (REG_MULTI_SZ != type)
218 {
219 crWarning("unexpected data type! %d", type);
220 continue;
221 }
222 rc = VERR_BUFFER_OVERFLOW;
223 pBufPos = NULL;
224 cbBufRemain = 0;
225 CRASSERT(cbCur > 0 && cbCur < UINT32_MAX/2);
226 cbTotal += cbCur;
227 continue;
228 }
229 if (ERROR_SUCCESS != lRc)
230 {
231 crDebug("RegQueryValueExA failed, %d", lRc);
232 continue;
233 }
234
235 if (REG_MULTI_SZ != type)
236 {
237 crWarning("unexpected data type! %d", type);
238 continue;
239 }
240
241 /* succeeded */
242 CRASSERT(cbCur > 0 && cbCur < UINT32_MAX/2);
243 pBufPos += cbCur;
244 cbBufRemain -= cbCur;
245 cbTotal += cbCur;
246 CRASSERT(cbBufRemain < UINT32_MAX/2);
247 }
248
249 RegCloseKey(hSubkey);
250 }
251
252 RegCloseKey(hKey);
253
254 if (cbTotal)
255 {
256 /* include second null termination */
257 CRASSERT(!pBufPos || pBufPos[0] == '\0');
258 ++cbTotal;
259 }
260
261 if (pcbResult)
262 *pcbResult = cbTotal;
263
264 return rc;
265}
266
267static int renderspuAtiQuirk_ApplyForModule(LPCSTR pszAtiDll)
268{
269 int rc;
270 HMODULE hAtiDll;
271
272 crDebug("renderspuAtiQuirk_ApplyForModule (%s)", pszAtiDll);
273
274 hAtiDll = GetModuleHandleA(pszAtiDll);
275 if (!hAtiDll)
276 {
277 crDebug("GetModuleHandle failed, %d", GetLastError());
278 return VERR_NOT_FOUND;
279 }
280
281 rc = renderspuIatPatcherPatchFunction(hAtiDll, "user32.dll", "GetForegroundWindow", (void*)renderspuAtiQuirk_GetForegroundWindow);
282 if (RT_FAILURE(rc))
283 {
284 crDebug("renderspuIatPatcherPatchFunction failed, %d", rc);
285 return rc;
286 }
287
288 crDebug("renderspuAtiQuirk_ApplyForModule SUCCEEDED!");
289 crInfo("ATI Fullscreen quirk patch SUCCEEDED!");
290
291 return VINF_SUCCESS;
292}
293
294static LPCSTR renderspuRegMultiSzNextVal(LPCSTR pszBuf)
295{
296 pszBuf += strlen(pszBuf) + sizeof (pszBuf[0]);
297
298 if (pszBuf[0] == '\0')
299 return NULL;
300
301 return pszBuf;
302}
303
304static LPCSTR renderspuRegMultiSzCurVal(LPCSTR pszBuf)
305{
306 if (pszBuf[0] == '\0')
307 return NULL;
308
309 return pszBuf;
310}
311
312
313static int renderspuAtiQuirk_Apply()
314{
315 char aBuf[4096];
316 DWORD cbResult = 0;
317 LPCSTR pszVal;
318 int rc;
319
320 crDebug("renderspuAtiQuirk_Apply..");
321
322 rc = renderspuAtiQuirk_GetICDDriverList(aBuf, sizeof (aBuf), &cbResult);
323 if (RT_FAILURE(rc))
324 {
325 crDebug("renderspuAtiQuirk_GetICDDriverList failed, rc(%d)", rc);
326 return rc;
327 }
328
329 for (pszVal = renderspuRegMultiSzCurVal(aBuf);
330 pszVal;
331 pszVal = renderspuRegMultiSzNextVal(pszVal))
332 {
333 renderspuAtiQuirk_ApplyForModule(pszVal);
334 }
335
336 return VINF_SUCCESS;
337}
338
339static GLboolean renderspuAtiQuirk_Needed()
340{
341 const char * pszString = render_spu.ws.glGetString(GL_VENDOR);
342 if (pszString && strstr(pszString, "ATI"))
343 return GL_TRUE;
344 pszString = render_spu.ws.glGetString(GL_RENDERER);
345 if (pszString && strstr(pszString, "ATI"))
346 return GL_TRUE;
347 return GL_FALSE;
348}
349
350static void renderspuAtiQuirk_ChkApply()
351{
352 static GLboolean fChecked = GL_FALSE;
353 if (fChecked)
354 return;
355
356 fChecked = GL_TRUE;
357 if (!renderspuAtiQuirk_Needed())
358 return;
359
360 crInfo("This is an ATI card, taking care of fullscreen..");
361
362 /*
363 * ATI WDDM-based graphics have an issue with rendering fullscreen.
364 * See public tickets #9775 & #9267 .
365 * Namely ATI drivers check whether ogl window is foreground and fullscreen
366 * and if so - do D3DKMTSetDisplayMode for ogl surface,
367 * which prevented any other data from being displayed, no matter what.
368 *
369 * Here we check whether we're using an ATI card and if so, patch the ogl ICD driver's IAT
370 * to replace GetForegroundWindow reference with our renderspuAtiQuirk_GetForegroundWindow,
371 * which always returns NULL.
372 */
373 renderspuAtiQuirk_Apply();
374}
375
376#define WINDOW_NAME window->title
377
378static BOOL
379bSetupPixelFormat( HDC hdc, GLbitfield visAttribs );
380
381GLboolean renderspu_SystemInitVisual( VisualInfo *visual )
382{
383 if (visual->visAttribs & CR_PBUFFER_BIT) {
384 crWarning("Render SPU: PBuffers not support on Windows yet.");
385 }
386
387 /* In the windows world, we need a window before a context.
388 * Use the device_context as a marker to do just that */
389
390 return TRUE;
391}
392
393void renderspu_SystemDestroyWindow( WindowInfo *window )
394{
395 VBOX_RENDERSPU_DESTROY_WINDOW vrdw;
396
397 CRASSERT(window);
398
399 /*DestroyWindow( window->hWnd );*/
400
401 vrdw.hWnd = window->hWnd;
402
403 if (render_spu.dwWinThreadId)
404 {
405 PostThreadMessage(render_spu.dwWinThreadId, WM_VBOX_RENDERSPU_DESTROY_WINDOW, 0, (LPARAM) &vrdw);
406 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
407 }
408 else
409 {
410 crError("Render SPU: window thread is not running");
411 }
412
413 window->hWnd = NULL;
414 window->visual = NULL;
415 if (window->hRgn)
416 {
417 DeleteObject(window->hRgn);
418 window->hRgn = NULL;
419 }
420}
421
422static LONG WINAPI
423MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
424{
425 /* int w,h; */
426
427 switch ( uMsg ) {
428 case WM_PAINT:
429 {
430 WindowInfo *pWindow = (WindowInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
431 if (pWindow)
432 {
433 const struct VBOXVR_SCR_COMPOSITOR * pCompositor;
434
435 pCompositor = renderspuVBoxCompositorAcquire(pWindow);
436 if (pCompositor)
437 {
438 HDC hDC;
439 PAINTSTRUCT Paint;
440
441 Assert(pWindow->device_context);
442 hDC = BeginPaint(pWindow->hWnd, &Paint);
443 if (hDC)
444 {
445 BOOL bRc;
446 pWindow->redraw_device_context = hDC;
447
448 renderspuVBoxPresentCompositionGeneric(pWindow, pCompositor, NULL, 1, true);
449
450 bRc = EndPaint(pWindow->hWnd, &Paint);
451
452 pWindow->redraw_device_context = NULL;
453
454 renderspuVBoxCompositorRelease(pWindow);
455
456 if (!bRc)
457 {
458 DWORD winEr = GetLastError();
459 crWarning("EndPaint failed, winEr %d", winEr);
460 }
461 }
462 else
463 {
464 DWORD winEr = GetLastError();
465 crWarning("BeginPaint failed, winEr %d", winEr);
466 }
467 }
468 }
469 break;
470 }
471 case WM_SIZE:
472 /* w = LOWORD( lParam );
473 * h = HIWORD( lParam ); */
474
475 /* glViewport( 0, 0, w, h ); */
476#if 0
477 glViewport( -render_spu.mural_x, -render_spu.mural_y,
478 render_spu.mural_width, render_spu.mural_height );
479 glScissor( -render_spu.mural_x, -render_spu.mural_y,
480 render_spu.mural_width, render_spu.mural_height );
481#endif
482 break;
483
484 case WM_CLOSE:
485 crWarning( "Render SPU: caught WM_CLOSE -- quitting." );
486 exit( 0 );
487 break;
488
489 case WM_DESTROY:
490 crDebug("Render SPU: caught WM_DESTROY for our window %x", hWnd);
491 break;
492
493 case WM_NCHITTEST:
494 crDebug("WM_NCHITTEST");
495 return HTNOWHERE;
496 }
497
498 return DefWindowProc( hWnd, uMsg, wParam, lParam );
499}
500
501static BOOL
502bSetupPixelFormatEXT( HDC hdc, GLbitfield visAttribs)
503{
504 PIXELFORMATDESCRIPTOR ppfd;
505 int pixelFormat;
506 int attribList[100];
507 float fattribList[] = { 0.0, 0.0 };
508 int numFormats;
509 int i = 0;
510 BOOL vis;
511
512 CRASSERT(visAttribs & CR_RGB_BIT); /* anybody need color index */
513
514 crWarning("Render SPU: Using WGL_EXT_pixel_format to select visual ID.");
515
516 attribList[i++] = WGL_DRAW_TO_WINDOW_EXT;
517 attribList[i++] = GL_TRUE;
518 attribList[i++] = WGL_ACCELERATION_EXT;
519 attribList[i++] = WGL_FULL_ACCELERATION_EXT;
520 attribList[i++] = WGL_COLOR_BITS_EXT;
521 attribList[i++] = 24;
522 attribList[i++] = WGL_RED_BITS_EXT;
523 attribList[i++] = 1;
524 attribList[i++] = WGL_GREEN_BITS_EXT;
525 attribList[i++] = 1;
526 attribList[i++] = WGL_BLUE_BITS_EXT;
527 attribList[i++] = 1;
528
529 crWarning("Render SPU: Visual chosen is... RGB");
530
531 if (visAttribs & CR_ALPHA_BIT)
532 {
533 attribList[i++] = WGL_ALPHA_BITS_EXT;
534 attribList[i++] = 1;
535 crWarning("A");
536 }
537
538 crWarning(", ");
539
540 if (visAttribs & CR_DOUBLE_BIT) {
541 attribList[i++] = WGL_DOUBLE_BUFFER_EXT;
542 attribList[i++] = GL_TRUE;
543 crWarning("DB, ");
544 }
545
546 if (visAttribs & CR_STEREO_BIT) {
547 attribList[i++] = WGL_STEREO_EXT;
548 attribList[i++] = GL_TRUE;
549 crWarning("Stereo, ");
550 }
551
552 if (visAttribs & CR_DEPTH_BIT)
553 {
554 attribList[i++] = WGL_DEPTH_BITS_EXT;
555 attribList[i++] = 1;
556 crWarning("Z, ");
557 }
558
559 if (visAttribs & CR_STENCIL_BIT)
560 {
561 attribList[i++] = WGL_STENCIL_BITS_EXT;
562 attribList[i++] = 1;
563 crWarning("Stencil, ");
564 }
565
566 if (visAttribs & CR_ACCUM_BIT)
567 {
568 attribList[i++] = WGL_ACCUM_RED_BITS_EXT;
569 attribList[i++] = 1;
570 attribList[i++] = WGL_ACCUM_GREEN_BITS_EXT;
571 attribList[i++] = 1;
572 attribList[i++] = WGL_ACCUM_BLUE_BITS_EXT;
573 attribList[i++] = 1;
574 crWarning("Accum, ");
575 if (visAttribs & CR_ALPHA_BIT)
576 {
577 attribList[i++] = WGL_ACCUM_ALPHA_BITS_EXT;
578 attribList[i++] = 1;
579 crWarning("Accum Alpha, ");
580 }
581 }
582
583 if (visAttribs & CR_MULTISAMPLE_BIT)
584 {
585 attribList[i++] = WGL_SAMPLE_BUFFERS_EXT;
586 attribList[i++] = 1;
587 attribList[i++] = WGL_SAMPLES_EXT;
588 attribList[i++] = 4;
589 crWarning("Multisample, ");
590 }
591
592 crWarning("\n");
593
594 /* End the list */
595 attribList[i++] = 0;
596 attribList[i++] = 0;
597
598 vis = render_spu.ws.wglChoosePixelFormatEXT( hdc, attribList, fattribList, 1, &pixelFormat, &numFormats);
599
600 crDebug("Render SPU: wglChoosePixelFormatEXT (vis 0x%x, LastError 0x%x, pixelFormat 0x%x", vis, GetLastError(), pixelFormat);
601
602#ifdef VBOX_CR_SERVER_FORCE_WGL
603 render_spu.ws.wglSetPixelFormat( hdc, pixelFormat, &ppfd );
604#else
605 SetPixelFormat( hdc, pixelFormat, &ppfd );
606#endif
607
608 crDebug("Render SPU: wglSetPixelFormat (Last error 0x%x)", GetLastError());
609
610 return vis;
611}
612
613static BOOL
614bSetupPixelFormatNormal( HDC hdc, GLbitfield visAttribs )
615{
616 PIXELFORMATDESCRIPTOR pfd = {
617 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
618 1, /* version number */
619 PFD_DRAW_TO_WINDOW | /* support window */
620 PFD_SUPPORT_OPENGL, /* support OpenGL */
621 PFD_TYPE_RGBA, /* RGBA type */
622 24, /* 24-bit color depth */
623 0, 0, 0, 0, 0, 0, /* color bits ignored */
624 0, /* no alpha buffer */
625 0, /* shift bit ignored */
626 0, /* no accumulation buffer */
627 0, 0, 0, 0, /* accum bits ignored */
628 0, /* set depth buffer */
629 0, /* set stencil buffer */
630 0, /* no auxiliary buffer */
631 PFD_MAIN_PLANE, /* main layer */
632 0, /* reserved */
633 0, 0, 0 /* layer masks ignored */
634 };
635 PIXELFORMATDESCRIPTOR *ppfd = &pfd;
636 char s[1000];
637 GLbitfield b = 0;
638 int pixelformat;
639
640 renderspuMakeVisString( visAttribs, s );
641
642 crDebug( "Render SPU: WGL wants these visual capabilities: %s", s);
643
644 /* These really come into play with sort-last configs */
645 if (visAttribs & CR_DEPTH_BIT)
646 ppfd->cDepthBits = 24;
647 if (visAttribs & CR_ACCUM_BIT)
648 ppfd->cAccumBits = 16;
649 if (visAttribs & CR_RGB_BIT)
650 ppfd->cColorBits = 24;
651 if (visAttribs & CR_STENCIL_BIT)
652 ppfd->cStencilBits = 8;
653 if (visAttribs & CR_ALPHA_BIT)
654 ppfd->cAlphaBits = 8;
655 if (visAttribs & CR_DOUBLE_BIT)
656 ppfd->dwFlags |= PFD_DOUBLEBUFFER;
657 if (visAttribs & CR_STEREO_BIT)
658 ppfd->dwFlags |= PFD_STEREO;
659
660 /*
661 * We call the wgl functions directly if the SPU was loaded
662 * by our faker library, otherwise we have to call the GDI
663 * versions.
664 */
665#ifdef VBOX_CR_SERVER_FORCE_WGL
666 if (crGetenv( "CR_WGL_DO_NOT_USE_GDI" ) != NULL)
667 {
668 pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd );
669 /* doing this twice is normal Win32 magic */
670 pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd );
671 if ( pixelformat == 0 )
672 {
673 crError( "render_spu.ws.wglChoosePixelFormat failed" );
674 }
675 if ( !render_spu.ws.wglSetPixelFormat( hdc, pixelformat, ppfd ) )
676 {
677 crError( "render_spu.ws.wglSetPixelFormat failed" );
678 }
679
680 render_spu.ws.wglDescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd );
681 }
682 else
683#endif
684 {
685 /* Okay, we were loaded manually. Call the GDI functions. */
686 pixelformat = ChoosePixelFormat( hdc, ppfd );
687 /* doing this twice is normal Win32 magic */
688 pixelformat = ChoosePixelFormat( hdc, ppfd );
689 if ( pixelformat == 0 )
690 {
691 crError( "ChoosePixelFormat failed" );
692 }
693 if ( !SetPixelFormat( hdc, pixelformat, ppfd ) )
694 {
695 crError( "SetPixelFormat failed (Error 0x%x)", GetLastError() );
696 }
697
698 DescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd );
699 }
700
701
702 if (ppfd->cDepthBits > 0)
703 b |= CR_DEPTH_BIT;
704 if (ppfd->cAccumBits > 0)
705 b |= CR_ACCUM_BIT;
706 if (ppfd->cColorBits > 8)
707 b |= CR_RGB_BIT;
708 if (ppfd->cStencilBits > 0)
709 b |= CR_STENCIL_BIT;
710 if (ppfd->cAlphaBits > 0)
711 b |= CR_ALPHA_BIT;
712 if (ppfd->dwFlags & PFD_DOUBLEBUFFER)
713 b |= CR_DOUBLE_BIT;
714 if (ppfd->dwFlags & PFD_STEREO)
715 b |= CR_STEREO_BIT;
716
717 renderspuMakeVisString( b, s );
718
719 crDebug( "Render SPU: WGL chose these visual capabilities: %s", s);
720 return TRUE;
721}
722
723static BOOL
724bSetupPixelFormat( HDC hdc, GLbitfield visAttribs )
725{
726 /* According to http://www.opengl.org/resources/faq/technical/mswindows.htm
727 we shouldn't be using wgl functions to setup pixel formats unless we're loading ICD driver.
728 In particular, bSetupPixelFormatEXT bugs with Intel drivers.
729 */
730 return bSetupPixelFormatNormal(hdc, visAttribs);
731}
732
733GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
734{
735 HDESK desktop;
736 HINSTANCE hinstance;
737 WNDCLASS wc;
738 DWORD window_style;
739 int window_plus_caption_width;
740 int window_plus_caption_height;
741
742 window->hRgn = NULL;
743 window->visual = visual;
744 window->nativeWindow = 0;
745
746 if ( render_spu.use_L2 )
747 {
748 crWarning( "Going fullscreen because we think we're using Lightning-2." );
749 render_spu.fullscreen = 1;
750 }
751
752 /*
753 * Begin Windows / WGL code
754 */
755
756 hinstance = GetModuleHandle( NULL );
757 if (!hinstance)
758 {
759 crError( "Render SPU: Couldn't get a handle to my module." );
760 return GL_FALSE;
761 }
762 crDebug( "Render SPU: Got the module handle: 0x%x", hinstance );
763
764 /* If we were launched from a service, telnet, or rsh, we need to
765 * get the input desktop. */
766
767 desktop = OpenInputDesktop( 0, FALSE,
768 DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
769 DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
770 DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
771 DESKTOP_SWITCHDESKTOP | GENERIC_WRITE );
772
773 if ( !desktop )
774 {
775 crError( "Render SPU: Couldn't acquire input desktop" );
776 return GL_FALSE;
777 }
778 crDebug( "Render SPU: Got the desktop: 0x%x", desktop );
779
780 if ( !SetThreadDesktop( desktop ) )
781 {
782 /* If this function fails, it's probably because
783 * it's already been called (i.e., the render SPU
784 * is bolted to an application?) */
785
786 /*crError( "Couldn't set thread to input desktop" ); */
787 }
788 crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
789
790 if ( !GetClassInfo(hinstance, WINDOW_NAME, &wc) )
791 {
792 wc.style = CS_OWNDC;
793 wc.lpfnWndProc = (WNDPROC) MainWndProc;
794 wc.cbClsExtra = 0;
795 wc.cbWndExtra = 0;
796 wc.hInstance = hinstance;
797 wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
798 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
799 wc.hbrBackground = NULL;
800 wc.lpszMenuName = NULL;
801 wc.lpszClassName = WINDOW_NAME;
802
803 if ( !RegisterClass( &wc ) )
804 {
805 crError( "Render SPU: Couldn't register window class -- you're not trying "
806 "to do multi-pipe stuff on windows, are you?\n\nNote --"
807 "This error message is from 1997 and probably doesn't make"
808 "any sense any more, but it's nostalgic for Humper." );
809 return GL_FALSE;
810 }
811 crDebug( "Render SPU: Registered the class" );
812 }
813 crDebug( "Render SPU: Got the class information" );
814
815 /* Full screen window should be a popup (undecorated) window */
816#if 1
817 window_style = ( render_spu.fullscreen ? WS_POPUP : WS_CAPTION );
818#else
819 window_style = ( WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
820 window_style |= WS_SYSMENU;
821#endif
822
823 crDebug( "Render SPU: Fullscreen: %s", render_spu.fullscreen ? "yes" : "no");
824
825 if ( render_spu.fullscreen )
826 {
827#if 0
828
829 int smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
830 int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
831 int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
832
833 window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
834 window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
835
836 crDebug( "Render SPU: Window Dims: %d, %d", window->BltInfo.width, window->BltInfo.height );
837
838 window->x = render_spu->defaultX - smCxFixedFrame - 1;
839 window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
840
841 window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
842 window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
843
844#else
845 /* Since it's undecorated, we don't have to do anything fancy
846 * with these parameters. */
847
848 window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
849 window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
850 window->x = 0;
851 window->y = 0;
852 window_plus_caption_width = window->BltInfo.width;
853 window_plus_caption_height = window->BltInfo.height;
854
855#endif
856 }
857 else
858 {
859 /* CreateWindow takes the size of the entire window, so we add
860 * in the size necessary for the frame and the caption. */
861
862 int smCxFixedFrame, smCyFixedFrame, smCyCaption;
863 smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
864 crDebug( "Render SPU: Got the X fixed frame" );
865 smCyFixedFrame = GetSystemMetrics( SM_CYFIXEDFRAME );
866 crDebug( "Render SPU: Got the Y fixed frame" );
867 smCyCaption = GetSystemMetrics( SM_CYCAPTION );
868 crDebug( "Render SPU: Got the Caption " );
869
870 window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
871 window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
872
873 window->x = render_spu.defaultX - smCxFixedFrame;
874 window->y = render_spu.defaultY - smCyFixedFrame - smCyCaption;
875 }
876
877 crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
878 window->hWnd = CreateWindow( WINDOW_NAME, WINDOW_NAME,
879 window_style,
880 window->x, window->y,
881 window_plus_caption_width,
882 window_plus_caption_height,
883 NULL, NULL, hinstance, &render_spu );
884
885 if ( !window->hWnd )
886 {
887 crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
888 return GL_FALSE;
889 }
890
891 window->visible = showIt;
892
893 if (!showIt)
894 {
895 renderspu_SystemShowWindow( window, 0 );
896 if (window->BltInfo.height <= 0 || window->BltInfo.width <= 0)
897 {
898 renderspu_SystemWindowSize(window,
899 window->BltInfo.width > 0 ? window->BltInfo.width : 4,
900 window->BltInfo.height > 0 ? window->BltInfo.height : 4);
901 }
902 }
903 else
904 {
905 crDebug( "Render SPU: Showing the window" );
906 crDebug("renderspu_SystemCreateWindow: showwindow: %x", window->hWnd);
907 }
908
909 CRASSERT(!window->visible == !showIt);
910
911 /* Intel drivers require a window to be visible for proper 3D rendering,
912 * so set it visible and handle the visibility with visible regions (see below) */
913 ShowWindow( window->hWnd, SW_SHOWNORMAL );
914
915 SetForegroundWindow( window->hWnd );
916
917 SetWindowPos( window->hWnd, HWND_TOP, window->x, window->y,
918 window_plus_caption_width, window_plus_caption_height,
919 ( render_spu.fullscreen ? (SWP_SHOWWINDOW |
920 SWP_NOSENDCHANGING |
921 SWP_NOREDRAW |
922 SWP_NOACTIVATE ) :
923 0 ) );
924
925 if ( render_spu.fullscreen )
926 ShowCursor( FALSE );
927
928 window->device_context = GetDC( window->hWnd );
929 if (!window->device_context)
930 {
931 DWORD winEr = GetLastError();
932 crWarning("GetDC failed, winEr %d", winEr);
933 }
934
935 crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
936
937 if ( !bSetupPixelFormat( window->device_context, visual->visAttribs ) )
938 {
939 crError( "Render SPU: Couldn't set up the device context! Yikes!" );
940 return GL_FALSE;
941 }
942
943 return GL_TRUE;
944}
945
946GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
947{
948#if 0
949 HDESK desktop;
950#endif
951 HINSTANCE hinstance;
952 WNDCLASS wc;
953 DWORD window_style;
954 int window_plus_caption_width;
955 int window_plus_caption_height;
956
957 window->hRgn = NULL;
958 window->visual = visual;
959 window->nativeWindow = 0;
960
961 if ( render_spu.use_L2 )
962 {
963 crWarning( "Going fullscreen because we think we're using Lightning-2." );
964 render_spu.fullscreen = 1;
965 }
966
967 /*
968 * Begin Windows / WGL code
969 */
970
971 hinstance = GetModuleHandle( NULL );
972 if (!hinstance)
973 {
974 crError( "Render SPU: Couldn't get a handle to my module." );
975 return GL_FALSE;
976 }
977 crDebug( "Render SPU: Got the module handle: 0x%x", hinstance );
978
979#if 0
980 /* If we were launched from a service, telnet, or rsh, we need to
981 * get the input desktop. */
982
983 desktop = OpenInputDesktop( 0, FALSE,
984 DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
985 DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
986 DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
987 DESKTOP_SWITCHDESKTOP | GENERIC_WRITE );
988
989 if ( !desktop )
990 {
991 crError( "Render SPU: Couldn't acquire input desktop" );
992 return GL_FALSE;
993 }
994 crDebug( "Render SPU: Got the desktop: 0x%x", desktop );
995
996 if ( !SetThreadDesktop( desktop ) )
997 {
998 /* If this function fails, it's probably because
999 * it's already been called (i.e., the render SPU
1000 * is bolted to an application?) */
1001
1002 /*crError( "Couldn't set thread to input desktop" ); */
1003 }
1004 crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
1005#endif
1006
1007 if ( !GetClassInfo(hinstance, WINDOW_NAME, &wc) )
1008 {
1009 wc.style = CS_OWNDC; // | CS_PARENTDC;
1010 wc.lpfnWndProc = (WNDPROC) MainWndProc;
1011 wc.cbClsExtra = 0;
1012 wc.cbWndExtra = 0;
1013 wc.hInstance = hinstance;
1014 wc.hIcon = NULL; //LoadIcon( NULL, IDI_APPLICATION );
1015 wc.hCursor = NULL; //LoadCursor( NULL, IDC_ARROW );
1016 wc.hbrBackground = NULL;
1017 wc.lpszMenuName = NULL;
1018 wc.lpszClassName = WINDOW_NAME;
1019
1020 if ( !RegisterClass( &wc ) )
1021 {
1022 crError( "Render SPU: Couldn't register window class -- you're not trying "
1023 "to do multi-pipe stuff on windows, are you?\n\nNote --"
1024 "This error message is from 1997 and probably doesn't make"
1025 "any sense any more, but it's nostalgic for Humper." );
1026 return GL_FALSE;
1027 }
1028 crDebug( "Render SPU: Registered the class" );
1029 }
1030 crDebug( "Render SPU: Got the class information" );
1031
1032 /* Full screen window should be a popup (undecorated) window */
1033#if 1
1034 window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED;
1035 if (render_spu_parent_window_id)
1036 {
1037 window_style |= WS_CHILD;
1038 }
1039#else
1040 window_style = ( WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
1041 window_style |= WS_SYSMENU;
1042#endif
1043
1044 crDebug( "Render SPU: Fullscreen: %s", render_spu.fullscreen ? "yes" : "no");
1045
1046 if ( render_spu.fullscreen )
1047 {
1048#if 0
1049
1050 int smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
1051 int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
1052 int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
1053
1054 window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
1055 window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
1056
1057 crDebug( "Render SPU: Window Dims: %d, %d", window->BltInfo.width, window->BltInfo.height );
1058
1059 window->x = render_spu->defaultX - smCxFixedFrame - 1;
1060 window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
1061
1062 window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
1063 window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
1064
1065#else
1066 /* Since it's undecorated, we don't have to do anything fancy
1067 * with these parameters. */
1068
1069 window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
1070 window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
1071 window->x = 0;
1072 window->y = 0;
1073 window_plus_caption_width = window->BltInfo.width;
1074 window_plus_caption_height = window->BltInfo.height;
1075
1076#endif
1077 }
1078 else
1079 {
1080 /* CreateWindow takes the size of the entire window, so we add
1081 * in the size necessary for the frame and the caption. */
1082 int smCxFixedFrame, smCyFixedFrame, smCyCaption;
1083 smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
1084 crDebug( "Render SPU: Got the X fixed frame" );
1085 smCyFixedFrame = GetSystemMetrics( SM_CYFIXEDFRAME );
1086 crDebug( "Render SPU: Got the Y fixed frame" );
1087 smCyCaption = GetSystemMetrics( SM_CYCAPTION );
1088 crDebug( "Render SPU: Got the Caption " );
1089
1090 window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
1091 window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
1092
1093 window->x = render_spu.defaultX;
1094 window->y = render_spu.defaultY;
1095 }
1096
1097 crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
1098 /*window->hWnd = CreateWindowEx( WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
1099 WINDOW_NAME, WINDOW_NAME,
1100 window_style,
1101 window->x, window->y,
1102 window->BltInfo.width,
1103 window->BltInfo.height,
1104 (void*) render_spu_parent_window_id, NULL, hinstance, &render_spu );*/
1105 {
1106 CREATESTRUCT cs;
1107
1108 cs.lpCreateParams = window;
1109
1110 cs.dwExStyle = WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY;
1111 cs.lpszName = WINDOW_NAME;
1112 cs.lpszClass = WINDOW_NAME;
1113 cs.style = window_style;
1114 cs.x = window->x;
1115 cs.y = window->y;
1116 cs.cx = window->BltInfo.width;
1117 cs.cy = window->BltInfo.height;
1118 cs.hwndParent = (void*) render_spu_parent_window_id;
1119 cs.hMenu = NULL;
1120 cs.hInstance = hinstance;
1121
1122 if (render_spu.dwWinThreadId)
1123 {
1124 DWORD res;
1125 int cnt=0;
1126
1127 if (!PostThreadMessage(render_spu.dwWinThreadId, WM_VBOX_RENDERSPU_CREATE_WINDOW, 0, (LPARAM) &cs))
1128 {
1129 crError("Render SPU: PostThreadMessage failed with %i", GetLastError());
1130 return GL_FALSE;
1131 }
1132
1133 do
1134 {
1135 res = WaitForSingleObject(render_spu.hWinThreadReadyEvent, 1000);
1136 cnt++;
1137 }
1138 while ((res!=WAIT_OBJECT_0) && (cnt<10));
1139
1140 crDebug("Render SPU: window thread waited %i secs", cnt);
1141
1142 if (res!=WAIT_OBJECT_0)
1143 {
1144 crError("Render SPU: window thread not responded after %i tries", cnt);
1145 return GL_FALSE;
1146 }
1147 }
1148 else
1149 {
1150 crError("Render SPU: window thread is not running");
1151 return GL_FALSE;
1152 }
1153 }
1154
1155 if ( !window->hWnd )
1156 {
1157 crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
1158 return GL_FALSE;
1159 }
1160
1161 window->visible = 1;
1162
1163 if (!showIt)
1164 {
1165 renderspu_SystemShowWindow( window, 0 );
1166 if (window->BltInfo.height <= 0 || window->BltInfo.width <= 0)
1167 {
1168 renderspu_SystemWindowSize(window,
1169 window->BltInfo.width > 0 ? window->BltInfo.width : 4,
1170 window->BltInfo.height > 0 ? window->BltInfo.height : 4);
1171 }
1172 }
1173 else
1174 {
1175#ifdef DEBUG_misha
1176 crWarning( "Render SPU: Showing the window" );
1177#else
1178 crDebug( "Render SPU: Showing the window" );
1179#endif
1180 crDebug("renderspu_SystemCreateWindow: showwindow: %x", window->hWnd);
1181 }
1182
1183 CRASSERT(!window->visible == !showIt);
1184
1185 /* Intel drivers require a window to be visible for proper 3D rendering,
1186 * so set it visible and handle the visibility with visible regions (see below) */
1187 if (window->BltInfo.Base.id != CR_RENDER_DEFAULT_WINDOW_ID)
1188 {
1189 ShowWindow( window->hWnd, SW_SHOWNORMAL );
1190 }
1191 else
1192 {
1193 CRASSERT(!showIt);
1194 /* dummy window is always hidden in any way */
1195 }
1196
1197 //SetForegroundWindow( visual->hWnd );
1198
1199 SetWindowPos( window->hWnd, HWND_TOP, window->x, window->y,
1200 window->BltInfo.width, window->BltInfo.height,
1201 ( render_spu.fullscreen ?
1202 (SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOACTIVATE ) : SWP_NOACTIVATE
1203 ) );
1204 crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
1205 window->x, window->y, window->BltInfo.width, window->BltInfo.height);
1206
1207 if ( render_spu.fullscreen )
1208 ShowCursor( FALSE );
1209
1210 window->device_context = GetDC( window->hWnd );
1211 if (!window->device_context)
1212 {
1213 DWORD winEr = GetLastError();
1214 crWarning("GetDC failed, winEr %d", winEr);
1215 }
1216
1217 crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
1218
1219 if ( !bSetupPixelFormat( window->device_context, visual->visAttribs ) )
1220 {
1221 crError( "Render SPU: Couldn't set up the device context! Yikes!" );
1222 return GL_FALSE;
1223 }
1224
1225 /* set the window pointer data at the last step to ensure our WM_PAINT callback does not do anything until we are fully initialized */
1226#ifdef RT_STRICT
1227 SetLastError(NO_ERROR);
1228#endif
1229 {
1230 LONG_PTR oldVal = SetWindowLongPtr(window->hWnd, GWLP_USERDATA, (LONG_PTR)window);
1231 Assert(!oldVal && GetLastError() == NO_ERROR); RT_NOREF_PV(oldVal);
1232 }
1233
1234 return GL_TRUE;
1235}
1236
1237static void renderspuWindowRgnApply(WindowInfo *window)
1238{
1239 HRGN hRgn = window->hRgn;
1240 if (hRgn)
1241 {
1242 /* note: according to the docs, SetWindowRgn owns the regions after it is called,
1243 * and the regions will be freed automatically when needed,
1244 * i.e. the caller should not do that.
1245 * this is why we need to make a copy of the regions to be passed in */
1246
1247 int result;
1248 hRgn = CreateRectRgn(0, 0, 0, 0);
1249 if (!hRgn)
1250 {
1251 WARN(("CreateRectRgn failed"));
1252 return;
1253 }
1254
1255 result = CombineRgn(hRgn, window->hRgn, NULL, RGN_COPY);
1256 if (result == ERROR)
1257 {
1258 WARN(("CombineRgn failed"));
1259 return;
1260 }
1261 }
1262
1263 SetWindowRgn(window->hWnd, hRgn, true);
1264}
1265
1266/* Either show or hide the render SPU's window. */
1267void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
1268{
1269 if (showIt)
1270 {
1271 crDebug("SHOW renderspu_SystemShowWindow: %x", window->hWnd);
1272 renderspuWindowRgnApply(window);
1273 }
1274 else
1275 {
1276 HRGN hRgn;
1277 crDebug("HIDE renderspu_SystemShowWindow: %x", window->hWnd);
1278 hRgn = CreateRectRgn(0, 0, 0, 0);
1279 SetWindowRgn(window->hWnd, hRgn, true);
1280 /* note: according to the docs, SetWindowRgn owns the regions after it is called,
1281 * and the regions will be freed automatically when needed,
1282 * i.e. the caller should not do that */
1283 }
1284 window->visible = showIt;
1285}
1286
1287void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
1288{
1289 /* The !render_spu.force_present_main_thread code flow is actually inspired
1290 * by cocoa backend impl, here it forces rendering in WndProc, i.e. main
1291 * thread. It defaults to 0, because it is for debugging and working around
1292 * bugs. In principle would need root cause investigation. */
1293 if (!render_spu.force_present_main_thread)
1294 {
1295 const struct VBOXVR_SCR_COMPOSITOR *pCompositor;
1296 /* we do not want to be blocked with the GUI thread here, so only draw here if we are really able to do that w/o blocking */
1297 int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
1298 if (RT_SUCCESS(rc))
1299 {
1300 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0, false);
1301 renderspuVBoxCompositorRelease(window);
1302 }
1303 else if (rc != VERR_SEM_BUSY)
1304 {
1305 /* this is somewhat we do not expect */
1306 crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
1307 }
1308 }
1309
1310 {
1311 render_spu.self.Flush();
1312 renderspuVBoxPresentBlitterEnsureCreated(window, 0);
1313 RedrawWindow(window->hWnd, NULL, NULL, RDW_INTERNALPAINT);
1314 }
1315}
1316
1317GLboolean renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
1318{
1319 (void) sharedContext;
1320 context->visual = visual;
1321
1322 /* Found a visual, so we're o.k. to create the context now */
1323 if (0/*visual->device_context*/) {
1324
1325 //crDebug( "Render SPU: Using the DC: 0x%x", visual->device_context );
1326
1327 //context->hRC = render_spu.ws.wglCreateContext( visual->device_context );
1328 if (!context->hRC)
1329 {
1330 crError( "Render SPU: wglCreateContext failed (error 0x%x)", GetLastError() );
1331 return GL_FALSE;
1332 }
1333 } else {
1334 crDebug( "Render SPU: Delaying DC creation " );
1335 context->hRC = NULL; /* create it later in makecurrent */
1336 }
1337
1338
1339 return GL_TRUE;
1340}
1341
1342void renderspu_SystemDestroyContext( ContextInfo *context )
1343{
1344 render_spu.ws.wglDeleteContext( context->hRC );
1345 context->hRC = NULL;
1346}
1347
1348static GLboolean renderspuChkActivateSharedContext(ContextInfo *sharedContext)
1349{
1350 WindowInfo *window;
1351
1352 if (sharedContext->hRC)
1353 return GL_TRUE;
1354
1355 CRASSERT(sharedContext->BltInfo.Base.id);
1356
1357 if (sharedContext->shared)
1358 renderspuChkActivateSharedContext(sharedContext->shared);
1359
1360 window = renderspuGetDummyWindow(sharedContext->visual->visAttribs);
1361 if (!window)
1362 {
1363 crError("renderspuChkActivateSharedContext: renderspuGetDummyWindow failed!");
1364 return GL_FALSE;
1365 }
1366
1367 CRASSERT(window->device_context);
1368
1369 crDebug( "Render SPU: renderspuChkActivateSharedContext: made the DC: 0x%x", window->device_context );
1370
1371 sharedContext->hRC = render_spu.ws.wglCreateContext(window->device_context);
1372 if (!sharedContext->hRC)
1373 {
1374 crError( "Render SPU: (renderspuChkActivateSharedContext) Couldn't create the context for the window (error 0x%x)", GetLastError() );
1375 return GL_FALSE;
1376 }
1377
1378 return GL_TRUE;
1379}
1380
1381void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, ContextInfo *context )
1382{
1383 CRASSERT(render_spu.ws.wglMakeCurrent);
1384
1385 if (context && window) {
1386 if (window->visual != context->visual) {
1387 /*
1388 * XXX have to revisit this issue!!!
1389 *
1390 * But for now we destroy the current window
1391 * and re-create it with the context's visual abilities
1392 */
1393
1394 /** @todo Chromium has no correct code to remove window ids and associated info from
1395 * various tables. This is hack which just hides the root case.
1396 */
1397 crWarning("Recreating window in renderspu_SystemMakeCurrent\n");
1398 renderspu_SystemDestroyWindow( window );
1399 renderspu_SystemVBoxCreateWindow( context->visual, window->visible, window );
1400 }
1401
1402 if (0/*render_spu.render_to_app_window && nativeWindow*/)
1403 {
1404 /* The render_to_app_window option
1405 * is set and we've got a nativeWindow
1406 * handle, save the handle for
1407 * later calls to swapbuffers().
1408 *
1409 * NOTE: This doesn't work, except
1410 * for software driven Mesa.
1411 * We'd need to object link the
1412 * crappfaker and crserver to be able to share
1413 * the HDC values between processes.. FIXME!
1414 */
1415 if (context->shared)
1416 {
1417 /* first make sure we have shared context created */
1418 renderspuChkActivateSharedContext(context->shared);
1419 }
1420
1421 window->nativeWindow = (HDC) nativeWindow;
1422 if (context->hRC == 0) {
1423 context->hRC = render_spu.ws.wglCreateContext( window->nativeWindow );
1424 if (!context->hRC)
1425 {
1426 crError( "(MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
1427 }
1428 }
1429
1430 if (context->shared
1431 && context->shared->hRC
1432 && context->hRC)
1433 {
1434 /* share lists */
1435 render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
1436 }
1437
1438 render_spu.ws.wglMakeCurrent( window->nativeWindow, context->hRC );
1439 }
1440 else
1441 {
1442 if (!context->hRC) {
1443 CRASSERT(!nativeWindow);
1444 if (context->shared)
1445 {
1446 /* first make sure we have shared context created */
1447 renderspuChkActivateSharedContext(context->shared);
1448 }
1449
1450 context->hRC = render_spu.ws.wglCreateContext(window->device_context);
1451 if (!context->hRC)
1452 {
1453 crError( "Render SPU: (MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
1454 }
1455
1456 if (context->shared
1457 && context->shared->hRC
1458 && context->hRC)
1459 {
1460 /* share lists */
1461 BOOL bRc = render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
1462 if (!bRc)
1463 {
1464 DWORD winEr = GetLastError();
1465 crWarning("wglShareLists failed, winEr %d", winEr);
1466 }
1467 }
1468
1469 /*Requery ext function pointers, we skip dummy ctx as it should never be used with ext functions*/
1470 if (0 && context->BltInfo.Base.id)
1471 {
1472 int numFuncs, i;
1473 SPUNamedFunctionTable ext_table[1000];
1474
1475
1476 crDebug("Default server ctx created, requerying ext functions");
1477 /*requery ext functions*/
1478 numFuncs = renderspuCreateFunctions(ext_table);
1479 numFuncs += crLoadOpenGLExtensions( &render_spu.ws, ext_table+numFuncs);
1480 CRASSERT(numFuncs < 1000);
1481
1482 /*change spu dispatch*/
1483 crSPUChangeDispatch(&render_spu.self, ext_table);
1484
1485
1486 /*cleanup temp table*/
1487 for (i=0; i<numFuncs; ++i)
1488 {
1489 if (ext_table[i].name) crFree(ext_table[i].name);
1490 }
1491 }
1492 }
1493
1494 /*crDebug("MakeCurrent 0x%x, 0x%x", window->device_context, context->hRC);*/
1495 if (!render_spu.ws.wglMakeCurrent(!nativeWindow ? window->device_context : window->redraw_device_context, context->hRC))
1496 {
1497 DWORD err = GetLastError();
1498 crError("Render SPU: (MakeCurrent) failed to make 0x%x, 0x%x current with 0x%x error.", window->device_context, context->hRC, err);
1499 }
1500 }
1501
1502 renderspuAtiQuirk_ChkApply();
1503 }
1504 else {
1505 render_spu.ws.wglMakeCurrent( 0, 0 );
1506 }
1507}
1508
1509void renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
1510{
1511 int winprop;
1512 CRASSERT(window);
1513 CRASSERT(window->visual);
1514 if ( render_spu.fullscreen )
1515 winprop = SWP_SHOWWINDOW | SWP_NOSENDCHANGING |
1516 SWP_NOREDRAW | SWP_NOACTIVATE;
1517 else
1518 winprop = SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_NOZORDER; //SWP_SHOWWINDOW;
1519
1520 /*SetWindowRgn(window->hWnd, NULL, false);*/
1521
1522 if (!SetWindowPos( window->hWnd, HWND_TOP,
1523 window->x, window->y, w, h, winprop )) {
1524 crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
1525 } else {
1526 crDebug("Render SPU: SetWindowSize (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
1527 }
1528 /* save the new size */
1529 window->BltInfo.width = w;
1530 window->BltInfo.height = h;
1531}
1532
1533
1534void renderspu_SystemGetWindowGeometry( WindowInfo *window, GLint *x, GLint *y, GLint *w, GLint *h )
1535{
1536 RECT rect;
1537
1538 CRASSERT(window);
1539 CRASSERT(window->visual);
1540
1541 GetClientRect( window->hWnd, &rect );
1542 *x = rect.left;
1543 *y = rect.top;
1544 *w = rect.right - rect.left;
1545 *h = rect.bottom - rect.top;
1546}
1547
1548
1549void renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h )
1550{
1551 /* XXX fix this */
1552 (void) window;
1553 *w = 1600;
1554 *h = 1200;
1555}
1556
1557
1558void renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
1559{
1560 int winprop;
1561 CRASSERT(window);
1562 CRASSERT(window->visual);
1563 if ( render_spu.fullscreen )
1564 winprop = SWP_SHOWWINDOW | SWP_NOSENDCHANGING |
1565 SWP_NOREDRAW | SWP_NOACTIVATE;
1566 else
1567 winprop = SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_NOZORDER; //SWP_SHOWWINDOW;
1568
1569 /*SetWindowRgn(window->visual->hWnd, NULL, false);*/
1570
1571 if (!SetWindowPos( window->hWnd, HWND_TOP,
1572 x, y, window->BltInfo.width, window->BltInfo.height, winprop )) {
1573 crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, x, y, window->BltInfo.width, window->BltInfo.height);
1574 } else {
1575 crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
1576 x, y, window->BltInfo.width, window->BltInfo.height);
1577 }
1578 /* save the new position */
1579 window->x = x;
1580 window->y = y;
1581}
1582
1583GLboolean renderspu_SystemWindowNeedEmptyPresent(WindowInfo *window)
1584{
1585 return GL_FALSE;
1586}
1587
1588void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects)
1589{
1590 GLint i;
1591 HRGN hRgn, hTmpRgn;
1592 RECT rectRgnBound;
1593
1594 CRASSERT(window);
1595 CRASSERT(window->visual);
1596
1597 if (window->hRgn)
1598 {
1599 DeleteObject(window->hRgn);
1600 window->hRgn = NULL;
1601 }
1602
1603 hRgn = CreateRectRgn(0, 0, 0, 0);
1604
1605 for (i = 0; i < cRects; i++)
1606 {
1607 crDebug("Render SPU: CreateRectRgn #%d: (%d, %d)-(%d, %d)", i,
1608 pRects[4 * i], pRects[4 * i + 1], pRects[4 * i + 2], pRects[4 * i + 3]);
1609
1610 hTmpRgn = CreateRectRgn(pRects[4 * i], pRects[4 * i + 1], pRects[4 * i + 2], pRects[4 * i + 3]);
1611 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
1612 DeleteObject(hTmpRgn);
1613 }
1614
1615 if (GetRgnBox(hRgn, &rectRgnBound))
1616 {
1617 crDebug("Render SPU: Rgn bounding box (%d, %d)-(%d, %d)",
1618 rectRgnBound.left, rectRgnBound.top, rectRgnBound.right, rectRgnBound.bottom);
1619 }
1620
1621 window->hRgn = hRgn;
1622
1623 if (window->visible)
1624 renderspuWindowRgnApply(window);
1625
1626 crDebug("Render SPU: SetWindowRgn (%x, cRects=%i)", window->hWnd, cRects);
1627}
1628
1629static void renderspuHandleWindowMessages( HWND hWnd )
1630{
1631 MSG msg;
1632 while ( PeekMessage( &msg, hWnd, 0, 0xffffffff, PM_REMOVE ) )
1633 {
1634 TranslateMessage( &msg );
1635 DispatchMessage( &msg );
1636 }
1637
1638 //BringWindowToTop( hWnd );
1639}
1640
1641void renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
1642{
1643 int return_value;
1644
1645 /* peek at the windows message queue */
1646// renderspuHandleWindowMessages( w->hWnd );
1647
1648 /* render_to_app_window:
1649 * w->nativeWindow will only be non-zero if the
1650 * render_spu.render_to_app_window option is true and
1651 * MakeCurrent() recorded the nativeWindow handle in the WindowInfo
1652 * structure.
1653 */
1654 if (render_spu.render_to_app_window && w->nativeWindow) {
1655#ifdef VBOX_CR_SERVER_FORCE_WGL
1656 return_value = render_spu.ws.wglSwapBuffers( w->nativeWindow );
1657#else
1658 return_value = SwapBuffers( w->nativeWindow );
1659#endif
1660 } else {
1661 /*
1662 HRGN hRgn1, hRgn2, hRgn3;
1663 HWND hWndParent;
1664 LONG ws;
1665
1666 hRgn1 = CreateRectRgn(0, 0, w->BltInfo.width, w->BltInfo.height);
1667 hRgn2 = CreateRectRgn(50, 50, 100, 100);
1668 hRgn3 = CreateRectRgn(0, 0, 0, 0);
1669 CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
1670 SetWindowRgn(w->visual->hWnd, hRgn3, true);
1671 DeleteObject(hRgn1);
1672 DeleteObject(hRgn2);
1673
1674 hWndParent = GetParent(w->visual->hWnd);
1675 ws = GetWindowLong(hWndParent, GWL_STYLE);
1676 ws &= ~WS_CLIPCHILDREN;
1677 SetWindowLong(hWndParent, GWL_STYLE, ws);
1678
1679 RECT rcClip;
1680
1681 rcClip.left = 50;
1682 rcClip.top = 50;
1683 rcClip.right = 100;
1684 rcClip.bottom = 100;
1685 ValidateRect(w->visual->hWnd, &rcClip);
1686
1687 return_value = GetClipBox(w->visual->device_context, &rcClip);
1688 crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1689 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1690
1691 crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
1692
1693 return_value = ExcludeClipRect(w->visual->device_context, 50, 50, 100, 100);
1694 crDebug("ExcludeClipRect returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1695 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1696
1697 return_value = GetClipBox(w->visual->device_context, &rcClip);
1698 crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1699 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1700 crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
1701 */
1702#ifdef VBOX_CR_SERVER_FORCE_WGL
1703 return_value = render_spu.ws.wglSwapBuffers( w->device_context );
1704#else
1705 return_value = SwapBuffers( w->device_context );
1706#endif
1707 }
1708 if (!return_value)
1709 {
1710 /* GOD DAMN IT. The latest versions of the NVIDIA drivers
1711 * return failure from wglSwapBuffers, but it works just fine.
1712 * WHAT THE HELL?! */
1713
1714 crWarning( "wglSwapBuffers failed: return value of %d!", return_value);
1715 }
1716}
1717
1718void renderspu_SystemReparentWindow(WindowInfo *window)
1719{
1720 SetParent(window->hWnd, (HWND)render_spu_parent_window_id);
1721}
1722
1723int renderspu_SystemInit()
1724{
1725 return VINF_SUCCESS;
1726}
1727
1728int renderspu_SystemTerm()
1729{
1730 return VINF_SUCCESS;
1731}
1732
1733void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
1734{
1735
1736}
1737
1738uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
1739{
1740 return cFunctions;
1741}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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