Archived

This topic is now archived and is closed to further replies.

Rixter

DirectDraw Surface Problem

Recommended Posts

I have a very strange problem here, for some reason my program won''t create the primary surface using if(FAILED(lpDD->CreateSurface(&ddsd_, &primary_, NULL))) it gets to that line and stops. I''ve tried everything I can think of, taking it out of my class and putting it directly in WinMain, initializing the window several different ways, initializing directdraw several different ways, even intializing directdraw through the COM objects, all with the exact same result. I have all the includes I need and there are no problems until it reaches this point. If anyone has any idea what may be causing this, I could really use the help, thanks. __________________________________________ We get signal. There are bombs exploding all around us!!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I have the exact same problem. I''ve narrowed it down to adding a back buffer. I can get it to work in windowed mode without a back buffer though.

The return value that I would get is -2005532460 but I have no idea what DD code is associated with that.

Share this post


Link to post
Share on other sites
2 Anonymous

>get is -2005532460 but I have no idea what DD code is
>associated with that

DDERR_NOCOOPERATIVELEVELSET

Means you should set cooperative level BEFORE you create a surface.

Good luck.

Share this post


Link to post
Share on other sites
i know its stupid, but maybe itll help

did u remember to use your
ddsd.dwSize = sizeof(ddsd) ?

i once had the same prob, and it
turns out that was the prob, since
you must initialize it to zero

gil

Micro$oft beta testing:
"Does the splash screen works? SHIP IT!!!"

Share this post


Link to post
Share on other sites
Well, things seem to be working now. The code to initialize and do everything is exactly the same as before, but I put most of it into main (the initializing direct draw stuff), the surfaces seem to be created ok now (this is done in a seperate class) so I don''t really have any idea what the problem was. The only thing I can think of is that I could have passed the LPDIRECTDRAW7 thing wrong, don''t know how though. After I know things are working and stable, I may try to break things out again, but who knows.

__________________________________________
We get signal.
There are bombs exploding all around us!!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Now in windowed mode I dont have problems, but fullscreen is very hard to troubleshoot.

With fullscreen mode, it looks like it created the window because the background is the default window color and it looks like it changes the resolution to 640x400 because I get a large mouse pointer.

Here is the code I use (this is the function where it dies):
DDOBJ is LPDIRECTDRAW7
Primary and Back are LPDIRECTDRAWSURFACE7
RWidht is being passed 800 and RHeight is being passed 600

DDWnd::DDWnd(unsigned long RWidth, unsigned long RHeight)
{
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;

Primary = NULL;
Back = NULL;
ResX = RWidth;
ResY = RHeight;

hWnd = CreateWindowEx(
WS_EX_TOPMOST,
"#32770",
"",
WS_POPUP,
0,
0,
1,
1,
NULL,
NULL,
GetModuleHandle(NULL),
NULL);

if (DD_OK != DDOBJ->SetCooperativeLevel(hWnd,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN))
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return;
}

DDOBJ->SetDisplayMode(ResX, ResY, 16, 0, 0);

ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;

if (DDOBJ->CreateSurface(&ddsd, &Primary, NULL) == DDERR_NOCOOPERATIVELEVELSET)
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return;
}

ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
Primary->GetAttachedSurface(&ddscaps, &Back);
}

Share this post


Link to post
Share on other sites
2 Anonymous

I checked my code for DD7 init and it looks almost exactly
the same, except that it''s located in WinMain().

It works fine with DX Retail and it fails to CreateSurface with DX Debug (for whatever reason). So, make sure you run DX Retail.
Also, you gotta be sure that DDWnd constructor is launched from the main thread, or else...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Thank you Friday 13. In all the DD tutorials I read not one mentioned that debug would affect anything.

Share this post


Link to post
Share on other sites
1. In a debugger (F5 with debug app in MSVC), calling GetModuleHandle to find the application instance can end up getting the DEBUGGERS instance. Your program is run as a child process - I won''t go into the gory details, but normally its impossible for two applications to run at the same time and see each others address space - MSVC/a debugger has to do some nasty stuff to make it sort of appear like its happened.

2. If any objects based on DDWnd are global/static in your program, then thats ***VERY BAD***. Static/Global constructors get called **before** the C runtime library initialisation for your application has completed (if anyone needs the gory but clever details [__xc_a etc] I''ll explain them).

Doing any allocation or system coding in a constructor (static or not) is bad programming practice IMO - the only way to get errors back to client code is via exceptions, and a constructor isn''t a very nice place to cause one from (ie. object in half constructed state, partway through the allocator code).



--
Simon O''''Connor
Creative Asylum Ltd
www.creative-asylum.com

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Well, the no debug mode helped some. Now I just get a screen with the default window color and an hour glass until my clock class I set up kicks in in 10 seconds and ends the program since it doesn''t respond to any key strokes. Here is the WinMain code where MainWnd is a DDWnd* and InitDD() calls DirectDrawCreateEx and creates MainWnd with MainWnd = new DDWnd(640, 400)

int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdParam, int nCmdShow)
{
LPMSG msg = new MSG;

nClock = new Clock;
if (!InitDD()) return 1;

while (1)
{
//So I dont have to restart my comp if it doesn''t work!
if (nClock->GetElapsed() >= 10000)
{
delete MainWnd;
if (DDOBJ) DDOBJ->Release();
return 0;
}

if (PeekMessage(msg, NULL, 0, 0, PM_NOREMOVE))
{
switch (msg->message)
{
case WM_KEYDOWN:
switch (msg->wParam)
{
case VK_ESCAPE:
return 0;
break;
};
break;
default:
TranslateMessage(msg);
DispatchMessage(msg);
};
}
else
{
MainWnd->Primary->Flip(NULL, DDFLIP_WAIT);
}
}

delete MainWnd;

if (DDOBJ) DDOBJ->Release();

return 0;
}

Share this post


Link to post
Share on other sites
2 Anonymous

>Now I just get a screen with the default window color

You didn't expect something to show up before you actually draw it, did you? Also, make sure you intercept WM_ERASEBKGND, WM_NCPAINT, WM_NCCALCSIZE and never allow them to DefWndProc. Otherwise, the system redraws your window each time you flip.

BTW, I personally keep my draw-flip loop in a separate thread,
apart from the MessageLoop.

Edited by - Friday13 on August 13, 2001 3:44:53 AM

Share this post


Link to post
Share on other sites
Anonymous was me. Anyway, I intercepted the 3 messages, but I still get the grey screen with the hour glass. I placed a sound file to play each time it does the flip routine and the sound never plays which leads me to believe it never makes it to the flip routine.

Invader X
http://www.invadersrealm.com

Share this post


Link to post
Share on other sites
Invader X

Nice to meet you.

Like I said, try to Clear2 at least (let alone drawing something)so you can see if any change happens to the back buffer at all. Besides, i''m not sure how this construction:

if PeekMessage(...) Translate ELSE flip

should work. Maybe you''re getting some constant flow of incoming messages so you never get to ELSE clause. Or, maybe you''re getting no messages and, since you don''t draw anything, it''s flipping so fast you don''t even notice, but you can''t say ''cos you didn''t make changes to the surfaces.

Share this post


Link to post
Share on other sites
Thanks. It works now.

You were right that it was set up to have a constant flow of messages. When I double checked it again I noticed that I was using PM_NOREMOVE which left the messages in the queue so they were always being read again. I switched to PM_REMOVE and it works.

Thanks again =)

Share this post


Link to post
Share on other sites