Skip to main content
GameDev.net gamedev.net
🔒 Locked

DirectDraw problem

Started by staticVoid2 Jan 27, 2008 at 5:25 AM 19 replies 2k views
Original Post
staticVoid2
staticVoid2
hi, I'm fairly new to directdraw and am running into a few problems - when you set the cooperative mode, what should you normally pass as the handle to the window? I tried NULL, HWND_DESKTOP(include windows.h) and eventually i created a basic win32 app which displayed a window and passed the handle of that which was the only thing that worked. here's the code:


#include <ddraw.h>

int main() {

   HGRESULT check;
   LPDIRECTDRAW lpdd;

   check = DirectDrawCreate(NULL, &lpdd, NULL);
   if(check != DD_OK)
      return -1;

   check = lpdd->setCooperativeMode( <???> , DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
   if(check != DD_OK)
      return -1;

   check = lpdd->setDisplayMode(800, 600, 8);
   if(check != DD_OK)
      return -1;
   

}



when I pass a handle to a window after CreateWindowEx it shows it at fullscreen at 800x600 res. any ideas?
renman29
renman29
If I remember correctly, you would pass the hwnd you used to create your window app. ie:
g_hwnd = NULL; //global var
...
g_hwnd = CreateWindowEx(....
...
DDraw->SetCooperativeLevel(g_hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);

Hmm. If that's what you're already doing then that would be right I think.

staticVoid2
staticVoid2
thanx, it does work but i thought directdraw gave you direct acces to video memory and therefore windows would not be displayed? or do you have to create a palette first?
jollyjeffers
jollyjeffers
Yes, DirectDraw in fullscreen exclusive mode does give you direct access (although, under Windows Vista I think this may well be emulated now). However the DirectDraw runtime as well as your software must still interact with the underlying operating system and creating a Window is a primary mechanism for this. The Window will still receive Windows Messages that you'll need to be aware of.

hth
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
staticVoid2
staticVoid2
I'm using windows vista, heres a screen shot of what it looks like:
Free Image Hosting at www.ImageShack.us

is that what it's supposed to look like(in fullscreen)?
Evil Steve
Evil Steve
Quote:
Original post by staticVoid2
I'm using windows vista, heres a screen shot of what it looks like:
Free Image Hosting at www.ImageShack.us

is that what it's supposed to look like(in fullscreen)?
That's not fullscreen. If you can see the window border, it's not fullscreen. Are you creating the window? I've never actually used DirectDraw with Vista, are you sure you want to be using it ratehr than Direct3D?
staticVoid2
staticVoid2
the window shows on the fullscreen - i thought direct3d was just an extension of directdraw but with functions for texturemapping, vector conversions etc.
Evil Steve
Evil Steve
Quote:
Original post by staticVoid2
the window shows on the fullscreen - i thought direct3d was just an extension of directdraw but with functions for texturemapping, vector conversions etc.
I'm confused - the screenshot you showed shows a window title. If it was fullscreen the window title shouldn't be visible.

Direct3D provides direct access to the graphics card. It used to be the case (10 years ago) that DirectDraw was best for performance, but now almost every card can do 3D, Direct3D is lower level. As Jack said, DirectDraw is emulated through Direct3D in Vista, so using DirectDraw will actually be slower than using Direct3D.

What exactly are you trying to do? It may be simpler to use DirectDraw, but unless you're writing something extremely low level, you'll almost certainly be better off with D3D.
staticVoid2
staticVoid2
that is what appears on screen with the code I use - here's the full source code, I just used visual c++'s template for a win32 app:
#include <ddraw.h>#include <cstdio>#include <windows.h>/*  Declare Windows procedure  */LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);/*  Make the class name into a global variable  */char szClassName[ ] = "WindowsApp";FILE * log;LPDIRECTDRAW lpDD;LPDIRECTDRAWSURFACE ddPrimary;DDSURFACEDESC ddsd;int WINAPI WinMain (HINSTANCE hThisInstance,                    HINSTANCE hPrevInstance,                    LPSTR lpszArgument,                    int nFunsterStil){    HWND hwnd;               /* This is the handle for our window */    MSG messages;            /* Here messages to the application are saved */    WNDCLASSEX wincl;        /* Data structure for the windowclass */    /* The Window structure */    wincl.hInstance = hThisInstance;    wincl.lpszClassName = szClassName;    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */    wincl.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;                 /* Catch double-clicks */    wincl.cbSize = sizeof (WNDCLASSEX);    /* Use default icon and mouse-pointer */    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);    wincl.lpszMenuName = NULL;                 /* No menu */    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */    wincl.cbWndExtra = 0;                      /* structure or the window instance */    /* Use Windows's default color as the background of the window */    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;    /* Register the window class, and if it fails quit the program */    if (!RegisterClassEx (&wincl))        return 0;    /* The class is registered, let's create the program*/    hwnd = CreateWindowEx (           0,                   /* Extended possibilites for variation */           szClassName,         /* Classname */           "Windows App",       /* Title Text */           WS_OVERLAPPEDWINDOW, /* default window */           CW_USEDEFAULT,       /* Windows decides the position */           CW_USEDEFAULT,       /* where the window ends up on the screen */           544,                 /* The programs width */           375,                 /* and height in pixels */           NULL,        /* The window is a child-window to desktop */           NULL,                /* No menu */           hThisInstance,       /* Program Instance handler */           NULL                 /* No Window Creation data */           );    /* Make the window visible on the screen */   // ShowWindow (hwnd, nFunsterStil);   HRESULT check;   log = fopen("C:\\ddlog.txt", "w");   check = DirectDrawCreate(NULL, &lpDD, NULL);   if(check != DD_OK) {	  lpDD->Release();      fputs("could not create direct draw", log);   }   check = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_ALLOWREBOOT);   if(check != DD_OK) {   	  lpDD->Release();      fputs("could not set cooperative mode", log);   }   check = lpDD->SetDisplayMode(800, 600, 8);   if(check != DD_OK) {   	  lpDD->Release();      fputs("could not set display mode\r\n", log);   }   ddsd.dwSize = sizeof(ddsd);   ddsd.dwFlags = DDSD_CAPS;   ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;   ddsd.dwBackBufferCount = 1;   check = lpDD->CreateSurface( &ddsd , &ddPrimary, NULL);   if(check != DD_OK) {      fputs("could not create surface\r\n", log);   }HDC hdc;if (ddPrimary->GetDC(&hdc) == DD_OK){    SetBkColor( hdc, RGB( 0, 0, 255 ) );    SetTextColor( hdc, RGB( 255, 255, 0 ) );    TextOut( hdc, 0, 0, "hello world!", 12 );    ddPrimary->ReleaseDC(hdc);}    /* Run the message loop. It will run until GetMessage() returns 0 */    while (GetMessage (&messages, NULL, 0, 0))    {        /* Translate virtual-key messages into character messages */        TranslateMessage(&messages);        /* Send message to WindowProcedure */        DispatchMessage(&messages);    }    /* The program return-value is 0 - The value that PostQuitMessage() gave */    return messages.wParam;}/*  This function is called by the Windows function DispatchMessage()  */LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){    switch (message)                  /* handle the messages */    {        case WM_DESTROY:            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */            break;        default:                      /* for messages that we don't deal with */            return DefWindowProc (hwnd, message, wParam, lParam);    }    return 0;}


Quote:

What exactly are you trying to do?


I'm trying(beginning) to create a basic 3d engine, I was quite a bit through it in Java but I decided to switch to c++ for speed.
Evil Steve
Evil Steve
Quote:
Original post by staticVoid2
I'm trying(beginning) to create a basic 3d engine, I was quite a bit through it in Java but I decided to switch to c++ for speed.
Unless you mean a software rasterizer (And it's for learning purposes, not speed), why on earth aren't you using Direct3D? [smile]
1. It's hardware accelerated, DDraw isn't
2. You get alpha blending for free
3. You get rotation for free

There's a few things wrong with the code I see:
1. WS_OVERLAPPEDWINDOW means "A normal window". You probably want to use WS_POPUP, which has no borders.
2. wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; should be wincl.hbrBackground = (HBRUSH) (COLOR_BACKGROUND+1);
3. Your window size bares no resemblance to the size of surface you tell DDraw to use.
4. You shouldn't check against DD_OK, use the SUCCEEDED and FAILED macros instead. I know several DDraw functions return values other than DD_OK for success.
5. If DirectDrawCreate fails, lpDD isn't initialised, so Release()ing it will cause a crash.

Also, you seem to be using an out of date version of DirectDraw. DDraw 1 is absolutely ancient (1995 I assume). If you are going to use DirectDraw, you should at least be using DirectDraw 7.
staticVoid2
staticVoid2
I just downloaded the latest directx sdk an included those files, does that not include directdraw7 ? why do the TextOut, SetBkColor methods not have an effect on the device context of the primary surface - I got this code from a tutorial on the msdn2 website.
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnardirdraw/html/msdn_directd5.asp
Evil Steve
Evil Steve
Quote:
Original post by staticVoid2
I just downloaded the latest directx sdk an included those files, does that not include directdraw7 ? why do the TextOut, SetBkColor methods not have an effect on the device context of the primary surface - I got this code from a tutorial on the msdn2 website.
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnardirdraw/html/msdn_directd5.asp
It does, but they're backwards compatible. You need to request version 7 by calling QueryInterface() on the IDirctDraw object, or preferably call DirectDrawCreateEx instead, which will create a IDirectDraw7 interface directly.

It's been a long time since I did DirectDraw stuff; have you checked that GetDC() succeeds? The primary surface is a bit weird, and I wouldn't really be surprised if GetDC() or any DC-related functions failed on it (Maybe even silently).

Are you sure you want to be using DirectDraw? You're in for a world of pain if you want to use it for 3D; for instance you'll have to do alpha blending by locking both surfaces and manually copying pixels, you'll have to write a rotozoomer to do any rotation, and it's likely to be slow unless you're only using it to draw frames (I.e. using it as a screen sized array of pixels).
staticVoid2
staticVoid2
are most 3d engines not built upon directdraw?
S1CA
S1CA
Quote:
Original post by staticVoid2
are most 3d engines not built upon directdraw?


In the DirectX 7 days, yes. Now, no.

Direct3D8, 9, 10 exist on their own rather than through a layer on top of DirectDraw.
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
Stevo14
Stevo14
Quote:
Original post by staticVoid2
are most 3d engines not built upon directdraw?

No. Every 3D engine that I have ever heard of is built on either Direct3D or OpenGL.
The reason? Because Direct Draw is meant for 2 dimensions, and Direct3D is meant for 3 dimensions.

EDIT: S1CA is also correct. I was referring to modern 3D engines.
----Stevo
staticVoid2
staticVoid2
I've been looking at a few tutorials on direct3d an it looks a bit like a 3d engine itself - i thought some of the main functions of a 3d engine were to transform vectors, apply lighting etc. wheras direct3d looks like it does this for you?
Evil Steve
Evil Steve
Quote:
Original post by staticVoid2
I've been looking at a few tutorials on direct3d an it looks a bit like a 3d engine itself - i thought some of the main functions of a 3d engine were to transform vectors, apply lighting etc. wheras direct3d looks like it does this for you?
No, a 3D engine's purpose is to work at a higher level, dealing with maps, models, etc etc. A 3D engine will use Direct3D or OpenGL to do the actual low-level rendering. The 3D graphics API (D3D or OpenGL) is a lot lower level and generally deals with throwing vertices and textures at the graphics driver and letting it render.
For instance, to render a model in my 3D engine, it takes about 3 lines of code. Internally, the model and texture files are loaded from a resource pack, a texture, vertex buffer and index buffer are created, the object is added to a scene graph, and rendered every graphics update.

What you might be thinking of is a software rasterizer, which is where you pass in a bunch of triangles, and it transforms them and displays them. Although that'll be far slower than using D3D, since it won't be hardware accelerated at all. Writing a software rasterizer is a pretty good learning exercise though (Although it would probably be easier to write a pluggable software renderer for Direct3D).
The original Quake uses a software rasterizer (Written in assembly and C), which does a pretty good job, but it's still bound to be slower than if it was written to use OpenGL (The reason it wasn't was because graphics cards didn't exist when it was written).
staticVoid2
staticVoid2
I think ill just stick with directdraw until i final understand the in's and out's. There's a really good article on this site (Texture mapping mania(i think)) thats uses directdraw to render 1000's of triangles a second, I can't get the source to compile but the directdraw code seems a lot similar to mine although mines dosent work. Is there anyway you can check if the handle to the device context returned by GetDC is valid?
jollyjeffers
jollyjeffers
Quote:
There's a really good article on this site (Texture mapping mania(i think)) thats uses directdraw to render 1000's of triangles a second
How about writing code that renders 10's of millions of textured and lit triangles per second? I wrote up a journal entry last year that topped out at 34 million triangles per second [cool] (Ok, I'm showing off, but let me have my 15 seconds of glory please!)

I can see why you might want to stick with DirectDraw if you've found some material, but you're likely to do yourself more harm in the long run. DirectDraw techniques do not work with Direct3D - it was common for a long time to see posts from DD veterans getting appalling D3D performance because of this.

Your compiler issues could just be the tip of the iceberg - it's been mentioned that DirectDraw is approaching 10 years old now. It hasn't been updated, isn't supported and the vast majority of people who were familiar with it haven't touched in years - archives of web tutorials are probably your only semi-reliable source of information now. We can try and help you, but if you get stuck on DD7 you're probably on your own.

Quote:
Is there anyway you can check if the handle to the device context returned by GetDC is valid?
Suggests it's just a simple case of checking the HRESULT.

hth
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
staticVoid2
staticVoid2
I'm using DD7 now and it appears the exact same, are you supposed to still see windows when its in fullscreen? here's the new code im using:

#include <windows.h>#include <ddraw.h>LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);char szClassName[ ] = "WindowsApp";LPDIRECTDRAW7 lpDD;LPDIRECTDRAWSURFACE7 ddPrimeSurf;int WINAPI WinMain (HINSTANCE hThisInstance,                    HINSTANCE hPrevInstance,                    LPSTR lpszArgument,                    int nFunsterStil){    HWND hwnd;    MSG messages;    WNDCLASSEX wincl;    wincl.hInstance = hThisInstance;    wincl.lpszClassName = szClassName;    wincl.lpfnWndProc = WindowProcedure;    wincl.style = CS_DBLCLKS;    wincl.cbSize = sizeof (WNDCLASSEX);    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);    wincl.lpszMenuName = NULL;    wincl.cbClsExtra = 0;    wincl.cbWndExtra = 0;    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;    if (!RegisterClassEx (&wincl))        return 0;    hwnd = CreateWindowEx (           0,           szClassName,            "Windows App",           WS_POPUP,           CW_USEDEFAULT,           CW_USEDEFAULT,           800,           600,           HWND_DESKTOP,           NULL,           hThisInstance,           NULL           );   if(FAILED(DirectDrawCreateEx(NULL, (LPVOID*)&lpDD, IID_IDirectDraw7, NULL)))      return -1;   if(FAILED(lpDD->SetCooperativeLevel(hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE)))      return -1;   if(FAILED(lpDD->SetDisplayMode(800, 600, 8, 0, 0)))	  return -1;    while (GetMessage (&messages, NULL, 0, 0))    {        TranslateMessage(&messages);        DispatchMessage(&messages);    }    return messages.wParam;}LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){    switch (message)    {        case WM_DESTROY:            PostQuitMessage (0);            break;		case WM_KEYDOWN:			switch(LOWORD(wParam)) {		       case VK_ESCAPE:                  PostQuitMessage(0);			   break;			}	    break;        default:            return DefWindowProc (hwnd, message, wParam, lParam);    }    return 0;}

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.