/// \brief Loads a texture
/// \param file = the filename
bool CDX9TextureObject::LoadFromFile( const TCHAR * file )
{
	StdString szFilePath(file);
	szFilePath.MakeSafeFileName();

	DeInit();

	if (!m_Renderer)
		return false;

	LPDIRECT3DDEVICE9 pDevice = (LPDIRECT3DDEVICE9)m_Renderer->GetAPIDevice();
	if( !pDevice )
		return false;

	D3DXIMAGE_INFO srcInfo;
	LPDIRECT3DTEXTURE9 pTexture;
/*
	if( _tcsstr( file, _T(".hdr" ) )!= NULL )
	{
		bool retval = LoadHDRFile( (TCHAR*)file );
		return retval;
	}
*/
	LPVOID pFileData = NULL;
	UINT iFileDataSize = 0;
	if (!LoadFileIntoBuffer( szFilePath, pFileData, iFileDataSize, true ))
	{
		m_ToolBox->Log(LOGERROR, _T("Texture Object: %s failed to load\n"), szFilePath.c_str() );
		return false;
	}

	D3DFORMAT requestedFormat = EEDX9RequestedInternalFormatFromFileInMemory( pFileData, iFileDataSize );
	HRESULT hr = D3DXCreateTextureFromFileInMemoryEx( pDevice,
									pFileData, 
									iFileDataSize, 
									D3DX_DEFAULT, //width
									D3DX_DEFAULT, //height
									D3DX_DEFAULT, //number of mips
									0,	//usage - 0 unless for render targets
									requestedFormat,
									D3DPOOL_MANAGED,
									D3DX_DEFAULT,	//regular filter
									D3DX_DEFAULT,	//mip filter
									0, //color key, opaque black default
									&srcInfo,	//src info
									NULL, //palette
									&pTexture );
	SAFE_DELETE_ARRAY( pFileData );
	if( hr != D3D_OK )
	{
		m_ToolBox->Log(LOGERROR, _T("Texture Object: %s failed to load\n"), szFilePath.c_str() );
		return false;
	}

	D3DSURFACE_DESC textureDesc;
	pTexture->GetLevelDesc( 0, &textureDesc );
	m_Width = textureDesc.Width;
	m_Height = textureDesc.Height;
	m_Texture = pTexture;
	m_Filename = file;
	m_bRenderTarget = false;
	m_ColorDepth = EEDX9ColorBitsFromFormat( textureDesc.Format );
	m_Compressed = EEDX9IsCompressedFormat( textureDesc.Format );

	if( m_AutoGenMips )
	{
		pTexture->GenerateMipSubLevels();
	}

	return true;
}
static bool EnsureD3D11ResourcesAreCreated()
{
    if (g_D3D11VertexShader)
        return true;

    // D3D11 has to load resources. Wait for Unity to provide the streaming assets path first.
    if (s_UnityStreamingAssetsPath.empty())
        return false;

    D3D11_BUFFER_DESC desc;
    memset (&desc, 0, sizeof(desc));

    // vertex buffer
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.ByteWidth = 1024;
    desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    g_D3D11Device->CreateBuffer (&desc, NULL, &g_D3D11VB);

    // constant buffer
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.ByteWidth = 64; // hold 1 matrix
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.CPUAccessFlags = 0;
    g_D3D11Device->CreateBuffer (&desc, NULL, &g_D3D11CB);


    HRESULT hr = -1;
    Buffer vertexShader;
    Buffer pixelShader;
    std::string vertexShaderPath(s_UnityStreamingAssetsPath);
    vertexShaderPath += "/Shaders/DX11_9_1/SimpleVertexShader.cso";
    std::string fragmentShaderPath(s_UnityStreamingAssetsPath);
    fragmentShaderPath += "/Shaders/DX11_9_1/SimplePixelShader.cso";
    LoadFileIntoBuffer(vertexShaderPath, vertexShader);
    LoadFileIntoBuffer(fragmentShaderPath, pixelShader);

    if (vertexShader.size() > 0 && pixelShader.size() > 0)
    {
        hr = g_D3D11Device->CreateVertexShader(&vertexShader[0], vertexShader.size(), nullptr, &g_D3D11VertexShader);
        if (FAILED(hr)) DebugLog("Failed to create vertex shader.\n");
        hr = g_D3D11Device->CreatePixelShader(&pixelShader[0], pixelShader.size(), nullptr, &g_D3D11PixelShader);
        if (FAILED(hr)) DebugLog("Failed to create pixel shader.\n");
    }
    else
    {
        DebugLog("Failed to load vertex or pixel shader.\n");
    }
    // input layout
    if (g_D3D11VertexShader && vertexShader.size() > 0)
    {
        g_D3D11Device->CreateInputLayout (s_DX11InputElementDesc, 2, &vertexShader[0], vertexShader.size(), &g_D3D11InputLayout);
    }

    // render states
    D3D11_RASTERIZER_DESC rsdesc;
    memset (&rsdesc, 0, sizeof(rsdesc));
    rsdesc.FillMode = D3D11_FILL_SOLID;
    rsdesc.CullMode = D3D11_CULL_NONE;
    rsdesc.DepthClipEnable = TRUE;
    g_D3D11Device->CreateRasterizerState (&rsdesc, &g_D3D11RasterState);

    D3D11_DEPTH_STENCIL_DESC dsdesc;
    memset (&dsdesc, 0, sizeof(dsdesc));
    dsdesc.DepthEnable = TRUE;
    dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    dsdesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
    g_D3D11Device->CreateDepthStencilState (&dsdesc, &g_D3D11DepthState);

    D3D11_BLEND_DESC bdesc;
    memset (&bdesc, 0, sizeof(bdesc));
    bdesc.RenderTarget[0].BlendEnable = FALSE;
    bdesc.RenderTarget[0].RenderTargetWriteMask = 0xF;
    g_D3D11Device->CreateBlendState (&bdesc, &g_D3D11BlendState);

    return true;
}
bool CVertexShader::LoadVariant( IShaderDefines *pDefines, bool bCompile )
{
	// check for already compiled default version of the shader
	if (pDefines == NULL && m_VertexShader != NULL)
		return true;
	// check for already compiled variant of the shader
	if (pDefines != NULL)
	{
		unsigned long iEncoding = pDefines->GetValuesEncoding().iEncoding;
		SHADERVARIANTSMAP::iterator itr = m_ShaderVariants.find( iEncoding );
		if (itr != m_ShaderVariants.end())
			return true;
	}

	D3DXMACRO *pMacros = NULL;
	if (pDefines)
	{
		const int iMaxShaderDefineCount = 32;
		const int iValueCharSize = 64;
		static char szValues[iMaxShaderDefineCount][iValueCharSize];
		static D3DXMACRO vMacros[iMaxShaderDefineCount + 1];
		if (iMaxShaderDefineCount < pDefines->GetDefineCount())
		{
			m_ToolBox->Log( LOGFATALERROR, _T("Shader Define Count exceeds the internal buffer!\n") );
			return false;
		}

		DWORD i;
		for (i=0; i < pDefines->GetDefineCount(); i++)
		{
			vMacros[i].Name = pDefines->GetDefineName(i);
			vMacros[i].Definition = _itoa(pDefines->GetDefineValue(i), szValues[i], 10);
		}
		// null terminate macro list
		vMacros[i].Name = NULL;
		vMacros[i].Definition = NULL;
		pMacros = vMacros;
	}

	LPDIRECT3DVERTEXSHADER9 pShader = NULL;
	LPD3DXBUFFER shaderBuf = NULL;
	LPD3DXBUFFER pErrorMsgs = NULL;
	CDX9IncludeManager includeInterface;
	LPDIRECT3DDEVICE9 pDevice = (LPDIRECT3DDEVICE9)m_Renderer->GetAPIDevice();
	if( pDevice )
	{
		int len = _tcslen( (const TCHAR*)m_Code );
		LPCSTR profile = D3DXGetVertexShaderProfile( pDevice );

		bool bLoadedCompiled = false;
		HRESULT hr = E_FAIL;

		const TCHAR *szFile = GetName()->GetString();
		TCHAR drive[MAX_PATH];
		TCHAR directory[MAX_PATH];
		TCHAR filename[MAX_PATH];
		TCHAR fileext[MAX_PATH];
		TCHAR szDefinesTemp[65] = { '\0' };
		_tsplitpath( szFile, drive, directory, filename, fileext );

		StdString szCompiledFile;
		szCompiledFile += drive;
		szCompiledFile += directory;
		szCompiledFile += _T("Compiled\\");
		szCompiledFile += filename;
		if (pDefines)
		{
			szCompiledFile += _T("_enc");
			szCompiledFile += _itot(pDefines->GetValuesEncoding().iEncoding, szDefinesTemp, 10);
		}
		szCompiledFile += fileext;
#ifdef XBOX
		szCompiledFile = SetPathDrive( szCompiledFile, EngineGetToolBox()->GetDrive() );
#endif

		LPVOID pShaderFileData = NULL;
		UINT shaderLen = 0;
		struct _stat shaderFilestat;
		// checking if compiled version exists, if we can load it into a buffer and if the file stats of the shader (not compiled) are readable
		if (CheckFileExists(szCompiledFile) &&	( _tstat( szFile, &shaderFilestat ) == 0) && LoadFileIntoBuffer( szCompiledFile, pShaderFileData, shaderLen, true ))
		{
			m_ToolBox->Log( LOGINFORMATION, _T("Reading compiled shader file: %s\n"), szCompiledFile.c_str() );
			// create a shader buffer to store the compiled shader
			hr = D3DXCreateBuffer( shaderLen, &shaderBuf );
			if (SUCCEEDED(hr))
			{
				time_t storedMTime = 0;
				// get the compiled date out of the file
				memcpy( &storedMTime, pShaderFileData, sizeof(time_t) );
			
				// if the stored modified time in the compiled shader file is the same as the current
				// modified time of the shader file
				if( storedMTime == shaderFilestat.st_mtime )
				{
					// reduce the buffer size by the preamble (mod time)
					shaderLen -= (int)sizeof(time_t);
						
					// copy the compiled shader into the shader buffer
					memcpy( shaderBuf->GetBufferPointer(), ((TCHAR *) pShaderFileData)+ sizeof(time_t), shaderLen);
					bLoadedCompiled = true;
				}
			}
			SAFE_DELETE_ARRAY( pShaderFileData );
		}

		if (!bLoadedCompiled && bCompile)
		{
			if (pDefines)
				EngineGetToolBox()->Log( LOGINFORMATION, _T("Compiling shader %s:%d\n"), GetName()->GetString(), pDefines->GetValuesEncoding().iEncoding );
			else
				EngineGetToolBox()->Log( LOGINFORMATION, _T("Compiling shader %s\n"), GetName()->GetString() );

			hr = D3DXCompileShader( m_Code,
										len,//length of string in bytes
										pMacros, //can add that matrix of macros here
										&includeInterface, //for include directories
										"main",//? temp
										profile, //vs_1_1 for example
										0, //compiling options?
										&shaderBuf,
										&pErrorMsgs,
										NULL );
		}

		//now actually create the shader
		if( hr == D3D_OK &&
			shaderBuf )
		{
			if (!bLoadedCompiled)
			{
				struct _stat shaderFilestat;
				// get the shader file's modified time
				if (_tstat( szFile, &shaderFilestat ) == 0)
				{
					m_ToolBox->Log( LOGINFORMATION, _T("Writing compiled shader file: %s\n"), szCompiledFile.c_str() );
					// open a compiled shader file for writing
					FILE *fp = fopen( szCompiledFile, "wb" );
					if (fp)
					{
						// write shader file's modified time
						fwrite( &shaderFilestat.st_mtime, sizeof(time_t), 1, fp );
						// write compiled shader data
						fwrite( shaderBuf->GetBufferPointer(), shaderBuf->GetBufferSize(), 1, fp );
						fclose(fp);
					}
					else
					{
						m_ToolBox->Log( LOGWARNING, _T("Failed to write compiled shader file: %s\n"), szCompiledFile.c_str() );
					}
				}
			}

			hr = pDevice->CreateVertexShader( (DWORD *) shaderBuf->GetBufferPointer(), &pShader );
			assert( SUCCEEDED(hr) );
			if (!SUCCEEDED(hr))
			{
				m_ToolBox->Log( LOGWARNING, _T("Failed to create shader : %s\n"), szCompiledFile.c_str() );
			}

			SAFE_RELEASE( shaderBuf );
			SAFE_RELEASE( pErrorMsgs );

			if (pDefines == NULL) // we are compiling the default shader with no macro defines
			{
				assert( m_VertexShader == NULL ); // the default shader should only be compiled on Init when this is NULL
				m_VertexShader = pShader;
			}
			else if (pDefines != NULL) // we are compiling a variant of the shader
			{
				unsigned long iEncoding = pDefines->GetValuesEncoding().iEncoding;
				m_ShaderVariants[iEncoding] = pShader;
			}
			return true;
		}
	}	
	if( pErrorMsgs )
	{
		IHashString * name = GetName();
		TCHAR* debug_errors = (TCHAR*)pErrorMsgs->GetBufferPointer();
		m_ToolBox->Log( LOGERROR, _T("Could not create Vertex shader %s\nError message: %s\n"),
			name->GetString(), debug_errors );				
		SAFE_RELEASE( pErrorMsgs );				
	}
	SAFE_RELEASE( shaderBuf );

	return false;
}