Game Programming and Development Tools

DirectX (DirectDraw) Problem - Need Help! – Sturmritter

Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
To any and all who might have an answer!!!!

I've been trying to get a GDI-based Dialog blitted to an Offscreen DirectDraw (LPDIRECTDRAW7) Plain surface BEFORE it goes to the Primary Surface backbuffer!

ShowWindow(DialogWindow, SW_NORMAL); seems to put it in the backbuffer of the primary, so I tried to bypass that by creating the following code:

HDC hdcScreen, hdcBuffer;
LPRECT SourceRect;
HINSTANCE hInst;
#ifdef _WIN64
hInst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
#else
hInst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);
#endif
DlgWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, (DLGPROC)SampleDlgProc);

// Here's where ShowWindow(DlgWnd, SW_NORMAL); would normally go
// And here is where I've attempted a bypass to DrawSurface (Plain
// offscreen)

// Get Dialog Device Context
Manager->GetInterface(&DD7); // Gets an LPDIRECTDRAW7 pointer called DD7
DD7->GetGDISurface(&DDS7); // Get Surface from GDI and assigns to
// LPDIRECTDRAWSURFACE7 called DDS7
DDS7->GetDC(&hdcScreen);
// Get Draw Surface Device Context
DrawSurface->GetInterface(&DDS7);
DDS7->GetDC(&hdcBuffer);
// Get Dialog RECT structure and break into components...
GetWindowRect(DlgWnd, SourceRect);
long x = SourceRect->left;
long x2 = SourceRect->right;
long y = SourceRect->top;
long y2 = SourceRect->bottom;
// Finally Blit the data to the DrawSurface!!
BitBlt(hdcBuffer, x, y, x2, y2, hdcScreen, 0, 0, SRCCOPY);
// Now release the Device Contexts
DDS7->ReleaseDC(hdcScreen);
DDS7->ReleaseDC(hdcBuffer);

//*************************************************************

The code above compiles fine on MS Visual C++ compiler, but when I run program, my code returns an error that the Surface in question is locked by another thread. Is there a better way to accomplish my goal of blitting the dialog to an offscreen buffer? or can I force the surface to unlock somehow before relocking?

Any comments are appreciated. I'm just trying to learn here =)

Thanks in advance!

- Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"
Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
Well, I discovered my problem (Well, at least partially....)

I added another LPDIRECTDRAWSURFACE7 pointer called GDIPointer
to handle the GDI hdcScreen device context, because apparently the DDS7 pointer was locked by it when I attempted to use it to assign hdcBuffer DC as well.

The new code looks like this:

Manager->GetInterface(&DD7);
DD7->GetGDISurface(&GDIPointer);
GDIPointer->GetDC(&hdcScreen);
...
...
GDIPointer->Release(&hdcScreen);

While this works to blit the IMAGE of the current Dialog to an offscreen buffer, it does not track any dynamic changes to the Dialog. Therefore it seems a bit impractical for anything but static dialog boxes. HOWEVER, the process does work for any offscreen plain Direct Draw Surface! (Which is a good thing! hehe)

Try it and you can blit multiple dialog images about the screen as if they were sprites! hehe. Not particularly useful unless you want to create a dialog as sprite, but it's neat to learn these things.

I think I'm going to try another approach to blitting dialogs dynamically to offscreen buffers. I'll post what I learn here when I finish.

Hope that helps, and thanks to all who at least looked at my earlier post!

God Bless,

Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"
Briant

Member

Posts: 742
From: Stony Plain, Alberta, Canada
Registered: 01-20-2001
Hi,

Are you doing this just to learn how DDraw works? Or are you trying to get dialog boxes to appear (and work) overtop of the primary surface? Once you blit, it is no longer a dialog, but just a bitmap on a DX surface.

Brian

------------------

Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
I did it just to learn some capabilities, and see what could or could not be done.

