BBC BASIC for Windows
Programming >> Graphics and Games >> DirectDraw - IDirectDraw.CreateSurface%
http://bb4w.conforums.com/index.cgi?board=graphics&action=display&num=1261992475

DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 28th, 2009, 08:27am

I know this is tedious but could some kind soul take a glance at the code below and see why I can't get IDirectDraw.CreateSurface% to work?

Code:
      
      MODE 8
      
      DDSCL_NORMAL = &8
      DDSD_CAPS = 1
      DDSCAPS_PRIMARYSURFACE = &200
      
      SYS "GetSystemMetrics", 0 TO xscreen%
      SYS "GetSystemMetrics", 1 TO yscreen%
      
      SYS "LoadLibrary", "DDRAW.DLL" TO ddraw%
      IF ddraw%=0 THEN ERROR 100, "Direct Draw not available"
      SYS "GetProcAddress", ddraw%, "DirectDrawCreateEx" TO `DirectDrawCreateEx`
      
      DIM IID_IDirectDraw7{a%, b%, c%, d%}
      IID_IDirectDraw7.a% = &15E65EC0
      IID_IDirectDraw7.b% = &11D23B9C
      IID_IDirectDraw7.c% = &60002FB9
      IID_IDirectDraw7.d% = &5BEA9797
      
      DIM IDirectDraw{QueryInterface%, AddRef%, Release%, Compact%, CreateClipper%, \
      \               CreatePalette%, CreateSurface%, DuplicateSurface%, \
      \               EnumDisplayModes%, EnumSurfaces%, FlipToGDISurface%, \
      \               GetCaps%, GetDisplayMode%, GetFourCCCodes%, GetGDISurface%, \
      \               GetMonitorFrequency%, GetScanLine%, GetVerticalBlankStatus%, \
      \               Initialize%, RestoreDisplayMode%, SetCooperativeLevel%, \
      \               SetDisplayMode%, WaitForVerticalBlank%}
      
      SYS `DirectDrawCreateEx`, 0, ^IDirectDraw%, IID_IDirectDraw7{}, 0
      !(^IDirectDraw{}+4) = !IDirectDraw%
      
      ON CLOSE PROC0 : QUIT
      ON ERROR PROC0 : SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : QUIT
      
      REM Establish how DirectDraw will cooperate with GDI
      SYS IDirectDraw.SetCooperativeLevel%, IDirectDraw%, 0, DDSCL_NORMAL TO R%
      IF R% THEN ERROR 100,"Cannot set Cooperative Level "+STR$~R%
      
      DIM DDPIXELFORMAT{dwSize%,        \
      \                 dwFlags%,       \
      \                 dwFourCC%,      \
      \                 dwRGBBitCount%, \ Union!
      \                 dwRBitMask%,    \ Union!
      \                 dwGBitMask%,    \ Union!
      \                 dwBBitMask%,    \ Union!
      \                 dwRGBAlphaBitMask% } :REM Union!
      
      DIM DDCAPS{dwSize%, \
      \          dwCKeyCaps%, \
      \          dwPalCaps%, \
      \          dwBltCaps%, \
      \          dwAlphaCaps%, \
      \          dwOverlayCaps%, \
      \          dwVidMemTotal%, \
      \          dwVidMemFree%, \
      \          dwVidMemStride%, \
      \          dwMaxVisibleOverlays%, \
      \          dwCurrVisibleOverlays%, \
      \          dwNumFourCCCodes%, \
      \          dwAlignBoundarySrc%, \
      \          dwAlignSizeSrc%, \
      \          dwAlignBoundaryDest%, \
      \          dwAlignSizeDest%, \
      \          dwRops%, \ Possible error?
      \          dwMinOverlayStretch%, \
      \          dwMaxOverlayStretch%, \
      \          dwMiscCaps% }
      
      DIM ddsd{         dwSize%,      \
      \                 dwFlags%,     \
      \                 dwHeight%,    \
      \                 dwWidth%,     \
      \                 lPitch%,      \
      \                 lXPitch%,     \
      \                 dwBackBufferCount%, \
      \                 dwRefreshRate%,     \
      \                 lpSurface%,         \
      \                 ddckCKDestOverlay{l%,h%}, \
      \                 ddckCKDestBlt{l%,h%},     \
      \                 ddckCKSrcOverlay{l%,h%},  \
      \                 ddckCKSrcBlt{l%,h%},      \
      \                 pixelformat{} = DDPIXELFORMAT{},   \ possible error?
      \                 dwCaps%,                           \
      \                 dwSurfaceSize% }
      
      ddsd.dwSize% = DIM(ddsd{})
      ddsd.dwFlags% = DDSD_CAPS
      ddsd.dwCaps% = DDSCAPS_PRIMARYSURFACE
      
      SYS IDirectDraw.CreateSurface%, IDirectDraw%, ddsd{}, ^spSurface%, 0 TO R%
      IF R% THEN ERROR 100,"Cannot CreateSurface "+STR$~R%
      
      
      PROC0
      END
      
      DEF PROC0
      SYS IDirectDraw.Release%, IDirectDraw%
      SYS "FreeLibrary", ddraw%
      ENDPROC
      
 


I think the problem is related to my definition of the structures, but was wondering if anyone already has these definitions somewhere?

I am trying to translate http://www.codeproject.com/KB/mobile/CeScreenGrabber.aspx
"DirectDraw Screen Capture" - half way down the page.

Thank you,

Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Dec 28th, 2009, 09:39am

Quote:
I know this is tedious but could some kind soul take a glance at the code below and see why I can't get IDirectDraw.CreateSurface% to work?

The prototype for IDirectDraw7::CreateSurface is:

Code:
HRESULT CreateSurface(
    LPDDSURFACEDESC2 lpDDSurfaceDesc,         
    LPDIRECTDRAWSURFACE7 FAR *lplpDDSurface,  
    IUnknown FAR *pUnkOuter
); 

Note in particular that the first parameter is a pointer to a DDSURFACEDESC2 structure. As far as I can see, you're passing a DDSURFACEDESC structure (Windows Mobile and Windows CE only) instead.

I assume you realise that the IDirectDraw interface is obsolete? It isn't supported in DirectX8 or later and is available only for backwards compatibility with DirectX7. Strictly speaking you shouldn't be using it in 'new' projects.

Richard.
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 29th, 2009, 01:24am

Quote:
Note in particular that the first parameter is a pointer to a DDSURFACEDESC2 structure. As far as I can see, you're passing a DDSURFACEDESC structure (Windows Mobile and Windows CE only) instead.

Well, that would explain a bit..doh.
Quote:
I assume you realise that the IDirectDraw interface is obsolete? It isn't supported in DirectX8 or later and is available only for backwards compatibility with DirectX7. Strictly speaking you shouldn't be using it in 'new' projects.


Yes, I did realise but it was the only example I could find of capturing the Desktop. I was trying to get this to work and then was thinking of updating the code as and when I could. I am obviously intrested in speed... GetPixel is just way too slow..

I'll see where I get. Thanks for the reply.

Michael


Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Dec 29th, 2009, 02:30am

I seem to have got it working...

