Advertisement

res switching on the fly: Directx

Started by August 12, 2000 03:22 AM
10 comments, last by skitzo_smurf 24 years, 4 months ago
hey, Im trying to simply switch resolutions on the fly by pressing a key. Here is what I am doing 1.After creating main direct draw object I enumerate all display modes and store the valid ones in a structure. 2. do other initialization stuff( such as creating a few surfaces that hold bitmaps) 3. In game loop I look for the F1 or F2 key to switch modes. 4. If either key is pressed I do the following - switch to the new mode. TRY to restore surfaces. If that fails I delete all direct draw objects including the main direct draw object. Then I re-create all surfaces. Now One of two things happen 1) when I try to recreate the primary surface WITHOUT resetting the cooperative level( im using fullscreen, exclusive by the way) I get DDERR_NOCOOPERATIVELEVELSET 2) So I try to reset the cooperative level. Then I get DDERR_EXCLUSIVEMODEALREADYSET What am I doing wrong here? By the way, I may have left something out here...if you want more specifics just ask. thanks in advance, skitzo_smurf Edited by - skitzo_smurf on 8/12/00 3:44:56 AM
"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf
ok,
Maybe Im asking the wrong question here. Ill try again more specifically. If you call TestCooperativeLevel() and it returns DD_OK, THEN you call RestoreAllSurfaces() and that fails....what
course of action do you have to take to remake all of your surfaces? ALSO - please disregard the error messages from above. I am no longer getting them. Just treat this as a new post.
Ex:

        void restoreSurfaces(){   HRESULT hr;   hr = lpDD->TestCooperativeLevel();      if(hr == DD_OK)   {       hr = lpDD->RestoreAllSurfaces();              if(FAILED(hr))       {           // what is the PROPER course of action to take            // in this case?           // Currently I am releasing all surfaces and then           // destroying the main direct draw object, but           // it doesnt seem to work - maybe im doing something           // wrong       }       // now reload all of your bitmaps and such    }}ALSO - one more curiosity I have...is it okay to do this?void shutDown(){    //assume that lpDD is the main direct draw object   if( lpDD != NULL )   {         //first release all of your other surfaces in reverse        //order of creation                //now get rid of main object....can you rely on RefCount?        int refCount = lpDD->Release();        while(refCount != 0) refCount = lpDD->Release();        lpDD = NULL;   }}        


I heard that you cant rely on the number returned from Release
sometimes, but it appears that I have an extra reference to lpDD
and I dont know where its coming from. I THINK that may be the cause of my problem. Does EnumDisplayModes() ever make an extra reference to your main DDraw object?

DX = HEAD_ACHE,
skitzo_smurf

Edited by - skitzo_smurf on August 13, 2000 3:14:58 AM
"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf
Advertisement
uhh...anyone have any ideas or just a general algorithm for res switching? Please help me out. Look, I even used the really cool eyeball icon! That should count for something! Ill...uh...send you naked pics of me or something(you dont wanna see it though - TRUST ME). *background noise* "PUT THAT THING AWAY!!!!!"

*snap*,
skitzo_smurf

"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf
you are correct in not relying on the values returned from Release(). if you release all objects that need to be released (ie. primary surface and created surfaces) then the ddraw object you should be fine for shutdown.
make sure you do not destroy the window before releasing ddraw, this is what causes the strange window resizing behavior and "leftover buttons" in the taskbar.

as far as the other problem, are you recreating ddraw and setting your pointer to the new interface before calling RestoreAllSurfaces()? if i'm not mistaken the only error that can return is "invalid ddraw object".

also, how are you checking for F1/F2? by GetAsyncKeyState? do you suppose you could just be switching the resolutions too fast?

oh, and please DON'T send naked pictures. i'm not into smurfs

crazy166
some people think i'm crazy, some people know i am

Edited by - crazy166 on August 13, 2000 5:43:13 PM
Yes, I am using GetAsyncKeyState() to test for F1 or F2, and no, im calling RestoreAllSurfaces() BEFORE I make a new interface. If RestoreAllSurfaces() fails then I make a new interface. Any ideas? Oh..and thanks for replying. Ive been trying to get this to work for three days!

skitzo_smurf
"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf
this is going to sound stupid, but you didn''t release the old interface before calling restore...wait. then testcooperativelevel would''ve failed, right.

about the getasynckeystate, i just thought that perhaps your switching code is working, however, each time through the game loop while F1/F2 is down it may be switching AGAIN, which might cause some problems, i don''t know.

you may want to check the return from SetDisplayMode and if it fails, reset the mode to the previously selected mode.

if you would like, i can send you my wrapper for handling dx related stuff like resolution switching and selection this (can''t post, a little longish). it may give you some ideas, however it is using D3DX, so it probably won''t be very much cut-and-paste if you''re doing something 2d. D3DX also simplifies things nicely. you may want to try to use the D3DX utils to setup your devices.

crazy166
Advertisement
in fact, i just thought of something. if you are releasing your ddraw interface and recreating. you should also release all other interfaces,

DXShutDownAndRestore(){    if ( gpDD )    {        if ( gpPrimary )        {            gpPrimary->Release();        }        for ( all extra surfaces )        {            surf->Release();        }        gpDD->Release()    }    //now everything should be shutdown properly, restore    DirectDrawCreate( &gpDD );    gpDD->SetCooperativeMode( DDSCL_EXCLUSIVE );    //...} 


that may help.

crazy166
ok, my problem really isnt getting the display mode to change....its recreating the surfaces properly. Here is the important code

    /* This gets called when a function key is pressed. */HRESULT changeMode(int width, int height, int newColorDepth){    HRESULT hr;   DDSURFACEDESC2 ddsd;   DD_INIT_STRUCT(ddsd);	   // see if the new mode is listed in the user''s available   // display modes   // first set up a surface description to describe the mode to    // directdraw   ddsd.dwWidth = width;   ddsd.dwHeight = height;   ddsd.ddpfPixelFormat.dwRGBBitCount = newColorDepth;	   // if mode is available   if( modes.displayModeListed(ddsd))   {			// switch display mode	if(FAILED( hr =         ( lpDD->SetDisplayMode(width,height,newColorDepth,0,0))))	               handleError(hr,errorFile,                       "SetDisplayMode Failed in changeMode()",                        true);			return(hr);		    	// set the global variables describing the display mode          // to the new display mode	appWidth = width;	appHeight = height;	colorDepth = newColorDepth;	// restore or remake all surfaces in the game for the         // new video mode	restoreSurfaces();			// load the bitmaps back onto the surfaces	// first load the backGround onto the primary surface	bitmapToSurface(lpDDSPrimary,              fullScreenGraphics[currentBackGround],colorDepth);			else // else if mode not available	{	   // Output error telling user that the video            // mode is not supported by their hardware	   MessageBox(handleMain,                      "That display mode is not supported",                       NULL, MB_OK);           // return NULL for failure	   return NULL; //the display modwe was not supported	}}void restoreSurfaces(){   HRESULT hr;   // test the cooperative level to see if we can restore the    // surfaces   hr = lpDD->TestCooperativeLevel();   // if its okay to restore   if(hr == DD_OK)   {	      // restore the surfaces      hr = lpDD->RestoreAllSurfaces();		      if( FAILED(hr) )      {	  shutDown(); // releases ALL objects          // try to recreate the surfaces            // but first the main direct draw object          hr = DDrawCreate(lpDD);							  if( FAILED(hr) )	     handleError(hr,errorFile,                    "Couldnt recreate directdraw in restore()",                     true);	              /*This is where im confused. Do I have to reset the             cooperative level since I have a new DirectDraw             object??? If I DO - I get               DDERR_EXCLUSIVEMODEALREAYSET, If I DONT I get             DDERR_NOCOOPERATIVELEVELSET when I try to reallocate             memory for the primary surface. So, I tried              explicitly resetting the cooperative level to              DDSCL_NORMAL before I released the first interface              ....this gets me past the              DDERR_EXCLUSIVEMODEALREADYSET, but it STILL                doesnt work */             hr = lpDD->SetCooperativeLevel(                   handleMain,                   DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT |                    DDSCL_EXCLUSIVE);				    if( FAILED(hr) )		handleError(hr,errorFile,                              "SetCooperativeLevel failed",true);				    // NOW we can re-create the surfaces	    hr = DDrawCreatePrimary(lpDD, lpDDSPrimary,                                    lpDDSBack, 1);            if( FAILED(hr))		handleError(hr,errorFile,"DDrawCreatePrimary()                            failed",true);				    if( ( lpDDSBackGround =                  DDrawCreateSurface(lpDD, appWidth, appHeight,                                     DDSCAPS_SYSTEMMEMORY) )                 == NULL )		handleError(NULL, errorFile,                 "DDCreateSurface failed in gameInit()", true);					}      }   }}    


Sorry for the long post...Ok, ive tried this several ways. Either I get past the SetCooperativeLevel() and get a surface
creation error, or I flat out cant reset cooperativelevel.

ideas? Suggestions?,
skitzo_smurf
"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf
I dunno what "testcooperativelevel()" does...
but here''s what I''d do.

init:
create main dd object

main:
if key pressed{
setcooplevel(NORMAL);
release all
setcoolelevel(exclusive)
setdisplaymode()
create all surfaces
}

shutdown:
setcooplevel(normal)
release all
release main dd object
___________________________Freeware development:ruinedsoft.com
Thanks..im going to try immediately.

be back,
skitzo_smurf
"Innocent is just a nice way to say ignorant, and stupidity is ignorance with its clothes off."words of,skitzo_smurf

This topic is closed to new replies.

Advertisement