Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 8 of 8

Thread: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Hi,
    I have this strange problem on my laptop* where calling
    Code :
    ChangeDisplaySettings(NULL,0)
    returns DISP_CHANGE_RESTART (and does NOT change the display settings back to normal, but when the application closes it DOES).

    At first I thougth I was doing something wrong with the Win32 API, so I wrote this "small" test program. But it seems to work on all other computers I have access to (Combinations of XPPro, XPHome, Win2K / NVidia gf fx, gf4, Intel Extreme / Desktops, Laptops).

    What do you think? I would be very thankful for any hints.

    *DELL Inspiron 8500, WinXP Home, ATI Mobility Radeon 9000 (Newest Drivers)

    Here's my code:
    (Based on NeHe's tutorials.
    The commented out stuff are things I found while searching the archives of this and other forums, but nothing really helped)
    </font><blockquote><font size="1" face="Verdana, Arial">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">#include <windows.h>
    #include <gl\gl.h>
    #include <stdexcept>
    #include <iostream>

    class Window
    {
    HDC DC;
    HGLRC RC;
    HWND Wnd;
    HINSTANCE Instance;
    DEVMODE DMsaved;

    bool Keys[256];
    bool SysKeys[256];
    bool isActive;
    bool isFullscreen;
    bool isOpen;
    int Width;
    int Height;
    int Bits;

    static LRESULT CALLBACK WndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    Window *Win;
    if(Msg==WM_NCCREATE)
    {
    Win=reinterpret_cast<Window*>(reinterpret_cast<CRE ATESTRUCT*>(lParam)->lpCreateParams);
    //::SetWindowLong(Wnd,GWL_USERDATA,reinterpret_cast< LONG_PTR>(Win));
    ::SetWindowLongPtr(Wnd,GWLP_USERDATA,reinterpret_c ast<LONG_PTR>(Win));
    }
    else
    {
    Win=reinterpret_cast<Window*>(GetWindowLongPtr(Wnd ,GWLP_USERDATA));
    }

    switch(Msg)
    {
    case WM_ACTIVATE:
    {
    Win->isActive=(!HIWORD(wParam));
    return 0;
    }
    case WM_SYSCOMMAND:
    {
    switch (wParam)
    {
    case SC_SCREENSAVE:
    case SC_MONITORPOWER:
    return 0;
    }
    break;
    }
    case WM_CLOSE:
    {
    ::PostQuitMessage(0);
    return 0;
    }
    case WM_KEYDOWN:
    {
    Win->Keys[wParam]=true;
    return 0;
    }
    case WM_KEYUP:
    {
    Win->Keys[wParam]=false;
    return 0;
    }
    case WM_SYSKEYDOWN:
    {
    Win->SysKeys[wParam]=true;
    return 0;
    }
    case WM_SYSKEYUP:
    {
    Win->SysKeys[wParam]=false;
    return 0;
    }
    }
    return :efWindowProc(Wnd,Msg,wParam,lParam);
    }

    void EnterFullscreenHelper()
    {
    DEVMODE DisplayMode;
    memset(&DisplayMode,0,sizeof(DisplayMode));
    DisplayMode.dmSize=sizeof(DisplayMode);
    DisplayMode.dmPelsWidth = Width;
    DisplayMode.dmPelsHeight = Height;
    DisplayMode.dmBitsPerPel = Bits;
    DisplayMode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM _PELSHEIGHT;

    switch(::ChangeDisplaySettings((DEVMODE*)&DisplayM ode,CDS_FULLSCREEN))
    {
    case DISP_CHANGE_SUCCESSFUL: break;
    case DISP_CHANGE_BADFLAGS: throw std::runtime_error("EnterFullscreen failed: An invalid set of flags was passed in.");
    case DISP_CHANGE_BADMODE: throw std::runtime_error("EnterFullscreen failed: The graphics mode is not supported. ");
    case DISP_CHANGE_BADPARAM: throw std::runtime_error("EnterFullscreen failed: An invalid parameter was passed in. This can include an invalid flag or combination of flags. ");
    case DISP_CHANGE_FAILED: throw std::runtime_error("EnterFullscreen failed: The display driver failed the specified graphics mode. ");
    case DISP_CHANGE_NOTUPDATED: throw std::runtime_error("EnterFullscreen failed: Windows NT/2000/XP: Unable to write settings to the registry. ");
    case DISP_CHANGE_RESTART: throw std::runtime_error("EnterFullscreen failed: The computer must be restarted in order for the graphics mode to work. ");
    default: throw std::runtime_error("EnterFullscreen failed: Reason Unknown.");
    };

    ::ShowCursor(0);
    isFullscreen=true;
    }

    void LeaveFullscreenHelper()
    {
    isFullscreen=false;
    switch(::ChangeDisplaySettings(NULL,0))
    // switch(::ChangeDisplaySettings(&DMsaved,0))
    {
    case DISP_CHANGE_SUCCESSFUL: break;
    case DISP_CHANGE_BADFLAGS: throw std::runtime_error("LeaveFullscreen failed: An invalid set of flags was passed in.");
    case DISP_CHANGE_BADMODE: throw std::runtime_error("LeaveFullscreen failed: The graphics mode is not supported. ");
    case DISP_CHANGE_BADPARAM: throw std::runtime_error("LeaveFullscreen failed: An invalid parameter was passed in. This can include an invalid flag or combination of flags. ");
    case DISP_CHANGE_FAILED: throw std::runtime_error("LeaveFullscreen failed: The display driver failed the specified graphics mode. ");
    case DISP_CHANGE_NOTUPDATED: throw std::runtime_error("LeaveFullscreen failed: Windows NT/2000/XP: Unable to write settings to the registry. ");
    case DISP_CHANGE_RESTART: throw std::runtime_error("LeaveFullscreen failed: The computer must be restarted in order for the graphics mode to work. ");
    default: throw std::runtime_error("LeaveFullscreen failed: Reason Unknown.");
    };
    /* if(!::ChangeDisplaySettings(NULL,CDS_TEST))
    {
    ::ChangeDisplaySettings(NULL,CDS_RESET);
    ::ChangeDisplaySettings(&DMsaved,CDS_RESET);
    }
    else
    {
    ::ChangeDisplaySettings(NULL,CDS_RESET);
    }*/
    ::ShowCursor(1);
    }

    public:
    Window()
    :RC(0),DC(0),Wnd(0),Instance(0),isOpen(false),isAc tive(true),isFullscreen(true)
    {
    for(int i=0;i<256;i++)SysKeys[i]=Keys[i]=false;
    }
    ~Window()
    {
    Close();
    }

    void Open(char* Title, int Width, int Height, int Bits, bool tryFullscreen)
    {
    this->Width=Width;
    this->Height=Height;
    this->Bits=Bits;

    RECT WindowRect;
    WindowRect.left=(long)0;
    WindowRect.right=(long)Width;
    WindowRect.top=(long)0;
    WindowRect.bottom=(long)Height;

    Instance = GetModuleHandle(NULL);

    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = (WNDPROC) WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = Instance;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "OpenGL";
    if(!::RegisterClass(&wc)) throw std::runtime_error("Failed To Register The Window Class.");

    if(!::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DMsaved)) throw std::runtime_error("Failed To Enumerate The Display Settings.");

    isFullscreen=false;
    if(tryFullscreen) EnterFullscreenHelper();

    DWORD ExStyle;
    DWORD Style;
    if(isFullscreen)
    {
    ExStyle=WS_EX_APPWINDOW;
    Style=WS_POPUP;
    }
    else
    {
    ExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    Style=WS_OVERLAPPEDWINDOW;
    }
    ::AdjustWindowRectEx(&WindowRect, Style, FALSE, ExStyle);

    if (!(Wnd=::CreateWindowEx( ExStyle,
    "OpenGL",
    Title,
    Style /*| WS_CLIPSIBLINGS | WS_CLIPCHILDREN*/,
    0, 0,
    WindowRect.right-WindowRect.left,
    WindowRect.bottom-WindowRect.top,
    NULL,
    NULL,
    Instance,
    this)))
    {
    throw std::runtime_error("Window Creation Error.");
    }

    PIXELFORMATDESCRIPTOR pfd=
    {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    Bits,
    0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,PFD_MAIN_PLANE,0, 0,0,0
    };

    if(!(DC=::GetDC(Wnd)))
    {
    throw std::runtime_error("Can't Create A GL Device Context.");
    }

    GLuint PixelFormat;
    if(!(PixelFormat=::ChoosePixelFormat(DC,&pfd)))
    {
    throw std::runtime_error("Can't Find A Suitable PixelFormat.");
    }

    if(!::SetPixelFormat(DC,PixelFormat,&pfd))
    {
    throw std::runtime_error("Can't Set The PixelFormat.");
    }

    if(!(RC=::wglCreateContext(DC)))
    {
    throw std::runtime_error("Can't Set The PixelFormat.");
    }

    if(!::wglMakeCurrent(DC,RC))
    {
    throw std::runtime_error("Can't Set The PixelFormat.");
    }
    ::ShowWindow(Wnd,SW_SHOW);
    ::SetForegroundWindow(Wnd);
    ::SetFocus(Wnd);
    isOpen=true;
    }

    void Close()
    {
    if(!isOpen)return;
    isOpen=false;
    if(isFullscreen)
    {
    LeaveFullscreenHelper();
    }

    if(RC)
    {
    if(!::wglMakeCurrent(NULL,NULL))
    {
    throw std::runtime_error("Release Of DC And RC Failed.");
    }

    if(!::wglDeleteContext(RC))
    {
    throw std::runtime_error("Release Rendering Context Failed.");
    }
    RC=0;
    }

    if(DC&&!::ReleaseDC(Wnd,DC))
    {
    throw std::runtime_error("Release Device Context Failed.");
    DC=0;
    }

    if(Wnd&&!:estroyWindow(Wnd))
    {
    throw std::runtime_error("Could Not Release hWnd.");
    Wnd=0;
    }

    if(!::UnregisterClass("OpenGL",Instance))
    {
    throw std::runtime_error("Could Not Unregister Class.");
    Instance=0;
    }
    }

    bool Tick()
    {
    bool done=false;
    MSG msg;
    while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
    if (msg.message==WM_QUIT)
    {
    done=true;
    }
    else
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }
    return done;
    }

    void ToggleFullscreen()
    {
    int Style,ExStyle;
    if(isFullscreen)
    {
    LeaveFullscreenHelper();

    ExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
    Style=WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/;
    }
    else
    {
    EnterFullscreenHelper();

    ExStyle=WS_EX_APPWINDOW/*|WS_EX_TOPMOST*/;
    Style=WS_POPUP/*|WS_VISIBLE*/;
    }

    ::ShowWindow(Wnd,SW_HIDE); // <-- This keeps Desktop from getting "dirty" on W2k.

    ::SetWindowLongPtr(Wnd,GWL_STYLE,Style);
    ::SetWindowLongPtr(Wnd,GWL_EXSTYLE,ExStyle);

    if(!::SetWindowPos(Wnd,
    isFullscreen?HWND_TOPMOST:HWND_NOTOPMOST,
    0,0,Width,Height,
    /*SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|*/SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED))
    {
    throw std::runtime_error("SetWindowPos failed.");
    }
    }

    bool isInFullscreen() { return isFullscreen; }
    bool isKeyPressed(int i) { return Keys[i]; }
    bool isSysKeyPressed(int i) { return SysKeys[i]; }
    void AvoidRepeatingKey(int i) { Keys[i]=false; }
    void AvoidRepeatingSysKey(int i) { SysKeys[i]=false; }
    void Flip() { SwapBuffers(DC); }
    };

    #ifdef _WINDOWS
    int WINAPI WinMain( HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    #else
    int main(void)
    #endif
    {
    try
    {
    Window Win;
    Win.Open("[25] Press Alt-Enter to toggle fullscreen mode.",800,600,32,(MessageBox(NULL,"Would You Like To Start In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDYES));

    int Frame=0;
    while(!Win.Tick())
    {
    Frame++;
    glClearColor((Frame&1023)/1023.0f,Win.isInFullscreen()?1.0f:0.0f,0.0f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    Win.Flip();

    if(Win.isKeyPressed(VK_ESCAPE)

  2. #2
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Hmm.. Somehow the forum ate the last 20 lines of the code...
    </font><blockquote><font size="1" face="Verdana, Arial">code:</font><hr /><pre style="font-size:x-small; font-family: monospace;">//... continued from last message

    #ifdef _WINDOWS
    int WINAPI WinMain( HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    #else
    int main(void)
    #endif
    {
    try
    {
    Window Win;
    Win.Open("[25] Press Alt-Enter to toggle fullscreen mode.",800,600,32,(MessageBox(NULL,"Would You Like To Start In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDYES));

    int Frame=0;
    while(!Win.Tick())
    {
    Frame++;
    glClearColor((Frame&1023)/1023.0f,Win.isInFullscreen()?1.0f:0.0f,0.0f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    Win.Flip();

    if(Win.isKeyPressed(VK_ESCAPE)

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Strange. (Preview looked fine)

    Before I make a complete fool of myself (too late I guess ) here is a link to the source

    [edit]
    ( Just to clarify: samv==Rumzeus. Yes, I was already registered and logged in under this account when I posted the first two messages )[\edit]

  4. #4
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    While playing around whith the code some more I found that destroying and recreating the rendering context seems to help. The only problem remaining is that the computer completely freezes for 5 seconds

    Is this "normal"? A crappy driver? Am I misusing the API?

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Jan 2003
    Location
    Virginia
    Posts
    601

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    My only thought for this behaviour is either that the driver does have a bug or your display properties are set for changes to occur at restart rather than immediate.

    Open Display Properties dialog and verify the setting you have for Settings/Advanced/General/Compatibility is set to "Apply the new display settings without restarting".

    If that is set you should verify that you have the latest ATI drivers or Dell 8500 ATI Mobility Radeon 9000 drivers installed. And if all else fails contact Dell and/or ATI.

  6. #6
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Wow, I didn't actually know that setting existed. Thank you for that info. Unfortunately it is not the problem, as it _is_ set to "Apply the new display setting without restarting".

    Could anyone who owns an ATI mobility radeon 9000 (or even any ATI card) try to compile this and test if it fails? (Alt-Enter causes CDSTest.cpp to throw an exception / CDSTest2.cpp to freeze for 5 seconds) I could also provide exe files if that's preferred.

    The strange thing is, (some) other applications/games do not have this problem...

  7. #7
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Small update: really seems like an ATI problem. Another laptop with a radeon mobility has the same problem. (Updating the drivers slightly changed the behaviour, but didn't fix it).

  8. #8
    Junior Member Newbie
    Join Date
    Dec 2001
    Location
    Switzerland
    Posts
    29

    Re: ChangeDisplaySettings(NULL,0) returns DISP_CHANGE_RESTART (on ATI?)

    Just pretending anyone out there cares

    Another (non-dell) mobility radeon (9200) laptop has no problem at all with this...

    A problem with dell's drivers?

    Just wondering: Does anyone know in what way / to which degree laptop manufacturers customize video drivers?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •