/* 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 IDirect3DDevice9 * d3d_device_ptr; static struct hlsl_program prg[SSNES_HLSL_MAX_SHADERS] = {0}; static bool hlsl_active = false; static unsigned active_index = 0; 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 texCoord : 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 = rotation_value; } void hlsl_set_params(void) { if (!hlsl_active) return; d3d_device_ptr->SetVertexShaderConstantF(0, (FLOAT*)&prg[active_index].mvp, 4); } static bool load_program(unsigned index, const char *prog, bool path_is_file) { SSNES_LOG("test\n"); bool ret, ret_fp, ret_vp; ID3DXBuffer *listing_f = NULL; ID3DXBuffer *listing_v = NULL; ID3DXBuffer *code_f = NULL; ID3DXBuffer *code_v = NULL; ret = true; ret_fp = false; ret_vp = false; 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, (UINT)strlen(prog), NULL, NULL, "main_fragment", "ps_2_0", 0, &code_f, &listing_f, NULL ); ret_vp = D3DXCompileShader(prog, (UINT)strlen(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 0 if (!load_stock()) return false; #endif SSNES_LOG("Loading HLSL file: %s\n", path); if (!load_program(0, path, true)) return false; return true; } static void hlsl_deinit_progs(void) { if (prg[0].fprg) D3DResource_Release((D3DResource *)prg[0].fprg); if (prg[0].vprg) D3DResource_Release((D3DResource *)prg[0].vprg); memset(prg, 0, sizeof(prg)); } static void hlsl_deinit_state(void) { hlsl_active = false; d3d_device_ptr = NULL; hlsl_deinit_progs(); } static bool load_preset(const char *path) { return false; } bool hlsl_init(const char *path, IDirect3DDevice9 * device_ptr) { if (device_ptr != NULL) d3d_device_ptr = device_ptr; else return false; if (strstr(path, ".cgp")) { if (!load_preset(path)) return false; } else { if (!load_plain(path)) return false; } active_index = 0; hlsl_active = true; return true; } void hlsl_use(unsigned index) { if (hlsl_active && prg[index].vprg && prg[index].fprg) { active_index = index; D3DDevice_SetVertexShader(d3d_device_ptr, prg[index].vprg); D3DDevice_SetPixelShader(d3d_device_ptr, prg[index].fprg); } } // Full deinit. void hlsl_deinit(void) { if (!hlsl_active) return; hlsl_deinit_state(); }