Eventually I do want to be able to draw the actual dialog onto the primary surface without it erasing everything there. (I'm not familiar enough with clipper objects to figure out how to associate it properly. I.e. with the dialog or with the surface.)

Additionally I've got an interesting methodology that may hold some promise.

Basically I have 3 surfaces I am working with. 1 Primary, and 2 plain.

One plain surface is my basic construction site for bitmaps. Another plain surface I use specifically to display FPS and other data to benchmark.

My method right now is to take my constructions, blit them to my FPS/data display surface, then blit the combined surfaces to the primary back buffer and then flip the page.

How would I construct a clipper for the Dialog if I were to show the dialog window after I flip the primary backbuffer?

Thanks in advance!

- Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"
Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
Btw, Here is my Current RedrawScreen Function:

/*

Each surface is encapsulated to include Blit routines called by function Surface::BlitTo(*Surface, long SourceX, long SourceY);

DD7 is a global LPDIRECTDRAW7 pointer
DDS7 is a global LPDIRECTDRAWSURFACE7 pointer
FPSSurface is my FPS/Data Surface
DrawSurface is my text/data surface

Surface is the Primary Surface and Surface::Show() is function to flip surface buffers and display front.

TextTo is a class to bitmap textstrings.

Surfacebuffer is a local LPDIRECTDRAWSURFACE7 pointer in case of need to Restore lost surfaces.

FPSCounterOn and DialogOn are global booleans which flag if these items ought to be displayed.
*/
//***********************************************************************

bool RedrawScreen()
{
//******** Time Variables for FPS calculations
int time;
int timediff;

LPDIRECTDRAW7 dd7;
LPDIRECTDRAWSURFACE7 Surfacebuffer;
Manager->GetInterface(&dd7); // Get Manager Interface pointer
if(dd7 == NULL) return false; // If not present, return
FPSSurface->GetInterface(&DDS7); // Get pointer for FPS Display
Surface->GetInterface(&Surfacebuffer);
time = timeGetTime();
timediff = time - timelast;
count++;
if(timediff >= 1000) // on clock tick
{
frame = count;
timelast = time;
timediff = 0;
count = 0;
}
//******** FPS Display routine
if(Surfacebuffer->IsLost()) // Restore all surfaces
{
Surfacebuffer->Restore();
DrawSurface->GetInterface(&Surfacebuffer);
Surfacebuffer->Restore();
FPSSurface->GetInterface(&Surfacebuffer);
Surfacebuffer->Restore();
}
char buff[40]; // create FPS display buffer
itoa(frame, buff, 10); // convert FPS into string for display
// Check for FPS On/off
if(FPSCounterOn)
{
TextTo->SelectFont(Font2);
TextTo->DrawText(DDS7, 0, 0, "FPS:");
TextTo->DrawText(DDS7, 60, 0, buff); // draw text to DrawSurface
TextTo->SelectFont(Font1);
FPSSurface->BlitTo(*Surface, 0, 0);
DrawSurface->BlitTo(*FPSSurface, 0, 0);
if(DialogOn)
{
ShowWindow(DlgWnd, SW_SHOWNORMAL);
}

}
else if(DialogOn)
{
FPSSurface->BlitTo(*Surface, 0, 0);
DrawSurface->BlitTo(*FPSSurface, 0, 0);
ShowWindow(DlgWnd, SW_SHOWNORMAL);
}
else
{
FPSSurface->BlitTo(*Surface, 0, 0);
DrawSurface->BlitTo(*FPSSurface, 0, 0);
}
Surface->Show(); // Flip BackBuffer and Display as new Primary
// Question to Reader here: Should I ShowDialogWindow here after flipping
// and displaying content buffer, or not?
return true;
}
//************************************************************************

Can someone determine where my flaw in logic is? What I get is a quick blit of the dialog to the front buffer before it suddenly disappears.

Is this due to the last command being Surface->Show(); ?
I'll see if that's the case, but I've tried almost every combination of ShowWindow and buffer flip imaginable, and I'm wondering if I ought to encapsulate a dialog checker in my Show() function.

Again, any solutions or comments are welcome!

- Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"
Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
Well, I've conquered this problem after all!

Eliminating most of the primary surface buffer flipping, I created a clipper to the primary surface and then simplay flip the buffer only if no dialog needs to be displayed. (Aparently ShowWindow is basically a flip which blits the GDI surface to the front primary surface buffer.)

Here is my solution to the above RedrawScreen function():

// Create a clipper for the Primary Surface in order to display GDI
Manager->GetInterface(&DD7);
DD7->CreateClipper(0, &Clipper, NULL);
Clipper->SetHWnd( 0, WndHandle);
Surface->GetInterface(&DDS7);
DDS7->SetClipper(Clipper);

bool RedrawScreen()
{
//******** Time Variables for FPS calculations
int time;
int timediff;

LPDIRECTDRAW7 dd7;
LPDIRECTDRAWSURFACE7 Surfacebuffer;
Manager->GetInterface(&dd7); // Get Manager Interface pointer
if(dd7 == NULL) return false; // If not present, return
FPSSurface->GetInterface(&DDS7); // Get pointer for FPS Display
time = timeGetTime();
timediff = time - timelast;
count++;
if(timediff >= 1000) // on clock tick
{
frame = count;
timelast = time;
timediff = 0;
count = 0;
}
//******** FPS Display routine
Surface->GetInterface(&Surfacebuffer); // Check for lost surfaces
if(Surfacebuffer->IsLost()) // Restore all surfaces
{
Surfacebuffer->Restore();
DrawSurface->GetInterface(&Surfacebuffer);
Surfacebuffer->Restore();
FPSSurface->GetInterface(&Surfacebuffer);
Surfacebuffer->Restore();
}
char FPSBuff[40];
itoa(frame, FPSBuff, 10); // convert FPS into string for display
// Check for FPS On/off
if(FPSCounterOn)
{
TextTo->SelectFont(Font2);
TextTo->DrawText(DDS7, 0, 0, "FPS:");
TextTo->DrawText(DDS7, 60, 0, FPSBuff); // draw text to DrawSurface
TextTo->SelectFont(Font1);
FPSSurface->BlitTo(*Surface, 0, 0);
DrawSurface->BlitTo(*FPSSurface, 0, 0);
}
else
{
FPSSurface->BlitTo(*Surface, 0, 0);
DrawSurface->BlitTo(*FPSSurface, 0, 0);
}
if(!DialogOn) Surface->Show();
return true;

Thanks for all your help!

God Bless,
- Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"
Briant

Member

Posts: 742
From: Stony Plain, Alberta, Canada
Registered: 01-20-2001
Hey,

You can improve the performace by moving this chunk of code:


LPDIRECTDRAW7 dd7;
LPDIRECTDRAWSURFACE7 Surfacebuffer;
Manager->GetInterface(&dd7); // Get Manager Interface pointer
if(dd7 == NULL) return false; // If not present, return
FPSSurface->GetInterface(&DDS7); // Get pointer for FPS Display

Move it outside of the RedrawScreen function, because you should only need to do these steps once.

Brian

------------------

Sturmritter

Member

Posts: 17
From: San Rafael, CA, USA
Registered: 06-13-2002
Thanks Brian! I'll try that as well.


Now on to another DirectX question:

Do you happen to know any clean methods of dynamically changing the screen display modes and restoring the surfaces?

Now that I have my dialog working, I've made it into a combo-list box which allows me to select display modes.

When I activate it, however, I get the screen mode change, but when I attempt to restore my surfaces, I crash to the desktop.

Any ideas on how to solve this? I've tried resetting the clipper for the primary surface and resetting the general display modes of my offscreen surfaces with no success.

Do I need to create whole new surfaces at the new resolutions and then blit the information to them? or is their any easier and more time-efficient method?

Thanks in advance!

- Sturmritter

------------------

quote:
...in the immortal words of Socrates who said, "I drank WHAT?!?!?"