diff --git a/Makefile b/Makefile index 3972d52e75..4c482a5bf0 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ ifeq ($(HAVE_GLFW), 1) endif ifeq ($(HAVE_CG), 1) + OBJ += gfx/shader_cg.o LIBS += -lCg -lCgGL endif diff --git a/gfx/gl.c b/gfx/gl.c index 3e9b38c351..5c0a8088fd 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -30,8 +30,11 @@ #ifdef HAVE_CG -#include -#include +#include "shader_cg.h" +#endif + +#ifdef HAVE_XML +#include "shader_glsl.h" #endif static const GLfloat vertexes[] = { @@ -49,23 +52,10 @@ static const GLfloat tex_coords[] = { }; static bool keep_aspect = true; -#ifdef HAVE_CG -static CGparameter cg_mvp_matrix; -static bool cg_active = false; -#endif static GLuint gl_width = 0, gl_height = 0; typedef struct gl { bool vsync; -#ifdef HAVE_CG - CGcontext cgCtx; - CGprogram cgFPrg; - CGprogram cgVPrg; - CGprofile cgFProf; - CGprofile cgVProf; - CGparameter cg_video_size, cg_texture_size, cg_output_size; - CGparameter cg_Vvideo_size, cg_Vtexture_size, cg_Voutput_size; // Vertexes -#endif GLuint texture; GLuint tex_filter; @@ -180,6 +170,56 @@ static const input_driver_t input_glfw = { .ident = "glfw" }; +static inline bool gl_shader_init(void) +{ +#ifdef HAVE_CG + if (strlen(g_settings.video.cg_shader_path) > 0) + return gl_cg_init(g_settings.video.cg_shader_path); +#endif + +#ifdef HAVE_XML + if (strlen(g_settings.video.bsnes_shader_path) > 0) + return gl_glsl_init(g_settings.video.bsnes_shader_path); +#endif + + return true; +} + +static inline void gl_shader_deinit(void) +{ +#ifdef HAVE_CG + gl_cg_deinit(); +#endif + +#ifdef HAVE_XML + gl_glsl_deinit(); +#endif +} + +static inline void gl_shader_set_proj_matrix(void) +{ +#ifdef HAVE_CG + gl_cg_set_proj_matrix(); +#endif + +#ifdef HAVE_XML + gl_glsl_set_proj_matrix(); +#endif +} + +static inline void gl_shader_set_params(unsigned width, unsigned height, + unsigned tex_width, unsigned tex_height, + unsigned out_width, unsigned out_height) +{ +#ifdef HAVE_CG + gl_cg_set_params(width, height, tex_width, tex_height, out_width, out_height); +#endif + +#ifdef HAVE_XML + gl_glsl_set_params(width, height, tex_width, tex_height, out_width, out_height); +#endif +} + static void GLFWCALL resize(int width, int height) { glMatrixMode(GL_PROJECTION); @@ -215,10 +255,9 @@ static void GLFWCALL resize(int width, int height) glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); -#ifdef HAVE_CG - if (cg_active) - cgGLSetStateMatrixParameter(cg_mvp_matrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); -#endif + + gl_shader_set_proj_matrix(); + gl_width = out_width; gl_height = out_height; } @@ -260,18 +299,7 @@ static bool gl_frame(void *data, const uint16_t* frame, int width, int height, i glClear(GL_COLOR_BUFFER_BIT); -#if HAVE_CG - if (cg_active) - { - cgGLSetParameter2f(gl->cg_video_size, width, height); - cgGLSetParameter2f(gl->cg_texture_size, gl->tex_w, gl->tex_h); - cgGLSetParameter2f(gl->cg_output_size, gl_width, gl_height); - - cgGLSetParameter2f(gl->cg_Vvideo_size, width, height); - cgGLSetParameter2f(gl->cg_Vtexture_size, gl->tex_w, gl->tex_h); - cgGLSetParameter2f(gl->cg_Voutput_size, gl_width, gl_height); - } -#endif + gl_shader_set_params(width, height, gl->tex_w, gl->tex_h, gl_width, gl_height); if (width != gl->last_width || height != gl->last_height) // res change. need to clear out texture. { @@ -310,10 +338,8 @@ static bool gl_frame(void *data, const uint16_t* frame, int width, int height, i static void gl_free(void *data) { gl_t *gl = data; -#ifdef HAVE_CG - if (cg_active) - cgDestroyContext(gl->cgCtx); -#endif + + gl_shader_deinit(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDeleteTextures(1, &gl->texture); @@ -352,6 +378,7 @@ static void* gl_init(video_info_t *video, const input_driver_t **input) if (!res) { glfwTerminate(); + free(gl); return NULL; } @@ -400,60 +427,10 @@ static void* gl_init(video_info_t *video, const input_driver_t **input) gl->last_width = gl->tex_w; gl->last_height = gl->tex_h; -#ifdef HAVE_CG - cg_active = false; - if (strlen(g_settings.video.cg_shader_path) > 0) - { - SSNES_LOG("Loading Cg file: %s\n", g_settings.video.cg_shader_path); - gl->cgCtx = cgCreateContext(); - if (gl->cgCtx == NULL) - { - fprintf(stderr, "Failed to create Cg context\n"); - goto error; - } - gl->cgFProf = cgGLGetLatestProfile(CG_GL_FRAGMENT); - gl->cgVProf = cgGLGetLatestProfile(CG_GL_VERTEX); - if (gl->cgFProf == CG_PROFILE_UNKNOWN || gl->cgVProf == CG_PROFILE_UNKNOWN) - { - fprintf(stderr, "Invalid profile type\n"); - goto error; - } - cgGLSetOptimalOptions(gl->cgFProf); - cgGLSetOptimalOptions(gl->cgVProf); - gl->cgFPrg = cgCreateProgramFromFile(gl->cgCtx, CG_SOURCE, g_settings.video.cg_shader_path, gl->cgFProf, "main_fragment", 0); - gl->cgVPrg = cgCreateProgramFromFile(gl->cgCtx, CG_SOURCE, g_settings.video.cg_shader_path, gl->cgVProf, "main_vertex", 0); - if (gl->cgFPrg == NULL || gl->cgVPrg == NULL) - { - CGerror err = cgGetError(); - fprintf(stderr, "CG error: %s\n", cgGetErrorString(err)); - goto error; - } - cgGLLoadProgram(gl->cgFPrg); - cgGLLoadProgram(gl->cgVPrg); - cgGLEnableProfile(gl->cgFProf); - cgGLEnableProfile(gl->cgVProf); - cgGLBindProgram(gl->cgFPrg); - cgGLBindProgram(gl->cgVPrg); - - gl->cg_video_size = cgGetNamedParameter(gl->cgFPrg, "IN.video_size"); - gl->cg_texture_size = cgGetNamedParameter(gl->cgFPrg, "IN.texture_size"); - gl->cg_output_size = cgGetNamedParameter(gl->cgFPrg, "IN.output_size"); - gl->cg_Vvideo_size = cgGetNamedParameter(gl->cgVPrg, "IN.video_size"); - gl->cg_Vtexture_size = cgGetNamedParameter(gl->cgVPrg, "IN.texture_size"); - gl->cg_Voutput_size = cgGetNamedParameter(gl->cgVPrg, "IN.output_size"); - cg_mvp_matrix = cgGetNamedParameter(gl->cgVPrg, "modelViewProj"); - cgGLSetStateMatrixParameter(cg_mvp_matrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); - cg_active = true; - } -#endif + gl_shader_init(); *input = &input_glfw; return gl; -#ifdef HAVE_CG -error: - free(gl); - return NULL; -#endif } const video_driver_t video_gl = { diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c new file mode 100644 index 0000000000..1c1005a794 --- /dev/null +++ b/gfx/shader_cg.c @@ -0,0 +1,104 @@ +/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes. + * Copyright (C) 2010 - Hans-Kristian Arntzen + * + * Some code herein may be based on code found in BSNES. + * + * 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_cg.h" +#include +#include +#include "general.h" + +static CGcontext cgCtx; +static CGprogram cgFPrg; +static CGprogram cgVPrg; +static CGprofile cgFProf; +static CGprofile cgVProf; +static CGparameter cg_video_size, cg_texture_size, cg_output_size; +static CGparameter cg_Vvideo_size, cg_Vtexture_size, cg_Voutput_size; // Vertexes +static CGparameter cg_mvp_matrix; +static bool cg_active = false; + +void gl_cg_set_proj_matrix(void) +{ + if (cg_active) + cgGLSetStateMatrixParameter(cg_mvp_matrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); +} + +void gl_cg_set_params(unsigned width, unsigned height, + unsigned tex_width, unsigned tex_height, + unsigned out_width, unsigned out_height) +{ + if (cg_active) + { + cgGLSetParameter2f(cg_video_size, width, height); + cgGLSetParameter2f(cg_texture_size, tex_width, tex_height); + cgGLSetParameter2f(cg_output_size, out_width, out_height); + + cgGLSetParameter2f(cg_Vvideo_size, width, height); + cgGLSetParameter2f(cg_Vtexture_size, tex_width, tex_height); + cgGLSetParameter2f(cg_Voutput_size, out_width, out_height); + } +} + +void gl_cg_deinit(void) +{ + if (cg_active) + cgDestroyContext(cgCtx); +} + +bool gl_cg_init(const char *path) +{ + SSNES_LOG("Loading Cg file: %s\n", path); + cgCtx = cgCreateContext(); + if (cgCtx == NULL) + { + SSNES_ERR("Failed to create Cg context\n"); + return false; + } + cgFProf = cgGLGetLatestProfile(CG_GL_FRAGMENT); + cgVProf = cgGLGetLatestProfile(CG_GL_VERTEX); + if (cgFProf == CG_PROFILE_UNKNOWN || cgVProf == CG_PROFILE_UNKNOWN) + { + SSNES_ERR("Invalid profile type\n"); + return false; + } + cgGLSetOptimalOptions(cgFProf); + cgGLSetOptimalOptions(cgVProf); + cgFPrg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, path, cgFProf, "main_fragment", 0); + cgVPrg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, path, cgVProf, "main_vertex", 0); + if (cgFPrg == NULL || cgVPrg == NULL) + { + CGerror err = cgGetError(); + SSNES_ERR("CG error: %s\n", cgGetErrorString(err)); + return false; + } + cgGLLoadProgram(cgFPrg); + cgGLLoadProgram(cgVPrg); + cgGLEnableProfile(cgFProf); + cgGLEnableProfile(cgVProf); + cgGLBindProgram(cgFPrg); + cgGLBindProgram(cgVPrg); + + cg_video_size = cgGetNamedParameter(cgFPrg, "IN.video_size"); + cg_texture_size = cgGetNamedParameter(cgFPrg, "IN.texture_size"); + cg_output_size = cgGetNamedParameter(cgFPrg, "IN.output_size"); + cg_Vvideo_size = cgGetNamedParameter(cgVPrg, "IN.video_size"); + cg_Vtexture_size = cgGetNamedParameter(cgVPrg, "IN.texture_size"); + cg_Voutput_size = cgGetNamedParameter(cgVPrg, "IN.output_size"); + cg_mvp_matrix = cgGetNamedParameter(cgVPrg, "modelViewProj"); + cgGLSetStateMatrixParameter(cg_mvp_matrix, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); + cg_active = true; + return true; +} diff --git a/gfx/shader_cg.h b/gfx/shader_cg.h new file mode 100644 index 0000000000..f788466c0a --- /dev/null +++ b/gfx/shader_cg.h @@ -0,0 +1,34 @@ +/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes. + * Copyright (C) 2010 - Hans-Kristian Arntzen + * + * Some code herein may be based on code found in BSNES. + * + * 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_CG_H +#define __SSNES_CG_H + +#include + +bool gl_cg_init(const char *path); + +void gl_cg_deinit(void); + +void gl_cg_set_proj_matrix(void); + +void gl_cg_set_params(unsigned width, unsigned height, + unsigned tex_width, unsigned tex_height, + unsigned out_width, unsigned out_height); + +#endif