News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

DirectDraw test using COM methods only

Started by gabor, May 04, 2006, 06:46:48 AM

Previous topic - Next topic

gabor

Hello everyone!

I got the idea to get familiar with the COM programing. To make it more worth to bother with I've choosen DirectX, more precisley old DirectDraw (ddraw7 or older) to play with.
Here is my goal:
- create an IDirectDraw component using CoCreateInstance
- initialize it via its Initialize method
- call SetDisplayMode and everything else...

I have some problems at the initializing step, I keep getting an error message telling me that the passed GUID is wrong. I might left something out, but I cannot figure out what. Or is my code entirely rubbish?
DirectX and/or COM professionals (and non-professionals) please have a look at my code and add your comments! I attached the whole stuff, but quote the important parts:


.data
        CLSID_DirectDraw GUID {0D7B70EE0h,04340h,011CFh,{0B0h,063h,000h,020h,0AFh,0C2h,0CDh,035h}}
        IID_IDirectDraw  GUID {06C14DB80h,0A733h,011CEh,{0A5h,021h,000h,020h,0AFh,00Bh,0E5h,060h}}

.code
        invoke CoCreateInstance,offset CLSID_DirectDraw,NULL,CLSCTX_ALL,offset IID_IDirectDraw,offset lpDD
        mov    edx,offset szError1
        cmp    eax,S_OK
        jnz @End
; Initialize
        coinvoke lpDD,IDirectDraw,Initialize,offset CLSID_DirectDraw ; <-- this is where the error occures
        mov    edx,offset szError2
        cmp    eax,DD_OK
        jnz @End
; SetCooperativeLevel
        coinvoke lpDD,IDirectDraw,SetCooperativeLevel,hMainWnd,DDSCL_ALLOWMODEX or DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE or DDSCL_ALLOWREBOOT
        mov    edx,offset szError3
        cmp    eax,DD_OK
        jnz @End
        xor    eax,eax
@End:
        ret


Any opinions appreciated!

Thx,
  Gábor

[attachment deleted by admin]

Gustav


IIRC you may get error DDERR_ALREADYINITIALIZED when calling Initialize because it has been done internally already.


Ossa

Quote from: Gustav on May 04, 2006, 09:49:36 AM
IIRC you may get error DDERR_ALREADYINITIALIZED when calling Initialize because it has been done internally already.

Only if the interface is created using DirectDrawCreate - he uses CoCreateInstance - it is uninitialised. But I would normally use the DirectDrawCreate function, not CoCreateInstance, so I might be quite off on some things I say from here on.

