gb_emulator / gb_emulator / include / gb_emulator / gb_video_d3d11.h

/*  Copyright © 2011 Chris Spencer <>

    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
    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 <>.  */

#ifndef GB_VIDEO_D3D11_H_82F60180_1B66_11E1_BA99_0002A5D5C51B
#define GB_VIDEO_D3D11_H_82F60180_1B66_11E1_BA99_0002A5D5C51B

#include <stdint.h>

#include <boost/filesystem/path.hpp>
#include <boost/shared_ptr.hpp>

#include <atlbase.h>
#include <atlcom.h>

#include <gb_emulator/gb_config.h>
#include <gb_emulator/gb_video.hpp>

struct _CGcontext;
struct _CGprogram;

struct ID3D11Buffer;
struct ID3D11Device;
struct ID3D11DeviceContext;
struct ID3D11InputLayout;
struct ID3D11PixelShader;
struct ID3D11RenderTargetView;
struct ID3D11SamplerState;
struct ID3D11ShaderResourceView;
struct ID3D11Texture2D;
struct ID3D11VertexShader;
struct IDXGISwapChain;

//! Direct3D 11 video driver.
class GbVideoD3D11: public GbVideo
	//! Constructor.
	 * \param gb The emulator context.
	 * \param renderer The renderer to use. If set to \c GbConfig::RENDER_HARDWARE then colour
	 * decoding will be offloaded onto the graphics hardware which results in a big decrease in CPU
	 * usage, but the result of that is that the fancy image scaling effects are disabled, so
	 * software rendering should be used unless performance is an issue.
	 * \param installDir The installation directory.
	GbVideoD3D11(Gb &gb, GbConfig::Renderer renderer, const boost::filesystem::path &installDir);

	//! Destructor.

	//! Indicates whether Direct3D 11 is available.
	 * This function does a runtime check to see whether Direct3D 11 can be used on this system. If
	 * not then none of the other functions in this class may be used.
	 * \return Whether Direct3D 11 is available.
	bool isAvailable();

	//! Initialises Direct3D and opens the display.
	void initialise();

	// Direct3D stuff
	boost::shared_ptr<HINSTANCE__> d3d11_;

	ATL::CComPtr<ID3D11Device> device_;
	ATL::CComPtr<ID3D11DeviceContext> deviceContext_;
	ATL::CComPtr<IDXGISwapChain> swapChain_;
	ATL::CComPtr<ID3D11RenderTargetView> renderTarget_;

	ATL::CComPtr<ID3D11Buffer> vertexBuffer_;
	ATL::CComPtr<ID3D11InputLayout> layout_;
	ATL::CComPtr<ID3D11Texture2D> texture_;
	ATL::CComPtr<ID3D11SamplerState> sampler_;

	// Cg stuff
	boost::shared_ptr<_CGcontext> cgContext_;
	boost::shared_ptr<_CGprogram> vertexShader_;
	boost::shared_ptr<_CGprogram> basicPixelShader_;
	boost::shared_ptr<_CGprogram> dmgPixelShader_;
	boost::shared_ptr<_CGprogram> gbcPixelShader_;

	// The rendering method
	GbConfig::Renderer renderer_;

	// The installation directory
	boost::filesystem::path installDir_;

	// Indicates which pixel shader is bound. There are separate shaders for GBC and DMG mode
	// because they have different colour formats. This is only used when hardware rendering is
	// used.
	bool gbcBound_;

	// RGB pixel buffers. These is only used in software rendering mode.
	boost::scoped_array<uint32_t> unscaledPixelBuffer_;
	boost::scoped_array<uint32_t> scaledPixelBuffer_;

	// Window message procedure
	static LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

	// Initialisation functions
	void createRenderTarget();
	void initPipeline();
	void initGraphics();

	// Redraws the display
	void draw(uint16_t *pixelBuffer, bool gbc);

	// Disabled operations
	GbVideoD3D11(const GbVideoD3D11 &);
	GbVideoD3D11 & operator=(const GbVideoD3D11 &);