views:

1167

answers:

4

I'm new to OpenGL but I've written a small application that runs fine in a window. Now i'd like to run it fullscreen.

There is this from the FAQ, but it seems to require GLUT, which is not open source. What's a good method for putting an OpenGL app into fullscreen mode? On Windows XP for now, but I'll be porting to other platforms.

+2  A: 

I'm assuming you're creating the OpenGL window the "hard way" (via win32)

the code below hails from NeHe, the link points to a tutorial containing OpenGL window creation with fullscreen support :

in case your compiler doesn't define CDS_FULLSCREEN, add :

#define CDS_FULLSCREEN 4

at the top of your app.

if (fullscreen) 
    {
DEVMODE dmScreenSettings;       // Device Mode
     memset(&dmScreenSettings,0,sizeof(dmScreenSettings));  // Makes Sure Memory's Cleared
     dmScreenSettings.dmSize=sizeof(dmScreenSettings);  // Size Of The Devmode Structure
     dmScreenSettings.dmPelsWidth = width;   // Selected Screen Width
     dmScreenSettings.dmPelsHeight = height;   // Selected Screen Height
     dmScreenSettings.dmBitsPerPel = bits;    // Selected Bits Per Pixel
     dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
     if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
     {
// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
      if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
      {(...)
Maciek
Thanks! Tried it...worked, sort of. I used (width, height) = (640, 480) and indeed Windows did go into 640x480 mode, but my window was not taking up the whole screen, and the start bar was still showing despite the comment in the code snippet.
I. J. Kennedy
Glad it helped, please mark it as answer :)
Maciek
As I mentioned, it only put the screen in 640x480 mode. It didn't do anything resembling "full screen". It's a start though.
I. J. Kennedy
This is just an excerpt from the tutorial. I'd download the project from the tutorial and grab the entire CreateGLWindow function.
Steve Wortham
Just to clarify -- there are steps not included in this snippet such as a call to AdjustWindowRectEx() which will resize the window to the requested resolution. If you copy the full source all of those little details should be taken care of.
Steve Wortham
+2  A: 

I'm partial to SDL for OpenGL window mangament and context wrangling.

genpfault
A: 

Here is how SDL does it (MS Windows):

// query desktop video settings
DEVMODE SDL_desktop_mode;
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);

settings.dmBitsPerPel = video->format->BitsPerPixel;
settings.dmPelsWidth = width;
settings.dmPelsHeight = height;
settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
// make sure to use monitor frequency that works in fullscreen
if (width <= (int)SDL_desktop_mode.dmPelsWidth &&
   height <= (int)SDL_desktop_mode.dmPelsHeight) {
      settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
      settings.dmFields |= DM_DISPLAYFREQUENCY;
      }
changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
if (! changed && (settings.dmFields & DM_DISPLAYFREQUENCY)) {
   settings.dmFields &= ~DM_DISPLAYFREQUENCY;
   changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
}

What SDL does when you set fullscreen mode and your target resolution is not the desktop resolution is to make sure you are using the proper monitor frequency for fullscreen mode by simply telling the driver to apply the frequency that the desktop has been using (which runs in fullscreen, so its refresh rate will work with any resolution in fullscreen mode).

karx11erx
+1  A: 

Maciek's answer should work. You just need the full source from the NeHe tutorial.

There is much more source involved in taking care of all the little details like resizing the Window to fullscreen, covering up the start bar. Here's the CreateGLWindow function from one of my apps (a near-copy of NeHe's method).

