wglgears: add srgb-mode to usage
[mesa-demos.git] / src / wgl / rtotex / window.cpp
blob022128173e039f0ca84d28190765352cc9907fb6
1 //////////////////////////////////////////////////////////////////////////////////////////
2 // WINDOW.cpp
3 // functions to set up an opengl capable window
4 // Downloaded from: www.paulsprojects.net
5 // Created: 21st June 2002
6 // Modified: 26th August 2002 - Added Input management
7 // 3rd September 2002 - Added WINDOW::MakeCurrent - to restore focus to
8 // window after switch
9 //
10 // Copyright (c) 2006, Paul Baker
11 // Distributed under the New BSD Licence. (See accompanying file License.txt or copy at
12 // http://www.paulsprojects.net/NewBSDLicense.txt)
13 //////////////////////////////////////////////////////////////////////////////////////////
15 #include "windows.h"
16 #include "GL/gl.h"
17 #include "GL/glu.h"
18 #include "log.h"
19 #include "window.h"
21 extern LOG errorLog;
23 bool WINDOW::Init(const char * windowTitle,
24 int newWidth, int newHeight,
25 int newColorBits, int newDepthBits, int newStencilBits,
26 int fullscreenflag)
27 //CREATE WINDOW
29 WNDCLASS wc; //windows class structure
30 DWORD dwExStyle; //extended style info.
31 DWORD dwStyle; //style info
33 //set class's member variables
34 title=windowTitle;
35 width=newWidth;
36 height=newHeight;
37 colorBits=newColorBits;
38 depthBits=newDepthBits;
39 stencilBits=newStencilBits;
41 //set class's fullscreen flag
42 if(fullscreenflag == FULL_SCREEN)
44 fullscreen=true;
47 if(fullscreenflag == WINDOWED_SCREEN)
49 fullscreen=false;
52 if(fullscreenflag == CHOOSE_SCREEN) //Ask user if fullscreen
54 if(MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?","Start FullScreen",MB_YESNO|MB_ICONQUESTION)==IDNO)
56 fullscreen=false; //If answered no
58 else
60 fullscreen=true; //if answered yes
64 RECT WindowRect; //grab rect. upper left/lower right values
65 WindowRect.left=(long)0;
66 WindowRect.right=(long)width;
67 WindowRect.top=(long)0;
68 WindowRect.bottom=(long)height;
70 hInstance= GetModuleHandle(NULL); //Grab an instance for window
71 wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
72 //window style: redraw on move, own DC
73 wc.lpfnWndProc= (WNDPROC) WndProc; //Wndproc handles messages
74 wc.cbClsExtra= 0;
75 wc.cbWndExtra= 0; //no extra window data
76 wc.hInstance= hInstance; //Set the instance
77 wc.hIcon= LoadIcon(NULL, IDI_WINLOGO); //load default icon
78 wc.hCursor= LoadCursor(NULL, IDC_ARROW); //Load arrow cursor
79 wc.hbrBackground=NULL; //No background rqd for GL
80 wc.lpszMenuName=NULL; //No menu
81 wc.lpszClassName="OpenGL"; //set class name
83 if(!RegisterClass(&wc)) //try to register class
85 errorLog.OutputError("Failed to register the window class");
86 return FALSE;
88 else
89 errorLog.OutputSuccess("Window Class Registered");
91 if(fullscreen) //try to set up fullscreen?
93 DEVMODE dmScreenSettings; //Device mode
94 memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
95 //clear memory
96 dmScreenSettings.dmSize=sizeof(dmScreenSettings);
97 //size of devmode structure
98 dmScreenSettings.dmPelsWidth=width; //selected width
99 dmScreenSettings.dmPelsHeight=height; //selected height
100 dmScreenSettings.dmBitsPerPel=colorBits; //selected bpp
101 dmScreenSettings.dmFields=DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
103 if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
104 //try to set mode.CDS_FULLSCREEN removes start bar
106 //If mode fails, give 2 options, quit or run in window
107 if(MessageBox(NULL, "The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?",title, MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
109 fullscreen=FALSE; //if "yes", try windowed
111 else
113 //tell user program is closing
114 errorLog.OutputError("Program Closed, As Fullscreen Mode Not Supported.");
115 return FALSE; //exit and return FALSE
120 if (fullscreen) //still fullscreen?
122 dwExStyle=WS_EX_APPWINDOW; //window extended style
123 dwStyle=WS_POPUP | WS_VISIBLE; //window style (no border), visible
124 ShowCursor(FALSE); //hide mouse pointer
126 else
128 dwExStyle=WS_EX_CLIENTEDGE; //window extended style(3d look)
129 dwStyle=WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_VISIBLE;
130 //window style (close button, title bar, border, visible)
133 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
134 //adjust window to actual requested size, rather than including borders in size. in fullscreen, no effect
136 if(!(hWnd=CreateWindowEx( dwExStyle, //extended style for window
137 "OpenGL", //class name
138 title, //window title
139 WS_CLIPSIBLINGS | //required style
140 WS_CLIPCHILDREN | //required style
141 dwStyle, //Selected style
142 0, 0, //window position
143 WindowRect.right-WindowRect.left, //calculate adjusted width
144 WindowRect.bottom-WindowRect.top, //calculate adjusted height
145 NULL, // no parent window
146 NULL, //No Menu
147 hInstance, //Instance
148 NULL))) //Dont pass anything to WM_CREATE
150 Shutdown(); //if not set up, reset display
151 errorLog.OutputError("Window Creation Error.");
152 //pop up error message
153 return FALSE; //return false, to quit program
155 else
156 errorLog.OutputSuccess("Window Created.");
158 //set up pixel format(openGL supporting, RGBA, correct bits
159 GLuint pixelFormat; //holds result after searching for mode match
161 //calculate alpha bits
162 int alphaBits=0;
164 if(colorBits==32)
165 alphaBits=8;
167 static PIXELFORMATDESCRIPTOR pfd= //pfd tells windows how we want things to be
169 sizeof(PIXELFORMATDESCRIPTOR), //size of Pixel format descriptor
170 1, //Version Number
171 PFD_DRAW_TO_WINDOW | //must support window
172 PFD_SUPPORT_OPENGL | //must support opengl
173 PFD_DOUBLEBUFFER, //must support double buffer
174 PFD_TYPE_RGBA, //request RGBA format
175 colorBits, //select colour depth
176 0, 0, 0, 0, 0, 0, //colour bits ignored
177 alphaBits, //alpha buffer bits
178 0, //shift bit ignored
179 0, //no accumulation buffer
180 0, 0, 0, 0, //accumulation bits ignored
181 depthBits, //z buffer bits
182 stencilBits, //stencil buffer bits
183 0, //no auxiliary buffer
184 PFD_MAIN_PLANE, //main drawing layer
185 0, //reserved
186 0, 0, 0 //layer masks ignored
189 if(!(hDC=GetDC(hWnd))) //did we get a device context?
190 { //if not
191 Shutdown(); //Reset display
192 errorLog.OutputError("Can't Create a GL Device context.");
193 return FALSE; //return false, to exit
195 else
196 errorLog.OutputSuccess("DC Created");
198 if(!(pixelFormat=ChoosePixelFormat(hDC,&pfd))) //found a matching pixel format?
199 { //if not
200 Shutdown();
201 errorLog.OutputError("Can't Find a Suitable PixelFormat.");
202 return FALSE;
204 else
205 errorLog.OutputSuccess("Pixel Format Found.");
207 if(!SetPixelFormat(hDC, pixelFormat,&pfd)) //are we able to set pixel format?
208 { //if not
209 Shutdown();
210 errorLog.OutputError("Can't set the pixelformat.");
211 return FALSE;
213 else
214 errorLog.OutputSuccess("Pixel Format set.");
216 if(!(hRC=wglCreateContext(hDC))) //are we able to get rendering context?
217 { //if not
218 Shutdown();
219 errorLog.OutputError("Can't create a GL rendering context.");
220 return FALSE;
222 else
223 errorLog.OutputSuccess("GL Rendering Context Created.");
225 if(!MakeCurrent()) //are we able to activate rendering context?
226 { //if not
227 Shutdown();
228 return FALSE;
230 else
231 errorLog.OutputSuccess("GL Rendering Context Activated.");
233 //get pixel format parameters
234 static PIXELFORMATDESCRIPTOR finalPfd;
235 DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &finalPfd);
237 //output window parameters
238 errorLog.OutputNewline();
239 errorLog.OutputSuccess("Window Size: (%d, %d)", width, height);
240 errorLog.OutputSuccess("Color Buffer Bits (R, G, B, A): (%d, %d, %d, %d)",
241 finalPfd.cRedBits,
242 finalPfd.cGreenBits,
243 finalPfd.cBlueBits,
244 finalPfd.cAlphaBits);
245 errorLog.OutputSuccess("Depth Buffer Bits: %d", finalPfd.cDepthBits);
246 errorLog.OutputSuccess("Stencil Buffer Bits: %d", finalPfd.cStencilBits);
247 errorLog.OutputNewline();
249 ShowWindow(hWnd,SW_SHOW); //show window
250 SetForegroundWindow(hWnd); //slightly higher priority
251 SetFocus(hWnd); //Set keyboard focus to the window
253 errorLog.OutputSuccess("Window Created!");
254 errorLog.OutputNewline();
256 //Init the font
257 HFONT font; //windows font ID
259 //create 96 display lists
260 base = glGenLists(96);
262 font = CreateFont( -18, //font height
263 0, //default width
264 0, 0, //angles - escapement, orientation
265 FW_BOLD, //font weight, 0-1000, NORMAL, BOLD
266 false, //italic
267 false, //underline
268 false, //strikeout
269 ANSI_CHARSET, //character set
270 OUT_TT_PRECIS, //precision
271 CLIP_DEFAULT_PRECIS, //clip precision
272 ANTIALIASED_QUALITY, //output quality
273 FF_DONTCARE | DEFAULT_PITCH,//family and pitch
274 "Courier New"); //font name
276 //select the font
277 SelectObject(hDC, font);
279 //create 96 display lists, starting at 32
280 wglUseFontBitmaps(hDC, 32, 96, base);
282 errorLog.OutputSuccess("Font created successfully.");
284 return TRUE; //success!
287 void WINDOW::Shutdown(void) //PROPERLY KILL WINDOW
289 //Delete font display lists
290 glDeleteLists(base, 96);
292 if (fullscreen)
294 ChangeDisplaySettings(NULL, 0); //restore desktop mode
295 ShowCursor(TRUE); //show mouse cursor
298 errorLog.OutputNewline();
300 if(hRC) //have a rendering context?
302 if(!wglMakeCurrent(NULL, NULL)) //try to release rend cont
304 errorLog.OutputError("Release of DC and RC Failed.");
306 else
307 errorLog.OutputSuccess("DC and RC released.");
309 if(!wglDeleteContext(hRC)) //try to delete RC
311 errorLog.OutputError("Release Rendering Context Failed.");
313 else
314 errorLog.OutputSuccess("Rendering Context Released.");
316 hRC=NULL; //set RC to NULL
319 if(hDC && !ReleaseDC(hWnd, hDC)) //Are we able to release DC?
321 errorLog.OutputError("Release of Device Context Failed.");
322 hDC=NULL;
324 else
325 errorLog.OutputSuccess("Device Context Released.");
327 if(hWnd && !DestroyWindow(hWnd)) //Can we destroy window?
329 errorLog.OutputError("Could not release hWnd");
330 hWnd=NULL;
332 else
333 errorLog.OutputSuccess("hWnd released.");
335 if (!UnregisterClass("OpenGL", hInstance)) //can we unreg. class?
337 errorLog.OutputError("Could Not Unregister Class.");
338 hInstance=NULL;
340 else
341 errorLog.OutputSuccess("Class unregistered.");
344 bool WINDOW::MakeCurrent()
346 if(!wglMakeCurrent(hDC, hRC))
348 errorLog.OutputError("Unable to change current context");
349 return false;
352 return true;
356 //DEAL WITH ALL WINDOW MESSAGES
357 //Message Pump
358 bool WINDOW::HandleMessages(void)
360 while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //Is there a message waiting?
362 if(msg.message==WM_QUIT)
363 return false; //if a quit message, return false
365 //handle input
366 if(msg.message==WM_KEYDOWN)
367 SetKeyPressed(msg.wParam);
369 if(msg.message==WM_KEYUP)
370 SetKeyReleased(msg.wParam);
372 if(msg.message==WM_LBUTTONDOWN)
373 SetLeftButtonPressed();
375 if(msg.message==WM_RBUTTONDOWN)
376 SetRightButtonPressed();
378 TranslateMessage(&msg); //Translate Message
379 DispatchMessage(&msg); //dispatch message
381 return true;
384 LRESULT CALLBACK WINDOW::WndProc( HWND hWnd, //handle for this window
385 UINT uMsg, //Message for this window
386 WPARAM wParam, //Additional message information
387 LPARAM lParam) //Additional Message information
390 switch (uMsg) //check for windows messages
392 case WM_SYSCOMMAND: //Intercept system commands
394 switch (wParam) //check system calls
396 case SC_SCREENSAVE: //screensaver trying to start?
397 case SC_MONITORPOWER: //monitor trying to enter powersave?
398 return 0; //prevent from happening
400 break;
403 case WM_CLOSE: //receive close message?
404 PostQuitMessage(0); //send quit message
405 return 0; //quit back
406 break;
409 //pass all unhandled messages to DefWindowProc, windows can handle
410 return DefWindowProc(hWnd,uMsg,wParam,lParam);
413 void WINDOW::SwapBuffers(void)
415 ::SwapBuffers(hDC); //swap buffers
418 //void WINDOW::CheckGLError - check for an opengl error
419 void WINDOW::CheckGLError(void)
421 GLenum error;
422 error=glGetError();
423 if(!(error==GL_NO_ERROR))
425 errorLog.OutputError("OpenGL Error:");
426 if(error==GL_INVALID_ENUM)
428 errorLog.OutputError(" GL_INVALID_ENUM");
429 errorLog.OutputError(" GLenum Argument out of range.");
431 if(error==GL_INVALID_VALUE)
433 errorLog.OutputError(" GL_INVALID_VALUE");
434 errorLog.OutputError(" Numeric Argument out of range.");
436 if(error==GL_INVALID_OPERATION)
438 errorLog.OutputError(" GL_INVALID_OPERATION");
439 errorLog.OutputError(" Invalid Operation in current state.");
441 if(error==GL_STACK_UNDERFLOW)
443 errorLog.OutputError(" GL_STACK_UNDERFLOW");
444 errorLog.OutputError(" Stack Underflow.");
446 if(error==GL_STACK_OVERFLOW)
448 errorLog.OutputError(" GL_STACK_OVERFLOW");
449 errorLog.OutputError(" Stack Overflow.");
451 if(error==GL_OUT_OF_MEMORY)
453 errorLog.OutputError(" GL_OUT_OF_MEMORY");
454 errorLog.OutputError(" Out of memory.");
459 void WINDOW::SaveScreenshot(void)
461 FILE * file;
463 //first calculate the filename to save to
464 char filename[32];
466 for(int i=0; i<1000; i++)
468 sprintf(filename, "screen%03d.tga", i);
470 //try opening this file - if not possible, use this filename
471 file=fopen(filename, "rb");
473 if(!file)
475 break;
478 //otherwise, the file exists, try next, except if this is the last one
479 fclose(file);
481 if(i==999)
483 errorLog.OutputError("No space to save screenshot - 0-999 exist");
484 return;
488 errorLog.OutputSuccess("Saving %s", filename);
490 GLubyte TGAheader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //Uncompressed TGA header
491 GLubyte infoHeader[6];
493 unsigned char * data=new unsigned char[4*width*height];
494 if(!data)
496 errorLog.OutputError("Unable to allocate memory for screen data");
497 return;
500 //read in the screen data
501 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
503 //data needs to be in BGR format
504 //swap b and r
505 for(int i=0; i<(int)width*height*4; i+=4)
507 //repeated XOR to swap bytes 0 and 2
508 data[i] ^= data[i+2] ^= data[i] ^= data[i+2];
511 //open the file
512 file = fopen(filename, "wb");
514 //save header
515 fwrite(TGAheader, 1, sizeof(TGAheader), file);
517 //save info header
518 infoHeader[0]=(width & 0x00FF);
519 infoHeader[1]=(width & 0xFF00) >> 8;
520 infoHeader[2]=(height & 0x00FF);
521 infoHeader[3]=(height & 0xFF00) >> 8;
522 infoHeader[4]=32;
523 infoHeader[5]=0;
525 //save info header
526 fwrite(infoHeader, 1, sizeof(infoHeader), file);
528 //save the image data
529 fwrite(data, 1, width*height*4, file);
531 fclose(file);
533 errorLog.OutputSuccess("Saved Screenshot: %s", filename);
534 return;
537 //Text writing functions
538 void WINDOW::StartTextMode(void)
540 //If not yet created, make display list
541 if(!startTextModeList)
543 startTextModeList=glGenLists(1);
544 glNewList(startTextModeList, GL_COMPILE);
546 //save states
547 glPushAttrib(GL_ALL_ATTRIB_BITS);
548 glListBase(base-32); //set the list base
550 //set modelview matrix
551 glPushMatrix();
552 glLoadIdentity();
554 //set projection matrix
555 glMatrixMode(GL_PROJECTION);
556 glPushMatrix();
557 glLoadIdentity();
558 glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
560 //set states
561 glDisable(GL_DEPTH_TEST);
562 glDisable(GL_TEXTURE_2D);
563 glDisable(GL_LIGHTING);
565 glBlendFunc(GL_ONE, GL_ONE); //if blending, use additive
567 glEndList();
570 glCallList(startTextModeList);
573 void WINDOW::Print(int x, int y, const char * string, ...)
575 char text[256]; //Holds our string
576 va_list va; //pointer to list of arguments
578 if(string==NULL) //If there's no text
579 return; //Do nothing
581 va_start(va, string); //parse string for variables
582 vsprintf(text, string, va); //convert to actual numbers
583 va_end(va); //results stored in text
585 glRasterPos2i(x, y); //go to correct raster position
587 glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); //call display lists
590 void WINDOW::EndTextMode(void)
592 //restore states
593 glPopMatrix();
594 glMatrixMode(GL_MODELVIEW);
595 glPopMatrix();
596 glPopAttrib();
599 //Update input
600 void WINDOW::Update()
602 //Mouse buttons are marked as pressed by windows messages
603 //see if any have been released
604 if(mouseLDown && !GetAsyncKeyState(VK_LBUTTON))
605 mouseLDown=false;
607 if(mouseRDown && !GetAsyncKeyState(VK_RBUTTON))
608 mouseRDown=false;
610 //Update the mouse position
611 static POINT mousePosition;
612 GetCursorPos(&mousePosition);
614 oldMouseX=mouseX;
615 oldMouseY=mouseY;
617 mouseX=mousePosition.x;
618 mouseY=mousePosition.y;