Beispiel #1
0
/**
 * menu_shader_manager_set_preset:
 * @shader                   : Shader handle.   
 * @type                     : Type of shader.
 * @preset_path              : Preset path to load from.
 *
 * Sets shader preset.
 **/
void menu_shader_manager_set_preset(void *data,
      unsigned type, const char *preset_path)
{
#ifdef HAVE_SHADER_MANAGER
   struct video_shader *shader   = (struct video_shader*)data;
   config_file_t *conf           = NULL;
   bool refresh                  = false;
   settings_t *settings          = config_get_ptr();

   if (!video_driver_set_shader((enum rarch_shader_type)type, preset_path))
   {
      configuration_set_bool(settings, settings->bools.video_shader_enable, false);
      return;
   }

   /* Makes sure that we use Menu Preset shader on driver reinit.
    * Only do this when the cgp actually works to avoid potential errors. */
   strlcpy(settings->paths.path_shader,
         preset_path ? preset_path : "",
         sizeof(settings->paths.path_shader));
   configuration_set_bool(settings, settings->bools.video_shader_enable, true);

   if (!preset_path || !shader)
      return;

   /* Load stored Preset into menu on success. 
    * Used when a preset is directly loaded.
    * No point in updating when the Preset was 
    * created from the menu itself. */
   conf = config_file_new(preset_path);

   if (!conf)
      return;

   RARCH_LOG("Setting Menu shader: %s.\n", preset_path);

   if (video_shader_read_conf_cgp(conf, shader))
   {
      video_shader_resolve_relative(shader, preset_path);
      video_shader_resolve_parameters(conf, shader);
   }
   config_file_free(conf);

   menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
#endif
}
Beispiel #2
0
/**
 * menu_shader_manager_set_preset:
 * @shader                   : Shader handle.   
 * @type                     : Type of shader.
 * @preset_path              : Preset path to load from.
 *
 * Sets shader preset.
 **/