First - the GUID definitions. Although I believe that you have the correct values, a much simpler way to achieve the same result (at no cost to file size, despite the .lib's size) is to EXTERNDEF the GUIDs and then link with dxguid.lib


EXTERNDEF C CLSID_DirectDraw:GUID
EXTERNDEF C IID_IDirectDraw:GUID


Second - you have been inconsistent between using IDirectDraw and IDirectDraw7 - you initialise IDirectDraw, but release IDirectDraw7... this isnt causing any problems yet, but be careful.

Third your call the IDirectDraw::Initialize should pass NULL as the parameter (apprently - it seems to work, but not too sure why):


coinvoke lpDD,IDirectDraw,Initialize,NULL


Fourth, with this done you get the following error on SetCooperativeLevel:


HRESULT: 0x80070057 (2147942487)
Name: E_INVALIDARG
Description: An invalid parameter was passed to the returning function
Severity code: Failed
Facility Code: FACILITY_WIN32 (7)
Error Code: 0x0057 (87)


But I'm not too sure just yet, which parameter that is, or whether this is because I switched to using NULL as the parameter above.

Will get back to you when I figure out whats going on,
Ossa
Website (very old): ossa.the-wot.co.uk

Ossa

OK, I'm really not too sure what's going on there, but I'd say that your window handle isn't valid for some reason.

Here is a zip containing an example I wrote a while ago that I just altered to use your startup method and it works fine (it uses my own port of the DirectDraw include, so I'm not currently using the coinvoke method of calling, but it shouldn't be hard to swap to that).

Ossa

[edit] Oops - forgot the file! [/edit]

[edit] Ok, 1 small error in my conversion of that. Uploaded new one. (also got rid of the dxguid.lib inclusion and used gabor's direct GUID inclusion method) [/edit]

[attachment deleted by admin]
Website (very old): ossa.the-wot.co.uk

Ossa

Interesting thing I just tried, I converted that file to use the coinvoke system (rather than my stdinvoke system) and it stopped working... will check the definitions of the the DX interfaces.

Ossa
Website (very old): ossa.the-wot.co.uk

gabor

Thanks a lot for your help!!!


After I had posted this topic I noticed some of those problems in my code. After correcting them the result was the same :(
When I call Initialize with IID parameter set to NULL it is working indeed, but I don't know why neither. Well, maybe it's not so important.

Finally, I found the reason of the SetCooperativeLevel error. In the file ddtype.inc the DDSCL_xxx constants were incorrect. Like this:



Wrong:
DDSCL_FULLSCREEN       EQU 000000011h
DDSCL_ALLOWREBOOT      EQU 000000021h
DDSCL_NOWINDOWCHANGES  EQU 000000041h
...

Correct:
DDSCL_FULLSCREEN       EQU 00000001h
DDSCL_ALLOWREBOOT      EQU 00000002h
DDSCL_NOWINDOWCHANGES  EQU 00000004h
...

There was a needless 1 at the end of every constant.  :eek Sorry for this bumper...

I hope this topic proves to be a bit usefull after all, in case someone is interested in creating DDraw (or any DX) objects/interfaces via the CoCreateInstance, etc. way.

I updated the zip file.

thx
Gábor

Siekmanski

Hello gabor

I looked into your source and saw that you used CoCreateInstance to get the interface  :naughty:
This is the way to go:

        invoke DirectDrawCreateEx,NULL,addr lpDD,addr IID_IDirectDraw7,NULL

And these are the right SETCOOPERATIVELEVEL FLAGS
yours are wrong...

    DDSCL_ALLOWMODEX         equ   64
    DDSCL_ALLOWREBOOT        equ    2
    DDSCL_CREATEDEVICEWINDOW equ  512
    DDSCL_EXCLUSIVE          equ   16
    DDSCL_FULLSCREEN         equ    1
    DDSCL_MULTITHREADED      equ 1024
    DDSCL_NORMAL             equ    8
    DDSCL_NOWINDOWCHANGES    equ    4
    DDSCL_SETDEVICEWINDOW    equ  256
    DDSCL_SETFOCUSWINDOW     equ  128

you must link with ddraw.lib and ddraw.inc

and you are ready to go....

Have fun I did it with coinvoke 2 years ago and translated all the DIRECTX9 includes

I included the corrected source



[attachment deleted by admin]

Ossa

Quote from: Siekmanski on May 04, 2006, 01:32:40 PM
This is the way to go:

invoke   DirectDrawCreateEx,NULL,addr lpDD,addr IID_IDirectDraw7,NULL

It doesn't make that much difference except for one added function call, and since his whole point was to use CoCreateInstance in order to learn COM better (a very nice way to go about it, btw), it would kind of defeat the whole purpose.

Quote from: gabor on May 04, 2006, 06:46:48 AM
I got the idea to get familiar with the COM programing. To make it more worth to bother with I've choosen DirectX, more precisley old DirectDraw (ddraw7 or older) to play with.
Here is my goal:
- create an IDirectDraw component using CoCreateInstance
- initialize it via its Initialize method
- call SetDisplayMode and everything else...

Anyway... doesn't really matter since the problem is all fixed now.

Quote from: gabor on May 04, 2006, 12:08:14 PM
Finally, I found the reason of the SetCooperativeLevel error. In the file ddtype.inc the DDSCL_xxx constants were incorrect.

That explains it, thanks gabor, that was really bugging me. I guess it shows that it might be better to use one of the standard DX include files that have been tested extensively (the one I included up there can't be used with coinvoke directly though, sorry).

Anyway, thanks for posting the solution to your problem, gabor.

Ossa
Website (very old): ossa.the-wot.co.uk

Siekmanski

Quote
Here is my goal:
- create an IDirectDraw component using CoCreateInstance
- initialize it via its Initialize method
- call SetDisplayMode and everything else...

yeah I need to learn how to read better  :red

sorry guys....

gabor

Hi!

To keep you guys busy I come up with another idea:

I've decided to code a small fire effect (a very old algo, used in 10 year old or even older intros, demos) using DirectX. What makes it a bit difficult is that I want to make it windowed   not fullscreen.
The hard part is using the PrimarySurface since this surface is responsible for the whole screen. When I access the surface directly I am able to overpaint areas that belong to other windows... That is not good.
I tried to track the position of my widow to be able to lock and change the surface at my window's rectangle only. But then, when I drag an other window over my window that windows gets overpainted again... Some masking or clipping would be needed?

I suspect this is not the best way of creating windowed DX graphics...
What I would like to know: is there a way to paint on the window's area only (using a DC maybe?)  but using the DX stuff (buffers, blitter etc.). I read something about relations between DirectX and Device Contexts, maybe I should check out that completely...

If someone knows how to do this please give me some hints!

Greets, Gábor

Ossa

Quote from: gabor on May 04, 2006, 04:48:17 PM
I suspect this is not the best way of creating windowed DX graphics...
What I would like to know: is there a way to paint on the window's area only (using a DC maybe?) but using the DX stuff (buffers, blitter etc.). I read something about relations between DirectX and Device Contexts, maybe I should check out that completely...

Use IDirectDrawClipper. Here's a very rubbish example that I coded ages ago. It doesn't use coinvoke, and it uses my stdinvoke system, but it should show you the main elements... you will however need to add in some updating code, as the painted region doesnt bother following the window around. (Its the second example)

Ossa

[edit] that wasn't clear: the clipper moves, but the objects drawn inside don't - so there is nothing drawn outside the window, but the objects aren't neccessarily drawn inside it either. Just run it and move the window around and you'll get what I mean. [/edit]

[edit] If there are any files that I forgot, the whole lot is up on my webspace: - http://web.mit.edu/rcassels/www/DirectXPort/ [/edit]

[attachment deleted by admin]
Website (very old): ossa.the-wot.co.uk

daydreamer

this example of procedural texture, isnt fully unrolled yet as its still in development I only use MOVD single pixel output, while MMX/SSE2 is capable of unroll it to render 4 pixels per reg I use and I am only using half the amount of regs, so a double/triple amount of regs could be used to further unroll it
just press esc to finish
I call it from a timer, as its unnesserary to run it at fullspeed to make other apps lag



[attachment deleted by admin]

u

I've already moved from GDI to DirectDraw1 for my MDI/SDI software, and win32-compiles of my commercial PalmOS games.
Both engines that I use (closed sourcecode) are spawned from "ILIX", which I published to the public at www.ultranos.com/asm
In my MDI/SDI apps I make extensive use of clippers (actually, one clipper), one or two backbuffers that are as big as the screen (and in the same bitdepth), and some custom clipping. Here you have to obey the screendepth, or nVidia cards will cry... (ATi cards don't have a prob). 33fps are no problem so far, with updatability up to 140fps when the user starts dragging stuff. In this dirty way, I'm actually saving 95% of the awful code I'd have otherwise had to write ^^.

In the win32-compiles of games, I need it all custom-drawn. So, Blt is just another asm-coded blending proc in the software engine, and I just need to lock+update+unlock+blt the back buffer.
Please use a smaller graphic in your signature.