Code:
      
      MODE 8
      
      DDSCL_NORMAL = &8
      DDSD_CAPS = 1
      DDSCAPS_PRIMARYSURFACE = &200
      
      SYS "GetSystemMetrics", 0 TO xscreen%
      SYS "GetSystemMetrics", 1 TO yscreen%
      
      SYS "LoadLibrary", "DDRAW.DLL" TO ddraw%
      IF ddraw%=0 THEN ERROR 100, "Direct Draw not available"
      SYS "GetProcAddress", ddraw%, "DirectDrawCreateEx" TO `DirectDrawCreateEx`
      
      DIM IID_IDirectDraw7{a%, b%, c%, d%}
      IID_IDirectDraw7.a% = &15E65EC0
      IID_IDirectDraw7.b% = &11D23B9C
      IID_IDirectDraw7.c% = &60002FB9
      IID_IDirectDraw7.d% = &5BEA9797
      
      DIM IDirectDraw{QueryInterface%, AddRef%, Release%, Compact%, CreateClipper%, \
      \               CreatePalette%, CreateSurface%, DuplicateSurface%, \
      \               EnumDisplayModes%, EnumSurfaces%, FlipToGDISurface%, \
      \               GetCaps%, GetDisplayMode%, GetFourCCCodes%, GetGDISurface%, \
      \               GetMonitorFrequency%, GetScanLine%, GetVerticalBlankStatus%, \
      \               Initialize%, RestoreDisplayMode%, SetCooperativeLevel%, \
      \               SetDisplayMode%, WaitForVerticalBlank%}
      
      SYS `DirectDrawCreateEx`, 0, ^IDirectDraw%, IID_IDirectDraw7{}, 0
      !(^IDirectDraw{}+4) = !IDirectDraw%
      
      REM Apparently should give a pointer to the Primary Surface...
      REM PRINT IDirectDraw%
      REM PRINT !(IDirectDraw%+4)
      REM PRINT !(!(IDirectDraw%+4)+44)
      
      ON CLOSE PROC0 : QUIT
      ON ERROR PROC0 : SYS "MessageBox", @hwnd%, REPORT$, 0, 48 : QUIT
      
      REM Establish how DirectDraw will cooperate with GDI
      SYS IDirectDraw.SetCooperativeLevel%, IDirectDraw%, 0, DDSCL_NORMAL TO R%
      IF R% THEN ERROR 100,"Cannot set Cooperative Level "+STR$~R%
      
      DIM DDPIXELFORMAT{dwSize%,        \
      \                 dwFlags%,       \
      \                 dwFourCC%,      \
      \                 dwRGBBitCount%, \ Union!
      \                 dwRBitMask%,    \ Union!
      \                 dwGBitMask%,    \ Union!
      \                 dwBBitMask%,    \ Union!
      \                 dwRGBAlphaBitMask% } :REM Union!
      DIM DDSCAPS2{ \
      \ dwCaps%,  \
      \ dwCaps2%, \
      \ dwCaps3%, \
      \ dwCaps4% }
      
      DIM DDCAPS{dwSize%, \
      \          dwCKeyCaps%, \
      \          dwPalCaps%, \
      \          dwBltCaps%, \
      \          dwAlphaCaps%, \
      \          dwOverlayCaps%, \
      \          dwVidMemTotal%, \
      \          dwVidMemFree%, \
      \          dwVidMemStride%, \
      \          dwMaxVisibleOverlays%, \
      \          dwCurrVisibleOverlays%, \
      \          dwNumFourCCCodes%, \
      \          dwAlignBoundarySrc%, \
      \          dwAlignSizeSrc%, \
      \          dwAlignBoundaryDest%, \
      \          dwAlignSizeDest%, \
      \          dwRops%, \
      \          dwMinOverlayStretch%, \
      \          dwMaxOverlayStretch%, \
      \          dwMiscCaps% }
      
      
      DIM ddsd{                  \
      \          dwSize%,                   \
      \          dwFlags%,                  \
      \          dwHeight%,                 \
      \          dwWidth%,                  \
      \          dwPitchOrLinearSize%,      \
      \          dwBackBufferCount%,        \
      \          dwMipMapCount%,            \
      \          dwAlphaBitDepth%,          \
      \          dwReserved%,               \
      \          lpSurface%,                \
      \          ddckCKDestOverlay{l%,h%},  \
      \          ddckCKDestBlt{l%,h%},      \
      \          ddckCKSrcOverlay{l%,h%},   \
      \          ddckCKSrcBlt{l%,h%},       \
      \          ddpfPixelFormat{} = DDPIXELFORMAT{}, \
      \          ddsCaps{} = DDSCAPS2{},    \
      \          dwTextureStage%  }
      
      
      ddsd.dwSize% = DIM(ddsd{})
      ddsd.dwFlags% = DDSD_CAPS
      ddsd.ddsCaps.dwCaps% = DDSCAPS_PRIMARYSURFACE
      
      SYS IDirectDraw.CreateSurface%, IDirectDraw%, ddsd{}, ^spSurface%, 0 TO R%
      IF R% THEN ERROR 100,"Cannot CreateSurface "+STR$~R%
      
      PROC0
      END
      
      DEF PROC0
      SYS IDirectDraw.Release%, IDirectDraw%
      SYS "FreeLibrary", ddraw%
      ENDPROC
      
 