void menu_shader_manager_set_preset(struct video_shader *shader,
      unsigned type, const char *preset_path)
{
#ifdef HAVE_SHADER_MANAGER
   config_file_t *conf         = NULL;
   settings_t *settings        = config_get_ptr();

   settings->video.shader_enable = false;

   if (!video_driver_set_shader((enum rarch_shader_type)type, preset_path))
      return;

   /* Makes sure that we use Menu Preset shader on driver reinit.
    * Only do this when the cgp actually works to avoid potential errors. */
   strlcpy(settings->video.shader_path, preset_path ? preset_path : "",
         sizeof(settings->video.shader_path));
   settings->video.shader_enable = true;

   if (!preset_path)
      return;
   if (!shader)
      return;

   /* Load stored Preset into menu on success. 
    * Used when a preset is directly loaded.
    * No point in updating when the Preset was 
    * created from the menu itself. */
   conf = config_file_new(preset_path);

   if (!conf)
      return;

   RARCH_LOG("Setting Menu shader: %s.\n", preset_path ? preset_path : "N/A (stock)");

   if (video_shader_read_conf_cgp(conf, shader))
   {
      video_shader_resolve_relative(shader, preset_path);
      video_shader_resolve_parameters(conf, shader);
   }
   config_file_free(conf);

   menu_entries_set_refresh(false);
#endif
}
Beispiel #3
0
static bool gl_cg_load_preset(void *data, const char *path)
{
   unsigned i;
   config_file_t *conf = NULL;
   cg_shader_data_t *cg_data = (cg_shader_data_t*)data;

   if (!gl_cg_load_stock(cg_data))
      return false;

   RARCH_LOG("Loading Cg meta-shader: %s\n", path);
   conf = config_file_new(path);
   if (!conf)
   {
      RARCH_ERR("Failed to load preset.\n");
      return false;
   }

   cg_data->shader = (struct video_shader*)calloc(1, sizeof(*cg_data->shader));
   if (!cg_data->shader)
   {
      config_file_free(conf);
      return false;
   }

   if (!video_shader_read_conf_cgp(conf, cg_data->shader))
   {
      RARCH_ERR("Failed to parse CGP file.\n");
      config_file_free(conf);
      return false;
   }

   video_shader_resolve_relative(cg_data->shader, path);
   video_shader_resolve_parameters(conf, cg_data->shader);
   config_file_free(conf);

   if (cg_data->shader->passes > GFX_MAX_SHADERS - 3)
   {
      RARCH_WARN("Too many shaders ... Capping shader amount to %d.\n",
            GFX_MAX_SHADERS - 3);
      cg_data->shader->passes = GFX_MAX_SHADERS - 3;
   }

   for (i = 0; i < cg_data->shader->passes; i++)
      if (*cg_data->shader->pass[i].alias)
         snprintf(cg_data->cg_alias_define[i],
               sizeof(cg_data->cg_alias_define[i]),
               "-D%s_ALIAS",
               cg_data->shader->pass[i].alias);

   for (i = 0; i < cg_data->shader->passes; i++)
   {
      if (!gl_cg_load_shader(cg_data, i))
      {
         RARCH_ERR("Failed to load shaders ...\n");
         return false;
      }
   }

   if (!gl_load_luts(cg_data->shader, cg_data->lut_textures))
   {
      RARCH_ERR("Failed to load lookup textures ...\n");
      return false;
   }

   if (!gl_cg_load_imports(cg_data))
   {
      RARCH_ERR("Failed to load imports ...\n");
      return false;
   }

   return true;
}
Beispiel #4
0
static bool d3d_init_multipass(d3d_video_t *d3d)
{
   unsigned i;
   bool use_extra_pass;
   video_shader_pass *pass = NULL;
   config_file_t *conf     = config_file_new(d3d->shader_path.c_str());

   if (!conf)
   {
      RARCH_ERR("Failed to load preset.\n");
      return false;
   }

   memset(&d3d->shader, 0, sizeof(d3d->shader));

   if (!video_shader_read_conf_cgp(conf, &d3d->shader))
   {
      config_file_free(conf);
      RARCH_ERR("Failed to parse CGP file.\n");
      return false;
   }

   config_file_free(conf);

   video_shader_resolve_relative(&d3d->shader, d3d->shader_path.c_str());

   RARCH_LOG("[D3D9 Meta-Cg] Found %u shaders.\n", d3d->shader.passes);

   for (i = 0; i < d3d->shader.passes; i++)
   {
      if (d3d->shader.pass[i].fbo.valid)
         continue;

      d3d->shader.pass[i].fbo.scale_y = 1.0f;
      d3d->shader.pass[i].fbo.scale_x = 1.0f;
      d3d->shader.pass[i].fbo.type_x  = RARCH_SCALE_INPUT;
      d3d->shader.pass[i].fbo.type_y  = RARCH_SCALE_INPUT;
   }

   use_extra_pass       = d3d->shader.passes < GFX_MAX_SHADERS &&
      d3d->shader.pass[d3d->shader.passes - 1].fbo.valid;

   if (use_extra_pass)
   {
      d3d->shader.passes++;
      pass              = (video_shader_pass*)
         &d3d->shader.pass[d3d->shader.passes - 1];

      pass->fbo.scale_x = pass->fbo.scale_y = 1.0f;
      pass->fbo.type_x  = pass->fbo.type_y = RARCH_SCALE_VIEWPORT;
      pass->filter      = RARCH_FILTER_UNSPEC;
   }
   else
   {
      pass              = (video_shader_pass*)
         &d3d->shader.pass[d3d->shader.passes - 1];

      pass->fbo.scale_x = pass->fbo.scale_y = 1.0f;
      pass->fbo.type_x  = pass->fbo.type_y = RARCH_SCALE_VIEWPORT;
   }

   return true;
}
Beispiel #5
0
static void *gl_glsl_init(void *data, const char *path)
{
   unsigned i;
   struct shader_program_info shader_prog_info;
   bool shader_support        = false;
#ifdef GLSL_DEBUG
   char *error_string         = NULL;
#endif
   config_file_t *conf        = NULL;
   const char *stock_vertex   = NULL;
   const char *stock_fragment = NULL;
   glsl_shader_data_t   *glsl = (glsl_shader_data_t*)
      calloc(1, sizeof(glsl_shader_data_t));

   if (!glsl)
      return NULL;

   (void)shader_support;

#ifndef HAVE_OPENGLES
   RARCH_LOG("[GLSL]: Checking GLSL shader support ...\n");
   shader_support = glCreateProgram && glUseProgram && glCreateShader
      && glDeleteShader && glShaderSource && glCompileShader && glAttachShader
      && glDetachShader && glLinkProgram && glGetUniformLocation
      && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv
      && glUniformMatrix4fv
      && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv
      && glGetProgramInfoLog
      && glDeleteProgram && glGetAttachedShaders
      && glGetAttribLocation && glEnableVertexAttribArray
      && glDisableVertexAttribArray
      && glVertexAttribPointer
      && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer;

   if (!shader_support)
   {
      RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n");
      goto error;
   }
#endif

   glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader));
   if (!glsl->shader)
      goto error;

   if (!string_is_empty(path))
   {
      bool ret             = false;
      const char *path_ext = path_get_extension(path);

      if (string_is_equal_fast(path_ext, "glslp", 5))
      {
         conf = config_file_new(path);
         if (conf)
         {
            ret = video_shader_read_conf_cgp(conf, glsl->shader);
            glsl->shader->modern = true;
         }
      }
      else if (string_is_equal_fast(path_ext, "glsl", 4))
      {
         strlcpy(glsl->shader->pass[0].source.path, path,
               sizeof(glsl->shader->pass[0].source.path));
         glsl->shader->passes = 1;
         glsl->shader->modern = true;
         ret = true;
      }

      if (!ret)
      {
         RARCH_ERR("[GL]: Failed to parse GLSL shader.\n");
         goto error;
      }
   }
   else
   {
      RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n");
      glsl->shader->passes = 1;
      glsl->shader->pass[0].source.string.vertex   =
         strdup(glsl_core ? stock_vertex_core : stock_vertex_modern);
      glsl->shader->pass[0].source.string.fragment =
         strdup(glsl_core ? stock_fragment_core : stock_fragment_modern);
      glsl->shader->modern = true;
   }

   if (!string_is_empty(path))
      video_shader_resolve_relative(glsl->shader, path);
   video_shader_resolve_parameters(conf, glsl->shader);

   if (conf)
   {
      config_file_free(conf);
      conf = NULL;
   }

   stock_vertex = (glsl->shader->modern) ?
      stock_vertex_modern : stock_vertex_legacy;
   stock_fragment = (glsl->shader->modern) ?
      stock_fragment_modern : stock_fragment_legacy;

   if (glsl_core)
   {
      stock_vertex = stock_vertex_core;
      stock_fragment = stock_fragment_core;
   }

