VirtualBox

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

Last change on this file since 43285 was 43285, checked in by vboxsync, 12 years ago

crOpenGL/win: fix window flashing, take 2

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