I'll keep people posted (if they are interested!)
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Dec 29th, 2009, 09:02am

Quote:
Yes, I did realise but it was the only example I could find of capturing the Desktop.... GetPixel is just way too slow.

What exactly are you trying to do? If you want to read pixels from the desktop quickly, why not simply BitBlt the entire desktop DC into a DIBSection? No need for anything complicated like DirectDraw or DirectX!

Richard.

Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jan 2nd, 2010, 03:25am

Quote:
What exactly are you trying to do? If you want to read pixels from the desktop quickly, why not simply BitBlt the entire desktop DC into a DIBSection? No need for anything complicated like DirectDraw or DirectX!


My aim was to capture the desktop, modify it, and then BitBlt it back, many frames a second. I will do some 'speed tests' on BitBlt. I have been away for the new year. I suppose I was slightly enamoured by the potential of directly accessing the primary surface (monitor) through DDRAW. I realise it is depreciated.

Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by admin on Jan 2nd, 2010, 09:46am

Quote:
My aim was to capture the desktop, modify it, and then BitBlt it back, many frames a second.

Write to the desktop DC? Can you even do that on Vista/Windows 7? I would have anticipated you would hit security restrictions in attempting that (unless running as an administrator) but I've not tried it.

Can't you achieve what you want by overlaying a transparent (layered) window on the desktop, and drawing to that? There have been several previous examples of doing that in BB4W.

Richard.
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jan 4th, 2010, 02:47am

Quote:
Write to the desktop DC? Can you even do that on Vista/Windows 7?


Code:
      MODE 8
      SYS "GetSystemMetrics", 0 TO xscreen%
      SYS "GetSystemMetrics", 1 TO yscreen%
      
      SYS "CreateDC", "DISPLAY", 0, 0, 0 TO hdcScreen%
      SYS "CreateCompatibleDC", hdcScreen% TO hdcCompatible%
      SYS "CreateCompatibleBitmap", hdcScreen%, xscreen%, yscreen% TO hbitmap%
      SYS "SelectObject", hdcCompatible%, hbitmap% TO oldbm%
      
      
      REPEAT
        SYS "BitBlt", hdcCompatible%, 0, 0, xscreen%, yscreen%, hdcScreen%, 0, 0, &CC0020 TO R%
        IF R% = 0 THEN  ERROR 100, "Failed to BitBlt"
        
        CIRCLE FILL RND(1280), RND(1024), RND(100)
        
        SYS "BitBlt", hdcScreen%, 0,0, 640, 512, @memhdc%, 0, 0,  &CC0020 TO R%
        IF R% = 0 THEN  ERROR 100, "Failed to BitBlt"
        
       
      UNTIL FALSE
 

(Obviously - no cleanup code)

Works on my Vista Ultimate x64 edition. Which did rather surprise me, and you can draw to the desktop DC with SYS "LineTo" @desktopDC%, X%, Y%. So access seems pretty free. I am interested to see if DirectX/DDRAW provides a faster way of interacting with it.

Michael
Re: DirectDraw - IDirectDraw.CreateSurface%
Post by Michael Hutton on Jul 28th, 2015, 7:41pm

Oh! ...and this also works with Windows 8 (v6).

Forgot about this.

Michael