home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CDX.ZIP / Src / Cdx / Screen.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-14  |  13.6 KB  |  483 lines

  1. //////////////////////////////////////////////////////////////////////////////////
  2. // Project Name:   [ CDX Class Library - CDX.lib ]
  3. // Author:         [ Dan Farley - 97308096@brookes.ac.uk ]
  4. // Source File:    [ CDX_Screen Implementation ]
  5. // Revision:       [ 1.6 ]
  6. //////////////////////////////////////////////////////////////////////////////////
  7. #include "CDX.h"
  8.  
  9. //////////////////////////////////////////////////////////////////////////////////
  10. // CDX_Screen Constructor
  11. //////////////////////////////////////////////////////////////////////////////////
  12. CDX_Screen::CDX_Screen()
  13. {
  14.     Initialise();
  15. }
  16.  
  17. //////////////////////////////////////////////////////////////////////////////////
  18. // CDX_Screen Destructor
  19. //////////////////////////////////////////////////////////////////////////////////
  20. CDX_Screen::~CDX_Screen(void)
  21. {
  22.     Finalise();
  23. }
  24.  
  25. //////////////////////////////////////////////////////////////////////////////////
  26. // CDX_Screen Initialise
  27. //////////////////////////////////////////////////////////////////////////////////
  28. void CDX_Screen::Initialise(void)
  29. {
  30.     m_DirectDraw = NULL;
  31.     m_Direct3D = NULL;
  32.     m_Device = NULL;
  33.     m_Viewport = NULL;
  34.     m_FrontBuffer = NULL;
  35.     m_BackBuffer = NULL;
  36.     m_DepthBuffer = NULL;
  37.     m_Width = 0;
  38.     m_Height = 0;
  39.     m_Bpp = 0;
  40.     m_Hwnd = NULL;
  41.     m_IsFullScreen = FALSE;
  42.     m_Is3D = FALSE;
  43.     m_IsFPU = TRUE;
  44. }
  45.  
  46. //////////////////////////////////////////////////////////////////////////////////
  47. // CDX_Screen Finalise
  48. //////////////////////////////////////////////////////////////////////////////////
  49. void CDX_Screen::Finalise(void)
  50. {
  51.     SAFE_RELEASE(m_Viewport);
  52.     SAFE_RELEASE(m_Device);
  53.     SAFE_DELETE(m_BackBuffer);
  54.     SAFE_DELETE(m_DepthBuffer);
  55.     SAFE_DELETE(m_FrontBuffer);
  56.     SAFE_RELEASE(m_Direct3D);
  57.     SAFE_RELEASE(m_DirectDraw);
  58. }
  59.  
  60. //////////////////////////////////////////////////////////////////////////////////
  61. // EnumDriver
  62. //////////////////////////////////////////////////////////////////////////////////
  63. static BOOL WINAPI EnumDriver(GUID FAR* guid, LPSTR desc, LPSTR name, LPVOID context)
  64. {
  65.     LPDIRECTDRAW directdraw;
  66.     DDCAPS caps;
  67.  
  68.     // Make sure the guid is valid
  69.     if(guid)
  70.     {
  71.         // Try to create a DirectDraw object
  72.         DirectDrawCreate(guid, &directdraw, NULL);
  73.  
  74.         // Get the DirectDraw capabilities
  75.         memset(&caps, 0, sizeof(DDCAPS));
  76.         caps.dwSize = sizeof(DDCAPS);
  77.  
  78.         directdraw->GetCaps(&caps, NULL);
  79.  
  80.         // Does this driver have 3D hardware capabilites?
  81.         if(caps.dwCaps & DDCAPS_3D)
  82.         {
  83.             *(LPDIRECTDRAW*)context = directdraw;
  84.             return DDENUMRET_CANCEL;
  85.         }
  86.  
  87.         *(LPDIRECTDRAW*)context = NULL;
  88.         directdraw->Release();
  89.     }
  90.     return DDENUMRET_OK;
  91. }
  92.  
  93. //////////////////////////////////////////////////////////////////////////////////
  94. // EnumFormat
  95. //////////////////////////////////////////////////////////////////////////////////
  96. static HRESULT WINAPI EnumFormat(DDPIXELFORMAT* format, VOID* desired)
  97. {
  98.     // Stop if this is ANY type of depth buffer
  99.     if(format->dwFlags == DDPF_ZBUFFER)
  100.     {
  101.         memcpy(desired, format, sizeof(DDPIXELFORMAT));
  102.         return D3DENUMRET_CANCEL;
  103.     }
  104.  
  105.     return D3DENUMRET_OK;
  106. }
  107.  
  108. //////////////////////////////////////////////////////////////////////////////////
  109. // CDX_Screen CreateDirectDraw
  110. //////////////////////////////////////////////////////////////////////////////////
  111. HRESULT CDX_Screen::CreateDirectDraw(void)
  112. {
  113.     LPDIRECTDRAW directdraw = NULL;
  114.     HRESULT rval;
  115.  
  116.     if(m_IsFullScreen && m_Is3D)
  117.     {
  118.         // Enumerate the hardware drivers
  119.         rval = DirectDrawEnumerate(EnumDriver, &directdraw);
  120.         if(rval != DD_OK) return rval;
  121.     }
  122.  
  123.     if(directdraw == NULL)
  124.     {
  125.         // If no hardware found then use a software driver
  126.         rval = DirectDrawCreate(NULL, &directdraw, NULL);
  127.         if(rval != DD_OK) return rval;
  128.     }
  129.  
  130.     // Get the latest interface
  131.     rval = directdraw->QueryInterface(IID_IDirectDraw4, (LPVOID*)&m_DirectDraw);
  132.     if(rval != DD_OK) return rval;
  133.  
  134.     SAFE_RELEASE(directdraw);
  135.  
  136.     // Set the cooperative level flags
  137.     DWORD Mode = DDSCL_NORMAL;
  138.  
  139.     if(m_IsFullScreen)
  140.         Mode = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX;
  141.  
  142.     if(m_IsFPU) Mode |= DDSCL_FPUSETUP;
  143.  
  144.     // Set the cooperative level
  145.     rval = m_DirectDraw->SetCooperativeLevel(m_Hwnd, Mode);
  146.     if(rval != DD_OK) return rval;
  147.  
  148.     return rval;
  149. }
  150.  
  151. //////////////////////////////////////////////////////////////////////////////////
  152. // CDX_Screen CreateBuffers
  153. //////////////////////////////////////////////////////////////////////////////////
  154. HRESULT CDX_Screen::CreateBuffers(void)
  155. {
  156.     HRESULT rval;
  157.  
  158.     m_FrontBuffer = new CDX_Surface();
  159.     m_BackBuffer = new CDX_Surface();
  160.  
  161.     if(m_IsFullScreen)
  162.     {
  163.         // Set the screen and viewport dimensions
  164.         SetRect(&m_ScreenRect, 0, 0, m_Width, m_Height);
  165.         SetRect(&m_ViewportRect, 0, 0, m_Width, m_Height);
  166.  
  167.         DWORD Mode = 0;
  168.  
  169.         // Check for Mode 13h
  170.         if((m_Width == 320) && (m_Height == 200) && (m_Bpp == 8))
  171.             Mode = DDSDM_STANDARDVGAMODE;
  172.  
  173.         // Set the dispay mode
  174.         rval = m_DirectDraw->SetDisplayMode(m_Width, m_Height, m_Bpp, 0, Mode);
  175.         if(rval != DD_OK) return rval;
  176.  
  177.         // Set the front buffer flags for fullscreen mode
  178.         m_FrontBuffer->m_Desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  179.         m_FrontBuffer->m_Desc.dwBackBufferCount = 1;
  180.         m_FrontBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  181.                                                DDSCAPS_FLIP |
  182.                                                DDSCAPS_COMPLEX;
  183.         if(m_Is3D) m_FrontBuffer->m_Desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
  184.     }
  185.     else
  186.     {
  187.         // Set the screen and viewport dimensions
  188.         GetClientRect(m_Hwnd, &m_ViewportRect);
  189.         GetClientRect(m_Hwnd, &m_ScreenRect);
  190.         ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.left);
  191.         ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.right);
  192.         m_Width  = m_ScreenRect.right - m_ScreenRect.left;
  193.         m_Height = m_ScreenRect.bottom - m_ScreenRect.top;
  194.  
  195.         // Set the front buffer flags for windowed mode
  196.         m_FrontBuffer->m_Desc.dwFlags = DDSD_CAPS;
  197.         m_FrontBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  198.     }
  199.  
  200.     // Create the front buffer
  201.     rval = m_FrontBuffer->Create(this);
  202.     if(rval != DD_OK) return rval;
  203.  
  204.     if(m_IsFullScreen)
  205.     {
  206.         m_FrontBuffer->m_Caps.dwCaps = DDSCAPS_BACKBUFFER;
  207.         m_FrontBuffer->m_Surface->GetAttachedSurface(
  208.             &m_FrontBuffer->m_Caps,
  209.             &m_BackBuffer->m_Surface);
  210.     }
  211.     else
  212.     {
  213.         m_BackBuffer->m_Desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  214.         m_BackBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  215.  
  216.         if(m_Is3D) m_BackBuffer->m_Desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE;
  217.  
  218.         m_BackBuffer->m_Desc.dwWidth = m_Width;
  219.         m_BackBuffer->m_Desc.dwHeight = m_Height;
  220.  
  221.         // Create the back buffer
  222.         rval = m_BackBuffer->Create(this);
  223.         if(rval != DD_OK) return rval;
  224.  
  225.         LPDIRECTDRAWCLIPPER clipper;
  226.  
  227.         // Create the window clipper
  228.         rval = m_DirectDraw->CreateClipper(0, &clipper, NULL);
  229.         if(rval != DD_OK) return rval;
  230.  
  231.         rval = clipper->SetHWnd(0, m_Hwnd);
  232.         if(rval != DD_OK) return rval;
  233.  
  234.         rval = m_FrontBuffer->m_Surface->SetClipper(clipper);
  235.         if(rval != DD_OK) return rval;;
  236.     
  237.         SAFE_RELEASE(clipper);
  238.     }
  239.  
  240.     return rval;
  241. }
  242.  
  243. //////////////////////////////////////////////////////////////////////////////////
  244. // CDX_Screen CreateDirect3D
  245. //////////////////////////////////////////////////////////////////////////////////
  246. HRESULT CDX_Screen::CreateDirect3D(void)
  247. {
  248.     HRESULT rval;
  249.  
  250.     // Create the Direct3D instance
  251.     rval = m_DirectDraw->QueryInterface(IID_IDirect3D3, (LPVOID*)&m_Direct3D);
  252.     if(rval != S_OK) return rval;
  253.  
  254.     // Search for a hardware device
  255.     D3DFINDDEVICERESULT result;
  256.     D3DFINDDEVICESEARCH search;
  257.  
  258.     ZeroMemory(&result, sizeof(D3DFINDDEVICERESULT));
  259.     ZeroMemory(&search, sizeof(D3DFINDDEVICESEARCH));
  260.     result.dwSize = sizeof(D3DFINDDEVICERESULT);
  261.     search.dwSize = sizeof(D3DFINDDEVICESEARCH);
  262.     search.dwFlags = D3DFDS_HARDWARE;
  263.     search.bHardware = TRUE;
  264.  
  265.     rval = m_Direct3D->FindDevice(&search, &result);
  266.     if(rval != D3D_OK) return rval;
  267.  
  268.     // Set the device description and memory type
  269.     m_MemoryType = DDSCAPS_VIDEOMEMORY;
  270.     memcpy(&m_DeviceDesc, &result.ddHwDesc, sizeof(D3DDEVICEDESC));
  271.  
  272.     // Enumerate a format for our z-buffer
  273.     ZeroMemory(&m_PixelFormat, sizeof(DDPIXELFORMAT));
  274.     m_PixelFormat.dwFlags = DDPF_ZBUFFER;
  275.  
  276.     // Get an appropiate pixel format from enumeration of the formats
  277.     rval = m_Direct3D->EnumZBufferFormats(
  278.         result.guid,
  279.         EnumFormat,
  280.         (LPVOID)&m_PixelFormat);
  281.     if(rval != D3D_OK) return rval;
  282.  
  283.     return rval;
  284. }
  285.  
  286. //////////////////////////////////////////////////////////////////////////////////
  287. // CDX_Screen CreateZBuffer
  288. //////////////////////////////////////////////////////////////////////////////////
  289. HRESULT CDX_Screen::CreateZBuffer(void)
  290. {
  291.     HRESULT rval;
  292.  
  293.     // Check if the device supports z-bufferless hidden surface removal
  294.     DWORD rastercaps = m_DeviceDesc.dpcTriCaps.dwRasterCaps;
  295.     if(rastercaps & D3DPRASTERCAPS_ZBUFFERLESSHSR) return S_OK;
  296.  
  297.     // Setup the surface description for the depth buffer
  298.     m_DepthBuffer = new CDX_Surface;
  299.  
  300.     m_DepthBuffer->m_Desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT |
  301.         DDSD_CAPS | DDSD_PIXELFORMAT;
  302.     m_DepthBuffer->m_Desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_MemoryType;
  303.     m_DepthBuffer->m_Desc.dwWidth = m_Width;
  304.     m_DepthBuffer->m_Desc.dwHeight = m_Height;
  305.     memcpy(&m_DepthBuffer->m_Desc.ddpfPixelFormat, &m_PixelFormat,
  306.         sizeof(DDPIXELFORMAT));
  307.  
  308.     // Create the depth buffer
  309.     rval = m_DepthBuffer->Create(this);
  310.     if(rval != DD_OK) return rval;
  311.  
  312.     rval = m_BackBuffer->m_Surface->AddAttachedSurface(m_DepthBuffer->m_Surface);
  313.     if(rval != DD_OK) return rval;
  314.  
  315.     return rval;
  316. }
  317.  
  318. //////////////////////////////////////////////////////////////////////////////////
  319. // CDX_Screen CreateDevice
  320. //////////////////////////////////////////////////////////////////////////////////
  321. HRESULT CDX_Screen::CreateDevice(void)
  322. {
  323.     // Try to create a hardware device
  324.     return m_Direct3D->CreateDevice(
  325.         IID_IDirect3DHALDevice,
  326.         m_BackBuffer->m_Surface,
  327.         &m_Device,
  328.         NULL);
  329. }
  330.  
  331. //////////////////////////////////////////////////////////////////////////////////
  332. // CDX_Screen CreateViewport
  333. //////////////////////////////////////////////////////////////////////////////////
  334. HRESULT CDX_Screen::CreateViewport(void)
  335. {
  336.     HRESULT rval;
  337.     D3DVIEWPORT2 viewport;
  338.  
  339.     memset(&viewport, 0, sizeof(D3DVIEWPORT2));
  340.     viewport.dwSize = sizeof(D3DVIEWPORT2);
  341.     viewport.dwX = 0;
  342.     viewport.dwY = 0;
  343.     viewport.dwWidth  = m_Width;
  344.     viewport.dwHeight = m_Height;
  345.     viewport.dvClipX = -1.0f;
  346.     viewport.dvClipWidth = 2.0f;
  347.     viewport.dvClipHeight = (D3DVALUE)(m_Height * 2.0 / m_Width);
  348.     viewport.dvClipY = viewport.dvClipHeight / 2.0f;
  349.     viewport.dvMinZ = 0.0f;
  350.     viewport.dvMaxZ = 1.0f;
  351.  
  352.     // Create the Viewport
  353.     rval = m_Direct3D->CreateViewport(&m_Viewport, NULL);
  354.     if(rval != D3D_OK) return rval;
  355.  
  356.     rval = m_Device->AddViewport(m_Viewport);
  357.     if(rval != D3D_OK) return rval;
  358.  
  359.     rval = m_Viewport->SetViewport2(&viewport);
  360.     if(rval != D3D_OK) return rval;
  361.  
  362.     rval = m_Device->SetCurrentViewport(m_Viewport);
  363.     if(rval != D3D_OK) return rval;
  364.  
  365.     return rval;
  366. }
  367.  
  368. //////////////////////////////////////////////////////////////////////////////////
  369. // CDX_Screen Create
  370. //////////////////////////////////////////////////////////////////////////////////
  371. HRESULT CDX_Screen::Create(HWND hwnd, DWORD width, DWORD height, DWORD bpp, DWORD flags)
  372. {
  373.     HRESULT rval;
  374.  
  375.     Finalise();
  376.     Initialise();
  377.  
  378.     // Set some internal variables
  379.     m_Width = width;
  380.     m_Height = height;
  381.     m_Bpp = bpp;
  382.     m_Hwnd = hwnd;
  383.  
  384.     // What flags were requested?
  385.     if(flags & CDXCREATE_FULLSCREEN) m_IsFullScreen = TRUE;
  386.     if(flags & CDXCREATE_3D) m_Is3D = TRUE;
  387.     if(flags & CDXCREATE_NO_FPUSETUP) m_IsFPU = FALSE;
  388.  
  389.     // Create the DirectDraw instance
  390.     rval = CreateDirectDraw();
  391.     if(rval != DD_OK) goto CREATE_FAILED;
  392.  
  393.     if(m_Is3D)
  394.     {
  395.         // Create the Direct3D instance
  396.         rval = CreateDirect3D();
  397.         if(rval != DD_OK) goto CREATE_FAILED;
  398.     }
  399.  
  400.     // Create the front and back buffers
  401.     rval = CreateBuffers();
  402.     if(rval != DD_OK) goto CREATE_FAILED;
  403.  
  404.     if(m_Is3D)
  405.     {
  406.         // Create a Z buffer if required
  407.         if(flags & CDXCREATE_ZBUFFER)
  408.         {
  409.             rval = CreateZBuffer();
  410.             if(rval != DD_OK) goto CREATE_FAILED;
  411.         }
  412.  
  413.         // Create the device
  414.         rval = CreateDevice();
  415.         if(rval != DD_OK) goto CREATE_FAILED;
  416.  
  417.         // Create the viewport
  418.         rval = CreateViewport();
  419.         if(rval != DD_OK) goto CREATE_FAILED;
  420.     }
  421.  
  422.     goto CREATE_SUCCESS;
  423.  
  424. CREATE_FAILED:
  425.  
  426.     Finalise();
  427.  
  428. CREATE_SUCCESS:
  429.  
  430.     return rval;
  431. }
  432.  
  433. //////////////////////////////////////////////////////////////////////////////////
  434. // CDX_Screen Flip - swaps the front and back buffers
  435. //////////////////////////////////////////////////////////////////////////////////
  436. HRESULT CDX_Screen::Flip(void)
  437. {
  438.     HRESULT rval;
  439.  
  440.     if(m_IsFullScreen)
  441.     {
  442.         rval = m_FrontBuffer->m_Surface->Flip(NULL, DDFLIP_WAIT);
  443.     }
  444.     else
  445.     {
  446.         GetClientRect(m_Hwnd, &m_ScreenRect);
  447.         ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.left);
  448.         ClientToScreen(m_Hwnd, (LPPOINT)&m_ScreenRect.right);
  449.  
  450.         rval = m_FrontBuffer->m_Surface->Blt(
  451.             &m_ScreenRect,
  452.             m_BackBuffer->m_Surface,
  453.             NULL,
  454.             DDFLIP_WAIT,
  455.             NULL);
  456.     }
  457.     if(rval == DDERR_SURFACELOST) Restore();
  458.  
  459.     return rval;
  460. }
  461.  
  462. //////////////////////////////////////////////////////////////////////////////////
  463. // CDX_Screen Restore - restores the front buffer if it is lost
  464. //////////////////////////////////////////////////////////////////////////////////
  465. HRESULT CDX_Screen::Restore(void)
  466. {
  467.     HRESULT rval = DD_OK;
  468.  
  469.   if(m_FrontBuffer)
  470.         if(m_FrontBuffer->m_Surface->IsLost())
  471.             rval = m_FrontBuffer->m_Surface->Restore();
  472.  
  473.   if(m_BackBuffer)
  474.         if(m_BackBuffer->m_Surface->IsLost())
  475.             rval = m_BackBuffer->m_Surface->Restore();
  476.  
  477.   if(m_DepthBuffer)
  478.         if(m_DepthBuffer->m_Surface->IsLost())
  479.             rval = m_DepthBuffer->m_Surface->Restore();
  480.  
  481.     return rval;
  482. }
  483.