#ifdef HAVE_OPENGLES
   if (!glsl->shader->modern)
   {
      RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n");
      goto error;
   }
#else
   if (glsl_core && !glsl->shader->modern)
   {
      RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n");
      goto error;
   }
#endif

   /* Find all aliases we use in our GLSLP and add #defines for them so
    * that a shader can choose a fallback if we are not using a preset. */
   *glsl->alias_define = '\0';
   for (i = 0; i < glsl->shader->passes; i++)
   {
      if (*glsl->shader->pass[i].alias)
      {
         char define[128];

         define[0] = '\0';

         snprintf(define, sizeof(define), "#define %s_ALIAS\n",
               glsl->shader->pass[i].alias);
         strlcat(glsl->alias_define, define, sizeof(glsl->alias_define));
      }
   }

   shader_prog_info.vertex   = stock_vertex;
   shader_prog_info.fragment = stock_fragment;
   shader_prog_info.is_file  = false;

   if (!gl_glsl_compile_program(glsl, 0, &glsl->prg[0], &shader_prog_info))
   {
      RARCH_ERR("GLSL stock programs failed to compile.\n");
      goto error;
   }

   if (!gl_glsl_compile_programs(glsl, &glsl->prg[1]))
      goto error;

   if (!gl_load_luts(glsl->shader, glsl->lut_textures))
   {
      RARCH_ERR("[GL]: Failed to load LUTs.\n");
      goto error;
   }

   for (i = 0; i <= glsl->shader->passes; i++)
      gl_glsl_find_uniforms(glsl, i, glsl->prg[i].id, &glsl->uniforms[i]);

