VirtualBox

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

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

CrOpenGL: comments

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