VirtualBox

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

Last change on this file since 39736 was 39736, checked in by vboxsync, 13 years ago

coOpenGL: followup to fix XP hosts, bugs #10071 and #10088

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 44.4 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
8#define WIN32_LEAN_AND_MEAN
9#include <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 crWarning("RegGetValueA 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 qwirk 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 Assert(0);
323 rc = renderspuAtiQuirk_GetICDDriverList(aBuf, sizeof (aBuf), &cbResult);
324 if (RT_FAILURE(rc))
325 {
326 crDebug("renderspuAtiQuirk_GetICDDriverList failed, rc(%d)", rc);
327 return rc;
328 }
329
330 for (pszVal = renderspuRegMultiSzCurVal(aBuf);
331 pszVal;
332 pszVal = renderspuRegMultiSzNextVal(pszVal))
333 {
334 renderspuAtiQuirk_ApplyForModule(pszVal);
335 }
336
337 return VINF_SUCCESS;
338}
339
340static GLboolean renderspuAtiQuirk_Needed()
341{
342 const char * pszString = render_spu.ws.glGetString(GL_VENDOR);
343 if (pszString && strstr(pszString, "ATI"))
344 return GL_TRUE;
345 pszString = render_spu.ws.glGetString(GL_RENDERER);
346 if (pszString && strstr(pszString, "ATI"))
347 return GL_TRUE;
348 return GL_FALSE;
349}
350
351static void renderspuAtiQuirk_ChkApply()
352{
353 static GLboolean fChecked = GL_FALSE;
354 if (fChecked)
355 return;
356
357 fChecked = GL_TRUE;
358 if (!renderspuAtiQuirk_Needed())
359 return;
360
361 crInfo("This is an ATI card, taking care of fullscreen..");
362
363 /*
364 * ATI WDDM-based graphics have an issue with rendering fullscreen.
365 * See public tickets #9775 & #9267 .
366 * Namely ATI drivers check whether ogl window is foreground and fullscreen
367 * and if so - do D3DKMTSetDisplayMode for ogl surface,
368 * which prevented any other data from being displayed, no matter what.
369 *
370 * Here we check whether we're using an ATI card and if so, patch the ogl ICD driver's IAT
371 * to replace GetForegroundWindow reference with our renderspuAtiQuirk_GetForegroundWindow,
372 * which always returns NULL.
373 */
374 renderspuAtiQuirk_Apply();
375}
376
377#define WINDOW_NAME window->title
378
379static BOOL
380bSetupPixelFormat( HDC hdc, GLbitfield visAttribs );
381
382GLboolean renderspu_SystemInitVisual( VisualInfo *visual )
383{
384 if (visual->visAttribs & CR_PBUFFER_BIT) {
385 crWarning("Render SPU: PBuffers not support on Windows yet.");
386 }
387
388 /* In the windows world, we need a window before a context.
389 * Use the device_context as a marker to do just that */
390 visual->device_context = 0;
391
392 return TRUE;
393}
394
395void renderspu_SystemDestroyWindow( WindowInfo *window )
396{
397 VBOX_RENDERSPU_DESTROY_WINDOW vrdw;
398
399 CRASSERT(window);
400
401 /*DestroyWindow( window->hWnd );*/
402
403 vrdw.hWnd = window->hWnd;
404
405 if (render_spu.dwWinThreadId)
406 {
407 PostThreadMessage(render_spu.dwWinThreadId, WM_VBOX_RENDERSPU_DESTROY_WINDOW, 0, (LPARAM) &vrdw);
408 WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);
409 }
410 else
411 {
412 crError("Render SPU: window thread is not running");
413 }
414
415 window->hWnd = NULL;
416 window->visual = NULL;
417}
418
419static LONG WINAPI
420MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
421{
422 /* int w,h; */
423
424 switch ( uMsg ) {
425
426 case WM_SIZE:
427 /* w = LOWORD( lParam );
428 * h = HIWORD( lParam ); */
429
430 /* glViewport( 0, 0, w, h ); */
431#if 0
432 glViewport( -render_spu.mural_x, -render_spu.mural_y,
433 render_spu.mural_width, render_spu.mural_height );
434 glScissor( -render_spu.mural_x, -render_spu.mural_y,
435 render_spu.mural_width, render_spu.mural_height );
436#endif
437 break;
438
439 case WM_CLOSE:
440 crWarning( "Render SPU: caught WM_CLOSE -- quitting." );
441 exit( 0 );
442 break;
443
444 case WM_DESTROY:
445 crDebug("Render SPU: caught WM_DESTROY for our window %x", hWnd);
446 break;
447
448 case WM_NCHITTEST:
449 crDebug("WM_NCHITTEST");
450 return HTNOWHERE;
451 }
452
453 return DefWindowProc( hWnd, uMsg, wParam, lParam );
454}
455
456static BOOL
457bSetupPixelFormatEXT( HDC hdc, GLbitfield visAttribs)
458{
459 PIXELFORMATDESCRIPTOR ppfd;
460 int pixelFormat;
461 int attribList[100];
462 float fattribList[] = { 0.0, 0.0 };
463 int numFormats;
464 int i = 0;
465 BOOL vis;
466
467 CRASSERT(visAttribs & CR_RGB_BIT); /* anybody need color index */
468
469 crWarning("Render SPU: Using WGL_EXT_pixel_format to select visual ID.");
470
471 attribList[i++] = WGL_DRAW_TO_WINDOW_EXT;
472 attribList[i++] = GL_TRUE;
473 attribList[i++] = WGL_ACCELERATION_EXT;
474 attribList[i++] = WGL_FULL_ACCELERATION_EXT;
475 attribList[i++] = WGL_COLOR_BITS_EXT;
476 attribList[i++] = 24;
477 attribList[i++] = WGL_RED_BITS_EXT;
478 attribList[i++] = 1;
479 attribList[i++] = WGL_GREEN_BITS_EXT;
480 attribList[i++] = 1;
481 attribList[i++] = WGL_BLUE_BITS_EXT;
482 attribList[i++] = 1;
483
484 crWarning("Render SPU: Visual chosen is... RGB");
485
486 if (visAttribs & CR_ALPHA_BIT)
487 {
488 attribList[i++] = WGL_ALPHA_BITS_EXT;
489 attribList[i++] = 1;
490 crWarning("A");
491 }
492
493 crWarning(", ");
494
495 if (visAttribs & CR_DOUBLE_BIT) {
496 attribList[i++] = WGL_DOUBLE_BUFFER_EXT;
497 attribList[i++] = GL_TRUE;
498 crWarning("DB, ");
499 }
500
501 if (visAttribs & CR_STEREO_BIT) {
502 attribList[i++] = WGL_STEREO_EXT;
503 attribList[i++] = GL_TRUE;
504 crWarning("Stereo, ");
505 }
506
507 if (visAttribs & CR_DEPTH_BIT)
508 {
509 attribList[i++] = WGL_DEPTH_BITS_EXT;
510 attribList[i++] = 1;
511 crWarning("Z, ");
512 }
513
514 if (visAttribs & CR_STENCIL_BIT)
515 {
516 attribList[i++] = WGL_STENCIL_BITS_EXT;
517 attribList[i++] = 1;
518 crWarning("Stencil, ");
519 }
520
521 if (visAttribs & CR_ACCUM_BIT)
522 {
523 attribList[i++] = WGL_ACCUM_RED_BITS_EXT;
524 attribList[i++] = 1;
525 attribList[i++] = WGL_ACCUM_GREEN_BITS_EXT;
526 attribList[i++] = 1;
527 attribList[i++] = WGL_ACCUM_BLUE_BITS_EXT;
528 attribList[i++] = 1;
529 crWarning("Accum, ");
530 if (visAttribs & CR_ALPHA_BIT)
531 {
532 attribList[i++] = WGL_ACCUM_ALPHA_BITS_EXT;
533 attribList[i++] = 1;
534 crWarning("Accum Alpha, ");
535 }
536 }
537
538 if (visAttribs & CR_MULTISAMPLE_BIT)
539 {
540 attribList[i++] = WGL_SAMPLE_BUFFERS_EXT;
541 attribList[i++] = 1;
542 attribList[i++] = WGL_SAMPLES_EXT;
543 attribList[i++] = 4;
544 crWarning("Multisample, ");
545 }
546
547 crWarning("\n");
548
549 /* End the list */
550 attribList[i++] = 0;
551 attribList[i++] = 0;
552
553 vis = render_spu.ws.wglChoosePixelFormatEXT( hdc, attribList, fattribList, 1, &pixelFormat, &numFormats);
554
555 crDebug("Render SPU: wglChoosePixelFormatEXT (vis 0x%x, LastError 0x%x, pixelFormat 0x%x", vis, GetLastError(), pixelFormat);
556
557 render_spu.ws.wglSetPixelFormat( hdc, pixelFormat, &ppfd );
558
559 crDebug("Render SPU: wglSetPixelFormat (Last error 0x%x)", GetLastError());
560
561 return vis;
562}
563
564static BOOL
565bSetupPixelFormatNormal( HDC hdc, GLbitfield visAttribs )
566{
567 PIXELFORMATDESCRIPTOR pfd = {
568 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
569 1, /* version number */
570 PFD_DRAW_TO_WINDOW | /* support window */
571 PFD_SUPPORT_OPENGL, /* support OpenGL */
572 PFD_TYPE_RGBA, /* RGBA type */
573 24, /* 24-bit color depth */
574 0, 0, 0, 0, 0, 0, /* color bits ignored */
575 0, /* no alpha buffer */
576 0, /* shift bit ignored */
577 0, /* no accumulation buffer */
578 0, 0, 0, 0, /* accum bits ignored */
579 0, /* set depth buffer */
580 0, /* set stencil buffer */
581 0, /* no auxiliary buffer */
582 PFD_MAIN_PLANE, /* main layer */
583 0, /* reserved */
584 0, 0, 0 /* layer masks ignored */
585 };
586 PIXELFORMATDESCRIPTOR *ppfd = &pfd;
587 char s[1000];
588 GLbitfield b = 0;
589 int pixelformat;
590
591 renderspuMakeVisString( visAttribs, s );
592
593 crDebug( "Render SPU: WGL wants these visual capabilities: %s", s);
594
595 /* These really come into play with sort-last configs */
596 if (visAttribs & CR_DEPTH_BIT)
597 ppfd->cDepthBits = 24;
598 if (visAttribs & CR_ACCUM_BIT)
599 ppfd->cAccumBits = 16;
600 if (visAttribs & CR_RGB_BIT)
601 ppfd->cColorBits = 24;
602 if (visAttribs & CR_STENCIL_BIT)
603 ppfd->cStencilBits = 8;
604 if (visAttribs & CR_ALPHA_BIT)
605 ppfd->cAlphaBits = 8;
606 if (visAttribs & CR_DOUBLE_BIT)
607 ppfd->dwFlags |= PFD_DOUBLEBUFFER;
608 if (visAttribs & CR_STEREO_BIT)
609 ppfd->dwFlags |= PFD_STEREO;
610
611 /*
612 * We call the wgl functions directly if the SPU was loaded
613 * by our faker library, otherwise we have to call the GDI
614 * versions.
615 */
616 if (crGetenv( "CR_WGL_DO_NOT_USE_GDI" ) != NULL)
617 {
618 pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd );
619 /* doing this twice is normal Win32 magic */
620 pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd );
621 if ( pixelformat == 0 )
622 {
623 crError( "render_spu.ws.wglChoosePixelFormat failed" );
624 }
625 if ( !render_spu.ws.wglSetPixelFormat( hdc, pixelformat, ppfd ) )
626 {
627 crError( "render_spu.ws.wglSetPixelFormat failed" );
628 }
629
630 render_spu.ws.wglDescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd );
631 }
632 else
633 {
634 /* Okay, we were loaded manually. Call the GDI functions. */
635 pixelformat = ChoosePixelFormat( hdc, ppfd );
636 /* doing this twice is normal Win32 magic */
637 pixelformat = ChoosePixelFormat( hdc, ppfd );
638 if ( pixelformat == 0 )
639 {
640 crError( "ChoosePixelFormat failed" );
641 }
642 if ( !SetPixelFormat( hdc, pixelformat, ppfd ) )
643 {
644 crError( "SetPixelFormat failed (Error 0x%x)", GetLastError() );
645 }
646
647 DescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd );
648 }
649
650
651 if (ppfd->cDepthBits > 0)
652 b |= CR_DEPTH_BIT;
653 if (ppfd->cAccumBits > 0)
654 b |= CR_ACCUM_BIT;
655 if (ppfd->cColorBits > 8)
656 b |= CR_RGB_BIT;
657 if (ppfd->cStencilBits > 0)
658 b |= CR_STENCIL_BIT;
659 if (ppfd->cAlphaBits > 0)
660 b |= CR_ALPHA_BIT;
661 if (ppfd->dwFlags & PFD_DOUBLEBUFFER)
662 b |= CR_DOUBLE_BIT;
663 if (ppfd->dwFlags & PFD_STEREO)
664 b |= CR_STEREO_BIT;
665
666 renderspuMakeVisString( b, s );
667
668 crDebug( "Render SPU: WGL chose these visual capabilities: %s", s);
669 return TRUE;
670}
671
672static BOOL
673bSetupPixelFormat( HDC hdc, GLbitfield visAttribs )
674{
675 /* According to http://www.opengl.org/resources/faq/technical/mswindows.htm
676 we shouldn't be using wgl functions to setup pixel formats unless we're loading ICD driver.
677 In particular, bSetupPixelFormatEXT bugs with Intel drivers.
678 */
679 return bSetupPixelFormatNormal(hdc, visAttribs);
680}
681
682GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
683{
684 HDESK desktop;
685 HINSTANCE hinstance;
686 WNDCLASS wc;
687 DWORD window_style;
688 int window_plus_caption_width;
689 int window_plus_caption_height;
690
691 window->visual = visual;
692 window->nativeWindow = 0;
693
694 if ( render_spu.use_L2 )
695 {
696 crWarning( "Going fullscreen because we think we're using Lightning-2." );
697 render_spu.fullscreen = 1;
698 }
699
700 /*
701 * Begin Windows / WGL code
702 */
703
704 hinstance = GetModuleHandle( NULL );
705 if (!hinstance)
706 {
707 crError( "Render SPU: Couldn't get a handle to my module." );
708 return GL_FALSE;
709 }
710 crDebug( "Render SPU: Got the module handle: 0x%x", hinstance );
711
712 /* If we were launched from a service, telnet, or rsh, we need to
713 * get the input desktop. */
714
715 desktop = OpenInputDesktop( 0, FALSE,
716 DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
717 DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
718 DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
719 DESKTOP_SWITCHDESKTOP | GENERIC_WRITE );
720
721 if ( !desktop )
722 {
723 crError( "Render SPU: Couldn't acquire input desktop" );
724 return GL_FALSE;
725 }
726 crDebug( "Render SPU: Got the desktop: 0x%x", desktop );
727
728 if ( !SetThreadDesktop( desktop ) )
729 {
730 /* If this function fails, it's probably because
731 * it's already been called (i.e., the render SPU
732 * is bolted to an application?) */
733
734 /*crError( "Couldn't set thread to input desktop" ); */
735 }
736 crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
737
738 if ( !GetClassInfo(hinstance, WINDOW_NAME, &wc) )
739 {
740 wc.style = CS_OWNDC;
741 wc.lpfnWndProc = (WNDPROC) MainWndProc;
742 wc.cbClsExtra = 0;
743 wc.cbWndExtra = 0;
744 wc.hInstance = hinstance;
745 wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
746 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
747 wc.hbrBackground = NULL;
748 wc.lpszMenuName = NULL;
749 wc.lpszClassName = WINDOW_NAME;
750
751 if ( !RegisterClass( &wc ) )
752 {
753 crError( "Render SPU: Couldn't register window class -- you're not trying "
754 "to do multi-pipe stuff on windows, are you?\n\nNote --"
755 "This error message is from 1997 and probably doesn't make"
756 "any sense any more, but it's nostalgic for Humper." );
757 return GL_FALSE;
758 }
759 crDebug( "Render SPU: Registered the class" );
760 }
761 crDebug( "Render SPU: Got the class information" );
762
763 /* Full screen window should be a popup (undecorated) window */
764#if 1
765 window_style = ( render_spu.fullscreen ? WS_POPUP : WS_CAPTION );
766#else
767 window_style = ( WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
768 window_style |= WS_SYSMENU;
769#endif
770
771 crDebug( "Render SPU: Fullscreen: %s", render_spu.fullscreen ? "yes" : "no");
772
773 if ( render_spu.fullscreen )
774 {
775#if 0
776
777 int smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
778 int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
779 int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
780
781 window->width = GetSystemMetrics( SM_CXSCREEN ) ;
782 window->height = GetSystemMetrics( SM_CYSCREEN ) ;
783
784 crDebug( "Render SPU: Window Dims: %d, %d", window->width, window->height );
785
786 window->x = render_spu->defaultX - smCxFixedFrame - 1;
787 window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
788
789 window_plus_caption_width = window->width + 2 * smCxFixedFrame;
790 window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
791
792#else
793 /* Since it's undecorated, we don't have to do anything fancy
794 * with these parameters. */
795
796 window->width = GetSystemMetrics( SM_CXSCREEN ) ;
797 window->height = GetSystemMetrics( SM_CYSCREEN ) ;
798 window->x = 0;
799 window->y = 0;
800 window_plus_caption_width = window->width;
801 window_plus_caption_height = window->height;
802
803#endif
804 }
805 else
806 {
807 /* CreateWindow takes the size of the entire window, so we add
808 * in the size necessary for the frame and the caption. */
809
810 int smCxFixedFrame, smCyFixedFrame, smCyCaption;
811 smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
812 crDebug( "Render SPU: Got the X fixed frame" );
813 smCyFixedFrame = GetSystemMetrics( SM_CYFIXEDFRAME );
814 crDebug( "Render SPU: Got the Y fixed frame" );
815 smCyCaption = GetSystemMetrics( SM_CYCAPTION );
816 crDebug( "Render SPU: Got the Caption " );
817
818 window_plus_caption_width = window->width + 2 * smCxFixedFrame;
819 window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
820
821 window->x = render_spu.defaultX - smCxFixedFrame;
822 window->y = render_spu.defaultY - smCyFixedFrame - smCyCaption;
823 }
824
825 crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
826 window->hWnd = CreateWindow( WINDOW_NAME, WINDOW_NAME,
827 window_style,
828 window->x, window->y,
829 window_plus_caption_width,
830 window_plus_caption_height,
831 NULL, NULL, hinstance, &render_spu );
832
833 if ( !window->hWnd )
834 {
835 crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
836 return GL_FALSE;
837 }
838
839 if (showIt) {
840 /* NO ERROR CODE FOR SHOWWINDOW */
841 crDebug( "Render SPU: Showing the window" );
842 crDebug("renderspu_SystemCreateWindow: showwindow: %x", window->hWnd);
843 ShowWindow( window->hWnd, SW_SHOWNORMAL );
844 }
845
846 SetForegroundWindow( window->hWnd );
847
848 SetWindowPos( window->hWnd, HWND_TOP, window->x, window->y,
849 window_plus_caption_width, window_plus_caption_height,
850 ( render_spu.fullscreen ? (SWP_SHOWWINDOW |
851 SWP_NOSENDCHANGING |
852 SWP_NOREDRAW |
853 SWP_NOACTIVATE ) :
854 0 ) );
855
856 if ( render_spu.fullscreen )
857 ShowCursor( FALSE );
858
859 window->device_context = GetDC( window->hWnd );
860
861 crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
862
863 if ( !bSetupPixelFormat( window->device_context, visual->visAttribs ) )
864 {
865 crError( "Render SPU: Couldn't set up the device context! Yikes!" );
866 return GL_FALSE;
867 }
868
869 return GL_TRUE;
870}
871
872GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
873{
874#if 0
875 HDESK desktop;
876#endif
877 HINSTANCE hinstance;
878 WNDCLASS wc;
879 DWORD window_style;
880 int window_plus_caption_width;
881 int window_plus_caption_height;
882
883 window->visual = visual;
884 window->nativeWindow = 0;
885
886 if ( render_spu.use_L2 )
887 {
888 crWarning( "Going fullscreen because we think we're using Lightning-2." );
889 render_spu.fullscreen = 1;
890 }
891
892 /*
893 * Begin Windows / WGL code
894 */
895
896 hinstance = GetModuleHandle( NULL );
897 if (!hinstance)
898 {
899 crError( "Render SPU: Couldn't get a handle to my module." );
900 return GL_FALSE;
901 }
902 crDebug( "Render SPU: Got the module handle: 0x%x", hinstance );
903
904#if 0
905 /* If we were launched from a service, telnet, or rsh, we need to
906 * get the input desktop. */
907
908 desktop = OpenInputDesktop( 0, FALSE,
909 DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
910 DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
911 DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
912 DESKTOP_SWITCHDESKTOP | GENERIC_WRITE );
913
914 if ( !desktop )
915 {
916 crError( "Render SPU: Couldn't acquire input desktop" );
917 return GL_FALSE;
918 }
919 crDebug( "Render SPU: Got the desktop: 0x%x", desktop );
920
921 if ( !SetThreadDesktop( desktop ) )
922 {
923 /* If this function fails, it's probably because
924 * it's already been called (i.e., the render SPU
925 * is bolted to an application?) */
926
927 /*crError( "Couldn't set thread to input desktop" ); */
928 }
929 crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
930#endif
931
932 if ( !GetClassInfo(hinstance, WINDOW_NAME, &wc) )
933 {
934 wc.style = CS_OWNDC; // | CS_PARENTDC;
935 wc.lpfnWndProc = (WNDPROC) MainWndProc;
936 wc.cbClsExtra = 0;
937 wc.cbWndExtra = 0;
938 wc.hInstance = hinstance;
939 wc.hIcon = NULL; //LoadIcon( NULL, IDI_APPLICATION );
940 wc.hCursor = NULL; //LoadCursor( NULL, IDC_ARROW );
941 wc.hbrBackground = NULL;
942 wc.lpszMenuName = NULL;
943 wc.lpszClassName = WINDOW_NAME;
944
945 if ( !RegisterClass( &wc ) )
946 {
947 crError( "Render SPU: Couldn't register window class -- you're not trying "
948 "to do multi-pipe stuff on windows, are you?\n\nNote --"
949 "This error message is from 1997 and probably doesn't make"
950 "any sense any more, but it's nostalgic for Humper." );
951 return GL_FALSE;
952 }
953 crDebug( "Render SPU: Registered the class" );
954 }
955 crDebug( "Render SPU: Got the class information" );
956
957 /* Full screen window should be a popup (undecorated) window */
958#if 1
959 window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED;
960 if (render_spu_parent_window_id)
961 {
962 window_style |= WS_CHILD;
963 }
964#else
965 window_style = ( WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN );
966 window_style |= WS_SYSMENU;
967#endif
968
969 crDebug( "Render SPU: Fullscreen: %s", render_spu.fullscreen ? "yes" : "no");
970
971 if ( render_spu.fullscreen )
972 {
973#if 0
974
975 int smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
976 int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
977 int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
978
979 window->width = GetSystemMetrics( SM_CXSCREEN ) ;
980 window->height = GetSystemMetrics( SM_CYSCREEN ) ;
981
982 crDebug( "Render SPU: Window Dims: %d, %d", window->width, window->height );
983
984 window->x = render_spu->defaultX - smCxFixedFrame - 1;
985 window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
986
987 window_plus_caption_width = window->width + 2 * smCxFixedFrame;
988 window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
989
990#else
991 /* Since it's undecorated, we don't have to do anything fancy
992 * with these parameters. */
993
994 window->width = GetSystemMetrics( SM_CXSCREEN ) ;
995 window->height = GetSystemMetrics( SM_CYSCREEN ) ;
996 window->x = 0;
997 window->y = 0;
998 window_plus_caption_width = window->width;
999 window_plus_caption_height = window->height;
1000
1001#endif
1002 }
1003 else
1004 {
1005 /* CreateWindow takes the size of the entire window, so we add
1006 * in the size necessary for the frame and the caption. */
1007 int smCxFixedFrame, smCyFixedFrame, smCyCaption;
1008 smCxFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME );
1009 crDebug( "Render SPU: Got the X fixed frame" );
1010 smCyFixedFrame = GetSystemMetrics( SM_CYFIXEDFRAME );
1011 crDebug( "Render SPU: Got the Y fixed frame" );
1012 smCyCaption = GetSystemMetrics( SM_CYCAPTION );
1013 crDebug( "Render SPU: Got the Caption " );
1014
1015 window_plus_caption_width = window->width + 2 * smCxFixedFrame;
1016 window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
1017
1018 window->x = render_spu.defaultX;
1019 window->y = render_spu.defaultY;
1020 }
1021
1022 crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
1023 /*window->hWnd = CreateWindowEx( WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
1024 WINDOW_NAME, WINDOW_NAME,
1025 window_style,
1026 window->x, window->y,
1027 window->width,
1028 window->height,
1029 (void*) render_spu_parent_window_id, NULL, hinstance, &render_spu );*/
1030 {
1031 CREATESTRUCT cs;
1032
1033 cs.lpCreateParams = &window->hWnd;
1034
1035 cs.dwExStyle = WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY;
1036 cs.lpszName = WINDOW_NAME;
1037 cs.lpszClass = WINDOW_NAME;
1038 cs.style = window_style;
1039 cs.x = window->x;
1040 cs.y = window->y;
1041 cs.cx = window->width;
1042 cs.cy = window->height;
1043 cs.hwndParent = (void*) render_spu_parent_window_id;
1044 cs.hMenu = NULL;
1045 cs.hInstance = hinstance;
1046
1047 if (render_spu.dwWinThreadId)
1048 {
1049 DWORD res;
1050 int cnt=0;
1051
1052 if (!PostThreadMessage(render_spu.dwWinThreadId, WM_VBOX_RENDERSPU_CREATE_WINDOW, 0, (LPARAM) &cs))
1053 {
1054 crError("Render SPU: PostThreadMessage failed with %i", GetLastError());
1055 return GL_FALSE;
1056 }
1057
1058 do
1059 {
1060 res = WaitForSingleObject(render_spu.hWinThreadReadyEvent, 1000);
1061 cnt++;
1062 }
1063 while ((res!=WAIT_OBJECT_0) && (cnt<10));
1064
1065 crDebug("Render SPU: window thread waited %i secs", cnt);
1066
1067 if (res!=WAIT_OBJECT_0)
1068 {
1069 crError("Render SPU: window thread not responded after %i tries", cnt);
1070 return GL_FALSE;
1071 }
1072 }
1073 else
1074 {
1075 crError("Render SPU: window thread is not running");
1076 return GL_FALSE;
1077 }
1078 }
1079
1080 if ( !window->hWnd )
1081 {
1082 crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
1083 return GL_FALSE;
1084 }
1085
1086 if (showIt) {
1087 /* NO ERROR CODE FOR SHOWWINDOW */
1088 crDebug( "Render SPU: Showing the window" );
1089 crDebug("renderspu_SystemVBoxCreateWindow: showwindow: %x", window->hWnd);
1090 ShowWindow( window->hWnd, SW_SHOWNORMAL );
1091 }
1092
1093 //SetForegroundWindow( visual->hWnd );
1094
1095 SetWindowPos( window->hWnd, HWND_TOP, window->x, window->y,
1096 window->width, window->height,
1097 ( render_spu.fullscreen ?
1098 (SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOACTIVATE ) : SWP_NOACTIVATE
1099 ) );
1100 crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
1101 window->x, window->y, window->width, window->height);
1102
1103 if ( render_spu.fullscreen )
1104 ShowCursor( FALSE );
1105
1106 window->device_context = GetDC( window->hWnd );
1107
1108 crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
1109
1110 if ( !bSetupPixelFormat( window->device_context, visual->visAttribs ) )
1111 {
1112 crError( "Render SPU: Couldn't set up the device context! Yikes!" );
1113 return GL_FALSE;
1114 }
1115
1116 return GL_TRUE;
1117}
1118
1119
1120/* Either show or hide the render SPU's window. */
1121void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
1122{
1123 if (showIt)
1124 {
1125 crDebug("SHOW renderspu_SystemShowWindow: %x", window->hWnd);
1126 ShowWindow( window->hWnd, SW_SHOWNORMAL );
1127 }
1128 else
1129 {
1130 crDebug("HIDE renderspu_SystemShowWindow: %x", window->hWnd);
1131 ShowWindow( window->hWnd, SW_HIDE );
1132 }
1133}
1134
1135GLboolean renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
1136{
1137 (void) sharedContext;
1138 context->visual = visual;
1139
1140 /* Found a visual, so we're o.k. to create the context now */
1141 if (0/*visual->device_context*/) {
1142
1143 //crDebug( "Render SPU: Using the DC: 0x%x", visual->device_context );
1144
1145 //context->hRC = render_spu.ws.wglCreateContext( visual->device_context );
1146 if (!context->hRC)
1147 {
1148 crError( "Render SPU: wglCreateContext failed (error 0x%x)", GetLastError() );
1149 return GL_FALSE;
1150 }
1151 } else {
1152 crDebug( "Render SPU: Delaying DC creation " );
1153 context->hRC = NULL; /* create it later in makecurrent */
1154 }
1155
1156
1157 return GL_TRUE;
1158}
1159
1160void renderspu_SystemDestroyContext( ContextInfo *context )
1161{
1162 render_spu.ws.wglDeleteContext( context->hRC );
1163 context->hRC = NULL;
1164}
1165
1166void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, ContextInfo *context )
1167{
1168 CRASSERT(render_spu.ws.wglMakeCurrent);
1169
1170 if (context && window) {
1171 if (window->visual != context->visual) {
1172 /*
1173 * XXX have to revisit this issue!!!
1174 *
1175 * But for now we destroy the current window
1176 * and re-create it with the context's visual abilities
1177 */
1178
1179 /*@todo Chromium has no correct code to remove window ids and associated info from
1180 * various tables. This is hack which just hides the root case.
1181 */
1182 crDebug("Recreating window in renderspu_SystemMakeCurrent\n");
1183 renderspu_SystemDestroyWindow( window );
1184 renderspu_SystemVBoxCreateWindow( context->visual, window->visible, window );
1185 }
1186
1187 if (render_spu.render_to_app_window && nativeWindow)
1188 {
1189 /* The render_to_app_window option
1190 * is set and we've got a nativeWindow
1191 * handle, save the handle for
1192 * later calls to swapbuffers().
1193 *
1194 * NOTE: This doesn't work, except
1195 * for software driven Mesa.
1196 * We'd need to object link the
1197 * crappfaker and crserver to be able to share
1198 * the HDC values between processes.. FIXME!
1199 */
1200 window->nativeWindow = (HDC) nativeWindow;
1201 if (context->hRC == 0) {
1202 context->hRC = render_spu.ws.wglCreateContext( window->nativeWindow );
1203 if (!context->hRC)
1204 {
1205 crError( "(MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
1206 }
1207 }
1208 render_spu.ws.wglMakeCurrent( window->nativeWindow, context->hRC );
1209 }
1210 else
1211 {
1212 if (!context->visual->device_context) {
1213 context->visual->device_context = GetDC( window->hWnd );
1214
1215 crDebug( "Render SPU: MakeCurrent made the DC: 0x%x", context->visual->device_context );
1216
1217 if ( !bSetupPixelFormat( context->visual->device_context, context->visual->visAttribs ) )
1218 {
1219 crError( "Render SPU: (MakeCurrent) Couldn't set up the device context! Yikes!" );
1220 }
1221 }
1222
1223 if (!context->hRC) {
1224 context->hRC = render_spu.ws.wglCreateContext(context->visual->device_context);
1225 if (!context->hRC)
1226 {
1227 crError( "Render SPU: (MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
1228 }
1229
1230 /*Requery ext function pointers, we skip dummy ctx as it should never be used with ext functions*/
1231 if (0 && context->id)
1232 {
1233 int numFuncs, i;
1234 SPUNamedFunctionTable ext_table[1000];
1235
1236
1237 crDebug("Default server ctx created, requerying ext functions");
1238 /*requery ext functions*/
1239 numFuncs = renderspuCreateFunctions(ext_table);
1240 numFuncs += crLoadOpenGLExtensions( &render_spu.ws, ext_table+numFuncs);
1241 CRASSERT(numFuncs < 1000);
1242
1243 /*change spu dispatch*/
1244 crSPUChangeDispatch(&render_spu.self, ext_table);
1245
1246
1247 /*cleanup temp table*/
1248 for (i=0; i<numFuncs; ++i)
1249 {
1250 if (ext_table[i].name) crFree(ext_table[i].name);
1251 }
1252 }
1253 }
1254
1255 /*crDebug("MakeCurrent 0x%x, 0x%x", window->device_context, context->hRC);*/
1256 if (!render_spu.ws.wglMakeCurrent(window->device_context, context->hRC))
1257 {
1258 DWORD err = GetLastError();
1259 crError("Render SPU: (MakeCurrent) failed to make 0x%x, 0x%x current with 0x%x error.", window->device_context, context->hRC, err);
1260 }
1261 }
1262
1263 renderspuAtiQuirk_ChkApply();
1264 }
1265 else {
1266 render_spu.ws.wglMakeCurrent( 0, 0 );
1267 }
1268}
1269
1270void renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
1271{
1272 int winprop;
1273 CRASSERT(window);
1274 CRASSERT(window->visual);
1275 if ( render_spu.fullscreen )
1276 winprop = SWP_SHOWWINDOW | SWP_NOSENDCHANGING |
1277 SWP_NOREDRAW | SWP_NOACTIVATE;
1278 else
1279 winprop = SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_NOZORDER; //SWP_SHOWWINDOW;
1280
1281 /*SetWindowRgn(window->hWnd, NULL, false);*/
1282
1283 if (!SetWindowPos( window->hWnd, HWND_TOP,
1284 window->x, window->y, w, h, winprop )) {
1285 crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
1286 } else {
1287 crDebug("Render SPU: SetWindowSize (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
1288 }
1289 /* save the new size */
1290 window->width = w;
1291 window->height = h;
1292}
1293
1294
1295void renderspu_SystemGetWindowGeometry( WindowInfo *window, GLint *x, GLint *y, GLint *w, GLint *h )
1296{
1297 RECT rect;
1298
1299 CRASSERT(window);
1300 CRASSERT(window->visual);
1301
1302 GetClientRect( window->hWnd, &rect );
1303 *x = rect.left;
1304 *y = rect.top;
1305 *w = rect.right - rect.left;
1306 *h = rect.bottom - rect.top;
1307}
1308
1309
1310void renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h )
1311{
1312 /* XXX fix this */
1313 (void) window;
1314 *w = 1600;
1315 *h = 1200;
1316}
1317
1318
1319void renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
1320{
1321 int winprop;
1322 CRASSERT(window);
1323 CRASSERT(window->visual);
1324 if ( render_spu.fullscreen )
1325 winprop = SWP_SHOWWINDOW | SWP_NOSENDCHANGING |
1326 SWP_NOREDRAW | SWP_NOACTIVATE;
1327 else
1328 winprop = SWP_NOACTIVATE | SWP_DEFERERASE | SWP_NOSENDCHANGING | SWP_NOZORDER; //SWP_SHOWWINDOW;
1329
1330 /*SetWindowRgn(window->visual->hWnd, NULL, false);*/
1331
1332 if (!SetWindowPos( window->hWnd, HWND_TOP,
1333 x, y, window->width, window->height, winprop )) {
1334 crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, x, y, window->width, window->height);
1335 } else {
1336 crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
1337 x, y, window->width, window->height);
1338 }
1339}
1340
1341void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint* pRects)
1342{
1343 GLint i;
1344 HRGN hRgn, hTmpRgn;
1345
1346 CRASSERT(window);
1347 CRASSERT(window->visual);
1348
1349 hRgn = CreateRectRgn(0, 0, 0, 0);
1350
1351 for (i=0; i<cRects; i++)
1352 {
1353 hTmpRgn = CreateRectRgn(pRects[4*i], pRects[4*i+1], pRects[4*i+2], pRects[4*i+3]);
1354 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
1355 DeleteObject(hTmpRgn);
1356 }
1357
1358 SetWindowRgn(window->hWnd, hRgn, true);
1359 crDebug("Render SPU: SetWindowRgn (%x, cRects=%i)", window->hWnd, cRects);
1360}
1361
1362static void renderspuHandleWindowMessages( HWND hWnd )
1363{
1364 MSG msg;
1365 while ( PeekMessage( &msg, hWnd, 0, 0xffffffff, PM_REMOVE ) )
1366 {
1367 TranslateMessage( &msg );
1368 DispatchMessage( &msg );
1369 }
1370
1371 //BringWindowToTop( hWnd );
1372}
1373
1374void renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
1375{
1376 int return_value;
1377
1378 /* peek at the windows message queue */
1379 renderspuHandleWindowMessages( w->hWnd );
1380
1381 /* render_to_app_window:
1382 * w->nativeWindow will only be non-zero if the
1383 * render_spu.render_to_app_window option is true and
1384 * MakeCurrent() recorded the nativeWindow handle in the WindowInfo
1385 * structure.
1386 */
1387 if (render_spu.render_to_app_window && w->nativeWindow) {
1388 return_value = render_spu.ws.wglSwapBuffers( w->nativeWindow );
1389 } else {
1390 /*
1391 HRGN hRgn1, hRgn2, hRgn3;
1392 HWND hWndParent;
1393 LONG ws;
1394
1395 hRgn1 = CreateRectRgn(0, 0, w->width, w->height);
1396 hRgn2 = CreateRectRgn(50, 50, 100, 100);
1397 hRgn3 = CreateRectRgn(0, 0, 0, 0);
1398 CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
1399 SetWindowRgn(w->visual->hWnd, hRgn3, true);
1400 DeleteObject(hRgn1);
1401 DeleteObject(hRgn2);
1402
1403 hWndParent = GetParent(w->visual->hWnd);
1404 ws = GetWindowLong(hWndParent, GWL_STYLE);
1405 ws &= ~WS_CLIPCHILDREN;
1406 SetWindowLong(hWndParent, GWL_STYLE, ws);
1407
1408 RECT rcClip;
1409
1410 rcClip.left = 50;
1411 rcClip.top = 50;
1412 rcClip.right = 100;
1413 rcClip.bottom = 100;
1414 ValidateRect(w->visual->hWnd, &rcClip);
1415
1416 return_value = GetClipBox(w->visual->device_context, &rcClip);
1417 crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1418 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1419
1420 crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
1421
1422 return_value = ExcludeClipRect(w->visual->device_context, 50, 50, 100, 100);
1423 crDebug("ExcludeClipRect returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1424 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1425
1426 return_value = GetClipBox(w->visual->device_context, &rcClip);
1427 crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
1428 return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
1429 crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
1430 */
1431 return_value = render_spu.ws.wglSwapBuffers( w->device_context );
1432 }
1433 if (!return_value)
1434 {
1435 /* GOD DAMN IT. The latest versions of the NVIDIA drivers
1436 * return failure from wglSwapBuffers, but it works just fine.
1437 * WHAT THE HELL?! */
1438
1439 crWarning( "wglSwapBuffers failed: return value of %d!", return_value);
1440 }
1441}
1442
1443void renderspu_SystemReparentWindow(WindowInfo *window)
1444{
1445 SetParent(window->hWnd, (HWND)render_spu_parent_window_id);
1446}
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