RetroArch/gfx/drivers_shader/shader_gl_cg.c

1307 lines
37 KiB
C
Raw Normal View History

2012-04-21 23:13:50 +02:00
/* RetroArch - A frontend for libretro.
2014-01-01 01:50:59 +01:00
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
2016-01-10 04:41:52 +01:00
* Copyright (C) 2011-2016 - Daniel De Matteis
*
2012-04-21 23:13:50 +02:00
* RetroArch 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.
*
2012-04-21 23:13:50 +02:00
* RetroArch 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.
*
2012-04-21 23:31:57 +02:00
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER
2012-11-15 09:40:31 +01:00
#pragma comment(lib, "cg")
#pragma comment(lib, "cggl")
#endif
2014-10-02 12:50:27 +02:00
#include <stdint.h>
2015-10-31 20:53:08 +01:00
#include <string.h>
2014-10-02 13:32:42 +02:00
2016-04-23 18:19:35 +02:00
#include "../include/Cg/cg.h"
2014-10-02 13:32:42 +02:00
#ifdef HAVE_OPENGL
2015-11-17 08:01:33 +01:00
#include "../common/gl_common.h"
2016-04-23 18:19:35 +02:00
#include "../include/Cg/cgGL.h"
2014-10-02 13:32:42 +02:00
#endif
2014-10-21 07:58:58 +02:00
#include <compat/strl.h>
#include <compat/posix_string.h>
2014-10-22 03:35:04 +02:00
#include <file/config_file.h>
2014-10-22 00:23:06 +02:00
#include <file/file_path.h>
2016-02-05 13:51:30 +01:00
#include <retro_assert.h>
2015-06-15 05:09:01 +02:00
#include <rhash.h>
2016-01-20 06:16:55 +01:00
#include <string/stdstring.h>
2015-06-15 05:09:01 +02:00
2015-10-31 20:53:08 +01:00
#include "../video_shader_driver.h"
#include "../video_shader_parse.h"
2016-05-08 05:29:10 +02:00
#include "../../core.h"
2015-06-15 05:09:01 +02:00
#include "../../dynamic.h"
#include "../../managers/state_manager.h"
2015-01-12 16:00:13 +01:00
#include "../video_state_tracker.h"
2016-04-24 20:25:56 +02:00
#include "../drivers/gl_shaders/pipeline_xmb_ribbon_simple.cg.h"
2016-01-08 21:01:34 +01:00
#define SEMANTIC_TEXCOORD 0x92ee91cdU
#define SEMANTIC_TEXCOORD0 0xf0c0cb9dU
#define SEMANTIC_TEXCOORD1 0xf0c0cb9eU
#define SEMANTIC_COLOR 0x0ce809a4U
#define SEMANTIC_COLOR0 0xa9e93e54U
#define SEMANTIC_POSITION 0xd87309baU
2016-04-16 04:34:32 +02:00
#define PREV_TEXTURES (GFX_MAX_TEXTURES - 1)
#if 0
#define RARCH_CG_DEBUG
#endif
2016-04-16 04:34:32 +02:00
struct cg_fbo_params
{
CGparameter vid_size_f;
CGparameter tex_size_f;
CGparameter vid_size_v;
CGparameter tex_size_v;
CGparameter tex;
CGparameter coord;
};
2016-04-25 12:51:01 +02:00
struct shader_program_cg
2016-04-16 04:34:32 +02:00
{
CGprogram vprg;
CGprogram fprg;
CGparameter tex;
CGparameter lut_tex;
CGparameter color;
CGparameter vertex;
CGparameter vid_size_f;
CGparameter tex_size_f;
CGparameter out_size_f;
CGparameter frame_cnt_f;
CGparameter frame_dir_f;
CGparameter vid_size_v;
CGparameter tex_size_v;
CGparameter out_size_v;
CGparameter frame_cnt_v;
CGparameter frame_dir_v;
CGparameter mvp;
struct cg_fbo_params fbo[GFX_MAX_SHADERS];
struct cg_fbo_params orig;
struct cg_fbo_params feedback;
struct cg_fbo_params prev[PREV_TEXTURES];
};
typedef struct cg_shader_data
{
2016-04-25 10:15:57 +02:00
struct video_shader *shader;
char alias_define[GFX_MAX_SHADERS][128];
2016-04-16 04:34:32 +02:00
unsigned active_idx;
2016-04-22 14:00:11 +02:00
struct
{
CGparameter elems[32 * PREV_TEXTURES + 2 + 4 + GFX_MAX_SHADERS];
unsigned index;
} attribs;
2016-04-25 10:15:57 +02:00
2016-04-16 04:34:32 +02:00
CGprofile cgVProf;
CGprofile cgFProf;
2016-04-25 12:51:01 +02:00
struct shader_program_cg prg[GFX_MAX_SHADERS];
2016-04-16 04:34:32 +02:00
GLuint lut_textures[GFX_MAX_TEXTURES];
2016-04-25 10:15:57 +02:00
state_tracker_t *state_tracker;
2016-04-16 04:34:32 +02:00
CGcontext cgCtx;
} cg_shader_data_t;
2016-04-25 12:51:01 +02:00
struct uniform_cg
2016-04-13 01:42:40 +02:00
{
2016-04-16 19:29:45 +02:00
CGparameter loc;
};
2016-04-25 12:51:01 +02:00
#define gl_cg_set_coord_array(param, cg, ptr, len) \
2016-04-25 12:33:38 +02:00
{ \
cgGLSetParameterPointer(param, len, GL_FLOAT, 0, ptr); \
cgGLEnableClientState(param); \
2016-04-25 12:51:01 +02:00
cg->attribs.elems[cg->attribs.index++] = param; \
2016-04-25 12:33:38 +02:00
}
2016-04-25 11:59:46 +02:00
#define cg_gl_set_texture_parameter(param, texture) \
if (param) \
{ \
cgGLSetTextureParameter(param, texture); \
cgGLEnableTextureParameter(param); \
}
#include "../drivers/gl_shaders/opaque.cg.h"
static void gl_cg_set_uniform_parameter(
2016-04-16 19:29:45 +02:00
void *data,
2016-04-16 19:41:48 +02:00
struct uniform_info *param,
2016-04-16 19:29:45 +02:00
void *uniform_data)
{
CGparameter location;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2016-04-16 19:44:44 +02:00
if (!param || !param->enabled)
2016-04-13 01:42:40 +02:00
return;
2016-04-16 19:29:45 +02:00
if (param->lookup.enable)
{
char ident[64];
CGprogram prog = 0;
switch (param->lookup.type)
{
case SHADER_PROGRAM_VERTEX:
2016-04-25 12:51:01 +02:00
prog = cg->prg[param->lookup.idx].vprg;
break;
case SHADER_PROGRAM_FRAGMENT:
default:
2016-04-25 12:51:01 +02:00
prog = cg->prg[param->lookup.idx].fprg;
break;
}
if (param->lookup.add_prefix)
2016-04-17 17:59:40 +02:00
snprintf(ident, sizeof(ident), "IN.%s", param->lookup.ident);
location = cgGetNamedParameter(prog, param->lookup.add_prefix ? ident : param->lookup.ident);
}
2016-04-16 19:29:45 +02:00
else
{
2016-04-25 12:51:01 +02:00
struct uniform_cg *cg_param = (struct uniform_cg*)uniform_data;
2016-04-16 19:29:45 +02:00
location = cg_param->loc;
}
2016-04-13 01:42:40 +02:00
switch (param->type)
{
case UNIFORM_1F:
2016-04-16 19:29:45 +02:00
cgGLSetParameter1f(location, param->result.f.v0);
2016-04-13 01:42:40 +02:00
break;
case UNIFORM_2F:
2016-04-16 19:29:45 +02:00
cgGLSetParameter2f(location, param->result.f.v0, param->result.f.v1);
2016-04-13 02:54:01 +02:00
break;
case UNIFORM_3F:
2016-04-16 19:29:45 +02:00
cgGLSetParameter3f(location, param->result.f.v0, param->result.f.v1,
2016-04-13 02:54:01 +02:00
param->result.f.v2);
break;
case UNIFORM_4F:
2016-04-16 19:29:45 +02:00
cgGLSetParameter4f(location, param->result.f.v0, param->result.f.v1,
2016-04-13 02:54:01 +02:00
param->result.f.v2, param->result.f.v3);
break;
case UNIFORM_1FV:
2016-04-16 19:29:45 +02:00
cgGLSetParameter1fv(location, param->result.floatv);
2016-04-13 02:54:01 +02:00
break;
case UNIFORM_2FV:
2016-04-16 19:29:45 +02:00
cgGLSetParameter2fv(location, param->result.floatv);
2016-04-13 02:54:01 +02:00
break;
case UNIFORM_3FV:
2016-04-16 19:29:45 +02:00
cgGLSetParameter3fv(location, param->result.floatv);
2016-04-13 02:54:01 +02:00
break;
case UNIFORM_4FV:
2016-04-16 19:29:45 +02:00
cgGLSetParameter3fv(location, param->result.floatv);
2016-04-13 01:42:40 +02:00
break;
2016-04-14 01:12:14 +02:00
case UNIFORM_1I:
/* Unimplemented - Cg limitation */
break;
2016-04-13 01:42:40 +02:00
}
}
2016-01-08 18:12:49 +01:00
2012-04-21 23:25:32 +02:00
#ifdef RARCH_CG_DEBUG
2011-05-23 21:43:08 +02:00
static void cg_error_handler(CGcontext ctx, CGerror error, void *data)
{
(void)ctx;
(void)data;
switch (error)
{
case CG_INVALID_PARAM_HANDLE_ERROR:
RARCH_ERR("CG: Invalid param handle.\n");
break;
case CG_INVALID_PARAMETER_ERROR:
RARCH_ERR("CG: Invalid parameter.\n");
break;
default:
break;
}
RARCH_ERR("CG error: \"%s\"\n", cgGetErrorString(error));
2011-05-23 21:43:08 +02:00
}
#endif
2015-12-05 07:33:21 +01:00
static void gl_cg_reset_attrib(void *data)
2011-11-12 18:31:22 +01:00
{
2013-10-22 21:26:33 +02:00
unsigned i;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2014-09-08 17:57:18 +02:00
/* Add sanity check that we did not overflow. */
2016-04-25 12:51:01 +02:00
retro_assert(cg->attribs.index <= ARRAY_SIZE(cg->attribs.elems));
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->attribs.index; i++)
cgGLDisableClientState(cg->attribs.elems[i]);
cg->attribs.index = 0;
2011-11-12 18:31:22 +01:00
}
2015-12-05 07:33:21 +01:00
static bool gl_cg_set_mvp(void *data, void *shader_data, const math_matrix_4x4 *mat)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)shader_data;
if (!cg || !cg->prg[cg->active_idx].mvp)
2016-04-17 04:55:58 +02:00
goto fallback;
2014-08-27 03:28:22 +02:00
2016-04-25 12:51:01 +02:00
cgGLSetMatrixParameterfc(cg->prg[cg->active_idx].mvp, mat->data);
2016-04-17 04:55:58 +02:00
return true;
fallback:
gl_ff_matrix(mat);
2014-08-27 03:28:22 +02:00
return false;
}
2016-05-10 02:32:49 +02:00
static bool gl_cg_set_coords(void *handle_data, void *shader_data, const struct video_coords *coords)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)shader_data;
2016-04-25 12:51:01 +02:00
if (!cg || !coords)
goto fallback;
2016-04-25 12:51:01 +02:00
if (cg->prg[cg->active_idx].vertex)
gl_cg_set_coord_array(cg->prg[cg->active_idx].vertex, cg, coords->vertex, 2);
2016-04-25 12:33:38 +02:00
2016-04-25 12:51:01 +02:00
if (cg->prg[cg->active_idx].tex)
gl_cg_set_coord_array(cg->prg[cg->active_idx].tex, cg, coords->tex_coord, 2);
2016-04-25 12:33:38 +02:00
2016-04-25 12:51:01 +02:00
if (cg->prg[cg->active_idx].lut_tex)
gl_cg_set_coord_array(cg->prg[cg->active_idx].lut_tex, cg, coords->lut_tex_coord, 2);
2016-04-25 12:33:38 +02:00
2016-04-25 12:51:01 +02:00
if (cg->prg[cg->active_idx].color)
gl_cg_set_coord_array(cg->prg[cg->active_idx].color, cg, coords->color, 4);
return true;
2016-04-17 04:55:58 +02:00
fallback:
gl_ff_vertex(coords);
return false;
}
2016-04-13 01:42:40 +02:00
static void gl_cg_set_texture_info(
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg,
2016-04-13 01:42:40 +02:00
const struct cg_fbo_params *params,
const struct gfx_tex_info *info)
{
2016-04-13 01:42:40 +02:00
unsigned i;
2016-04-25 12:51:01 +02:00
struct uniform_cg uniform_data[4];
2016-04-27 23:07:36 +02:00
struct uniform_info uniform_params[4] = {{0}};
2016-04-25 11:59:46 +02:00
CGparameter param = params->tex;
2016-04-13 01:42:40 +02:00
2016-04-25 11:59:46 +02:00
cg_gl_set_texture_parameter(param, info->tex);
uniform_params[0].location = 0;
uniform_params[0].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[0].type = UNIFORM_2F;
uniform_params[0].result.f.v0 = info->input_size[0];
uniform_params[0].result.f.v1 = info->input_size[1];
2016-04-16 19:29:45 +02:00
uniform_data[0].loc = params->vid_size_v;
2016-04-13 01:42:40 +02:00
uniform_params[1].location = 1;
uniform_params[1].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[1].type = UNIFORM_2F;
uniform_params[1].result.f.v0 = info->input_size[0];
uniform_params[1].result.f.v1 = info->input_size[1];
2016-04-16 19:29:45 +02:00
uniform_data[1].loc = params->vid_size_f;
2016-04-13 01:42:40 +02:00
uniform_params[2].location = 2;
uniform_params[2].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[2].type = UNIFORM_2F;
uniform_params[2].result.f.v0 = info->tex_size[0];
uniform_params[2].result.f.v1 = info->tex_size[1];
2016-04-16 19:29:45 +02:00
uniform_data[2].loc = params->tex_size_v;
2016-04-13 01:42:40 +02:00
uniform_params[3].location = 3;
uniform_params[3].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[3].type = UNIFORM_2F;
uniform_params[3].result.f.v0 = info->tex_size[0];
uniform_params[3].result.f.v1 = info->tex_size[1];
2016-04-16 19:29:45 +02:00
uniform_data[3].loc = params->tex_size_f;
2016-04-13 01:42:40 +02:00
for (i = 0; i < 4; i++)
2016-04-25 12:51:01 +02:00
gl_cg_set_uniform_parameter(cg, &uniform_params[i], &uniform_data[i]);
2016-04-25 12:33:38 +02:00
if (params->coord)
2016-04-25 12:51:01 +02:00
gl_cg_set_coord_array(params->coord, cg, info->coord, 2);
}
2015-12-05 07:33:21 +01:00
static void gl_cg_set_params(void *data, void *shader_data,
unsigned width, unsigned height,
unsigned tex_width, unsigned tex_height,
unsigned out_width, unsigned out_height,
unsigned frame_count,
const void *_info,
const void *_prev_info,
const void *_feedback_info,
const void *_fbo_info,
unsigned fbo_info_cnt)
{
unsigned i;
2016-04-25 12:51:01 +02:00
struct uniform_cg uniform_data[10];
2016-04-27 23:07:36 +02:00
struct uniform_info uniform_params[10] = {{0}};
2016-04-14 01:18:27 +02:00
unsigned uniform_count = 0;
const struct gfx_tex_info *info = (const struct gfx_tex_info*)_info;
const struct gfx_tex_info *prev_info = (const struct gfx_tex_info*)_prev_info;
const struct gfx_tex_info *feedback_info = (const struct gfx_tex_info*)_feedback_info;
2016-04-14 01:18:27 +02:00
const struct gfx_tex_info *fbo_info = (const struct gfx_tex_info*)_fbo_info;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)shader_data;
2016-04-25 12:51:01 +02:00
if (!cg || (cg->active_idx == 0))
2016-04-14 01:18:27 +02:00
return;
2016-04-25 12:51:01 +02:00
if (cg->active_idx == VIDEO_SHADER_STOCK_BLEND)
2011-11-12 18:31:22 +01:00
return;
2014-09-08 17:57:18 +02:00
/* Set frame. */
uniform_params[0].location = 0;
uniform_params[0].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[0].type = UNIFORM_2F;
uniform_params[0].result.f.v0 = width;
uniform_params[0].result.f.v1 = height;
2016-04-25 12:51:01 +02:00
uniform_data[0].loc = cg->prg[cg->active_idx].vid_size_f;
2016-04-13 01:42:40 +02:00
uniform_params[1].location = 1;
uniform_params[1].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[1].type = UNIFORM_2F;
uniform_params[1].result.f.v0 = tex_width;
uniform_params[1].result.f.v1 = tex_height;
2016-04-25 12:51:01 +02:00
uniform_data[1].loc = cg->prg[cg->active_idx].tex_size_f;
2016-04-13 01:42:40 +02:00
uniform_params[2].location = 2;
uniform_params[2].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[2].type = UNIFORM_2F;
uniform_params[2].result.f.v0 = out_width;
uniform_params[2].result.f.v1 = out_height;
2016-04-25 12:51:01 +02:00
uniform_data[2].loc = cg->prg[cg->active_idx].out_size_f;
2016-04-13 01:42:40 +02:00
uniform_params[3].location = 3;
uniform_params[3].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[3].type = UNIFORM_1F;
uniform_params[3].result.f.v0 = state_manager_frame_is_reversed() ? -1.0 : 1.0;
2016-04-25 12:51:01 +02:00
uniform_data[3].loc = cg->prg[cg->active_idx].frame_dir_f;
2016-04-13 01:42:40 +02:00
uniform_params[4].location = 4;
uniform_params[4].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[4].type = UNIFORM_2F;
uniform_params[4].result.f.v0 = width;
uniform_params[4].result.f.v1 = height;
2016-04-25 12:51:01 +02:00
uniform_data[4].loc = cg->prg[cg->active_idx].vid_size_v;
2016-04-13 01:42:40 +02:00
uniform_params[5].location = 5;
uniform_params[5].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[5].type = UNIFORM_2F;
uniform_params[5].result.f.v0 = tex_width;
uniform_params[5].result.f.v1 = tex_height;
2016-04-25 12:51:01 +02:00
uniform_data[5].loc = cg->prg[cg->active_idx].tex_size_v;
2016-04-13 01:42:40 +02:00
uniform_params[6].location = 6;
uniform_params[6].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[6].type = UNIFORM_2F;
uniform_params[6].result.f.v0 = out_width;
uniform_params[6].result.f.v1 = out_height;
2016-04-25 12:51:01 +02:00
uniform_data[6].loc = cg->prg[cg->active_idx].out_size_v;
2016-04-13 01:42:40 +02:00
uniform_params[7].location = 7;
uniform_params[7].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[7].type = UNIFORM_1F;
uniform_params[7].result.f.v0 = state_manager_frame_is_reversed() ? -1.0 : 1.0;
2016-04-25 12:51:01 +02:00
uniform_data[7].loc = cg->prg[cg->active_idx].frame_dir_v;
2016-04-13 01:46:29 +02:00
uniform_count += 8;
2011-11-12 18:31:22 +01:00
2016-04-25 12:51:01 +02:00
if (cg->prg[cg->active_idx].frame_cnt_f || cg->prg[cg->active_idx].frame_cnt_v)
{
2016-04-25 12:51:01 +02:00
unsigned modulo = cg->shader->pass[cg->active_idx - 1].frame_count_mod;
if (modulo)
frame_count %= modulo;
uniform_params[8].location = 8;
uniform_params[8].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[8].type = UNIFORM_1F;
uniform_params[8].result.f.v0 = (float)frame_count;
2016-04-25 12:51:01 +02:00
uniform_data[8].loc = cg->prg[cg->active_idx].frame_cnt_f;
2016-04-13 01:42:40 +02:00
uniform_params[9].location = 9;
uniform_params[9].enabled = true;
2016-04-13 01:42:40 +02:00
uniform_params[9].type = UNIFORM_1F;
uniform_params[9].result.f.v0 = (float)frame_count;
2016-04-25 12:51:01 +02:00
uniform_data[9].loc = cg->prg[cg->active_idx].frame_cnt_v;
2016-04-13 01:46:29 +02:00
uniform_count += 2;
}
2016-04-13 19:27:04 +02:00
for (i = 0; i < uniform_count; i++)
2016-04-25 12:51:01 +02:00
gl_cg_set_uniform_parameter(cg, &uniform_params[i], &uniform_data[i]);
2016-04-13 01:42:40 +02:00
2014-09-08 17:57:18 +02:00
/* Set lookup textures. */
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->shader->luts; i++)
2011-11-12 18:31:22 +01:00
{
2014-09-08 17:57:18 +02:00
CGparameter fparam = cgGetNamedParameter(
2016-04-25 12:51:01 +02:00
cg->prg[cg->active_idx].fprg, cg->shader->lut[i].id);
CGparameter vparam = cgGetNamedParameter(cg->prg[cg->active_idx].vprg,
cg->shader->lut[i].id);
2015-01-11 19:52:02 +01:00
2016-04-25 12:51:01 +02:00
cg_gl_set_texture_parameter(fparam, cg->lut_textures[i]);
cg_gl_set_texture_parameter(vparam, cg->lut_textures[i]);
2011-11-12 18:31:22 +01:00
}
2016-04-25 12:51:01 +02:00
if (cg->active_idx)
2011-11-12 18:31:22 +01:00
{
2016-04-25 13:02:05 +02:00
/* Set original texture. */
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].orig, info);
/* Set feedback texture. */
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].feedback, feedback_info);
/* Bind FBO textures. */
2013-10-22 21:26:33 +02:00
for (i = 0; i < fbo_info_cnt; i++)
2016-04-25 12:51:01 +02:00
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].fbo[i], &fbo_info[i]);
2011-11-12 18:31:22 +01:00
}
2016-04-25 13:02:05 +02:00
/* Set previous textures. */
for (i = 0; i < PREV_TEXTURES; i++)
gl_cg_set_texture_info(cg, &cg->prg[cg->active_idx].prev[i], &prev_info[i]);
2014-09-08 17:57:18 +02:00
/* #pragma parameters. */
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->shader->num_parameters; i++)
2014-05-23 12:09:57 +02:00
{
2016-04-14 01:12:14 +02:00
unsigned j;
2016-04-13 01:42:40 +02:00
2016-04-16 20:32:45 +02:00
uniform_params[0].lookup.type = SHADER_PROGRAM_VERTEX;
uniform_params[1].lookup.type = SHADER_PROGRAM_FRAGMENT;
2016-04-13 01:42:40 +02:00
2016-04-14 01:12:14 +02:00
for (j = 0; j < 2; j++)
2016-04-22 14:05:45 +02:00
{
uniform_params[j].lookup.enable = true;
2016-04-25 12:51:01 +02:00
uniform_params[j].lookup.idx = cg->active_idx;
uniform_params[j].lookup.ident = cg->shader->parameters[i].id;
2016-04-22 14:05:45 +02:00
uniform_params[j].location = j;
uniform_params[j].enabled = true;
uniform_params[j].type = UNIFORM_1F;
2016-04-25 12:51:01 +02:00
uniform_params[j].result.f.v0 = cg->shader->parameters[i].current;
gl_cg_set_uniform_parameter(cg, &uniform_params[j], NULL);
2016-04-22 14:05:45 +02:00
}
2014-05-23 12:09:57 +02:00
}
2014-09-08 17:57:18 +02:00
/* Set state parameters. */
2016-04-25 12:51:01 +02:00
if (cg->state_tracker)
2011-11-12 18:31:22 +01:00
{
2014-09-08 17:57:18 +02:00
/* Only query uniforms in first pass. */
static struct state_tracker_uniform tracker_info[GFX_MAX_VARIABLES];
2011-11-12 18:31:22 +01:00
static unsigned cnt = 0;
2016-04-25 12:51:01 +02:00
if (cg->active_idx == 1)
cnt = state_tracker_get_uniform(cg->state_tracker, tracker_info,
GFX_MAX_VARIABLES, frame_count);
2013-10-22 21:26:33 +02:00
for (i = 0; i < cnt; i++)
2011-11-12 18:31:22 +01:00
{
2016-04-14 01:15:16 +02:00
unsigned j;
2016-04-13 01:42:40 +02:00
2016-04-16 20:35:08 +02:00
uniform_params[0].lookup.type = SHADER_PROGRAM_VERTEX;
uniform_params[1].lookup.type = SHADER_PROGRAM_FRAGMENT;
2016-04-13 01:42:40 +02:00
2016-04-14 01:15:16 +02:00
for (j = 0; j < 2; j++)
2016-04-22 14:05:45 +02:00
{
uniform_params[j].lookup.enable = true;
2016-04-25 12:51:01 +02:00
uniform_params[j].lookup.idx = cg->active_idx;
2016-04-22 14:05:45 +02:00
uniform_params[j].lookup.ident = tracker_info[i].id;
uniform_params[j].location = j;
uniform_params[j].enabled = true;
uniform_params[j].type = UNIFORM_1F;
uniform_params[j].result.f.v0 = tracker_info[i].value;
2016-04-25 12:51:01 +02:00
gl_cg_set_uniform_parameter(cg, &uniform_params[j], NULL);
2016-04-22 14:05:45 +02:00
}
}
}
}
2015-12-05 07:33:21 +01:00
static void gl_cg_deinit_progs(void *data)
{
2013-10-22 21:26:33 +02:00
unsigned i;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2016-04-25 12:51:01 +02:00
if (!cg)
return;
RARCH_LOG("CG: Destroying programs.\n");
2016-04-25 12:51:01 +02:00
cgGLUnbindProgram(cg->cgFProf);
cgGLUnbindProgram(cg->cgVProf);
2012-02-20 16:22:58 +01:00
2014-09-08 17:57:18 +02:00
/* Programs may alias [0]. */
2013-10-22 21:26:33 +02:00
for (i = 1; i < GFX_MAX_SHADERS; i++)
2012-02-20 16:22:58 +01:00
{
2016-04-25 12:51:01 +02:00
if (cg->prg[i].fprg && cg->prg[i].fprg != cg->prg[0].fprg)
cgDestroyProgram(cg->prg[i].fprg);
if (cg->prg[i].vprg && cg->prg[i].vprg != cg->prg[0].vprg)
cgDestroyProgram(cg->prg[i].vprg);
2012-02-20 16:22:58 +01:00
}
2011-06-11 22:02:05 +02:00
2016-04-25 12:51:01 +02:00
if (cg->prg[0].fprg)
cgDestroyProgram(cg->prg[0].fprg);
if (cg->prg[0].vprg)
cgDestroyProgram(cg->prg[0].vprg);
2012-02-20 16:22:58 +01:00
2016-04-25 12:51:01 +02:00
memset(cg->prg, 0, sizeof(cg->prg));
2012-02-20 16:22:58 +01:00
}
2015-12-05 07:33:21 +01:00
static void gl_cg_destroy_resources(void *data)
2012-02-20 16:22:58 +01:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg)
return;
2015-12-05 07:33:21 +01:00
gl_cg_reset_attrib(data);
2012-02-20 16:22:58 +01:00
2015-12-05 07:33:21 +01:00
gl_cg_deinit_progs(data);
2012-02-20 16:22:58 +01:00
2016-04-25 12:51:01 +02:00
if (cg->shader && cg->shader->luts)
{
2016-04-25 12:51:01 +02:00
glDeleteTextures(cg->shader->luts, cg->lut_textures);
memset(cg->lut_textures, 0, sizeof(cg->lut_textures));
}
2016-04-25 12:51:01 +02:00
if (cg->state_tracker)
{
2016-04-25 12:51:01 +02:00
state_tracker_free(cg->state_tracker);
cg->state_tracker = NULL;
}
2016-04-25 12:51:01 +02:00
free(cg->shader);
cg->shader = NULL;
2012-02-20 16:22:58 +01:00
}
2011-06-11 22:02:05 +02:00
2014-09-08 17:57:18 +02:00
/* Final deinit. */
2015-12-05 07:33:21 +01:00
static void gl_cg_deinit_context_state(void *data)
2012-02-20 16:22:58 +01:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (cg->cgCtx)
2012-02-20 16:22:58 +01:00
{
RARCH_LOG("CG: Destroying context.\n");
2016-04-25 12:51:01 +02:00
cgDestroyContext(cg->cgCtx);
2012-02-20 16:22:58 +01:00
}
2016-04-25 12:51:01 +02:00
cg->cgCtx = NULL;
}
2014-09-08 17:57:18 +02:00
/* Full deinit. */
2015-12-05 07:33:21 +01:00
static void gl_cg_deinit(void *data)
2012-02-20 16:22:58 +01:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg)
return;
2016-04-25 12:51:01 +02:00
gl_cg_destroy_resources(cg);
gl_cg_deinit_context_state(cg);
2016-04-25 12:51:01 +02:00
free(cg);
2012-02-20 16:22:58 +01:00
}
2016-04-14 01:53:23 +02:00
static bool gl_cg_compile_program(
void *data,
unsigned idx,
2016-04-16 04:56:15 +02:00
void *program_data,
struct shader_program_info *program_info)
{
2016-04-16 04:31:24 +02:00
const char *list = NULL;
2014-12-08 17:05:21 +01:00
const char *argv[2 + GFX_MAX_SHADERS];
bool ret = true;
char *listing_f = NULL;
char *listing_v = NULL;
unsigned i, argc = 0;
2016-04-25 12:51:01 +02:00
struct shader_program_cg *program = (struct shader_program_cg*)program_data;
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2014-05-23 12:09:57 +02:00
if (!program)
2016-04-25 12:51:01 +02:00
program = &cg->prg[idx];
2014-12-08 17:05:21 +01:00
argv[argc++] = "-DPARAMETER_UNIFORM";
2014-05-23 15:19:32 +02:00
for (i = 0; i < GFX_MAX_SHADERS; i++)
{
2016-04-25 12:51:01 +02:00
if (*(cg->alias_define[i]))
argv[argc++] = cg->alias_define[i];
2014-05-23 15:19:32 +02:00
}
argv[argc] = NULL;
2014-05-23 15:19:32 +02:00
if (program_info->is_file)
2016-04-14 01:33:43 +02:00
program->fprg = cgCreateProgramFromFile(
2016-04-25 12:51:01 +02:00
cg->cgCtx, CG_SOURCE,
program_info->combined, cg->cgFProf, "main_fragment", argv);
2016-04-16 04:31:24 +02:00
else
2016-04-25 12:51:01 +02:00
program->fprg = cgCreateProgram(cg->cgCtx, CG_SOURCE,
program_info->combined, cg->cgFProf, "main_fragment", argv);
2016-04-16 04:31:24 +02:00
2016-04-25 12:51:01 +02:00
list = cgGetLastListing(cg->cgCtx);
2016-04-16 04:31:24 +02:00
if (list)
listing_f = strdup(list);
list = NULL;
if (program_info->is_file)
2016-04-14 01:33:43 +02:00
program->vprg = cgCreateProgramFromFile(
2016-04-25 12:51:01 +02:00
cg->cgCtx, CG_SOURCE,
program_info->combined, cg->cgVProf, "main_vertex", argv);
2011-03-06 19:56:35 +01:00
else
2016-04-25 12:51:01 +02:00
program->vprg = cgCreateProgram(cg->cgCtx, CG_SOURCE,
program_info->combined, cg->cgVProf, "main_vertex", argv);
2016-04-16 04:31:24 +02:00
2016-04-25 12:51:01 +02:00
list = cgGetLastListing(cg->cgCtx);
2016-04-16 04:31:24 +02:00
if (list)
listing_v = strdup(list);
2011-03-06 19:56:35 +01:00
2016-04-14 01:33:43 +02:00
if (!program->fprg || !program->vprg)
2011-03-06 19:56:35 +01:00
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("CG error: %s\n", cgGetErrorString(cgGetError()));
2012-01-25 22:55:34 +01:00
if (listing_f)
2012-04-21 23:25:32 +02:00
RARCH_ERR("Fragment:\n%s\n", listing_f);
2012-01-25 22:55:34 +01:00
else if (listing_v)
2012-04-21 23:25:32 +02:00
RARCH_ERR("Vertex:\n%s\n", listing_v);
2011-03-06 19:56:35 +01:00
2012-01-25 22:55:34 +01:00
ret = false;
goto end;
}
2011-03-06 19:56:35 +01:00
2016-04-14 01:33:43 +02:00
cgGLLoadProgram(program->fprg);
cgGLLoadProgram(program->vprg);
2012-01-25 22:55:34 +01:00
end:
2012-01-25 22:55:34 +01:00
free(listing_f);
free(listing_v);
return ret;
}
2016-01-08 21:01:34 +01:00
static void gl_cg_set_program_base_attrib(void *data, unsigned i)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2016-02-14 17:40:20 +01:00
CGparameter param = cgGetFirstParameter(
2016-04-25 12:51:01 +02:00
cg->prg[i].vprg, CG_PROGRAM);
2016-01-08 21:01:34 +01:00
for (; param; param = cgGetNextParameter(param))
{
uint32_t semantic_hash;
const char *semantic = NULL;
if (cgGetParameterDirection(param) != CG_IN
|| cgGetParameterVariability(param) != CG_VARYING)
continue;
semantic = cgGetParameterSemantic(param);
if (!semantic)
continue;
RARCH_LOG("CG: Found semantic \"%s\" in prog #%u.\n", semantic, i);
semantic_hash = djb2_calculate(semantic);
switch (semantic_hash)
{
case SEMANTIC_TEXCOORD:
case SEMANTIC_TEXCOORD0:
2016-04-25 12:51:01 +02:00
cg->prg[i].tex = param;
2016-01-08 21:01:34 +01:00
break;
case SEMANTIC_COLOR:
case SEMANTIC_COLOR0:
2016-04-25 12:51:01 +02:00
cg->prg[i].color = param;
2016-01-08 21:01:34 +01:00
break;
case SEMANTIC_POSITION:
2016-04-25 12:51:01 +02:00
cg->prg[i].vertex = param;
2016-01-08 21:01:34 +01:00
break;
case SEMANTIC_TEXCOORD1:
2016-04-25 12:51:01 +02:00
cg->prg[i].lut_tex = param;
2016-01-08 21:01:34 +01:00
break;
}
}
2016-04-25 12:51:01 +02:00
if (!cg->prg[i].tex)
cg->prg[i].tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.tex_coord");
if (!cg->prg[i].color)
cg->prg[i].color = cgGetNamedParameter(cg->prg[i].vprg, "IN.color");
if (!cg->prg[i].vertex)
cg->prg[i].vertex = cgGetNamedParameter(cg->prg[i].vprg, "IN.vertex_coord");
if (!cg->prg[i].lut_tex)
cg->prg[i].lut_tex = cgGetNamedParameter(cg->prg[i].vprg, "IN.lut_tex_coord");
2016-01-08 21:01:34 +01:00
}
2016-01-08 21:01:34 +01:00
static bool gl_cg_load_stock(void *data)
2012-01-25 22:55:34 +01:00
{
struct shader_program_info program_info;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
program_info.combined = stock_cg_gl_program;
program_info.is_file = false;
2016-04-25 12:51:01 +02:00
if (!gl_cg_compile_program(data, 0, &cg->prg[0], &program_info))
2016-04-22 14:37:11 +02:00
goto error;
2011-11-10 00:46:39 +01:00
2016-01-08 21:01:34 +01:00
gl_cg_set_program_base_attrib(data, 0);
2012-01-25 22:55:34 +01:00
return true;
2016-04-22 14:37:11 +02:00
error:
RARCH_ERR("Failed to compile passthrough shader, is something wrong with your environment?\n");
return false;
}
2011-07-04 13:33:09 +02:00
2016-01-08 21:01:34 +01:00
static bool gl_cg_load_plain(void *data, const char *path)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!gl_cg_load_stock(cg))
2012-01-25 22:55:34 +01:00
return false;
2016-04-25 12:51:01 +02:00
cg->shader = (struct video_shader*)
calloc(1, sizeof(*cg->shader));
if (!cg->shader)
return false;
2016-04-25 12:51:01 +02:00
cg->shader->passes = 1;
if (path)
2011-07-04 13:33:09 +02:00
{
struct shader_program_info program_info;
program_info.combined = path;
program_info.is_file = true;
RARCH_LOG("Loading Cg file: %s\n", path);
2016-04-25 12:51:01 +02:00
strlcpy(cg->shader->pass[0].source.path, path,
sizeof(cg->shader->pass[0].source.path));
if (!gl_cg_compile_program(data, 1, &cg->prg[1], &program_info))
2012-01-25 22:55:34 +01:00
return false;
}
else
{
RARCH_LOG("Loading stock Cg file.\n");
2016-04-25 12:51:01 +02:00
cg->prg[1] = cg->prg[0];
2011-07-04 13:33:09 +02:00
}
2016-04-25 12:51:01 +02:00
video_shader_resolve_parameters(NULL, cg->shader);
2012-01-25 22:55:34 +01:00
return true;
}
2015-12-05 07:33:21 +01:00
static bool gl_cg_load_imports(void *data)
{
2013-10-22 21:26:33 +02:00
unsigned i;
2016-01-28 03:22:23 +01:00
retro_ctx_memory_info_t mem_info;
2012-04-07 12:17:40 +02:00
struct state_tracker_info tracker_info = {0};
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2011-12-24 13:46:12 +01:00
2016-04-25 12:51:01 +02:00
if (!cg->shader->variables)
return true;
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->shader->variables; i++)
{
unsigned memtype;
2016-01-28 03:22:23 +01:00
2016-04-25 12:51:01 +02:00
switch (cg->shader->variable[i].ram_type)
{
2012-04-21 23:25:32 +02:00
case RARCH_STATE_WRAM:
2012-04-07 12:17:40 +02:00
memtype = RETRO_MEMORY_SYSTEM_RAM;
2011-05-28 15:06:46 +02:00
break;
2011-06-11 20:02:17 +02:00
default:
memtype = -1u;
}
2016-01-28 03:22:23 +01:00
mem_info.id = memtype;
2016-05-08 01:33:57 +02:00
core_get_memory(&mem_info);
2016-01-28 03:22:23 +01:00
2014-09-08 17:57:18 +02:00
if ((memtype != -1u) &&
2016-04-25 12:51:01 +02:00
(cg->shader->variable[i].addr >= mem_info.size))
2011-05-28 15:06:46 +02:00
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Address out of bounds.\n");
return false;
2011-05-28 15:06:46 +02:00
}
}
2016-01-28 03:22:23 +01:00
mem_info.data = NULL;
mem_info.size = 0;
mem_info.id = RETRO_MEMORY_SYSTEM_RAM;
2016-05-08 01:33:57 +02:00
core_get_memory(&mem_info);
2016-01-28 03:22:23 +01:00
tracker_info.wram = (uint8_t*)mem_info.data;
2016-04-25 12:51:01 +02:00
tracker_info.info = cg->shader->variable;
tracker_info.info_elem = cg->shader->variables;
2011-06-06 20:18:31 +02:00
#ifdef HAVE_PYTHON
2016-04-25 12:51:01 +02:00
if (*cg->shader->script_path)
2011-06-06 20:18:31 +02:00
{
2016-04-25 12:51:01 +02:00
tracker_info.script = cg->shader->script_path;
tracker_info.script_is_file = true;
2011-06-06 20:18:31 +02:00
}
2011-06-07 15:33:29 +02:00
2014-09-08 17:57:18 +02:00
tracker_info.script_class =
2016-04-25 12:51:01 +02:00
*cg->shader->script_class ? cg->shader->script_class : NULL;
2011-06-06 20:18:31 +02:00
#endif
2016-04-25 12:51:01 +02:00
cg->state_tracker = state_tracker_init(&tracker_info);
if (!cg->state_tracker)
2012-04-21 23:25:32 +02:00
RARCH_WARN("Failed to initialize state tracker.\n");
return true;
}
2011-05-22 18:48:43 +02:00
2016-01-08 20:58:44 +01:00
static bool gl_cg_load_shader(void *data, unsigned i)
2012-01-25 22:55:34 +01:00
{
struct shader_program_info program_info;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2015-12-05 07:33:21 +01:00
2016-04-25 12:51:01 +02:00
program_info.combined = cg->shader->pass[i].source.path;
program_info.is_file = true;
RARCH_LOG("Loading Cg shader: \"%s\".\n",
2016-04-25 12:51:01 +02:00
cg->shader->pass[i].source.path);
2012-01-25 22:55:34 +01:00
2016-04-25 12:51:01 +02:00
if (!gl_cg_compile_program(data, i + 1, &cg->prg[i + 1],&program_info))
2012-01-25 22:55:34 +01:00
return false;
return true;
2012-01-25 22:55:34 +01:00
}
2016-01-08 21:01:34 +01:00
static bool gl_cg_load_preset(void *data, const char *path)
2011-05-22 17:02:09 +02:00
{
2013-10-22 21:26:33 +02:00
unsigned i;
2015-04-12 19:29:38 +02:00
config_file_t *conf = NULL;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2015-04-12 19:29:38 +02:00
2016-04-25 12:51:01 +02:00
if (!gl_cg_load_stock(cg))
2011-05-22 17:02:09 +02:00
return false;
2012-04-21 23:25:32 +02:00
RARCH_LOG("Loading Cg meta-shader: %s\n", path);
2015-04-12 19:29:38 +02:00
conf = config_file_new(path);
2011-05-22 17:02:09 +02:00
if (!conf)
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Failed to load preset.\n");
return false;
2011-05-22 17:02:09 +02:00
}
2016-04-25 12:51:01 +02:00
cg->shader = (struct video_shader*)calloc(1, sizeof(*cg->shader));
if (!cg->shader)
2015-01-27 15:35:31 +01:00
{
config_file_free(conf);
return false;
2015-01-27 15:35:31 +01:00
}
2011-05-22 17:02:09 +02:00
2016-04-25 12:51:01 +02:00
if (!video_shader_read_conf_cgp(conf, cg->shader))
{
RARCH_ERR("Failed to parse CGP file.\n");
config_file_free(conf);
return false;
}
2016-04-25 12:51:01 +02:00
video_shader_resolve_relative(cg->shader, path);
video_shader_resolve_parameters(conf, cg->shader);
2014-05-22 21:24:52 +02:00
config_file_free(conf);
2016-04-25 12:51:01 +02:00
if (cg->shader->passes > GFX_MAX_SHADERS - 3)
2011-05-22 18:48:43 +02:00
{
2014-09-08 17:57:18 +02:00
RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n",
GFX_MAX_SHADERS - 3);
2016-04-25 12:51:01 +02:00
cg->shader->passes = GFX_MAX_SHADERS - 3;
2011-05-22 18:48:43 +02:00
}
2014-05-23 15:19:32 +02:00
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->shader->passes; i++)
if (*cg->shader->pass[i].alias)
snprintf(cg->alias_define[i],
sizeof(cg->alias_define[i]),
"-D%s_ALIAS",
2016-04-25 12:51:01 +02:00
cg->shader->pass[i].alias);
2014-05-23 15:19:32 +02:00
2016-04-25 12:51:01 +02:00
for (i = 0; i < cg->shader->passes; i++)
2011-05-22 17:02:09 +02:00
{
2016-04-25 12:51:01 +02:00
if (!gl_cg_load_shader(cg, i))
2011-05-22 17:02:09 +02:00
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Failed to load shaders ...\n");
return false;
2011-05-22 17:02:09 +02:00
}
}
2016-04-25 12:51:01 +02:00
if (!gl_load_luts(cg->shader, cg->lut_textures))
2011-05-22 18:48:43 +02:00
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Failed to load lookup textures ...\n");
return false;
2011-05-22 18:48:43 +02:00
}
2011-05-22 17:02:09 +02:00
2016-04-25 12:51:01 +02:00
if (!gl_cg_load_imports(cg))
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Failed to load imports ...\n");
return false;
}
return true;
2011-05-22 17:02:09 +02:00
}
2016-02-14 17:40:20 +01:00
static void gl_cg_set_pass_attrib(
2016-04-25 12:51:01 +02:00
struct shader_program_cg *program,
2016-02-14 17:40:20 +01:00
struct cg_fbo_params *fbo,
const char *attr)
{
2015-06-13 02:10:06 +02:00
char attr_buf[64] = {0};
snprintf(attr_buf, sizeof(attr_buf), "%s.texture", attr);
if (!fbo->tex)
fbo->tex = cgGetNamedParameter(program->fprg, attr_buf);
snprintf(attr_buf, sizeof(attr_buf), "%s.video_size", attr);
if (!fbo->vid_size_v)
fbo->vid_size_v = cgGetNamedParameter(program->vprg, attr_buf);
if (!fbo->vid_size_f)
fbo->vid_size_f = cgGetNamedParameter(program->fprg, attr_buf);
snprintf(attr_buf, sizeof(attr_buf), "%s.texture_size", attr);
if (!fbo->tex_size_v)
fbo->tex_size_v = cgGetNamedParameter(program->vprg, attr_buf);
if (!fbo->tex_size_f)
fbo->tex_size_f = cgGetNamedParameter(program->fprg, attr_buf);
snprintf(attr_buf, sizeof(attr_buf), "%s.tex_coord", attr);
if (!fbo->coord)
fbo->coord = cgGetNamedParameter(program->vprg, attr_buf);
}
2016-04-17 03:56:20 +02:00
static INLINE void gl_cg_set_shaders(CGprogram frag, CGprogram vert)
{
cgGLBindProgram(frag);
cgGLBindProgram(vert);
}
2016-01-08 21:01:34 +01:00
static void gl_cg_set_program_attributes(void *data, unsigned i)
{
2013-10-22 21:26:33 +02:00
unsigned j;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2016-04-25 12:51:01 +02:00
if (!cg)
return;
2016-04-25 12:51:01 +02:00
gl_cg_set_shaders(cg->prg[i].fprg, cg->prg[i].vprg);
gl_cg_set_program_base_attrib(cg, i);
cg->prg[i].vid_size_f = cgGetNamedParameter (cg->prg[i].fprg, "IN.video_size");
cg->prg[i].tex_size_f = cgGetNamedParameter (cg->prg[i].fprg, "IN.texture_size");
cg->prg[i].out_size_f = cgGetNamedParameter (cg->prg[i].fprg, "IN.output_size");
cg->prg[i].frame_cnt_f = cgGetNamedParameter(cg->prg[i].fprg, "IN.frame_count");
cg->prg[i].frame_dir_f = cgGetNamedParameter(cg->prg[i].fprg, "IN.frame_direction");
cg->prg[i].vid_size_v = cgGetNamedParameter (cg->prg[i].vprg, "IN.video_size");
cg->prg[i].tex_size_v = cgGetNamedParameter (cg->prg[i].vprg, "IN.texture_size");
cg->prg[i].out_size_v = cgGetNamedParameter (cg->prg[i].vprg, "IN.output_size");
cg->prg[i].frame_cnt_v = cgGetNamedParameter(cg->prg[i].vprg, "IN.frame_count");
cg->prg[i].frame_dir_v = cgGetNamedParameter(cg->prg[i].vprg, "IN.frame_direction");
cg->prg[i].mvp = cgGetNamedParameter(cg->prg[i].vprg, "modelViewProj");
if (!cg->prg[i].mvp)
cg->prg[i].mvp = cgGetNamedParameter(cg->prg[i].vprg, "IN.mvp_matrix");
cg->prg[i].orig.tex = cgGetNamedParameter(cg->prg[i].fprg, "ORIG.texture");
cg->prg[i].orig.vid_size_v = cgGetNamedParameter(cg->prg[i].vprg, "ORIG.video_size");
cg->prg[i].orig.vid_size_f = cgGetNamedParameter(cg->prg[i].fprg, "ORIG.video_size");
cg->prg[i].orig.tex_size_v = cgGetNamedParameter(cg->prg[i].vprg, "ORIG.texture_size");
cg->prg[i].orig.tex_size_f = cgGetNamedParameter(cg->prg[i].fprg, "ORIG.texture_size");
cg->prg[i].orig.coord = cgGetNamedParameter(cg->prg[i].vprg, "ORIG.tex_coord");
cg->prg[i].feedback.tex = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.texture");
cg->prg[i].feedback.vid_size_v = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.video_size");
cg->prg[i].feedback.vid_size_f = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.video_size");
cg->prg[i].feedback.tex_size_v = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.texture_size");
cg->prg[i].feedback.tex_size_f = cgGetNamedParameter(cg->prg[i].fprg, "FEEDBACK.texture_size");
cg->prg[i].feedback.coord = cgGetNamedParameter(cg->prg[i].vprg, "FEEDBACK.tex_coord");
if (i > 1)
{
2015-06-13 02:10:06 +02:00
char pass_str[64] = {0};
snprintf(pass_str, sizeof(pass_str), "PASSPREV%u", i);
2016-04-25 12:51:01 +02:00
gl_cg_set_pass_attrib(&cg->prg[i], &cg->prg[i].orig, pass_str);
}
2013-10-22 21:26:33 +02:00
for (j = 0; j < PREV_TEXTURES; j++)
{
2015-06-13 02:10:06 +02:00
char attr_buf_tex[64] = {0};
char attr_buf_vid_size[64] = {0};
char attr_buf_tex_size[64] = {0};
char attr_buf_coord[64] = {0};
static const char *prev_names[PREV_TEXTURES] = {
"PREV",
"PREV1",
"PREV2",
"PREV3",
"PREV4",
"PREV5",
"PREV6",
};
2014-09-08 17:57:18 +02:00
snprintf(attr_buf_tex, sizeof(attr_buf_tex),
"%s.texture", prev_names[j]);
snprintf(attr_buf_vid_size, sizeof(attr_buf_vid_size),
"%s.video_size", prev_names[j]);
snprintf(attr_buf_tex_size, sizeof(attr_buf_tex_size),
"%s.texture_size", prev_names[j]);
snprintf(attr_buf_coord, sizeof(attr_buf_coord),
"%s.tex_coord", prev_names[j]);
2016-04-25 12:51:01 +02:00
cg->prg[i].prev[j].tex = cgGetNamedParameter(cg->prg[i].fprg,
2016-02-14 17:40:20 +01:00
attr_buf_tex);
2016-04-25 12:51:01 +02:00
cg->prg[i].prev[j].vid_size_v =
cgGetNamedParameter(cg->prg[i].vprg, attr_buf_vid_size);
cg->prg[i].prev[j].vid_size_f =
cgGetNamedParameter(cg->prg[i].fprg, attr_buf_vid_size);
2016-04-25 12:51:01 +02:00
cg->prg[i].prev[j].tex_size_v =
cgGetNamedParameter(cg->prg[i].vprg, attr_buf_tex_size);
cg->prg[i].prev[j].tex_size_f =
cgGetNamedParameter(cg->prg[i].fprg, attr_buf_tex_size);
2016-04-25 12:51:01 +02:00
cg->prg[i].prev[j].coord = cgGetNamedParameter(cg->prg[i].vprg,
2016-02-14 17:40:20 +01:00
attr_buf_coord);
}
for (j = 0; j + 1 < i; j++)
{
2015-06-13 02:10:06 +02:00
char pass_str[64] = {0};
snprintf(pass_str, sizeof(pass_str), "PASS%u", j + 1);
2016-04-25 12:51:01 +02:00
gl_cg_set_pass_attrib(&cg->prg[i], &cg->prg[i].fbo[j], pass_str);
2016-01-20 18:52:24 -05:00
snprintf(pass_str, sizeof(pass_str), "PASSPREV%u", i - (j + 1));
2016-04-25 12:51:01 +02:00
gl_cg_set_pass_attrib(&cg->prg[i], &cg->prg[i].fbo[j], pass_str);
2016-04-25 12:51:01 +02:00
if (*cg->shader->pass[j].alias)
gl_cg_set_pass_attrib(&cg->prg[i], &cg->prg[i].fbo[j],
cg->shader->pass[j].alias);
}
}
2015-12-05 07:33:21 +01:00
static void *gl_cg_init(void *data, const char *path)
2011-05-22 17:02:09 +02:00
{
2013-10-22 21:26:33 +02:00
unsigned i;
struct shader_program_info shader_prog_info;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)
2015-12-05 07:33:21 +01:00
calloc(1, sizeof(cg_shader_data_t));
2015-04-12 19:29:38 +02:00
2016-04-25 12:51:01 +02:00
if (!cg)
2015-12-05 07:33:21 +01:00
return NULL;
#ifdef HAVE_CG_RUNTIME_COMPILER
2011-12-03 01:26:56 +01:00
cgRTCgcInit();
#endif
2016-04-25 12:51:01 +02:00
cg->cgCtx = cgCreateContext();
2012-02-20 16:22:58 +01:00
2016-04-25 12:51:01 +02:00
if (!cg->cgCtx)
2011-05-22 17:02:09 +02:00
{
2016-01-08 20:46:33 +01:00
RARCH_ERR("Failed to create Cg context.\n");
2015-12-05 07:33:21 +01:00
goto error;
2011-05-22 17:02:09 +02:00
}
2012-04-21 23:25:32 +02:00
#ifdef RARCH_CG_DEBUG
2011-05-23 21:43:08 +02:00
cgGLSetDebugMode(CG_TRUE);
cgSetErrorHandler(cg_error_handler, NULL);
#endif
2016-04-25 12:51:01 +02:00
cg->cgFProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cg->cgVProf = cgGLGetLatestProfile(CG_GL_VERTEX);
if (
2016-04-25 12:51:01 +02:00
cg->cgFProf == CG_PROFILE_UNKNOWN ||
cg->cgVProf == CG_PROFILE_UNKNOWN)
2011-05-22 17:02:09 +02:00
{
2012-04-21 23:25:32 +02:00
RARCH_ERR("Invalid profile type\n");
goto error;
2011-05-22 17:02:09 +02:00
}
2016-04-25 12:51:01 +02:00
RARCH_LOG("[Cg]: Vertex profile: %s\n", cgGetProfileString(cg->cgVProf));
RARCH_LOG("[Cg]: Fragment profile: %s\n", cgGetProfileString(cg->cgFProf));
cgGLSetOptimalOptions(cg->cgFProf);
cgGLSetOptimalOptions(cg->cgVProf);
cgGLEnableProfile(cg->cgFProf);
cgGLEnableProfile(cg->cgVProf);
2011-05-22 17:02:09 +02:00
2016-04-25 12:51:01 +02:00
memset(cg->alias_define, 0, sizeof(cg->alias_define));
2014-05-23 15:19:32 +02:00
2016-01-20 06:16:55 +01:00
if (path && string_is_equal(path_get_extension(path), "cgp"))
2011-05-22 17:02:09 +02:00
{
2016-04-25 12:51:01 +02:00
if (!gl_cg_load_preset(cg, path))
goto error;
2011-05-22 17:02:09 +02:00
}
else
{
2016-04-25 12:51:01 +02:00
if (!gl_cg_load_plain(cg, path))
goto error;
2011-05-22 17:02:09 +02:00
}
2016-04-25 12:51:01 +02:00
cg->prg[0].mvp = cgGetNamedParameter(cg->prg[0].vprg, "IN.mvp_matrix");
2016-02-14 17:40:20 +01:00
2016-04-25 12:51:01 +02:00
for (i = 1; i <= cg->shader->passes; i++)
gl_cg_set_program_attributes(cg, i);
2011-05-23 21:04:25 +02:00
2014-09-08 17:57:18 +02:00
/* If we aren't using last pass non-FBO shader,
* this shader will be assumed to be "fixed-function".
*
* Just use prg[0] for that pass, which will be
* pass-through. */
2016-04-25 12:51:01 +02:00
cg->prg[cg->shader->passes + 1] = cg->prg[0];
2014-09-08 17:57:18 +02:00
/* No need to apply Android hack in Cg. */
2016-04-25 12:51:01 +02:00
cg->prg[VIDEO_SHADER_STOCK_BLEND] = cg->prg[0];
2016-04-25 12:51:01 +02:00
gl_cg_set_shaders(cg->prg[1].fprg, cg->prg[1].vprg);
2011-03-06 19:56:35 +01:00
2016-04-24 20:25:56 +02:00
shader_prog_info.combined = stock_xmb_simple;
shader_prog_info.is_file = false;
gl_cg_compile_program(
2016-04-25 12:51:01 +02:00
cg,
VIDEO_SHADER_MENU,
2016-04-25 12:51:01 +02:00
&cg->prg[VIDEO_SHADER_MENU],
&shader_prog_info);
gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU);
shader_prog_info.combined = stock_xmb_simple;
shader_prog_info.is_file = false;
gl_cg_compile_program(
2016-04-25 12:51:01 +02:00
cg,
VIDEO_SHADER_MENU_SEC,
2016-04-25 12:51:01 +02:00
&cg->prg[VIDEO_SHADER_MENU_SEC],
&shader_prog_info);
gl_cg_set_program_base_attrib(cg, VIDEO_SHADER_MENU_SEC);
2016-04-25 12:51:01 +02:00
gl_cg_reset_attrib(cg);
2016-04-25 12:51:01 +02:00
return cg;
error:
2016-04-25 12:51:01 +02:00
gl_cg_destroy_resources(cg);
if (!cg)
free(cg);
2015-12-05 07:33:21 +01:00
return NULL;
}
static void gl_cg_use(void *data, void *shader_data, unsigned idx, bool set_active)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)shader_data;
if (cg && cg->prg[idx].vprg && cg->prg[idx].fprg)
{
if (set_active)
{
2016-04-25 12:51:01 +02:00
gl_cg_reset_attrib(cg);
cg->active_idx = idx;
}
2011-11-12 18:31:22 +01:00
2016-04-25 12:51:01 +02:00
gl_cg_set_shaders(cg->prg[idx].fprg, cg->prg[idx].vprg);
}
}
2011-03-12 15:30:57 +01:00
2015-12-05 07:33:21 +01:00
static unsigned gl_cg_num(void *data)
2011-03-12 15:30:57 +01:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg)
return 0;
2016-04-25 12:51:01 +02:00
return cg->shader->passes;
2011-03-12 15:30:57 +01:00
}
2011-03-14 21:28:30 +01:00
2015-12-05 07:33:21 +01:00
static bool gl_cg_filter_type(void *data, unsigned idx, bool *smooth)
2011-03-14 21:28:30 +01:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (cg && idx &&
(cg->shader->pass[idx - 1].filter != RARCH_FILTER_UNSPEC)
)
2011-05-22 17:02:09 +02:00
{
2016-04-25 12:51:01 +02:00
*smooth = (cg->shader->pass[idx - 1].filter == RARCH_FILTER_LINEAR);
2011-05-22 17:02:09 +02:00
return true;
}
2014-08-27 03:28:22 +02:00
return false;
2011-03-14 21:28:30 +01:00
}
2015-12-05 07:33:21 +01:00
static enum gfx_wrap_type gl_cg_wrap_type(void *data, unsigned idx)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (cg && idx)
return cg->shader->pass[idx - 1].wrap;
2014-08-27 03:28:22 +02:00
return RARCH_WRAP_BORDER;
}
2015-12-05 07:33:21 +01:00
static void gl_cg_shader_scale(void *data, unsigned idx, struct gfx_fbo_scale *scale)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (cg && idx)
*scale = cg->shader->pass[idx - 1].fbo;
2011-05-22 17:02:09 +02:00
else
scale->valid = false;
}
2015-12-05 07:33:21 +01:00
static unsigned gl_cg_get_prev_textures(void *data)
{
2013-10-22 21:26:33 +02:00
unsigned i, j;
unsigned max_prev = 0;
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
2016-04-25 12:51:01 +02:00
if (!cg)
return 0;
2016-04-25 12:51:01 +02:00
for (i = 1; i <= cg->shader->passes; i++)
2013-10-22 21:26:33 +02:00
for (j = 0; j < PREV_TEXTURES; j++)
2016-04-25 12:51:01 +02:00
if (cg->prg[i].prev[j].tex)
2016-03-02 00:07:31 +01:00
max_prev = MAX(j + 1, max_prev);
return max_prev;
}
2015-12-05 07:33:21 +01:00
static bool gl_cg_get_feedback_pass(void *data, unsigned *pass)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg || cg->shader->feedback_pass < 0)
return false;
2016-04-25 12:51:01 +02:00
*pass = cg->shader->feedback_pass;
return true;
}
2015-12-05 07:33:21 +01:00
static bool gl_cg_mipmap_input(void *data, unsigned idx)
2014-05-11 13:13:38 +02:00
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (cg && idx)
return cg->shader->pass[idx - 1].mipmap;
2014-08-27 03:28:22 +02:00
return false;
2014-05-11 13:13:38 +02:00
}
2015-12-05 07:33:21 +01:00
static struct video_shader *gl_cg_get_current_shader(void *data)
{
2016-04-25 12:51:01 +02:00
cg_shader_data_t *cg = (cg_shader_data_t*)data;
if (!cg)
return NULL;
2016-04-25 12:51:01 +02:00
return cg->shader;
}
const shader_backend_t gl_cg_backend = {
gl_cg_init,
gl_cg_deinit,
gl_cg_set_params,
gl_cg_set_uniform_parameter,
2016-04-16 04:56:15 +02:00
gl_cg_compile_program,
gl_cg_use,
gl_cg_num,
gl_cg_filter_type,
gl_cg_wrap_type,
gl_cg_shader_scale,
gl_cg_set_coords,
gl_cg_set_mvp,
gl_cg_get_prev_textures,
gl_cg_get_feedback_pass,
2014-05-11 13:13:38 +02:00
gl_cg_mipmap_input,
gl_cg_get_current_shader,
RARCH_SHADER_CG,
2014-10-02 15:19:21 +02:00
"gl_cg"
};