#ifdef GLSL_DEBUG
   if (!gl_check_error(&error_string))
   {
      RARCH_ERR("%s\n", error_string);
      free(error_string);
      RARCH_WARN("Detected GL error in GLSL.\n");
   }
#endif

   if (glsl->shader->variables)
   {
      retro_ctx_memory_info_t mem_info;
      struct state_tracker_info info;

      mem_info.id         = RETRO_MEMORY_SYSTEM_RAM;

      core_get_memory(&mem_info);

      info.wram           = (uint8_t*)mem_info.data;
      info.info           = glsl->shader->variable;
      info.info_elem      = glsl->shader->variables;

      info.script         = NULL;
      info.script_class   = NULL;
#ifdef HAVE_PYTHON
      info.script         = glsl->shader->script;
      if (*glsl->shader->script_class)
         info.script_class= glsl->shader->script_class;
#endif
      info.script_is_file = NULL;

      glsl->state_tracker = state_tracker_init(&info);

      if (!glsl->state_tracker)
         RARCH_WARN("Failed to init state tracker.\n");
   }

   glsl->prg[glsl->shader->passes  + 1]     = glsl->prg[0];
   glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0];

   if (glsl->shader->modern)
   {
      shader_prog_info.vertex   =
            glsl_core ?
            stock_vertex_core_blend : stock_vertex_modern_blend;
      shader_prog_info.fragment =
            glsl_core ?
            stock_fragment_core_blend : stock_fragment_modern_blend;
      shader_prog_info.is_file  = false;

      gl_glsl_compile_program(
            glsl,
            VIDEO_SHADER_STOCK_BLEND,
            &glsl->prg[VIDEO_SHADER_STOCK_BLEND],
            &shader_prog_info
            );

      gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_STOCK_BLEND].id,
            &glsl->uniforms[VIDEO_SHADER_STOCK_BLEND]);
   }
   else
   {
      glsl->prg[VIDEO_SHADER_STOCK_BLEND] = glsl->prg[0];
      glsl->uniforms[VIDEO_SHADER_STOCK_BLEND] = glsl->uniforms[0];
   }

#ifdef HAVE_SHADERPIPELINE
#ifdef HAVE_OPENGLES
   if (gl_query_extension("GL_OES_standard_derivatives"))
   {
      shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy;
      shader_prog_info.fragment = stock_fragment_xmb;
   }
   else
   {
      shader_prog_info.vertex   = stock_vertex_xmb_ribbon_simple_legacy;
      shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple;
   }
#else
      shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_ribbon_modern : stock_vertex_xmb_ribbon_legacy;
      shader_prog_info.fragment = stock_fragment_xmb;
#endif
   shader_prog_info.is_file  = false;

   gl_glsl_compile_program(
         glsl,
         VIDEO_SHADER_MENU,
         &glsl->prg[VIDEO_SHADER_MENU],
         &shader_prog_info);
   gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU].id,
         &glsl->uniforms[VIDEO_SHADER_MENU]);

   shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_simple_modern : stock_vertex_xmb_ribbon_simple_legacy;
   shader_prog_info.fragment = stock_fragment_xmb_ribbon_simple;

   gl_glsl_compile_program(
         glsl,
         VIDEO_SHADER_MENU_2,
         &glsl->prg[VIDEO_SHADER_MENU_2],
         &shader_prog_info);
   gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_2].id,
         &glsl->uniforms[VIDEO_SHADER_MENU_2]);

#if defined(HAVE_OPENGLES)
   shader_prog_info.vertex   = stock_vertex_xmb_snow_modern;
