renderspu_wgl.c revision 9f52ff8b6b89d6ac4215d122a95b685170a5a382
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "cr_environment.h"
#include "cr_error.h"
#include "cr_string.h"
#include "renderspu.h"
#include "cr_mem.h"
static BOOL
{
crWarning("Render SPU: PBuffers not support on Windows yet.");
}
/* In the windows world, we need a window before a context.
* Use the device_context as a marker to do just that */
visual->device_context = 0;
return TRUE;
}
{
/*DestroyWindow( window->hWnd );*/
if (render_spu.dwWinThreadId)
{
}
else
{
crError("Render SPU: window thread is not running");
}
}
{
/* int w,h; */
switch ( uMsg ) {
case WM_SIZE:
/* w = LOWORD( lParam );
* h = HIWORD( lParam ); */
/* glViewport( 0, 0, w, h ); */
#if 0
#endif
break;
case WM_CLOSE:
crWarning( "Render SPU: caught WM_CLOSE -- quitting." );
exit( 0 );
break;
case WM_DESTROY:
crDebug( "Render SPU: caught WM_DESTROY for our window" );
break;
case WM_NCHITTEST:
crDebug("WM_NCHITTEST");
return HTNOWHERE;
}
}
static BOOL
{
int pixelFormat;
int attribList[100];
int numFormats;
int i = 0;
crWarning("Render SPU: Using WGL_EXT_pixel_format to select visual ID.");
attribList[i++] = WGL_DRAW_TO_WINDOW_EXT;
attribList[i++] = GL_TRUE;
attribList[i++] = WGL_ACCELERATION_EXT;
attribList[i++] = WGL_FULL_ACCELERATION_EXT;
attribList[i++] = WGL_COLOR_BITS_EXT;
attribList[i++] = 24;
attribList[i++] = WGL_RED_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_GREEN_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_BLUE_BITS_EXT;
attribList[i++] = 1;
crWarning("Render SPU: Visual chosen is... RGB");
if (visAttribs & CR_ALPHA_BIT)
{
attribList[i++] = WGL_ALPHA_BITS_EXT;
attribList[i++] = 1;
crWarning("A");
}
crWarning(", ");
if (visAttribs & CR_DOUBLE_BIT) {
attribList[i++] = WGL_DOUBLE_BUFFER_EXT;
attribList[i++] = GL_TRUE;
crWarning("DB, ");
}
if (visAttribs & CR_STEREO_BIT) {
attribList[i++] = WGL_STEREO_EXT;
attribList[i++] = GL_TRUE;
crWarning("Stereo, ");
}
if (visAttribs & CR_DEPTH_BIT)
{
attribList[i++] = WGL_DEPTH_BITS_EXT;
attribList[i++] = 1;
crWarning("Z, ");
}
if (visAttribs & CR_STENCIL_BIT)
{
attribList[i++] = WGL_STENCIL_BITS_EXT;
attribList[i++] = 1;
crWarning("Stencil, ");
}
if (visAttribs & CR_ACCUM_BIT)
{
attribList[i++] = WGL_ACCUM_RED_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_ACCUM_GREEN_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_ACCUM_BLUE_BITS_EXT;
attribList[i++] = 1;
crWarning("Accum, ");
if (visAttribs & CR_ALPHA_BIT)
{
attribList[i++] = WGL_ACCUM_ALPHA_BITS_EXT;
attribList[i++] = 1;
crWarning("Accum Alpha, ");
}
}
if (visAttribs & CR_MULTISAMPLE_BIT)
{
attribList[i++] = WGL_SAMPLE_BUFFERS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_SAMPLES_EXT;
attribList[i++] = 4;
crWarning("Multisample, ");
}
crWarning("\n");
/* End the list */
attribList[i++] = 0;
attribList[i++] = 0;
vis = render_spu.ws.wglChoosePixelFormatEXT( hdc, attribList, fattribList, 1, &pixelFormat, &numFormats);
crDebug("Render SPU: wglChoosePixelFormatEXT (vis 0x%x, LastError 0x%x, pixelFormat 0x%x", vis, GetLastError(), pixelFormat);
return vis;
}
static BOOL
{
sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
1, /* version number */
PFD_DRAW_TO_WINDOW | /* support window */
PFD_SUPPORT_OPENGL, /* support OpenGL */
PFD_TYPE_RGBA, /* RGBA type */
24, /* 24-bit color depth */
0, 0, 0, 0, 0, 0, /* color bits ignored */
0, /* no alpha buffer */
0, /* shift bit ignored */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits ignored */
0, /* set depth buffer */
0, /* set stencil buffer */
0, /* no auxiliary buffer */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0 /* layer masks ignored */
};
char s[1000];
GLbitfield b = 0;
int pixelformat;
renderspuMakeVisString( visAttribs, s );
crDebug( "Render SPU: WGL wants these visual capabilities: %s", s);
/* These really come into play with sort-last configs */
if (visAttribs & CR_DEPTH_BIT)
if (visAttribs & CR_ACCUM_BIT)
if (visAttribs & CR_RGB_BIT)
if (visAttribs & CR_STENCIL_BIT)
if (visAttribs & CR_ALPHA_BIT)
if (visAttribs & CR_DOUBLE_BIT)
if (visAttribs & CR_STEREO_BIT)
/*
* We call the wgl functions directly if the SPU was loaded
* by our faker library, otherwise we have to call the GDI
* versions.
*/
{
/* doing this twice is normal Win32 magic */
if ( pixelformat == 0 )
{
crError( "render_spu.ws.wglChoosePixelFormat failed" );
}
{
crError( "render_spu.ws.wglSetPixelFormat failed" );
}
}
else
{
/* Okay, we were loaded manually. Call the GDI functions. */
/* doing this twice is normal Win32 magic */
if ( pixelformat == 0 )
{
crError( "ChoosePixelFormat failed" );
}
{
}
}
if (ppfd->cDepthBits > 0)
b |= CR_DEPTH_BIT;
if (ppfd->cAccumBits > 0)
b |= CR_ACCUM_BIT;
b |= CR_RGB_BIT;
if (ppfd->cStencilBits > 0)
b |= CR_STENCIL_BIT;
if (ppfd->cAlphaBits > 0)
b |= CR_ALPHA_BIT;
b |= CR_DOUBLE_BIT;
b |= CR_STEREO_BIT;
renderspuMakeVisString( b, s );
crDebug( "Render SPU: WGL chose these visual capabilities: %s", s);
return TRUE;
}
static BOOL
{
/* According to http://www.opengl.org/resources/faq/technical/mswindows.htm
we shouldn't be using wgl functions to setup pixel formats unless we're loading ICD driver.
In particular, bSetupPixelFormatEXT bugs with Intel drivers.
*/
}
{
window->nativeWindow = 0;
if ( render_spu.use_L2 )
{
crWarning( "Going fullscreen because we think we're using Lightning-2." );
}
/*
* Begin Windows / WGL code
*/
if (!hinstance)
{
crError( "Render SPU: Couldn't get a handle to my module." );
return GL_FALSE;
}
/* If we were launched from a service, telnet, or rsh, we need to
* get the input desktop. */
if ( !desktop )
{
crError( "Render SPU: Couldn't aquire input desktop" );
return GL_FALSE;
}
if ( !SetThreadDesktop( desktop ) )
{
/* If this function fails, it's probably because
* it's already been called (i.e., the render SPU
* is bolted to an application?) */
/*crError( "Couldn't set thread to input desktop" ); */
}
crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
{
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if ( !RegisterClass( &wc ) )
{
crError( "Render SPU: Couldn't register window class -- you're not trying "
"to do multi-pipe stuff on windows, are you?\n\nNote --"
"This error message is from 1997 and probably doesn't make"
"any sense any more, but it's nostalgic for Humper." );
return GL_FALSE;
}
crDebug( "Render SPU: Registered the class" );
}
crDebug( "Render SPU: Got the class information" );
/* Full screen window should be a popup (undecorated) window */
#if 1
#else
#endif
if ( render_spu.fullscreen )
{
#if 0
#else
/* Since it's undecorated, we don't have to do anything fancy
* with these parameters. */
window->x = 0;
window->y = 0;
#endif
}
else
{
/* CreateWindow takes the size of the entire window, so we add
* in the size necessary for the frame and the caption. */
crDebug( "Render SPU: Got the X fixed frame" );
crDebug( "Render SPU: Got the Y fixed frame" );
crDebug( "Render SPU: Got the Caption " );
}
crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
{
crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
return GL_FALSE;
}
if (showIt) {
/* NO ERROR CODE FOR SHOWWINDOW */
crDebug( "Render SPU: Showing the window" );
}
SWP_NOACTIVATE ) :
0 ) );
if ( render_spu.fullscreen )
ShowCursor( FALSE );
{
crError( "Render SPU: Couldn't set up the device context! Yikes!" );
return GL_FALSE;
}
return GL_TRUE;
}
GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
{
window->nativeWindow = 0;
if ( render_spu.use_L2 )
{
crWarning( "Going fullscreen because we think we're using Lightning-2." );
}
/*
* Begin Windows / WGL code
*/
if (!hinstance)
{
crError( "Render SPU: Couldn't get a handle to my module." );
return GL_FALSE;
}
#if 0
/* If we were launched from a service, telnet, or rsh, we need to
* get the input desktop. */
if ( !desktop )
{
crError( "Render SPU: Couldn't aquire input desktop" );
return GL_FALSE;
}
if ( !SetThreadDesktop( desktop ) )
{
/* If this function fails, it's probably because
* it's already been called (i.e., the render SPU
* is bolted to an application?) */
/*crError( "Couldn't set thread to input desktop" ); */
}
crDebug( "Render SPU: Set the thread desktop -- this might have failed." );
#endif
{
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if ( !RegisterClass( &wc ) )
{
crError( "Render SPU: Couldn't register window class -- you're not trying "
"to do multi-pipe stuff on windows, are you?\n\nNote --"
"This error message is from 1997 and probably doesn't make"
"any sense any more, but it's nostalgic for Humper." );
return GL_FALSE;
}
crDebug( "Render SPU: Registered the class" );
}
crDebug( "Render SPU: Got the class information" );
/* Full screen window should be a popup (undecorated) window */
#if 1
{
window_style |= WS_CHILD;
}
#else
#endif
if ( render_spu.fullscreen )
{
#if 0
#else
/* Since it's undecorated, we don't have to do anything fancy
* with these parameters. */
window->x = 0;
window->y = 0;
#endif
}
else
{
/* CreateWindow takes the size of the entire window, so we add
* in the size necessary for the frame and the caption. */
crDebug( "Render SPU: Got the X fixed frame" );
crDebug( "Render SPU: Got the Y fixed frame" );
crDebug( "Render SPU: Got the Caption " );
}
crDebug( "Render SPU: Creating the window: (%d,%d), (%d,%d)", render_spu.defaultX, render_spu.defaultY, window_plus_caption_width, window_plus_caption_height );
/*window->hWnd = CreateWindowEx( WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY,
WINDOW_NAME, WINDOW_NAME,
window_style,
window->x, window->y,
window->width,
window->height,
(void*) render_spu_parent_window_id, NULL, hinstance, &render_spu );*/
{
if (render_spu.dwWinThreadId)
{
int cnt=0;
{
return GL_FALSE;
}
do
{
cnt++;
}
if (res!=WAIT_OBJECT_0)
{
return GL_FALSE;
}
}
else
{
crError("Render SPU: window thread is not running");
return GL_FALSE;
}
}
{
crError( "Render SPU: Create Window failed! That's almost certainly terrible." );
return GL_FALSE;
}
if (showIt) {
/* NO ERROR CODE FOR SHOWWINDOW */
crDebug( "Render SPU: Showing the window" );
}
//SetForegroundWindow( visual->hWnd );
( render_spu.fullscreen ?
) );
if ( render_spu.fullscreen )
ShowCursor( FALSE );
{
crError( "Render SPU: Couldn't set up the device context! Yikes!" );
return GL_FALSE;
}
return GL_TRUE;
}
/* Either show or hide the render SPU's window. */
{
if (showIt)
{
}
else
{
}
}
GLboolean renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
{
(void) sharedContext;
/* Found a visual, so we're o.k. to create the context now */
if (0/*visual->device_context*/) {
//crDebug( "Render SPU: Using the DC: 0x%x", visual->device_context );
//context->hRC = render_spu.ws.wglCreateContext( visual->device_context );
{
return GL_FALSE;
}
} else {
crDebug( "Render SPU: Delaying DC creation " );
}
return GL_TRUE;
}
{
}
{
/*
* XXX have to revisit this issue!!!
*
* But for now we destroy the current window
* and re-create it with the context's visual abilities
*/
/*@todo Chromium has no correct code to remove window ids and associated info from
* various tables. This is hack which just hides the root case.
*/
crDebug("Recreating window in renderspu_SystemMakeCurrent\n");
}
{
/* The render_to_app_window option
* is set and we've got a nativeWindow
* handle, save the handle for
* later calls to swapbuffers().
*
* NOTE: This doesn't work, except
* for software driven Mesa.
* We'd need to object link the
* crappfaker and crserver to be able to share
* the HDC values between processes.. FIXME!
*/
{
}
}
}
else
{
{
crError( "Render SPU: (MakeCurrent) Couldn't set up the device context! Yikes!" );
}
}
{
crError( "Render SPU: (MakeCurrent) Couldn't create the context for the window (error 0x%x)", GetLastError() );
}
}
{
crError("Render SPU: (MakeCurrent) failed to make 0x%x, 0x%x current with 0x%x error.", window->device_context, context->hRC, err);
}
}
}
else {
}
}
{
int winprop;
if ( render_spu.fullscreen )
else
/*SetWindowRgn(window->hWnd, NULL, false);*/
crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
} else {
crDebug("Render SPU: SetWindowSize (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
}
/* save the new size */
}
void renderspu_SystemGetWindowGeometry( WindowInfo *window, GLint *x, GLint *y, GLint *w, GLint *h )
{
}
{
/* XXX fix this */
(void) window;
*w = 1600;
*h = 1200;
}
{
int winprop;
if ( render_spu.fullscreen )
else
/*SetWindowRgn(window->visual->hWnd, NULL, false);*/
crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, x, y, window->width, window->height);
} else {
}
}
{
GLint i;
hRgn = CreateRectRgn(0, 0, 0, 0);
for (i=0; i<cRects; i++)
{
}
}
{
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
//BringWindowToTop( hWnd );
}
{
int return_value;
/* peek at the windows message queue */
/* render_to_app_window:
* w->nativeWindow will only be non-zero if the
* render_spu.render_to_app_window option is true and
* MakeCurrent() recorded the nativeWindow handle in the WindowInfo
* structure.
*/
} else {
/*
HRGN hRgn1, hRgn2, hRgn3;
HWND hWndParent;
LONG ws;
hRgn1 = CreateRectRgn(0, 0, w->width, w->height);
hRgn2 = CreateRectRgn(50, 50, 100, 100);
hRgn3 = CreateRectRgn(0, 0, 0, 0);
CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
SetWindowRgn(w->visual->hWnd, hRgn3, true);
DeleteObject(hRgn1);
DeleteObject(hRgn2);
hWndParent = GetParent(w->visual->hWnd);
ws = GetWindowLong(hWndParent, GWL_STYLE);
ws &= ~WS_CLIPCHILDREN;
SetWindowLong(hWndParent, GWL_STYLE, ws);
RECT rcClip;
rcClip.left = 50;
rcClip.top = 50;
rcClip.right = 100;
rcClip.bottom = 100;
ValidateRect(w->visual->hWnd, &rcClip);
return_value = GetClipBox(w->visual->device_context, &rcClip);
crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
return_value = ExcludeClipRect(w->visual->device_context, 50, 50, 100, 100);
crDebug("ExcludeClipRect returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
return_value = GetClipBox(w->visual->device_context, &rcClip);
crDebug("GetClipBox returned %d (NR=%d,SR=%d,CR=%d,ERR=%d)",
return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
*/
}
if (!return_value)
{
/* GOD DAMN IT. The latest versions of the NVIDIA drivers
* return failure from wglSwapBuffers, but it works just fine.
* WHAT THE HELL?! */
}
}
{
}