inline BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
    GLuint  PixelFormat;   // Holds The Results After Searching For A Match
    HINSTANCE hInstance;    // Holds The Instance Of The Application
    WNDCLASS wc;      // Windows Class Structure
    DWORD  dwExStyle;    // Window Extended Style
    DWORD  dwStyle;    // Window Style
    RECT  WindowRect;    // Grabs Rectangle Upper Left / Lower Right Values
    WindowRect.left=(long)0;   // Set Left Value To 0
    WindowRect.right=(long)width;  // Set Right Value To Requested Width
    WindowRect.top=(long)0;    // Set Top Value To 0
    WindowRect.bottom=(long)height;  // Set Bottom Value To Requested Height

  SCREENWIDTH=width; 
  SCREENHEIGHT=height; 

    fullscreen=fullscreenflag;   // Set The Global Fullscreen Flag

    hInstance   = GetModuleHandle(NULL);    // Grab An Instance For Our Window
    wc.style   = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
    wc.lpfnWndProc  = (WNDPROC) WndProc;     // WndProc Handles Messages
    wc.cbClsExtra  = 0;         // No Extra Window Data
    wc.cbWndExtra  = 0;         // No Extra Window Data
    wc.hInstance  = hInstance;       // Set The Instance
    wc.hIcon   = LoadIcon(NULL, IDI_WINLOGO);   // Load The Default Icon
    wc.hCursor   = LoadCursor(NULL, IDC_ARROW);   // Load The Arrow Pointer
    wc.hbrBackground = NULL;         // No Background Required For GL
    wc.lpszMenuName  = NULL;         // We Don't Want A Menu
    wc.lpszClassName = "OpenGL";        // Set The Class Name

    if (!RegisterClass(&wc))         // Attempt To Register The Window Class
    {
     MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;           // Return FALSE
    }

    if (fullscreen)            // Attempt Fullscreen Mode?
    {
     DEVMODE dmScreenSettings;        // Device Mode
     memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
     dmScreenSettings.dmSize=sizeof(dmScreenSettings);  // Size Of The Devmode Structure
     dmScreenSettings.dmPelsWidth = width;    // Selected Screen Width
     dmScreenSettings.dmPelsHeight = height;    // Selected Screen Height
     dmScreenSettings.dmBitsPerPel = bits;     // Selected Bits Per Pixel
     dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

     // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
     if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
     {
      // If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
      if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
      {
       fullscreen=FALSE;  // Windowed Mode Selected.  Fullscreen = FALSE
      }
      else
      {
       // Pop Up A Message Box Letting User Know The Program Is Closing.
       MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
       return FALSE;         // Return FALSE
      }
     }
    }

    if (fullscreen)            // Are We Still In Fullscreen Mode?
    {
     dwExStyle=WS_EX_APPWINDOW;        // Window Extended Style
     dwStyle=WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
     ShowCursor(FALSE);          // Hide Mouse Pointer
    }
    else
    {
     dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;      // Window Extended Style
     dwStyle=WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // Windows Style
    }

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust Window To True Requested Size

    // Create The Window
    if (!(hWnd=CreateWindowEx( dwExStyle,       // Extended Style For The Window
           "OpenGL",       // Class Name
           title,        // Window Title
           dwStyle |       // Defined Window Style
           WS_CLIPSIBLINGS |     // Required Window Style
           WS_CLIPCHILDREN,     // Required Window Style
           0, 0,        // Window Position
           WindowRect.right-WindowRect.left, // Calculate Window Width
           WindowRect.bottom-WindowRect.top, // Calculate Window Height
           NULL,        // No Parent Window
           NULL,        // No Menu
           hInstance,       // Instance
           NULL)))        // Dont Pass Anything To WM_CREATE
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    static PIXELFORMATDESCRIPTOR pfd=    // pfd Tells Windows How We Want Things To Be
    {
     sizeof(PIXELFORMATDESCRIPTOR),    // Size Of This Pixel Format Descriptor
     1,           // Version Number
     PFD_DRAW_TO_WINDOW |      // Format Must Support Window
     PFD_SUPPORT_OPENGL |      // Format Must Support OpenGL
     PFD_DOUBLEBUFFER,       // Must Support Double Buffering
     PFD_TYPE_RGBA,        // Request An RGBA Format
     bits,          // Select Our 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,         // Accumulation Bits Ignored
     32,           // 16Bit Z-Buffer (Depth Buffer)  
     0,           // No Stencil Buffer
     0,           // No Auxiliary Buffer
     PFD_MAIN_PLANE,        // Main Drawing Layer
     0,           // Reserved
     0, 0, 0          // Layer Masks Ignored
    };

    if (!(hDC=GetDC(hWnd)))       // Did We Get A Device Context?
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    if(!SetPixelFormat(hDC,PixelFormat,&pfd))  // Are We Able To Set The Pixel Format?
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    if (!(hRC=wglCreateContext(hDC)))    // Are We Able To Get A Rendering Context?
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    if(!wglMakeCurrent(hDC,hRC))     // Try To Activate The Rendering Context
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    ShowWindow(hWnd,SW_SHOW);      // Show The Window
    SetForegroundWindow(hWnd);      // Slightly Higher Priority
    SetFocus(hWnd);         // Sets Keyboard Focus To The Window
    ReSizeGLScene(width, height);     // Set Up Our Perspective GL Screen

    if (!InitGL())         // Initialize Our Newly Created GL Window
    {
     KillGLWindow();        // Reset The Display
     MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
     return FALSE;        // Return FALSE
    }

    return TRUE;         // Success
}

This is all included in NeHe Lesson 1.

Steve Wortham