#else
   shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy;
#endif
   shader_prog_info.fragment = stock_fragment_xmb_simple_snow;

   gl_glsl_compile_program(
         glsl,
         VIDEO_SHADER_MENU_3,
         &glsl->prg[VIDEO_SHADER_MENU_3],
         &shader_prog_info);
   gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_3].id,
         &glsl->uniforms[VIDEO_SHADER_MENU_3]);

#if defined(HAVE_OPENGLES)
   shader_prog_info.vertex   = stock_vertex_xmb_snow_modern;
#else
   shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy;
#endif
   shader_prog_info.fragment = stock_fragment_xmb_snow;

   gl_glsl_compile_program(
         glsl,
         VIDEO_SHADER_MENU_4,
         &glsl->prg[VIDEO_SHADER_MENU_4],
         &shader_prog_info);
   gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_4].id,
         &glsl->uniforms[VIDEO_SHADER_MENU_4]);

#if defined(HAVE_OPENGLES)
   shader_prog_info.vertex   = stock_vertex_xmb_snow_modern;
#else
   shader_prog_info.vertex   = glsl_core ? stock_vertex_xmb_snow_modern : stock_vertex_xmb_snow_legacy;
#endif
   shader_prog_info.fragment = stock_fragment_xmb_bokeh;

   gl_glsl_compile_program(
         glsl,
         VIDEO_SHADER_MENU_5,
         &glsl->prg[VIDEO_SHADER_MENU_5],
         &shader_prog_info);
   gl_glsl_find_uniforms(glsl, 0, glsl->prg[VIDEO_SHADER_MENU_5].id,
         &glsl->uniforms[VIDEO_SHADER_MENU_5]);
#endif

   gl_glsl_reset_attrib(glsl);

   for (i = 0; i < GFX_MAX_SHADERS; i++)
   {
      glGenBuffers(1, &glsl->vbo[i].vbo_primary);
      glGenBuffers(1, &glsl->vbo[i].vbo_secondary);
   }

   return glsl;

error:
   gl_glsl_destroy_resources(glsl);

   if (conf)
      config_file_free(conf);
   if (glsl)
      free(glsl);

   return NULL;
}
Beispiel #6
0
/**
 * menu_shader_manager_init:
 *
 * Initializes shader manager.
 **/
void menu_shader_manager_init(menu_handle_t *menu)
{
#ifdef HAVE_SHADER_MANAGER
   uint32_t ext_hash;
   char preset_path[PATH_MAX_LENGTH];
   const char *ext             = NULL;
   struct video_shader *shader = NULL;
   config_file_t *conf         = NULL;
   const char *config_path     = NULL;
   settings_t *settings        = config_get_ptr();
   global_t   *global          = global_get_ptr();

   if (!menu)
      return;

   shader = (struct video_shader*)menu->shader;

   if (*global->path.core_specific_config
         && settings->core_specific_config)
      config_path = global->path.core_specific_config;
   else if (*global->path.config)
      config_path = global->path.config;

   /* In a multi-config setting, we can't have
    * conflicts on menu.cgp/menu.glslp. */
   if (config_path)
   {
      fill_pathname_base(menu->default_glslp, config_path,
            sizeof(menu->default_glslp));
      path_remove_extension(menu->default_glslp);
      strlcat(menu->default_glslp, ".glslp", sizeof(menu->default_glslp));
      fill_pathname_base(menu->default_cgp, config_path,
            sizeof(menu->default_cgp));
      path_remove_extension(menu->default_cgp);
      strlcat(menu->default_cgp, ".cgp", sizeof(menu->default_cgp));
   }
   else
   {
      strlcpy(menu->default_glslp, "menu.glslp", sizeof(menu->default_glslp));
      strlcpy(menu->default_cgp, "menu.cgp", sizeof(menu->default_cgp));
   }

   ext = path_get_extension(settings->video.shader_path);
   ext_hash = menu_hash_calculate(ext);

   switch (ext_hash)
   {
      case MENU_VALUE_GLSLP:
      case MENU_VALUE_CGP:
         conf = config_file_new(settings->video.shader_path);
         if (conf)
         {
            if (video_shader_read_conf_cgp(conf, shader))
            {
               video_shader_resolve_relative(shader, settings->video.shader_path);
               video_shader_resolve_parameters(conf, shader);
            }
            config_file_free(conf);
         }
         break;
      case MENU_VALUE_GLSL:
      case MENU_VALUE_CG:
         strlcpy(shader->pass[0].source.path, settings->video.shader_path,
               sizeof(shader->pass[0].source.path));
         shader->passes = 1;
         break;
      default:
         {
            const char *shader_dir = *settings->video.shader_dir ?
               settings->video.shader_dir : settings->system_directory;

            fill_pathname_join(preset_path, shader_dir, "menu.glslp", sizeof(preset_path));
            conf = config_file_new(preset_path);

            if (!conf)
            {
               fill_pathname_join(preset_path, shader_dir, "menu.cgp", sizeof(preset_path));
               conf = config_file_new(preset_path);
            }

            if (conf)
            {
               if (video_shader_read_conf_cgp(conf, shader))
               {
                  video_shader_resolve_relative(shader, preset_path);
                  video_shader_resolve_parameters(conf, shader);
               }
               config_file_free(conf);
            }
         }
         break;
   }
#endif
}
Beispiel #7
0
/**
 * menu_shader_manager_init:
 *
 * Initializes shader manager.
 **/
void menu_shader_manager_init(void)
{
#ifdef HAVE_SHADER_MANAGER
   struct video_shader *shader = NULL;
   config_file_t *conf         = NULL;
   settings_t *settings        = config_get_ptr();
   const char *config_path     = path_get(RARCH_PATH_CONFIG);

   menu_driver_ctl(RARCH_MENU_CTL_SHADER_GET,
         &shader);

   /* In a multi-config setting, we can't have
    * conflicts on menu.cgp/menu.glslp. */
   if (config_path)
   {
      fill_pathname_base_ext(default_glslp, config_path,
            file_path_str(FILE_PATH_GLSLP_EXTENSION),
            sizeof(default_glslp));

      fill_pathname_base_ext(default_cgp, config_path,
            file_path_str(FILE_PATH_CGP_EXTENSION),
            sizeof(default_cgp));

      fill_pathname_base_ext(default_slangp, config_path,
            file_path_str(FILE_PATH_SLANGP_EXTENSION),
            sizeof(default_slangp));
   }
   else
   {
      strlcpy(default_glslp, "menu.glslp",
            sizeof(default_glslp));
      strlcpy(default_cgp, "menu.cgp",
            sizeof(default_cgp));
      strlcpy(default_slangp, "menu.slangp",
            sizeof(default_slangp));
   }

   switch (msg_hash_to_file_type(msg_hash_calculate(
               path_get_extension(settings->path.shader))))
   {
      case FILE_TYPE_SHADER_PRESET_GLSLP:
      case FILE_TYPE_SHADER_PRESET_CGP:
      case FILE_TYPE_SHADER_PRESET_SLANGP:
         conf = config_file_new(settings->path.shader);
         if (conf)
         {
            if (video_shader_read_conf_cgp(conf, shader))
            {
               video_shader_resolve_relative(shader,
                     settings->path.shader);
               video_shader_resolve_parameters(conf, shader);
            }
            config_file_free(conf);
         }
         break;
      case FILE_TYPE_SHADER_GLSL:
      case FILE_TYPE_SHADER_CG:
      case FILE_TYPE_SHADER_SLANG:
         strlcpy(shader->pass[0].source.path, settings->path.shader,
               sizeof(shader->pass[0].source.path));
         shader->passes = 1;
         break;
      default:
         {
            char preset_path[PATH_MAX_LENGTH];
            const char *shader_dir            = 
               *settings->directory.video_shader ?
               settings->directory.video_shader : settings->directory.system;

            preset_path[0] = '\0';

            fill_pathname_join(preset_path, shader_dir,
                  "menu.glslp", sizeof(preset_path));
            conf = config_file_new(preset_path);

            if (!conf)
            {
               fill_pathname_join(preset_path, shader_dir,
                     "menu.cgp", sizeof(preset_path));
               conf = config_file_new(preset_path);
            }

            if (!conf)
            {
               fill_pathname_join(preset_path, shader_dir,
                     "menu.slangp", sizeof(preset_path));
               conf = config_file_new(preset_path);
            }

            if (conf)
            {
               if (video_shader_read_conf_cgp(conf, shader))
               {
                  video_shader_resolve_relative(shader, preset_path);
                  video_shader_resolve_parameters(conf, shader);
               }
               config_file_free(conf);
            }
         }
         break;
   }
#endif
}
Beispiel #8
0
static bool gl_glsl_init(void *data, const char *path)
{
    unsigned i;
    config_file_t *conf        = NULL;
    glsl_shader_data_t *glsl   = NULL;
    const char *stock_vertex   = NULL;
    const char *stock_fragment = NULL;
    driver_t *driver           = driver_get_ptr();

    (void)data;

    glsl = (glsl_shader_data_t*)calloc(1, sizeof(glsl_shader_data_t));

    if (!glsl)
        return false;

#ifndef HAVE_OPENGLES2
    RARCH_LOG("Checking GLSL shader support ...\n");
    bool shader_support = glCreateProgram && glUseProgram && glCreateShader
                          && glDeleteShader && glShaderSource && glCompileShader && glAttachShader
                          && glDetachShader && glLinkProgram && glGetUniformLocation
                          && glUniform1i && glUniform1f && glUniform2fv && glUniform4fv
                          && glUniformMatrix4fv
                          && glGetShaderiv && glGetShaderInfoLog && glGetProgramiv
                          && glGetProgramInfoLog
                          && glDeleteProgram && glGetAttachedShaders
                          && glGetAttribLocation && glEnableVertexAttribArray
                          && glDisableVertexAttribArray
                          && glVertexAttribPointer
                          && glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer;

    if (!shader_support)
    {
        RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n");
        free(glsl);
        return false;
    }
#endif

    glsl->shader = (struct video_shader*)calloc(1, sizeof(*glsl->shader));
    if (!glsl->shader)
    {
        free(glsl);
        return false;
    }

    if (path)
    {
        bool ret;
        const char *path_ext = path_get_extension(path);

        if (!strcmp(path_ext, "glsl"))
        {
            strlcpy(glsl->shader->pass[0].source.path, path,
                    sizeof(glsl->shader->pass[0].source.path));
            glsl->shader->passes = 1;
            glsl->shader->modern = true;
            ret = true;
        }
        else if (!strcmp(path_ext, "glslp"))
        {
            conf = config_file_new(path);
            if (conf)
            {
                ret = video_shader_read_conf_cgp(conf, glsl->shader);
                glsl->shader->modern = true;
            }
            else
                ret = false;
        }
        else
            ret = false;

        if (!ret)
        {
            RARCH_ERR("[GL]: Failed to parse GLSL shader.\n");
            free(glsl->shader);
            free(glsl);
            return false;
        }
    }
    else
    {
        RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n");
        glsl->shader->passes = 1;
        glsl->shader->pass[0].source.string.vertex   =
            strdup(glsl_core ? stock_vertex_core : stock_vertex_modern);
        glsl->shader->pass[0].source.string.fragment =
            strdup(glsl_core ? stock_fragment_core : stock_fragment_modern);
        glsl->shader->modern = true;
    }

    video_shader_resolve_relative(glsl->shader, path);
    video_shader_resolve_parameters(conf, glsl->shader);

    if (conf)
    {
        config_file_free(conf);
        conf = NULL;
    }

    stock_vertex = (glsl->shader->modern) ?
                   stock_vertex_modern : stock_vertex_legacy;
    stock_fragment = (glsl->shader->modern) ?
                     stock_fragment_modern : stock_fragment_legacy;

    if (glsl_core)
    {
        stock_vertex = stock_vertex_core;
        stock_fragment = stock_fragment_core;
    }

#ifdef HAVE_OPENGLES2
    if (!glsl->shader->modern)
    {
        RARCH_ERR("[GL]: GLES context is used, but shader is not modern. Cannot use it.\n");
        goto error;
    }
#else
    if (glsl_core && !glsl->shader->modern)
    {
        RARCH_ERR("[GL]: GL core context is used, but shader is not core compatible. Cannot use it.\n");
        goto error;
    }
#endif

    /* Find all aliases we use in our GLSLP and add #defines for them so
     * that a shader can choose a fallback if we are not using a preset. */
    *glsl->glsl_alias_define = '\0';
    for (i = 0; i < glsl->shader->passes; i++)
    {
        if (*glsl->shader->pass[i].alias)
        {
            char define[128] = {0};

            snprintf(define, sizeof(define), "#define %s_ALIAS\n",
                     glsl->shader->pass[i].alias);
            strlcat(glsl->glsl_alias_define, define, sizeof(glsl->glsl_alias_define));
        }
    }

    if (!(glsl->gl_program[0] = compile_program(glsl, stock_vertex, stock_fragment, 0)))
    {
        RARCH_ERR("GLSL stock programs failed to compile.\n");
        goto error;
    }

    if (!compile_programs(glsl, &glsl->gl_program[1]))
        goto error;

    if (!gl_load_luts(glsl->shader, glsl->gl_teximage))
    {
        RARCH_ERR("[GL]: Failed to load LUTs.\n");
        goto error;
    }

    for (i = 0; i <= glsl->shader->passes; i++)
        find_uniforms(glsl, i, glsl->gl_program[i], &glsl->gl_uniforms[i]);

#ifdef GLSL_DEBUG
    if (!gl_check_error())
        RARCH_WARN("Detected GL error in GLSL.\n");
#endif

    if (glsl->shader->variables)
    {
        struct state_tracker_info info = {0};

        info.wram      = (uint8_t*)pretro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM);
        info.info      = glsl->shader->variable;
        info.info_elem = glsl->shader->variables;

#ifdef HAVE_PYTHON
        info.script = glsl->shader->script;
        info.script_class = *glsl->shader->script_class ?
                            glsl->shader->script_class : NULL;
#endif

        glsl->gl_state_tracker = state_tracker_init(&info);
        if (!glsl->gl_state_tracker)
            RARCH_WARN("Failed to init state tracker.\n");
    }

    glsl->gl_program[glsl->shader->passes  + 1] = glsl->gl_program[0];
    glsl->gl_uniforms[glsl->shader->passes + 1] = glsl->gl_uniforms[0];

    if (glsl->shader->modern)
    {
        glsl->gl_program[GL_SHADER_STOCK_BLEND] = compile_program(
                    glsl,
                    glsl_core ?
                    stock_vertex_core_blend : stock_vertex_modern_blend,
                    glsl_core ?
                    stock_fragment_core_blend : stock_fragment_modern_blend,
                    GL_SHADER_STOCK_BLEND);
        find_uniforms(glsl, 0, glsl->gl_program[GL_SHADER_STOCK_BLEND],
                      &glsl->gl_uniforms[GL_SHADER_STOCK_BLEND]);
    }
    else
    {
        glsl->gl_program [GL_SHADER_STOCK_BLEND] = glsl->gl_program[0];
        glsl->gl_uniforms[GL_SHADER_STOCK_BLEND] = glsl->gl_uniforms[0];
    }

    gl_glsl_reset_attrib(glsl);

    for (i = 0; i < GFX_MAX_SHADERS; i++)
    {
        glGenBuffers(1, &glsl->glsl_vbo[i].vbo_primary);
        glGenBuffers(1, &glsl->glsl_vbo[i].vbo_secondary);
    }

    driver->video_shader_data = glsl;

    return true;

error:
    gl_glsl_destroy_resources(glsl);

    if (glsl)
        free(glsl);

    return false;
}