diff --git a/360/fonts.cpp b/360/fonts.cpp
index f21b12e785..17e2fead84 100644
--- a/360/fonts.cpp
+++ b/360/fonts.cpp
@@ -282,7 +282,7 @@ static const char g_strFontShader[] =
"uniform float4 Color : register(c1);\n"
"uniform float2 TexScale : register(c2);\n"
"sampler FontTexture : register(s0);\n"
- "VS_OUT FontVertexShader( VS_IN In )\n"
+ "VS_OUT main_vertex( VS_IN In )\n"
"{\n"
"VS_OUT Out;\n"
"Out.Position.x = (In.Pos.x-0.5);\n"
@@ -295,7 +295,7 @@ static const char g_strFontShader[] =
"Out.ChannelSelector = In.ChannelSelector;\n"
"return Out;\n"
"}\n"
- "float4 FontPixelShader( VS_OUT In ) : COLOR0\n"
+ "float4 main_fragment( VS_OUT In ) : COLOR0\n"
"{\n"
"float4 FontTexel = tex2D( FontTexture, In.TexCoord0 );\n"
"if( dot( In.ChannelSelector, float4(1,1,1,1) ) )\n"
@@ -364,7 +364,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
ID3DXBuffer* pShaderCode;
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
- NULL, NULL, "FontVertexShader", "vs.2.0", 0,&pShaderCode, NULL, NULL );
+ NULL, NULL, "main_vertex", "vs.2.0", 0,&pShaderCode, NULL, NULL );
if (SUCCEEDED(hr))
{
hr = pd3dDevice->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(),
@@ -376,7 +376,7 @@ static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
{
// Step #3, create my pixel shader
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
- NULL, NULL, "FontPixelShader", "ps.2.0", 0,&pShaderCode, NULL, NULL );
+ NULL, NULL, "main_fragment", "ps.2.0", 0,&pShaderCode, NULL, NULL );
if ( SUCCEEDED(hr))
{
hr = pd3dDevice->CreatePixelShader( ( DWORD* )pShaderCode->GetBufferPointer(),
diff --git a/360/xdk360_video.cpp b/360/xdk360_video.cpp
index 0a46ee15cb..a77bc2dad1 100644
--- a/360/xdk360_video.cpp
+++ b/360/xdk360_video.cpp
@@ -19,6 +19,7 @@
#include "../driver.h"
#include "xdk360_video.h"
#include "xdk360_video_resources.h"
+#include "../gfx/hlsl_shader.h"
#include "../console/console_ext.h"
#include "../general.h"
#include "../message.h"
@@ -33,17 +34,6 @@ static bool g_first_msg;
unsigned g_frame_count;
void *g_d3d;
-struct hlsl_program_t
-{
- D3DXHANDLE vid_size_f;
- D3DXHANDLE tex_size_f;
- D3DXHANDLE out_size_f;
- D3DXHANDLE vid_size_v;
- D3DXHANDLE tex_size_v;
- D3DXHANDLE out_size_v;
- XMMATRIX modelViewProj;
-} hlsl_program;
-
struct XPR_HEADER
{
unsigned long dwMagic;
@@ -199,11 +189,11 @@ static void xdk360_gfx_free(void * data)
if (!vid)
return;
+ hlsl_deinit();
+
D3DResource_Release((D3DResource *)vid->lpTexture);
D3DResource_Release((D3DResource *)vid->vertex_buf);
- D3DResource_Release((D3DResource *)vid->pVertexDecl);
- D3DResource_Release((D3DResource *)vid->pPixelShader);
- D3DResource_Release((D3DResource *)vid->pVertexShader);
+ D3DResource_Release((D3DResource *)vid->v_decl);
D3DDevice_Release(vid->xdk360_render_device);
Direct3D_Release();
@@ -298,7 +288,8 @@ static void xdk360_set_orientation(void * data, uint32_t orientation)
break;
}
- hlsl_program.modelViewProj = XMMatrixRotationZ(angle);
+ hlsl_use(vid->xdk360_render_device, 0);
+ hlsl_set_proj_matrix(XMMatrixRotationZ(angle));
}
static void xdk360_set_aspect_ratio(void * data, uint32_t aspectratio_index)
@@ -355,54 +346,7 @@ static void *xdk360_gfx_init(const video_info_t *video, const input_driver_t **i
// D3DCREATE_HARDWARE_VERTEXPROCESSING is ignored on 360
ret = Direct3D_CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &vid->d3dpp, &vid->xdk360_render_device);
- ID3DXBuffer* pShaderCodeV = NULL;
- ID3DXBuffer* pShaderCodeP = NULL;
- ID3DXBuffer* pErrorMsg = NULL;
-
- ret = D3DXCompileShaderFromFile(
- g_settings.video.cg_shader_path, //filepath
- NULL, //macros
- NULL, //includes
- "main_vertex", // main function
- "vs_2_0", // shader profile
- 0, // flags
- &pShaderCodeV, // compiled operations
- &pErrorMsg, // errors
- NULL); // constants
-
- if (SUCCEEDED(ret))
- {
- SSNES_LOG("Vertex shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg");
- ret = D3DXCompileShaderFromFile(
- g_settings.video.cg_shader_path, //filepath
- NULL, //macros
- NULL, //includes
- "main_fragment", // main function
- "ps_2_0", // shader profile
- 0, // flags
- &pShaderCodeP, // compiled operations
- &pErrorMsg, // errors
- NULL); // constants
- }
-
- if (FAILED(ret))
- {
- if(pErrorMsg)
- SSNES_LOG("%s\n", (char*)pErrorMsg->GetBufferPointer());
- D3DDevice_Release(vid->xdk360_render_device);
- Direct3D_Release();
- free(vid);
- return NULL;
- }
- else
- {
- SSNES_LOG("Pixel shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg");
- }
-
- vid->pVertexShader = D3DDevice_CreateVertexShader((const DWORD*)pShaderCodeV->GetBufferPointer());
- vid->pPixelShader = D3DDevice_CreatePixelShader((const DWORD*)pShaderCodeP->GetBufferPointer());
- pShaderCodeV->Release();
- pShaderCodeP->Release();
+ hlsl_init(NULL);
vid->lpTexture = (D3DTexture*) D3DDevice_CreateTexture(512, 512, 1, 1, 0, D3DFMT_LIN_X1R5G5B5,
0, D3DRTYPE_TEXTURE);
@@ -435,7 +379,7 @@ static void *xdk360_gfx_init(const video_info_t *video, const input_driver_t **i
D3DDECL_END()
};
- vid->pVertexDecl = D3DDevice_CreateVertexDeclaration(VertexElements);
+ vid->v_decl = D3DDevice_CreateVertexDeclaration(VertexElements);
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET,
0xff000000, 1.0f, 0, FALSE);
@@ -459,10 +403,10 @@ static bool xdk360_gfx_frame(void *data, const void *frame,
unsigned width, unsigned height, unsigned pitch, const char *msg)
{
xdk360_video_t *vid = (xdk360_video_t*)data;
- g_frame_count++;
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET,
0xff000000, 1.0f, 0, FALSE);
+ g_frame_count++;
if (vid->last_width != width || vid->last_height != height)
{
@@ -490,9 +434,8 @@ static bool xdk360_gfx_frame(void *data, const void *frame,
vid->last_height = height;
}
- vid->xdk360_render_device->SetVertexShaderConstantF(0, (FLOAT*)&hlsl_program.modelViewProj, 4);
-
- //TODO: Update the shader constants
+ hlsl_use(vid->xdk360_render_device, 0);
+ hlsl_set_params(vid->xdk360_render_device);
D3DLOCKED_RECT d3dlr;
D3DTexture_LockRect(vid->lpTexture, 0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK);
@@ -510,10 +453,7 @@ static bool xdk360_gfx_frame(void *data, const void *frame,
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
- D3DDevice_SetVertexShader(vid->xdk360_render_device, vid->pVertexShader);
- D3DDevice_SetPixelShader(vid->xdk360_render_device, vid->pPixelShader);
-
- D3DDevice_SetVertexDeclaration(vid->xdk360_render_device, vid->pVertexDecl);
+ D3DDevice_SetVertexDeclaration(vid->xdk360_render_device, vid->v_decl);
D3DDevice_SetStreamSource_Inline(vid->xdk360_render_device, 0, vid->vertex_buf, 0,
sizeof(DrawVerticeFormats));
diff --git a/360/xdk360_video.h b/360/xdk360_video.h
index aefe24a265..5e31d1bb17 100644
--- a/360/xdk360_video.h
+++ b/360/xdk360_video.h
@@ -48,11 +48,9 @@ typedef struct xdk360_video
unsigned last_height;
IDirect3D9* xdk360_device;
IDirect3DDevice9* xdk360_render_device;
- IDirect3DVertexShader9 *pVertexShader;
- IDirect3DPixelShader9* pPixelShader;
- IDirect3DVertexDeclaration9* pVertexDecl;
IDirect3DVertexBuffer9* vertex_buf;
IDirect3DTexture9* lpTexture;
+ IDirect3DVertexDeclaration9* v_decl;
D3DPRESENT_PARAMETERS d3dpp;
XVIDEO_MODE video_mode;
} xdk360_video_t;
diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c
index d48850c58c..4c6c71c7f4 100644
--- a/gfx/shader_cg.c
+++ b/gfx/shader_cg.c
@@ -715,7 +715,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf)
state_tracker = state_tracker_init(&tracker_info);
if (!state_tracker)
- SSNES_WARN("Failed to init state tracker.\n");
+ SSNES_WARN("Failed to initialize state tracker.\n");
#ifdef HAVE_PYTHON
if (script)
diff --git a/gfx/shader_hlsl.c b/gfx/shader_hlsl.c
new file mode 100644
index 0000000000..a73ad70e29
--- /dev/null
+++ b/gfx/shader_hlsl.c
@@ -0,0 +1,203 @@
+/* SSNES - A frontend for libretro.
+ * Copyright (C) 2010-2012 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2012 - Daniel De Matteis
+ *
+ * SSNES 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 Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * SSNES 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 SSNES.
+ * If not, see .
+ */
+
+#include "shader_hlsl.h"
+#ifdef _XBOX
+#include
+#endif
+
+struct hlsl_program
+{
+ IDirect3DVertexShader9 *vprg;
+ IDirect3DPixelShader9 *fprg;
+ D3DXHANDLE vid_size_f;
+ D3DXHANDLE tex_size_f;
+ D3DXHANDLE out_size_f;
+ D3DXHANDLE vid_size_v;
+ D3DXHANDLE tex_size_v;
+ D3DXHANDLE out_size_v;
+ XMMATRIX mvp;
+};
+
+static struct hlsl_program prg[SSNES_HLSL_MAX_SHADERS];
+static bool hlsl_active = false;
+
+static const char *stock_hlsl_program =
+ "void main_vertex"
+ "("
+ " float2 position : POSITION,"
+ " float2 texCoord : TEXCOORD0,"
+ " uniform float4x4 modelViewProj : register(c0),"
+ " out float4 oPosition : POSITION,"
+ " out float2 otexCoord : TEXCOORD"
+ ")"
+ "{"
+ " oPosition = mul(modelViewProj, float4(position, 0.0, 1.0));"
+ " otexCoord = texCoord;"
+ "}"
+ ""
+ "struct output"
+ "{"
+ " float4 color: COLOR;"
+ "}"
+ ""
+ "struct input"
+ "{"
+ " float2 video_size;"
+ " float2 texture_size;"
+ " float2 output_size;"
+ "}"
+ ""
+ "output main_fragment(float2 tex : TEXCOORD0, uniform sampler2D decal : register(s0), uniform input IN)"
+ "{"
+ " output OUT;"
+ " OUT.color = tex2D(decal, tex);"
+ " return OUT;"
+ "}";
+
+void hlsl_set_proj_matrix(XMMATRIX rotation_value)
+{
+ if (hlsl_active && prg[active_index].mvp)
+ prg[active_index].mvp = rotation_value;
+}
+
+void hlsl_set_params(IDirect3DDevice9 * device)
+{
+ if (!hlsl_active)
+ return;
+
+ if (prg[active_index].mvp)
+ device->SetVertexShaderConstantF(0, (FLOAT*)&prg[active_index].mvp, 4);
+}
+
+static bool load_program(unsigned index, const char *prog, bool path_is_file)
+{
+ bool ret, ret_fp, ret_vp;
+ ID3DXBuffer *listing_f = NULL;
+ ID3DXBuffer *listing_v = NULL;
+ ID3DXBuffer *code_f = NULL;
+ ID3DXBuffer *code_v = NULL;
+
+ ret = true;
+
+ if (path_is_file)
+ {
+ ret_fp = D3DXCompileShaderFromFile(prog, NULL, NULL, "main_fragment", "ps_2_0", 0, &code_f, &listing_f, NULL);
+ ret_vp = D3DXCompileShaderFromFile(prog, NULL, NULL, "main_vertex", "vs_2_0", 0, &code_v, &listing_v, NULL);
+ }
+ else
+ {
+ ret_fp = D3DXCompileShader(prog, sizeof(prog), NULL, NULL, "main_fragment", "ps_2_0", 0, &code_f, &listing_f, NULL );
+ ret_vp = D3DXCompileShader(prog, sizeof(prog), NULL, NULL, "main_vertex", "vs_2_0", 0, &code_v, &listing_v, NULL );
+ }
+
+ if (FAILED(ret_fp) || FAILED(ret_vp))
+ {
+ SSNES_ERR("HLSL error:\n");
+ if(listing_f)
+ SSNES_ERR("Fragment:\n%s\n", (char*)listing_f->GetBufferPointer());
+ if(listing_v)
+ SSNES_ERR("Vertex:\n%s\n", (char*)listing_v->GetBufferPointer());
+
+ ret = false;
+ goto end;
+ }
+
+ prg[index].fprg = D3DDevice_CreatePixelShader((const DWORD*)code_f->GetBufferPointer());
+ prg[index].vprg = D3DDevice_CreateVertexShader((const DWORD*)code_v->GetBufferPointer());
+ code_f->Release();
+ code_v->Release();
+
+end:
+ free(listing_f);
+ free(listing_v);
+ return ret;
+}
+
+static bool load_stock(void)
+{
+ if (!load_program(0, stock_hlsl_program, false))
+ {
+ SSNES_ERR("Failed to compile passthrough shader, is something wrong with your environment?\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool load_plain(const char *path)
+{
+ if (!load_stock())
+ return false;
+
+#if 0
+ SSNES_LOG("Loading HLSL file: %s\n", path);
+
+ if (!load_program(1, path, true))
+ return false;
+#endif
+
+ return true;
+}
+
+static void hlsl_deinit_progs(void)
+{
+ D3DResource_Release((D3DResource *)vid->pPixelShader);
+ D3DResource_Release((D3DResource *)vid->pVertexShader);
+}
+
+static void hlsl_deinit_state(void)
+{
+ hlsl_active = false;
+
+ hlsl_deinit_progs();
+}
+
+bool hlsl_init(const char *path)
+{
+ if (strstr(path, ".cgp"))
+ {
+ if (!load_preset(path))
+ return false;
+ }
+ else
+ {
+ if (!load_plain(path))
+ return false;
+ }
+
+ hlsl_active = true;
+ return true;
+}
+
+void hlsl_use(IDirect3DDevice9 * device, unsigned index)
+{
+ if (hlsl_active && prg[index].vprg && prg[index].fprg)
+ {
+ active_index = index;
+ D3DDevice_SetVertexShader(device, prg[index].vprg);
+ D3DDevice_SetPixelShader(device, prg[index].fprg);
+ }
+}
+
+// Full deinit.
+void hlsl_deinit(void)
+{
+ if (!hlsl_active)
+ return;
+
+ hlsl_deinit_state();
+}
diff --git a/gfx/shader_hlsl.h b/gfx/shader_hlsl.h
new file mode 100644
index 0000000000..2ff3fac88e
--- /dev/null
+++ b/gfx/shader_hlsl.h
@@ -0,0 +1,34 @@
+/* SSNES - A frontend for libretro.
+ * Copyright (C) 2010-2012 - Hans-Kristian Arntzen
+ *
+ * SSNES 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 Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * SSNES 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 SSNES.
+ * If not, see .
+ */
+
+
+#ifndef __SSNES_HLSL_H
+#define __SSNES_HLSL_H
+
+#include
+
+bool hlsl_init(const char *path);
+
+void hlsl_deinit(void);
+
+void hlsl_set_proj_matrix(XMMATRIX rotation_value);
+
+void hlsl_set_params(IDirect3DDevice9 * device);
+
+void hlsl_use(IDirect3DDevice9 * device, unsigned index);
+
+#define SSNES_HLSL_MAX_SHADERS 16
+
+#endif