home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////////////////////////////////////////////////////
- // Project Name: [ CDX Class Library - CDX.lib ]
- // Author: [ Dan Farley - 97308096@brookes.ac.uk ]
- // Source File: [ CDX_Screen Implementation ]
- // Revision: [ 1.6 ]
- //////////////////////////////////////////////////////////////////////////////////
- #include "CDX.h"
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Constructor
- //////////////////////////////////////////////////////////////////////////////////
- CDX_Screen::CDX_Screen()
- {
- Initialise();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Destructor
- //////////////////////////////////////////////////////////////////////////////////
- CDX_Screen::~CDX_Screen(void)
- {
- Finalise();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Initialise
- //////////////////////////////////////////////////////////////////////////////////
- void CDX_Screen::Initialise(void)
- {
- m_DirectDraw = NULL;
- m_Direct3D = NULL;
- m_Device = NULL;
- m_Viewport = NULL;
- m_FrontBuffer = NULL;
- m_BackBuffer = NULL;
- m_DepthBuffer = NULL;
- m_Width = 0;
- m_Height = 0;
- m_Bpp = 0;
- m_Hwnd = NULL;
- m_IsFullScreen = FALSE;
- m_Is3D = FALSE;
- m_IsFPU = TRUE;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Finalise
- //////////////////////////////////////////////////////////////////////////////////
- void CDX_Screen::Finalise(void)
- {
- SAFE_RELEASE(m_Viewport);
- SAFE_RELEASE(m_Device);
- SAFE_DELETE(m_BackBuffer);
- SAFE_DELETE(m_DepthBuffer);
- SAFE_DELETE(m_FrontBuffer);
- SAFE_RELEASE(m_Direct3D);
- SAFE_RELEASE(m_DirectDraw);
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // EnumDriver
- //////////////////////////////////////////////////////////////////////////////////
- static BOOL WINAPI EnumDriver(GUID FAR* guid, LPSTR desc, LPSTR name, LPVOID context)
- {
- LPDIRECTDRAW directdraw;
- DDCAPS caps;
-
- // Make sure the guid is valid
- if(guid)
- {
- // Try to create a DirectDraw object
- DirectDrawCreate(guid, &directdraw, NULL);
-
- // Get the DirectDraw capabilities
- memset(&caps, 0, sizeof(DDCAPS));
- caps.dwSize = sizeof(DDCAPS);
-
- directdraw->GetCaps(&caps, NULL);
-
- // Does this driver have 3D hardware capabilites?
- if(caps.dwCaps & DDCAPS_3D)
- {
- *(LPDIRECTDRAW*)context = directdraw;
- return DDENUMRET_CANCEL;
- }
-
- *(LPDIRECTDRAW*)context = NULL;
- directdraw->Release();
- }
- return DDENUMRET_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // EnumFormat
- //////////////////////////////////////////////////////////////////////////////////
- static HRESULT WINAPI EnumFormat(DDPIXELFORMAT* format, VOID* desired)
- {
- // Stop if this is ANY type of depth buffer
- if(format->dwFlags == DDPF_ZBUFFER)
- {
- memcpy(desired, format, sizeof(DDPIXELFORMAT));
- return D3DENUMRET_CANCEL;
- }
-
- return D3DENUMRET_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateDirectDraw
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateDirectDraw(void)
- {
- LPDIRECTDRAW directdraw = NULL;
- HRESULT rval;
-
- if(m_IsFullScreen && m_Is3D)
- {
- // Enumerate the hardware drivers
- rval = DirectDrawEnumerate(EnumDriver, &directdraw);
- if(rval != DD_OK) return rval;
- }
-
- if(directdraw == NULL)
- {
- // If no hardware found then use a software driver
- rval = DirectDrawCreate(NULL, &directdraw, NULL);
- if(rval != DD_OK) return rval;
- }
-
- // Get the latest interface
- rval = directdraw->QueryInterface(IID_IDirectDraw4, (LPVOID*)&m_DirectDraw);
- if(rval != DD_OK) return rval;
-
- SAFE_RELEASE(directdraw);
-
- // Set the cooperative level flags
- DWORD Mode = DDSCL_NORMAL;
-
- if(m_IsFullScreen)
- Mode = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX;
-
- if(m_IsFPU) Mode |= DDSCL_FPUSETUP;
-
- // Set the cooperative level
- rval = m_DirectDraw->SetCooperativeLevel(m_Hwnd, Mode);
- if(rval != DD_OK) return rval;
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateBuffers
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateBuffers(void)
- {
- HRESULT rval;
-
- m_FrontBuffer = new CDX_Surface();
- m_BackBuffer = new CDX_Surface();
-
- if(m_IsFullScreen)
- {
- // Set the screen and viewport dimensions
- SetRect(&m_ScreenRect, 0, 0, m_Width, m_Height);
- SetRect(&m_ViewportRect, 0, 0, m_Width, m_Height);
-
- DWORD Mode = 0;
-
- // Check for Mode 13h
- if((m_Width == 320) && (m_Height == 200) && (m_Bpp == 8))
- Mode = DDSDM_STANDARDVGAMODE;
-
- // Set the dispay mode
- rval = m_DirectDraw->SetDisplayMode(m_Width, m_Height, m_Bpp, 0, Mode);
- if(rval != DD_OK) return rval;
-
- // Set the front buffer flags for fullscreen mode
- m_FrontBuffer->m_Desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
- m_FrontBuffer->m_Desc.dwBackBufferCount = 1;
- m_FrontBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
- DDSCAPS_FLIP |
- DDSCAPS_COMPLEX;
- if(m_Is3D) m_FrontBuffer->m_Desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
- }
- else
- {
- // Set the screen and viewport dimensions
- GetClientRect(m_Hwnd, &m_ViewportRect);
- GetClientRect(m_Hwnd, &m_ScreenRect);
- ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.left);
- ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.right);
- m_Width = m_ScreenRect.right - m_ScreenRect.left;
- m_Height = m_ScreenRect.bottom - m_ScreenRect.top;
-
- // Set the front buffer flags for windowed mode
- m_FrontBuffer->m_Desc.dwFlags = DDSD_CAPS;
- m_FrontBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- }
-
- // Create the front buffer
- rval = m_FrontBuffer->Create(this);
- if(rval != DD_OK) return rval;
-
- if(m_IsFullScreen)
- {
- m_FrontBuffer->m_Caps.dwCaps = DDSCAPS_BACKBUFFER;
- m_FrontBuffer->m_Surface->GetAttachedSurface(
- &m_FrontBuffer->m_Caps,
- &m_BackBuffer->m_Surface);
- }
- else
- {
- m_BackBuffer->m_Desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
- m_BackBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
-
- if(m_Is3D) m_BackBuffer->m_Desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
-
- m_BackBuffer->m_Desc.dwWidth = m_Width;
- m_BackBuffer->m_Desc.dwHeight = m_Height;
-
- // Create the back buffer
- rval = m_BackBuffer->Create(this);
- if(rval != DD_OK) return rval;
-
- LPDIRECTDRAWCLIPPER clipper;
-
- // Create the window clipper
- rval = m_DirectDraw->CreateClipper(0, &clipper, NULL);
- if(rval != DD_OK) return rval;
-
- rval = clipper->SetHWnd(0, m_Hwnd);
- if(rval != DD_OK) return rval;
-
- rval = m_FrontBuffer->m_Surface->SetClipper(clipper);
- if(rval != DD_OK) return rval;;
-
- SAFE_RELEASE(clipper);
- }
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateDirect3D
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateDirect3D(void)
- {
- HRESULT rval;
-
- // Create the Direct3D instance
- rval = m_DirectDraw->QueryInterface(IID_IDirect3D3, (LPVOID*)&m_Direct3D);
- if(rval != S_OK) return rval;
-
- // Search for a hardware device
- D3DFINDDEVICERESULT result;
- D3DFINDDEVICESEARCH search;
-
- ZeroMemory(&result, sizeof(D3DFINDDEVICERESULT));
- ZeroMemory(&search, sizeof(D3DFINDDEVICESEARCH));
- result.dwSize = sizeof(D3DFINDDEVICERESULT);
- search.dwSize = sizeof(D3DFINDDEVICESEARCH);
- search.dwFlags = D3DFDS_HARDWARE;
- search.bHardware = TRUE;
-
- rval = m_Direct3D->FindDevice(&search, &result);
- if(rval != D3D_OK) return rval;
-
- // Set the device description and memory type
- m_MemoryType = DDSCAPS_VIDEOMEMORY;
- memcpy(&m_DeviceDesc, &result.ddHwDesc, sizeof(D3DDEVICEDESC));
-
- // Enumerate a format for our z-buffer
- ZeroMemory(&m_PixelFormat, sizeof(DDPIXELFORMAT));
- m_PixelFormat.dwFlags = DDPF_ZBUFFER;
-
- // Get an appropiate pixel format from enumeration of the formats
- rval = m_Direct3D->EnumZBufferFormats(
- result.guid,
- EnumFormat,
- (LPVOID)&m_PixelFormat);
- if(rval != D3D_OK) return rval;
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateZBuffer
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateZBuffer(void)
- {
- HRESULT rval;
-
- // Check if the device supports z-bufferless hidden surface removal
- DWORD rastercaps = m_DeviceDesc.dpcTriCaps.dwRasterCaps;
- if(rastercaps & D3DPRASTERCAPS_ZBUFFERLESSHSR) return S_OK;
-
- // Setup the surface description for the depth buffer
- m_DepthBuffer = new CDX_Surface;
-
- m_DepthBuffer->m_Desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT |
- DDSD_CAPS | DDSD_PIXELFORMAT;
- m_DepthBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_MemoryType;
- m_DepthBuffer->m_Desc.dwWidth = m_Width;
- m_DepthBuffer->m_Desc.dwHeight = m_Height;
- memcpy(&m_DepthBuffer->m_Desc.ddpfPixelFormat, &m_PixelFormat,
- sizeof(DDPIXELFORMAT));
-
- // Create the depth buffer
- rval = m_DepthBuffer->Create(this);
- if(rval != DD_OK) return rval;
-
- rval = m_BackBuffer->m_Surface->AddAttachedSurface(m_DepthBuffer->m_Surface);
- if(rval != DD_OK) return rval;
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateDevice
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateDevice(void)
- {
- // Try to create a hardware device
- return m_Direct3D->CreateDevice(
- IID_IDirect3DHALDevice,
- m_BackBuffer->m_Surface,
- &m_Device,
- NULL);
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen CreateViewport
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::CreateViewport(void)
- {
- HRESULT rval;
- D3DVIEWPORT2 viewport;
-
- memset(&viewport, 0, sizeof(D3DVIEWPORT2));
- viewport.dwSize = sizeof(D3DVIEWPORT2);
- viewport.dwX = 0;
- viewport.dwY = 0;
- viewport.dwWidth = m_Width;
- viewport.dwHeight = m_Height;
- viewport.dvClipX = -1.0f;
- viewport.dvClipWidth = 2.0f;
- viewport.dvClipHeight = (D3DVALUE)(m_Height * 2.0 / m_Width);
- viewport.dvClipY = viewport.dvClipHeight / 2.0f;
- viewport.dvMinZ = 0.0f;
- viewport.dvMaxZ = 1.0f;
-
- // Create the Viewport
- rval = m_Direct3D->CreateViewport(&m_Viewport, NULL);
- if(rval != D3D_OK) return rval;
-
- rval = m_Device->AddViewport(m_Viewport);
- if(rval != D3D_OK) return rval;
-
- rval = m_Viewport->SetViewport2(&viewport);
- if(rval != D3D_OK) return rval;
-
- rval = m_Device->SetCurrentViewport(m_Viewport);
- if(rval != D3D_OK) return rval;
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Create
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::Create(HWND hwnd, DWORD width, DWORD height, DWORD bpp, DWORD flags)
- {
- HRESULT rval;
-
- Finalise();
- Initialise();
-
- // Set some internal variables
- m_Width = width;
- m_Height = height;
- m_Bpp = bpp;
- m_Hwnd = hwnd;
-
- // What flags were requested?
- if(flags & CDXCREATE_FULLSCREEN) m_IsFullScreen = TRUE;
- if(flags & CDXCREATE_3D) m_Is3D = TRUE;
- if(flags & CDXCREATE_NO_FPUSETUP) m_IsFPU = FALSE;
-
- // Create the DirectDraw instance
- rval = CreateDirectDraw();
- if(rval != DD_OK) goto CREATE_FAILED;
-
- if(m_Is3D)
- {
- // Create the Direct3D instance
- rval = CreateDirect3D();
- if(rval != DD_OK) goto CREATE_FAILED;
- }
-
- // Create the front and back buffers
- rval = CreateBuffers();
- if(rval != DD_OK) goto CREATE_FAILED;
-
- if(m_Is3D)
- {
- // Create a Z buffer if required
- if(flags & CDXCREATE_ZBUFFER)
- {
- rval = CreateZBuffer();
- if(rval != DD_OK) goto CREATE_FAILED;
- }
-
- // Create the device
- rval = CreateDevice();
- if(rval != DD_OK) goto CREATE_FAILED;
-
- // Create the viewport
- rval = CreateViewport();
- if(rval != DD_OK) goto CREATE_FAILED;
- }
-
- goto CREATE_SUCCESS;
-
- CREATE_FAILED:
-
- Finalise();
-
- CREATE_SUCCESS:
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Flip - swaps the front and back buffers
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::Flip(void)
- {
- HRESULT rval;
-
- if(m_IsFullScreen)
- {
- rval = m_FrontBuffer->m_Surface->Flip(NULL, DDFLIP_WAIT);
- }
- else
- {
- GetClientRect(m_Hwnd, &m_ScreenRect);
- ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.left);
- ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.right);
-
- rval = m_FrontBuffer->m_Surface->Blt(
- &m_ScreenRect,
- m_BackBuffer->m_Surface,
- NULL,
- DDFLIP_WAIT,
- NULL);
- }
- if(rval == DDERR_SURFACELOST) Restore();
-
- return rval;
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // CDX_Screen Restore - restores the front buffer if it is lost
- //////////////////////////////////////////////////////////////////////////////////
- HRESULT CDX_Screen::Restore(void)
- {
- HRESULT rval = DD_OK;
-
- if(m_FrontBuffer)
- if(m_FrontBuffer->m_Surface->IsLost())
- rval = m_FrontBuffer->m_Surface->Restore();
-
- if(m_BackBuffer)
- if(m_BackBuffer->m_Surface->IsLost())
- rval = m_BackBuffer->m_Surface->Restore();
-
- if(m_DepthBuffer)
- if(m_DepthBuffer->m_Surface->IsLost())
- rval = m_DepthBuffer->m_Surface->Restore();
-
- return rval;
- }
-