// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
// ***************************************************************************
// display_dlg.cpp : implementation file
// ***************************************************************************
#include "stdafx.h"
#include "client_config.h"
#include "display_dlg.h"
#include "cfg_file.h"
using namespace std;
using namespace NLMISC;
using namespace NL3D;
// ***************************************************************************
std::vector GLExtensions;
std::string GLRenderer;
std::string GLVendor;
std::string GLVersion;
std::string D3DDescription;
std::string D3DDeviceName;
std::string D3DDriver;
std::string D3DDriverVersion;
std::string D3DVendor;
uint VideoMemory;
uint HardwareSoundBuffer;
uint64 SystemMemory;
uint CPUFrequency;
bool GetGLInformations ()
{
// *** INIT VARIABLES
GLExtensions.clear ();
GLRenderer = "";
GLVendor = "";
GLVersion = "";
// *** INIT OPENGL
// Register a window class
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW ;//| CS_DBLCLKS;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(NULL);
wc.hIcon = (HICON)NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = WHITE_BRUSH;
wc.lpszClassName = "RyzomGetGlInformations";
wc.lpszMenuName = NULL;
if ( !RegisterClass(&wc) )
return false;
// Create a window
ULONG WndFlags = WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS;
RECT WndRect;
WndRect.left=0;
WndRect.top=0;
WndRect.right=100;
WndRect.bottom=100;
HWND hWnd = CreateWindow ( "RyzomGetGlInformations",
"",
WndFlags,
CW_USEDEFAULT,CW_USEDEFAULT,
WndRect.right,WndRect.bottom,
NULL,
NULL,
GetModuleHandle(NULL),
NULL);
if (!hWnd)
return false;
HDC hDC = GetDC(hWnd);
// Remove current gl context
wglMakeCurrent (hDC, NULL);
// Select pixel format
int depth = GetDeviceCaps (hDC, BITSPIXEL);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd,0,sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = (char)depth;
if(depth<=16)
pfd.cDepthBits = 16;
else
{
pfd.cDepthBits = 24;
pfd.cAlphaBits = 8;
}
pfd.iLayerType = PFD_MAIN_PLANE;
int pf=ChoosePixelFormat(hDC, &pfd);
if (!pf)
return false;
if ( !SetPixelFormat(hDC, pf, &pfd) )
return false;
// Create final context
HGLRC hRC = wglCreateContext (hDC);
wglMakeCurrent(hDC, hRC);
// *** GET INFORMATIONS
GLVendor = (const char *) glGetString (GL_VENDOR);
GLRenderer = (const char *) glGetString (GL_RENDERER);
GLVersion = (const char *) glGetString (GL_VERSION);
// Get extension string
string glext = (char*)glGetString(GL_EXTENSIONS);
const char *token = strtok ( (char*)glext.c_str (), " ");
while( token != NULL )
{
GLExtensions.push_back (token);
token = strtok( NULL, " ");
}
// Get proc adress
typedef const char* (APIENTRY * PFNWGFGETEXTENSIONSSTRINGARB) (HDC);
PFNWGFGETEXTENSIONSSTRINGARB wglGetExtensionsStringARB;
if ((wglGetExtensionsStringARB=(PFNWGFGETEXTENSIONSSTRINGARB)wglGetProcAddress("wglGetExtensionsStringARB")))
{
// Get extension string
glext = wglGetExtensionsStringARB (hDC);
token = strtok ( (char*)glext.c_str (), " ");
while( token != NULL )
{
GLExtensions.push_back (token);
token = strtok( NULL, " ");
}
}
// *** RELEASE OPENGL
if (hRC)
wglDeleteContext(hRC);
if (hWnd&&hDC)
{
ReleaseDC (hWnd,hDC);
DestroyWindow (hWnd);
}
// Done
return true;
}
// ***************************************************************************
bool GetD3DInformations (NL3D::IDriver *d3dDriver)
{
IDriver::CAdapter desc;
if (d3dDriver->getAdapter (0xffffffff, desc))
{
D3DDescription = desc.Description;
D3DDeviceName = desc.DeviceName;
D3DDriver = desc.Driver;
D3DDriverVersion = toString ((uint16)(desc.DriverVersion>>48))+"."+
toString ((uint16)(desc.DriverVersion>>32))+"."+
toString ((uint16)(desc.DriverVersion>>16))+"."+
toString ((uint16)(desc.DriverVersion&0xffff));
D3DVendor = desc.Vendor;
return true;
}
return false;
}
// ***************************************************************************
bool GetVideoMemory ()
{
VideoMemory = 0;
bool ret = false;
// Initialise Direct Draw
IDirectDraw *dd;
HRESULT result = DirectDrawCreate(NULL, &dd, NULL);
if (result == DD_OK)
{
DDCAPS caps;
memset (&caps, 0, sizeof(DDCAPS));
caps.dwSize = sizeof(DDCAPS);
dd->GetCaps (&caps, NULL);
VideoMemory = caps.dwVidMemTotal;
ret = true;
dd->Release ();
}
// Can't get it
return ret;
}
// ***************************************************************************
bool GetHardwareSoundBuffer ()
{
bool ret = false;
HardwareSoundBuffer = 0;
// The DirectSound object
#if (DIRECTSOUND_VERSION >= 0x0800)
LPDIRECTSOUND8 _DirectSound;
#else
LPDIRECTSOUND _DirectSound;
#endif
#if (DIRECTSOUND_VERSION >= 0x0800)
if (DirectSoundCreate8(NULL, &_DirectSound, NULL) == DS_OK)
#else
if (DirectSoundCreate(NULL, &_DirectSound, NULL) == DS_OK)
#endif
{
DSCAPS caps;
memset (&caps, 0, sizeof (DSCAPS));
caps.dwSize = sizeof (DSCAPS);
HRESULT result = _DirectSound->GetCaps (&caps);
if (result == DS_OK)
{
HardwareSoundBuffer = caps.dwFreeHw3DStaticBuffers;
ret = true;
}
_DirectSound->Release ();
}
return ret;
}
// ***************************************************************************
bool GetSystemInformations (IDriver *d3dDriver)
{
bool result = GetGLInformations ();
result |= GetD3DInformations (d3dDriver);
result |= GetVideoMemory ();
result |= GetHardwareSoundBuffer ();
SystemMemory = CSystemInfo::totalPhysicalMemory ();
CPUFrequency = (uint)(CSystemInfo::getProcessorFrequency () / (uint64)1000000);
return result;
}
// ***************************************************************************
std::vector VideoModes[2];
// ***************************************************************************
void RegisterVideoModes (uint driverId, IDriver *driver)
{
vector modes;
driver->getModes (modes);
uint i;
VideoModes[driverId].clear();
for (i=0; i= 800) && (modes[i].Width >= 600))
{
// Add this mode
CVideoMode mode;
mode.Width = modes[i].Width;
mode.Height = modes[i].Height;
mode.ColorDepth = modes[i].Depth;
mode.Frequency = modes[i].Frequency;
VideoModes[driverId].push_back (mode);
}
}
}
// ***************************************************************************
// CDisplayDlg dialog
// ***************************************************************************
CDisplayDlg::CDisplayDlg(CWnd* pParent /*=NULL*/)
: CBaseDialog(CDisplayDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDisplayDlg)
DriverChoiceMode = DrvChooseUnknwown;
Windowed = -1;
Width = 0;
Height = 0;
Mode = -1;
PositionX = 0;
PositionY = 0;
//}}AFX_DATA_INIT
}
// ***************************************************************************
void CDisplayDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDisplayDlg)
DDX_Control(pDX, IDC_DISPLAY_FS_TEXT0, TextFS0);
DDX_Control(pDX, IDC_DISPLAY_WND_TEXT0, TextWnd0);
DDX_Control(pDX, IDC_DISPLAY_WND_TEXT1, TextWnd1);
DDX_Control(pDX, IDC_DISPLAY_WND_TEXT2, TextWnd2);
DDX_Control(pDX, IDC_DISPLAY_WND_TEXT3, TextWnd3);
DDX_Control(pDX, IDC_POSITION_Y, PositionYCtrl);
DDX_Control(pDX, IDC_POSITION_X, PositionXCtrl);
DDX_Control(pDX, IDC_HEIGHT, HeightCtrl);
DDX_Control(pDX, IDC_WIDTH, WidthCtrl);
DDX_Control(pDX, IDC_MODE, ModeCtrl);
DDX_Radio(pDX, IDC_DRV3D_AUTO, DriverChoiceMode);
DDX_Radio(pDX, IDC_FULLSCREEN, Windowed);
DDX_Text(pDX, IDC_WIDTH, Width);
DDX_Text(pDX, IDC_HEIGHT, Height);
DDX_CBIndex(pDX, IDC_MODE, Mode);
DDX_Text(pDX, IDC_POSITION_X, PositionX);
DDX_Text(pDX, IDC_POSITION_Y, PositionY);
//}}AFX_DATA_MAP
}
// ***************************************************************************
BEGIN_MESSAGE_MAP(CDisplayDlg, CDialog)
//{{AFX_MSG_MAP(CDisplayDlg)
ON_BN_CLICKED(IDC_FULLSCREEN, OnFullscreen)
ON_BN_CLICKED(IDC_WINDOW, OnWindow)
ON_BN_CLICKED(IDC_DIRECT3D, OnDirect3d)
ON_BN_CLICKED(IDC_DRV3D_AUTO, OnDrv3DAuto)
ON_EN_CHANGE(IDC_HEIGHT, OnChangeHeight)
ON_BN_CLICKED(IDC_OPENGL, OnOpengl)
ON_EN_CHANGE(IDC_POSITION_X, OnChangePositionX)
ON_EN_CHANGE(IDC_WIDTH, OnChangeWidth)
ON_EN_CHANGE(IDC_POSITION_Y, OnChangePositionY)
ON_CBN_SELCHANGE(IDC_MODE, OnSelchangeMode)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// ***************************************************************************
// CDisplayDlg message handlers
// ***************************************************************************
void CDisplayDlg::OnFullscreen()
{
UpdateData (TRUE);
updateState ();
UpdateData (FALSE);
InvalidateConfig ();
}
// ***************************************************************************
void CDisplayDlg::OnWindow()
{
UpdateData (TRUE);
updateState ();
UpdateData (FALSE);
InvalidateConfig ();
}
// ***************************************************************************
void CDisplayDlg::updateState ()
{
ModeCtrl.EnableWindow (Windowed == 0);
TextFS0.EnableWindow (Windowed == 0);
WidthCtrl.EnableWindow (Windowed == 1);
HeightCtrl.EnableWindow (Windowed == 1);
PositionXCtrl.EnableWindow (Windowed == 1);
PositionYCtrl.EnableWindow (Windowed == 1);
TextWnd0.EnableWindow (Windowed == 1);
TextWnd1.EnableWindow (Windowed == 1);
TextWnd2.EnableWindow (Windowed == 1);
TextWnd3.EnableWindow (Windowed == 1);
// Fill the combobox values
ModeCtrl.ResetContent ();
uint i;
if (DriverChoiceMode != DrvChooseUnknwown)
{
TDriver actualDriver = getActualDriver();
for (i=0; i