/* DDSurface.cpp **************************************************************
Author: Paul Watt
Date: 9/30/2001
Purpose:
******************************************************************************/
#include "stdafx.h"
#include "DDSurface.h"
/* Public *********************************************************************
Author: Paul Watt
Date: 9/30/2001
Purpose: Constructor
******************************************************************************/
DDSurface::DDSurface()
{
m_pSurface = NULL;
m_hDC = NULL;
m_hWnd = NULL;
ZeroMemory(&m_ddsd, sizeof(DDSURFACEDESC2));
m_ddsd.dwSize = sizeof(DDSURFACEDESC2);
}
/* Public *********************************************************************
Author: Paul Watt
Date: 9/30/2001
Purpose: Destructor
******************************************************************************/
DDSurface::~DDSurface()
{
this->Release();
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/16/2001
Purpose: Allows a raw DirectDrawSurface Interface pointer to be attached and
encapsulated in this object. If this object currently has an object
then the function will fail. In order to release the interface pointer
without destroying the object call Release. If you would like to
extract the interface pointer and not release it then call Detach.
Parameters: pSurface[in]: The new interface pointer that will be attached to this
object.
Return: If the function successfully attaches the surface to this obect then
AddRef will be called on the surface and true will be returned, otherwise
false.
******************************************************************************/
bool DDSurface::Attach(IDirectDrawSurface7 *pSurface)
{
//C: Check if this object already has a surface set into it.
if (NULL != m_pSurface)
{
return false;
}
//C: Verify input parameters.
if (NULL == pSurface)
{
return false;
}
//C: Set this objects surface to the input surface.
m_pSurface = pSurface;
m_pSurface->AddRef();
//C: Initialize all of the necessary parameters.
m_pSurface->GetSurfaceDesc(&m_ddsd);
//C: Return success.
return true;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/16/2001
Purpose:
Parameters:
Return:
******************************************************************************/
bool DDSurface::Detach(IDirectDrawSurface7 **ppSurface)
{
//C: Verify input parameters.
if (NULL == ppSurface)
{
return false;
}
//C: Set ppSurface = to the interface pointer stored in this object.
*ppSurface = m_pSurface;
(*ppSurface)->AddRef();
//C: Release all of the memory associated with this object.
this->Release();
//C: Return success
return true;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 10/6/2001
Purpose:
Parameters:
Return:
******************************************************************************/
HRESULT DDSurface::Initialize(IDirectDraw7 *pDirectDraw, UINT nBufferCount)
{
//C: Verify input parameters
if (NULL == pDirectDraw)
{
return -1;
}
if ( nBufferCount==0 )
{
m_ddsd.dwFlags = DDSD_CAPS;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_VIDEOMEMORY;
}
else
{
m_ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
m_ddsd.dwBackBufferCount = nBufferCount;
}
HRESULT hr = pDirectDraw->CreateSurface(&m_ddsd, &m_pSurface, NULL);
//C: Finish initializing the ddsd field.
if (NULL != m_pSurface)
{
m_pSurface->GetSurfaceDesc(&m_ddsd);
}
//C: Verify that the current display mode is 32-bit or 24-bit color
// because this surface does not support any other modes at this
// point in time.
ATLASSERT (32 == m_ddsd.ddpfPixelFormat.dwRGBBitCount ||
24 == m_ddsd.ddpfPixelFormat.dwRGBBitCount ||
16 == m_ddsd.ddpfPixelFormat.dwRGBBitCount);
return hr;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 9/30/2001
Purpose: Frees all of the handles for this surface object before the
destructor is called. This will be useful in order for object
caching.
Parameters: NONE
Return: -
******************************************************************************/
void DDSurface::Release()
{
//C: Release the DC handle if one was ever obtained.
this->ReleaseDC();
//C: Release the surface handle.
if (NULL != m_pSurface)
{
m_pSurface->Release();
m_pSurface = NULL;
}
}
/* Public *********************************************************************
Author: Paul Watt
Date: 10/6/2001
Purpose:
Parameters:
Return:
******************************************************************************/
BYTE * DDSurface::Lock(RECT * pRect)
{
if ( FAILED(m_pSurface->Lock(pRect, & m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)) )
{
return NULL;
}
else
{
return (BYTE *) m_ddsd.lpSurface;
}
}
/* Public *********************************************************************
Author: Paul Watt
Date: 10/6/2001
Purpose:
Parameters:
Return:
******************************************************************************/
HRESULT DDSurface::Unlock(RECT * pRect)
{
m_ddsd.lpSurface = NULL; // make it unavailable
return m_pSurface->Unlock(pRect);
}
/* Global *********************************************************************
Author: Paul Watt
Date: 9/30/2001
Purpose: Restores this surfaces memory if the memory has been lost. Classes
that derive from this class will have to restore any data that was
previously stored on this surface.
Parameters: NONE
Return: HRESULT indicating success or failure.
******************************************************************************/
HRESULT DDSurface::RestoreSurface(void)
{
//C: Verify that the object has been initialized.
if ( m_pSurface )
{
//C: Check if the memory has been lost.
if ( m_pSurface->IsLost() )
{
//C: The memory has been lost, therefore restore. This will
// reallocate the memory for this surface.
return m_pSurface->Restore();
}
else
{
return DD_OK;
}
}
else
{
return E_FAIL;
}
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/9/2001
Purpose:
Parameters:
Return:
******************************************************************************/
HRESULT DDSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
{
return m_pSurface->SetClipper(lpDDClipper);
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/7/2001
Purpose: Fills the destination rectangle of this surface with dwFillColor.
Parameters: rDest[in]: A destination rectangle to be filled. If this value
is NULL, thent eh entire rectangle will be filled.
Return:
******************************************************************************/
HRESULT DDSurface::FillColor (RECT *pDest, DWORD dwFillColor)
{
DDBLTFX fx;
fx.dwSize = sizeof(fx);
fx.dwFillColor = dwFillColor;
RECT rSurface;
if (NULL == pDest)
{
rSurface.left = 0;
rSurface.top = 0;
rSurface.right = m_ddsd.dwWidth;
rSurface.bottom = m_ddsd.dwHeight;
pDest = &rSurface;
}
//C: Offset the rDest rectangle.
POINT ptOrigin;
GetOrigin(ptOrigin);
::OffsetRect(pDest, ptOrigin.x, ptOrigin.y);
return this->Blt(pDest,NULL, NULL, DDBLT_COLORFILL, &fx);
}
/* DDOffScreenSurface Implementation *****************************************/
/* Public *********************************************************************
Author: Paul Watt
Date: 11/9/2001
Purpose: Constructor
******************************************************************************/
DDOffScreenSurface::DDOffScreenSurface() : DDSurface()
{
//C: No current operations
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/9/2001
Purpose: Destructor
******************************************************************************/
DDOffScreenSurface::~DDOffScreenSurface()
{
//C: No current operations
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/9/2001
Purpose: Initializes this off screen surface to match the same parameters
as the hwnd that is passed in.
Parameters: pDirectDraw[in]: Handle to the instance of DirectDraw that is being
used.
hWnd[in]: A window whose dimensions should be used to calculate the
size of this surface. This parameter cannot be NULL;
Return:
******************************************************************************/
HRESULT DDOffScreenSurface::Initialize(IDirectDraw7 *pDirectDraw, UINT nBufferCount)
{
//C: The information that is required for this surface does not
// exist. Mainly the width and height of the surface.
return E_NOTIMPL;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 11/9/2001
Purpose:
Parameters:
Return:
******************************************************************************/
HRESULT DDOffScreenSurface::Initialize(IDirectDraw7 *pDirectDraw, DWORD dwWidth, DWORD dwHeight)
{
//C: Verify input parameters
if (NULL == pDirectDraw)
{
return -1;
}
m_ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
m_ddsd.dwWidth = dwWidth;
m_ddsd.dwHeight = dwHeight;
HRESULT hr = pDirectDraw->CreateSurface(&m_ddsd, &m_pSurface, NULL);
//C: Finish initializing the ddsd field.
if (NULL != m_pSurface)
{
m_pSurface->GetSurfaceDesc(&m_ddsd);
}
return hr;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 4/6/2002
Purpose: Initializes the new offscreen surface with the data found in the
pDIB bitmap.
Parameters: pDirectDraw7[in]: The directDraw instance to create this surface with.
pDIB[in]: The DIB in which to initialize the surface with. The
size of the buffer will be the same size as the bitmap.
Return: HRESULT indicating the status of this function.
******************************************************************************/
HRESULT DDOffScreenSurface::Initialize(IDirectDraw7 *pDirectDraw, const BITMAPINFO * pDIB)
{
//C: Verify input parameters
if (!pDirectDraw || !pDIB)
{
return E_INVALIDARG;
}
m_ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
m_ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
//C: Extract the size of the bitmap.
m_ddsd.dwWidth = pDIB->bmiHeader.biWidth;
m_ddsd.dwHeight = abs(pDIB->bmiHeader.biHeight);
HRESULT hr = pDirectDraw->CreateSurface(&m_ddsd, &m_pSurface, NULL);
//C: Finish initializing the ddsd field.
if (NULL != m_pSurface)
{
m_pSurface->GetSurfaceDesc(&m_ddsd);
}
//C: Place the image data from the bitmap into the surface.
return DrawBitmap(pDIB, 0, 0, m_ddsd.dwWidth, m_ddsd.dwHeight);
}
/* Global Functions **********************************************************/
/* Global *********************************************************************
Author: Paul Watt
Date: 10/6/2001
Purpose: Creates a new DDSurface object. This function will initialize
the new surface as well.
Parameters: pDirectDraw[in]: A Pointer to teh DD instance.
nBufferCount[in]: The number of buffers to attach to this surface.
hWnd[in]: A window that this surface will represent if any.
Return: A pointer to a new DDSurface will be returned if the function
succeeds, otherwise NULL.
******************************************************************************/
DDSurface* CreateSurface(IDirectDraw7 *pDirectDraw, UINT nBufferCount)
{
HRESULT hr;
DDSurface *pSurface = new DDSurface;
hr = pSurface->Initialize(pDirectDraw, nBufferCount);
if (FAILED(hr))
{
delete pSurface;
pSurface = NULL;
}
return pSurface;
}
/* Global *********************************************************************
Author: Paul Watt
Date: 4/6/2002
Purpose: Creates a new DDOffScreenSurface object that is initialized with
a bitmap.
Parameters: pDirectDraw[in]: A Pointer to the DD instance.
dwWidth[in]: The width of the new surface.
dwHeight[in]: The height of the new surface.
Return: A pointer to a new DDOffsecreenSurface will be returned if the function
succeeds, otherwise NULL.
******************************************************************************/
DDOffScreenSurface* CreateOffScreenSurface(IDirectDraw7 *pDirectDraw, DWORD dwWidth, DWORD dwHeight)
{
HRESULT hr;
DDOffScreenSurface *pSurface = new DDOffScreenSurface;
hr = pSurface->Initialize(pDirectDraw, dwWidth, dwHeight);
if (FAILED(hr))
{
delete pSurface;
pSurface = NULL;
}
return pSurface;
}
/* Global *********************************************************************
Author: Paul Watt
Date: 4/6/2002
Purpose: Creates a new DDOffScreenSurface object that is initialized with
a bitmap.
Parameters: pDirectDraw[in]: A Pointer to teh DD instance.
pDIB[in]:
Return: A pointer to a new DDOffScreenSurface will be returned if the function
succeeds, otherwise NULL.
******************************************************************************/
DDOffScreenSurface* CreateOffScreenSurface(IDirectDraw7 *pDirectDraw, const BITMAPINFO * pDIB)
{
HRESULT hr;
DDOffScreenSurface *pSurface = new DDOffScreenSurface;
hr = pSurface->Initialize(pDirectDraw, pDIB);
if (FAILED(hr))
{
delete pSurface;
pSurface = NULL;
}
return pSurface;
}
/* Global *********************************************************************
Author: Paul Watt
Date: 4/6/2002
Purpose: Creates a new surface, and initializes that surface with an image
loaded from a file.
Parameters: pDirectDraw[in]:
pszFileName[in]: The path to the image to intialize the surface with.
Return: If the function succeeds, then a pointer to a new DDOffscreenSurface
object that is initialized with the target image will be returned.
If the function fails then NULL will be returned.
******************************************************************************/
DDOffScreenSurface* CreateOffScreenSurface(IDirectDraw7 *pDirectDraw, const TCHAR* pszFileName)
{
HANDLE hFile = NULL;
HANDLE hMapping = NULL;
BYTE *pByte = NULL;
DDOffScreenSurface *pSurface = NULL;
try
{
//C: Open the image from pszFileName.
hFile = ::CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, NULL, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
throw NULL;
}
//C: MemoryMap the file.
hMapping = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (INVALID_HANDLE_VALUE == hMapping)
{
throw NULL;
}
pByte = (BYTE*)::MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
BITMAPINFO *pDIB = (BITMAPINFO*)(pByte + sizeof(BITMAPFILEHEADER));
if (!pDIB)
{
throw NULL;
}
//C: Create and initialize the new surface.
pSurface = CreateOffScreenSurface(pDirectDraw, pDIB);
}
catch (...)
{
//C: No current operations.
}
//C: Free resources.
if (pByte)
{
::UnmapViewOfFile(pByte);
}
if (hFile)
{
::CloseHandle(hFile);
}
if (hMapping)
{
::CloseHandle(hMapping);
}
//C: Exit.
return pSurface;
}