Commits

spencercw  committed 41d3173

Add preliminary OpenGL support.

  • Participants
  • Parent commits 2521d1a

Comments (0)

Files changed (21)

File gb_emulator.sln

 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gmock", "third_party\gmock\gmock.vcxproj", "{7941D140-2260-4136-B2DE-9AE502E3BB3E}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew", "third_party\glew\glew.vcxproj", "{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
 		{7941D140-2260-4136-B2DE-9AE502E3BB3E}.Release|Win32.Build.0 = Release|Win32
 		{7941D140-2260-4136-B2DE-9AE502E3BB3E}.Release|x64.ActiveCfg = Release|x64
 		{7941D140-2260-4136-B2DE-9AE502E3BB3E}.Release|x64.Build.0 = Release|x64
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Debug|Win32.ActiveCfg = Debug|Win32
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Debug|Win32.Build.0 = Debug|Win32
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Debug|x64.ActiveCfg = Debug|x64
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Debug|x64.Build.0 = Debug|x64
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Release|Win32.ActiveCfg = Release|Win32
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Release|Win32.Build.0 = Release|Win32
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Release|x64.ActiveCfg = Release|x64
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		{318C7CCA-CB33-4798-BCCE-EBB4ADE05C3C} = {E4EA39C2-326B-473E-8DFC-EB8206863544}
 		{CD8488DE-0838-46D1-980C-3E325A7CF560} = {E4EA39C2-326B-473E-8DFC-EB8206863544}
 		{652CAAA0-2AAC-435C-A1BA-CBD1F5B0945D} = {E4EA39C2-326B-473E-8DFC-EB8206863544}
+		{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB} = {E4EA39C2-326B-473E-8DFC-EB8206863544}
 		{3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {C7EBDEED-384A-453D-B21E-18EFFDFD0D1E}
 		{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {C7EBDEED-384A-453D-B21E-18EFFDFD0D1E}
 		{1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {C7EBDEED-384A-453D-B21E-18EFFDFD0D1E}

File gb_emulator/gb_emulator.vcxproj

       <WarningLevel>Level4</WarningLevel>
       <Optimization>Disabled</Optimization>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DEBUG;ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\glew\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>DEBUG;GB_EMULATOR_EXPORTS;GLEW_STATIC;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <LargeAddressAware>true</LargeAddressAware>
       <AdditionalLibraryDirectories>$(OutDir);$(BOOST_ROOT)\lib;$(CG_LIB_PATH);$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
-      <AdditionalDependencies>cg.lib;cgD3D11.lib;d3dx11d.lib;dxgi.lib;gb_net.lib;hqx.lib;libprotobuf.lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>cg.lib;cgD3D11.lib;cgGL.lib;d3dx11d.lib;dxgi.lib;gb_net.lib;glew.lib;hqx.lib;libprotobuf.lib;OpenGL32.Lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
       <ImageHasSafeExceptionHandlers>true</ImageHasSafeExceptionHandlers>
     </Link>
       <WarningLevel>Level4</WarningLevel>
       <Optimization>Disabled</Optimization>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>DEBUG;ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\glew\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>DEBUG;GB_EMULATOR_EXPORTS;GLEW_STATIC;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <LargeAddressAware>true</LargeAddressAware>
       <AdditionalLibraryDirectories>$(OutDir);$(BOOST_ROOT)\lib64;$(CG_LIB64_PATH);$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
-      <AdditionalDependencies>cg.lib;cgD3D11.lib;d3dx11d.lib;dxgi.lib;gb_net.lib;hqx.lib;libprotobuf.lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>cg.lib;cgD3D11.lib;cgGL.lib;d3dx11d.lib;dxgi.lib;gb_net.lib;glew.lib;hqx.lib;libprotobuf.lib;OpenGL32.Lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\glew\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>GB_EMULATOR_EXPORTS;GLEW_STATIC;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OptimizeReferences>true</OptimizeReferences>
       <LargeAddressAware>true</LargeAddressAware>
       <AdditionalLibraryDirectories>$(OutDir);$(BOOST_ROOT)\lib;$(CG_LIB_PATH);$(DIRECTX_SDK_ROOT)\Lib\x86</AdditionalLibraryDirectories>
-      <AdditionalDependencies>cg.lib;cgD3D11.lib;d3dx11.lib;dxgi.lib;hqx.lib;gb_net.lib;libprotobuf.lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>cg.lib;cgD3D11.lib;cgGL.lib;d3dx11.lib;dxgi.lib;hqx.lib;glew.lib;gb_net.lib;libprotobuf.lib;OpenGL32.Lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
       <ImageHasSafeExceptionHandlers>true</ImageHasSafeExceptionHandlers>
     </Link>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <TreatWarningAsError>true</TreatWarningAsError>
-      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>ENABLE_SNDFILE_WINDOWS_PROTOTYPES;GB_EMULATOR_EXPORTS;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)include;$(SolutionDir)gb_net\include;$(SolutionDir)third_party\glew\include;$(SolutionDir)third_party\hqx\include;$(SolutionDir)third_party\protobuf\src;$(BOOST_ROOT);$(CG_INC_PATH);$(DIRECTX_SDK_ROOT)\Include</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>GB_EMULATOR_EXPORTS;GLEW_STATIC;_SCL_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <OptimizeReferences>true</OptimizeReferences>
       <LargeAddressAware>true</LargeAddressAware>
       <AdditionalLibraryDirectories>$(OutDir);$(BOOST_ROOT)\lib64;$(CG_LIB64_PATH);$(DIRECTX_SDK_ROOT)\Lib\x64</AdditionalLibraryDirectories>
-      <AdditionalDependencies>cg.lib;cgD3D11.lib;d3dx11.lib;dxgi.lib;hqx.lib;gb_net.lib;libprotobuf.lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>cg.lib;cgD3D11.lib;cgGL.lib;d3dx11.lib;dxgi.lib;hqx.lib;glew.lib;gb_net.lib;libprotobuf.lib;OpenGL32.Lib;XInput.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Windows</SubSystem>
     </Link>
     <PostBuildEvent>
     <ClInclude Include="include\gb_emulator\gb_timers.h" />
     <ClInclude Include="include\gb_emulator\gb_video.h" />
     <ClInclude Include="include\gb_emulator\gb_video_d3d11.h" />
+    <ClInclude Include="include\gb_emulator\gb_video_opengl.h" />
+    <ClInclude Include="include\gb_emulator\gb_window.h" />
+    <ClInclude Include="include\gb_emulator\glew_error.h" />
     <ClInclude Include="src\gb_sound_tables.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\gb_timers.cpp" />
     <ClCompile Include="src\gb_video.cpp" />
     <ClCompile Include="src\gb_video_d3d11.cpp" />
+    <ClCompile Include="src\gb_video_opengl.cpp" />
+    <ClCompile Include="src\glew_error.cpp" />
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="gb.proto">
     <None Include="shaders\pixel_shader.cg" />
     <None Include="shaders\vertex_shader.cg" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\third_party\glew\glew.vcxproj">
+      <Project>{c922b8dd-6530-41fd-af96-0e15cb2eb1fb}</Project>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

File gb_emulator/gb_emulator.vcxproj.filters

     <ClInclude Include="include\gb_emulator\gb_comms_serial.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="include\gb_emulator\gb_video_opengl.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="include\gb_emulator\gb_window.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="include\gb_emulator\glew_error.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="gb.pb.cc">
     <ClCompile Include="src\gb_comms_serial.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\gb_video_opengl.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\glew_error.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="gb.proto">

File gb_emulator/include/gb_emulator/gb.h

 class GbDebugger;
 class GbInput;
 class GbMemoryImpl;
-class GbSoundSdl;
 class GbSoundWasapi;
 class GbVideoD3D11;
-class GbVideoSdl;
 
 //! Main class for the GameBoy emulator.
 /**
 	friend class GbInput;
 	friend class GbMemoryImpl;
 	friend class GbSound;
-	friend class GbSoundSdl;
 	friend class GbSoundWasapi;
 	friend class GbVideo;
 	friend class GbVideoD3D11;

File gb_emulator/include/gb_emulator/gb_config.h

 	{
 		VIDEO_DEFAULT,  //!< Use an appropriate default.
 		VIDEO_D3D11,    //!< Direct3D 11.
-		VIDEO_SDL       //!< SDL.
+		VIDEO_OPENGL    //!< OpenGL.
 	};
 
 	//! Drivers that may be used to output the sound emulation.
 	enum AudioDriver
 	{
 		AUDIO_DEFAULT,  //!< Use an appropriate default.
-		AUDIO_WASAPI,   //!< WASAPI.
-		AUDIO_SDL       //!< SDL.
+		AUDIO_WASAPI    //!< WASAPI.
 	};
 
 	//! Rendering method to use for the video emulation.

File gb_emulator/include/gb_emulator/gb_video_opengl.h

+/*  Copyright � 2012 Chris Spencer <spencercw@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GB_VIDEO_OPENGL_H_31E5B920_17BE_11E2_B364_0002A5D5C51B
+#define GB_VIDEO_OPENGL_H_31E5B920_17BE_11E2_B364_0002A5D5C51B
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include <boost/filesystem/path.hpp>
+
+#include <Windows.h>
+#include <GL/glew.h>
+#include <GL/GL.h>
+
+#include <gb_emulator/gb_video.h>
+
+struct _CGcontext;
+struct _CGprogram;
+
+//! OpenGL video driver.
+class GbVideoOpenGL:
+	public GbVideo
+{
+public:
+	//! Constructor.
+	/*
+	 * \param gb The emulator context.
+	 * \param installDir The installation directory.
+	 */
+	GbVideoOpenGL(Gb &gb, const boost::filesystem::path &installDir);
+
+	//! Destructor.
+	~GbVideoOpenGL();
+
+	//! Indicates whether OpenGL is available.
+	/**
+	 * The current implementation always returns true.
+	 * \return Whether OpenGL is available.
+	 */
+	bool isAvailable()
+	{
+		return true;
+	}
+
+	//! Initialises OpenGL and opens the display.
+	void initialise();
+
+	//! Returns the window handle.
+	HWND window() const
+	{
+		return window_;
+	}
+
+private:
+	// Dimensions of the texture to which the video is rendered
+	static const unsigned TEXTURE_WIDTH = 1024;
+	static const unsigned TEXTURE_HEIGHT = 1024;
+
+	// The window we are drawing into
+	HWND window_;
+	ATOM windowClass_;
+	HDC deviceContext_;
+	HGLRC renderContext_;
+
+	// OpenGL data
+	GLuint program_;
+	GLuint vertexBuffer_;
+	GLuint texture_;
+
+	// Cg data
+	std::unique_ptr<_CGcontext, void (*)(_CGcontext *)> cgContext_;
+	std::unique_ptr<_CGprogram, void (*)(_CGprogram *)> vertexShader_;
+	std::unique_ptr<_CGprogram, void (*)(_CGprogram *)> fragmentShader_;
+
+	// The installation directory
+	boost::filesystem::path installDir_;
+
+	// RGB pixel buffers
+	std::unique_ptr<uint32_t[]> unscaledPixelBuffer_;
+	std::unique_ptr<uint32_t[]> scaledPixelBuffer_;
+	std::unique_ptr<uint32_t[]> textureBuffer_;
+
+	// Redraws the display
+	void draw(uint16_t *pixelBuffer, bool gbc);
+
+	// Called when the render window is resized
+	void resize(GLsizei width, GLsizei height);
+
+	// Initialisation functions
+	void setupPixelFormat();
+	void initialiseGL(GLsizei width, GLsizei height);
+	void initialiseShaders();
+	GLuint createShader(GLenum type, const char *code);
+	GLuint createProgram(const std::vector<GLuint> &shaders);
+
+	// Callbacks
+	static void cgErrorCallback();
+
+	// Window message procedure
+	static LRESULT CALLBACK initialWindowProc(HWND window, unsigned message, WPARAM wParam,
+		LPARAM lParam);
+	static LRESULT CALLBACK windowProc(HWND window, unsigned message, WPARAM wParam, LPARAM lParam);
+	LRESULT doWindowProc(HWND window, unsigned message, WPARAM wParam, LPARAM lParam);
+
+	// Disabled operations
+	GbVideoOpenGL(const GbVideoOpenGL &);
+	GbVideoOpenGL & operator=(const GbVideoOpenGL &);
+};
+
+#endif

File gb_emulator/include/gb_emulator/glew_error.h

+/*  Copyright � 2012 Chris Spencer <spencercw@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GLEW_ERROR_H_2F27CA40_17C1_11E2_969F_0002A5D5C51B
+#define GLEW_ERROR_H_2F27CA40_17C1_11E2_969F_0002A5D5C51B
+
+#include <system_error>
+
+//! Error category for GLEW errors.
+class glew_error_category:
+	public std::error_category
+{
+public:
+	//! Returns the name of the category.
+	const char * name() const;
+
+	//! Returns an error message for the given error code.
+	std::string message(int ev) const;
+};
+
+//! Returns an instance of glew_error_category.
+const std::error_category & glew_category();
+
+#endif

File gb_emulator/shaders/pixel_shader.cg

 
 struct PixelInput
 {
-	float4 position : SV_POSITION;
+	float4 position : POSITION;
 	float2 texCoord : TEXCOORD0;
 };
 

File gb_emulator/shaders/vertex_shader.cg

 
 struct PixelInput
 {
-	float4 position : SV_POSITION;
+	float4 position : POSITION;
 	float2 texCoord : TEXCOORD0;
 };
 

File gb_emulator/src/gb.cpp

 #include <gb_emulator/gb_memory.h>
 #include <gb_emulator/gb_sound_wasapi.h>
 #include <gb_emulator/gb_video_d3d11.h>
+#include <gb_emulator/gb_video_opengl.h>
 
 namespace fs = boost::filesystem;
 namespace pb = google::protobuf;
 		}
 		break;
 
+	case GbConfig::VIDEO_OPENGL:
+		clog << "loading OpenGL video driver\n";
+		video_.reset(new GbVideoOpenGL(*this, installDir_));
+		break;
+
 	default:
 		assert(!"unknown video driver");
 	}

File gb_emulator/src/gb_video_opengl.cpp

+/*  Copyright � 2012 Chris Spencer <spencercw@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <gb_emulator/gb_video_opengl.h>
+
+#include <stdexcept>
+#include <string>
+#include <system_error>
+
+#include <Cg/cgGL.h>
+
+#include <GL/wglew.h>
+
+#include <gb_emulator/glew_error.h>
+
+namespace fs = boost::filesystem;
+using std::runtime_error;
+using std::string;
+using std::system_category;
+using std::system_error;
+
+GbVideoOpenGL::GbVideoOpenGL(Gb &gb, const fs::path &installDir):
+GbVideo(gb),
+window_(nullptr),
+windowClass_(0),
+deviceContext_(nullptr),
+renderContext_(nullptr),
+vertexBuffer_(0),
+texture_(0),
+cgContext_(nullptr, cgDestroyContext),
+vertexShader_(nullptr, cgDestroyProgram),
+fragmentShader_(nullptr, cgDestroyProgram),
+installDir_(installDir),
+unscaledPixelBuffer_(new uint32_t[WIDTH * HEIGHT]),
+scaledPixelBuffer_(new uint32_t[SCALED_WIDTH * SCALED_HEIGHT]),
+textureBuffer_(new uint32_t[TEXTURE_WIDTH * TEXTURE_HEIGHT])
+{
+}
+
+GbVideoOpenGL::~GbVideoOpenGL()
+{
+	// Destroy the window if it has been created
+	if (window_)
+	{
+		DestroyWindow(window_);
+	}
+	if (windowClass_)
+	{
+		UnregisterClassW(reinterpret_cast<wchar_t *>(windowClass_), GetModuleHandle(nullptr));
+	}
+}
+void GbVideoOpenGL::draw(uint16_t *pixelBuffer, bool gbc)
+{
+	// Perform post-processing in software
+	postProcess(pixelBuffer, gbc, unscaledPixelBuffer_.get(), scaledPixelBuffer_.get());
+
+	// Upload the texture into video memory
+	glBindTexture(GL_TEXTURE_2D, texture_);
+	for (unsigned y = 0; y != SCALED_HEIGHT; ++y)
+	{
+		memcpy(&textureBuffer_[y * TEXTURE_WIDTH], &scaledPixelBuffer_[y * SCALED_WIDTH],
+			SCALED_WIDTH * sizeof(uint32_t));
+	}
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_BGRA,
+		GL_UNSIGNED_BYTE, textureBuffer_.get());
+
+	// Update the display
+	glClearColor(0.f, 0.f, 0.f, 0.f);
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	glDrawArrays(GL_QUADS, 0, 4);
+	
+	if (!SwapBuffers(deviceContext_))
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to swap buffers");
+	}
+}
+
+void GbVideoOpenGL::resize(GLsizei width, GLsizei height)
+{
+	glViewport(0, 0, width, height);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Initialisation
+
+void GbVideoOpenGL::initialise()
+{
+	// Register the window class
+	WNDCLASSEXW windowClassData;
+	memset(&windowClassData, 0, sizeof(windowClassData));
+	windowClassData.cbSize = sizeof(windowClassData);
+	windowClassData.style = 0;
+	windowClassData.lpfnWndProc = &GbVideoOpenGL::initialWindowProc;
+	windowClassData.cbClsExtra = 0;
+	windowClassData.cbWndExtra = 0;
+	windowClassData.hInstance = GetModuleHandle(nullptr);
+	windowClassData.hIcon = nullptr;
+	windowClassData.hCursor = LoadCursor(nullptr, IDC_ARROW);
+	windowClassData.hbrBackground = nullptr;
+	windowClassData.lpszClassName = L"WindowClass";
+	windowClassData.hIconSm = nullptr;
+
+	windowClass_ = RegisterClassExW(&windowClassData);
+	if (!windowClass_)
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to register window class");
+	}
+
+	RECT windowRect = { 0, 0, SCALED_WIDTH, SCALED_HEIGHT };
+	if (!AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE))
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to set the main window size");
+	}
+
+	// Create the main window
+	window_ = CreateWindowExW(0, reinterpret_cast<const wchar_t *>(windowClass_), L"GbVideoOpenGL",
+		WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
+		windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, nullptr, nullptr,
+		windowClassData.hInstance, this);
+	if (!window_)
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to create the main window");
+	}
+
+	// Show the window; OpenGL is initialised in the window procedure
+	ShowWindow(window_, SW_SHOWNORMAL);
+	UpdateWindow(window_);
+}
+
+void GbVideoOpenGL::setupPixelFormat()
+{
+	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 = 32;
+	pfd.cDepthBits = 16;
+
+	int pixelFormat = ChoosePixelFormat(deviceContext_, &pfd);
+	if (!pixelFormat)
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to determine pixel format");
+	}
+
+	if (!SetPixelFormat(deviceContext_, pixelFormat, &pfd))
+	{
+		throw system_error(GetLastError(), system_category(), "Failed to set pixel format");
+	}
+}
+
+void GbVideoOpenGL::initialiseGL(GLsizei width, GLsizei height)
+{
+	// Initialise GLEW
+	GLenum error = glewInit();
+	if (error != GLEW_OK)
+	{
+		throw system_error(error, glew_category(), "Failed to initialise GLEW");
+	}
+
+	// Initialise Cg
+	cgContext_.reset(cgCreateContext());
+	if (!cgContext_)
+	{
+		throw runtime_error(string("Failed to create Cg context: ") +
+			cgGetLastErrorString(nullptr));
+	}
+	cgSetErrorCallback(cgErrorCallback);
+
+	// Disable vsync
+	wglSwapIntervalEXT(0);
+
+	// Set the viewport
+	glViewport(0, 0, width, height);
+
+	// Initialise the shaders
+	initialiseShaders();
+	
+	// Create the data buffers
+	// Vertices
+	static const GLfloat VERTICES[] = {
+		 1.f, -1.f, 0.f, 1.f,
+		-1.f, -1.f, 0.f, 1.f,
+		-1.f,  1.f, 0.f, 1.f,
+		 1.f,  1.f, 0.f, 1.f };
+
+	CGparameter positionParameter = cgGetNamedParameter(vertexShader_.get(), "input.position");
+	if (!positionParameter)
+	{
+		throw runtime_error(string("Failed to get 'input.position' parameter from shader: ") +
+			cgGetLastErrorString(nullptr));
+	}
+	cgGLEnableClientState(positionParameter);
+	cgGLSetParameterPointer(positionParameter, 4, GL_FLOAT, 0, VERTICES);
+
+	// Texture coordinates
+	static const GLfloat TEXTURE_X = static_cast<GLfloat>(SCALED_WIDTH)  / TEXTURE_WIDTH;
+	static const GLfloat TEXTURE_Y = static_cast<GLfloat>(SCALED_HEIGHT) / TEXTURE_HEIGHT;
+	static const GLfloat TEX_COORDS[] = {
+		TEXTURE_X, TEXTURE_Y,
+		0.f, TEXTURE_Y,
+		0.f, 0.f,
+		TEXTURE_X, 0.f };
+
+	CGparameter texCoordParameter = cgGetNamedParameter(vertexShader_.get(), "input.texCoord");
+	if (!texCoordParameter)
+	{
+		throw runtime_error(string("Failed to get 'input.texCoord' parameter from shader: ") +
+			cgGetLastErrorString(nullptr));
+	}
+	cgGLEnableClientState(texCoordParameter);
+	cgGLSetParameterPointer(texCoordParameter, 2, GL_FLOAT, 0, TEX_COORDS);
+
+	// Create the texture
+	glGenTextures(1, &texture_);
+	glBindTexture(GL_TEXTURE_2D, texture_);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	// Bind the texture to the shader
+	CGparameter samplerParam = cgGetNamedParameter(fragmentShader_.get(), "sampler");
+	if (!samplerParam)
+	{
+		throw runtime_error(string("Failed to get 'sampler' parameter from shader: ") +
+			cgGetLastErrorString(nullptr));
+	}
+	cgGLSetTextureParameter(samplerParam, texture_);
+
+	// Bind the shaders
+	cgGLSetManageTextureParameters(cgContext_.get(), CG_TRUE);
+	cgGLBindProgram(vertexShader_.get());
+	cgGLBindProgram(fragmentShader_.get());
+}
+
+void GbVideoOpenGL::initialiseShaders()
+{
+	// Compile the shaders
+	vertexShader_.reset(cgCreateProgramFromFile(cgContext_.get(), CG_SOURCE,
+		(installDir_ / "shaders/vertex_shader.cg").string().c_str(), CG_PROFILE_GLSLV, nullptr,
+		nullptr));
+	if (!vertexShader_)
+	{
+		throw runtime_error(string("Failed to compile vertex shader: ") +
+			cgGetLastErrorString(nullptr));
+	}
+
+	fragmentShader_.reset(cgCreateProgramFromFile(cgContext_.get(), CG_SOURCE,
+		(installDir_ / "shaders/pixel_shader.cg").string().c_str(), CG_PROFILE_GLSLF, "passThrough",
+		nullptr));
+	if (!vertexShader_)
+	{
+		throw runtime_error(string("Failed to compile fragment shader: ") +
+			cgGetLastErrorString(nullptr));
+	}
+
+	// Load the shaders into OpenGL
+	cgGLLoadProgram(vertexShader_.get());
+	cgGLLoadProgram(fragmentShader_.get());
+}
+
+void GbVideoOpenGL::cgErrorCallback()
+{
+	string message = string("Cg error: ") + cgGetLastErrorString(nullptr);
+	OutputDebugStringA(message.c_str());
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Window message operations
+
+LRESULT CALLBACK GbVideoOpenGL::initialWindowProc(HWND window, unsigned message, WPARAM wParam,
+	LPARAM lParam)
+{
+	// Wait for the creation message so we can get the parent pointer and apply it to the window
+	if (message == WM_NCCREATE)
+	{
+		CREATESTRUCTW *cs = reinterpret_cast<CREATESTRUCTW *>(lParam);
+		GbVideoOpenGL *parent = reinterpret_cast<GbVideoOpenGL *>(cs->lpCreateParams);
+
+		SetWindowLongPtrW(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(parent));
+		SetWindowLongPtrW(window, GWLP_WNDPROC,
+			reinterpret_cast<LONG_PTR>(&GbVideoOpenGL::windowProc));
+
+		// Defer
+		return parent->doWindowProc(window, message, wParam, lParam);
+	}
+	return DefWindowProcW(window, message, wParam, lParam);
+}
+
+LRESULT CALLBACK GbVideoOpenGL::windowProc(HWND window, unsigned message, WPARAM wParam, LPARAM lParam)
+{
+	// Get the pointer to the parent object
+	GbVideoOpenGL *parent = reinterpret_cast<GbVideoOpenGL *>(GetWindowLongPtrW(window, GWLP_USERDATA));
+	if (parent)
+	{
+		return parent->doWindowProc(window, message, wParam, lParam);
+	}
+	return DefWindowProcW(window, message, wParam, lParam);
+}
+
+LRESULT GbVideoOpenGL::doWindowProc(HWND window, unsigned message, WPARAM wParam, LPARAM lParam)
+{
+	switch (message)
+	{
+	case WM_CREATE:
+		// Initialise OpenGL
+		deviceContext_ = GetDC(window);
+		if (!deviceContext_)
+		{
+			throw system_error(GetLastError(), system_category(), "Failed to get device context");
+		}
+		setupPixelFormat();
+
+		renderContext_ = wglCreateContext(deviceContext_);
+		if (!renderContext_)
+		{
+			throw system_error(GetLastError(), system_category(), "Failed to create OpenGL render context");
+		}
+		
+		if (!wglMakeCurrent(deviceContext_, renderContext_))
+		{
+			throw system_error(GetLastError(), system_category(), "Failed to set render context");
+		}
+
+		{
+			RECT rect;
+			if (!GetClientRect(window, &rect))
+			{
+				throw system_error(GetLastError(), system_category(), "Failed to get window area");
+			}
+			initialiseGL(rect.right, rect.bottom);
+		}
+		break;
+
+	case WM_PAINT:
+		{
+			PAINTSTRUCT ps;
+			if (!BeginPaint(window, &ps))
+			{
+				throw system_error(GetLastError(), system_category(),
+					"Failed to prepare window for painting");
+			}
+			if (!EndPaint(window, &ps))
+			{
+				throw system_error(GetLastError(), system_category(),
+					"Failed to end window painting");
+			}
+		}
+		break;
+
+	case WM_SIZE:
+		{
+			RECT rect;
+			if (!GetClientRect(window, &rect))
+			{
+				throw system_error(GetLastError(), system_category(), "Failed to get window area");
+			}
+			resize(rect.right, rect.bottom);
+		}
+		break;
+
+	case WM_CLOSE:
+		// Clean up
+		if (renderContext_ && !wglDeleteContext(renderContext_))
+		{
+			throw system_error(GetLastError(), system_category(),
+				"Failed to release OpenGL render context");
+		}
+		renderContext_ = nullptr;
+
+		if (deviceContext_ && !ReleaseDC(window, deviceContext_))
+		{
+			throw system_error(GetLastError(), system_category(),
+				"Failed to release device context");
+		}
+		deviceContext_ = nullptr;
+
+		// Close the window
+		if (!DestroyWindow(window))
+		{
+			throw system_error(GetLastError(), system_category(), "Failed to destroy window");
+		}
+		window_ = nullptr;
+		break;
+
+	case WM_DESTROY:
+		// Clean up
+		if (renderContext_ && !wglDeleteContext(renderContext_))
+		{
+			throw system_error(GetLastError(), system_category(),
+				"Failed to release OpenGL render context");
+		}
+		renderContext_ = nullptr;
+
+		if (deviceContext_ && !ReleaseDC(window, deviceContext_))
+		{
+			throw system_error(GetLastError(), system_category(),
+				"Failed to release device context");
+		}
+		deviceContext_ = nullptr;
+
+		// Quit
+		PostQuitMessage(0);
+		break;
+
+	default:
+		return DefWindowProcW(window, message, wParam, lParam);
+	}
+
+	return 0;
+}

File gb_emulator/src/glew_error.cpp

+/*  Copyright � 2012 Chris Spencer <spencercw@gmail.com>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <gb_emulator/glew_error.h>
+
+#include <GL/glew.h>
+
+using std::error_category;
+using std::string;
+
+const char * glew_error_category::name() const
+{
+	return "glew";
+}
+
+string glew_error_category::message(int ev) const
+{
+	return reinterpret_cast<const char *>(glewGetErrorString(ev));
+}
+
+const error_category & glew_category()
+{
+	static const glew_error_category glew_category_const;
+	return glew_category_const;
+}

File gb_emulator_main/main.cpp

 	{
 		// Create the command line argument structures
 		arg_str *vDriverArg = arg_str0("v", "vdriver", "<driver>",
-			"the video driver to use [d3d11 (default), sdl]");
+			"the video driver to use [d3d11 (default), opengl]");
 		arg_str *aDriverArg = arg_str0("a", "adriver", "<driver>",
-			"the audio driver to use [wasapi (default), sdl]");
+			"the audio driver to use [wasapi (default)]");
 		arg_str *rendererArg = arg_str0(NULL, "renderer", "<method>",
 			"the render method to use [software (default), hardware (experimental)]");
 		arg_str *clientArg = arg_str0("c", "client", "<host>[:<port>]",
 			{
 				config.videoDriver = GbConfig::VIDEO_D3D11;
 			}
-			else if (!strcmp(vDriverArg->sval[0], "sdl"))
+			else if (!strcmp(vDriverArg->sval[0], "opengl"))
 			{
-				config.videoDriver = GbConfig::VIDEO_SDL;
+				config.videoDriver = GbConfig::VIDEO_OPENGL;
 			}
 			else
 			{
 			{
 				config.audioDriver = GbConfig::AUDIO_WASAPI;
 			}
-			else if (!strcmp(aDriverArg->sval[0], "sdl"))
-			{
-				config.audioDriver = GbConfig::AUDIO_SDL;
-			}
 			else
 			{
 				clog << "gb_emulator: invalid audio driver '" << aDriverArg->sval[0] << "'\n";

File third_party/glew/COPYING.txt

+The OpenGL Extension Wrangler Library
+Copyright (C) 2002-2007, Milan Ikits <milan ikits[]ieee org>
+Copyright (C) 2002-2007, Marcelo E. Magallon <mmagallo[]debian org>
+Copyright (C) 2002, Lev Povalahev
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, 
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, 
+  this list of conditions and the following disclaimer in the documentation 
+  and/or other materials provided with the distribution.
+* The name of the author may be used to endorse or promote products 
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Mesa 3-D graphics library
+Version:  7.0
+
+Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+Copyright (c) 2007 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

File third_party/glew/README.local.txt

+Name: GLEW
+URL: http://glew.sourceforge.net/
+Version: 1.9.0

File third_party/glew/glew.vcxproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C922B8DD-6530-41FD-AF96-0E15CB2EB1FB}</ProjectGuid>
+    <RootNamespace>glew</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;VC_EXTRALEAN;GLEW_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN;VC_EXTRALEAN;GLEW_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;VC_EXTRALEAN;GLEW_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <AdditionalIncludeDirectories>$(ProjectDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;VC_EXTRALEAN;GLEW_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="src\glew.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="include\GL\glew.h" />
+    <ClInclude Include="include\GL\wglew.h" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

File third_party/glew/glew.vcxproj.filters

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="src\glew.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="include\GL\glew.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="include\GL\wglew.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+</Project>