Example #1
0
bool retro_load_game(const struct retro_game_info *info)
{
   retro_variable var;

   if (!info)
      return false;

   strcpy(retro_path_info, info->path);
   if (strstr(info->path, ".obj") || strstr(info->path, ".mtl"))
      engine_program_cb = &engine_program_modelviewer;
   else
      engine_program_cb = &engine_program_instancingviewer;

   update_variables();

   var.key = "3dengine-sensor-enable";
   var.value = NULL;

   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
   {

      if (!strcmp(var.value, "enabled"))
      {
         if (sensor_initialized)
            return true;

         log_cb(RETRO_LOG_INFO, "Sensor interface found, enabling...\n");
         if (sensor_cb.set_sensor_state)
         {
            sensor_cb.set_sensor_state(0, RETRO_SENSOR_ACCELEROMETER_ENABLE, FPS);
            sensor_enable = true;
         }

         sensor_initialized = true;
      }
      if (!strcmp(var.value, "disabled"))
      {
         if (sensor_initialized)
            return true;

         log_cb(RETRO_LOG_INFO, "Sensor interface found, disabling...\n");
         if (sensor_cb.set_sensor_state)
         {
            sensor_cb.set_sensor_state(0, RETRO_SENSOR_ACCELEROMETER_DISABLE, FPS);
            sensor_enable = false;
         }
      }
   }

   var.key = "3dengine-location-enable";
   var.value = NULL;

   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
   {
      if (!strcmp(var.value, "enabled"))
      {
         location_enable = true;
         location_cb.initialized = location_initialized;
         location_cb.deinitialized = location_deinitialized;
         environ_cb(RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE, &location_cb);
      }
   }

   memset(&camera_cb, 0, sizeof(camera_cb));

   enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
   if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
   {
      if (log_cb)
         log_cb(RETRO_LOG_ERROR, "XRGB8888 is not supported.\n");
      return false;
   }

   var.key = "3dengine-camera-enable";
   var.value = NULL;

   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
   {
      if (!strcmp(var.value, "enabled"))
      {
         camera_enable = true;
         var.key = "3dengine-camera-type";
         var.value = NULL;

         if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
         {
            if (!strcmp(var.value, "texture"))
            {
               camera_cb.caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE);
               camera_cb.frame_opengl_texture = camera_gl_callback;
            }
            else
            {
               camera_cb.caps = (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER);
               camera_cb.frame_raw_framebuffer = camera_raw_fb_callback;
            }
         }

         camera_cb.initialized = camera_initialized;

         if (camera_enable && !environ_cb(RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, &camera_cb))
         {
            if (log_cb)
               log_cb(RETRO_LOG_ERROR, "camera is not supported.\n");
            return false;
         }
      }
   }

#ifdef HAVE_OPENGLES
   hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2;
#else
   hw_render.context_type = RETRO_HW_CONTEXT_OPENGL;
#endif
   hw_render.context_reset = context_reset;
   hw_render.depth = true;
   if (!camera_enable)
      hw_render.bottom_left_origin = true;
   if (!environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &hw_render))
      return false;

#ifdef HAVE_OPENGLES
   if (camera_enable && camera_cb.caps & (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER) && !gl_query_extension("BGRA8888"))
   {
      if (log_cb)
         log_cb(RETRO_LOG_ERROR, "no BGRA8888 support for raw framebuffer, exiting...\n");
      return false;
   }
   support_unpack_row_length = gl_query_extension("GL_EXT_unpack_subimage");
#else
   support_unpack_row_length = true;
#endif

   if (log_cb)
      log_cb(RETRO_LOG_INFO, "Loaded game!\n");


   if (engine_program_cb && engine_program_cb->load_game)
      engine_program_cb->load_game(info);

   return true;
}
Example #2
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;
}
Example #3
0
bool gl_check_capability(enum gl_capability_enum enum_idx)
{
   unsigned major       = 0;
   unsigned minor       = 0;
   const char *vendor   = (const char*)glGetString(GL_VENDOR);
   const char *renderer = (const char*)glGetString(GL_RENDERER);
   const char *version  = (const char*)glGetString(GL_VERSION);
#ifdef HAVE_OPENGLES
   if (version && sscanf(version, "OpenGL ES %u.%u", &major, &minor) != 2)
#else
   if (version && sscanf(version, "%u.%u", &major, &minor) != 2)
#endif
      major = minor = 0;

   (void)vendor;

   switch (enum_idx)
   {
      case GL_CAPS_GLES3_SUPPORTED:
#if defined(HAVE_OPENGLES)
         if (major >= 3)
            return true;
#endif
         break;
      case GL_CAPS_EGLIMAGE:
#if defined(HAVE_EGL) && defined(HAVE_OPENGLES)
         if (glEGLImageTargetTexture2DOES != NULL)
            return true;
#endif
         break;
      case GL_CAPS_SYNC:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;
#else
         if (gl_query_extension("ARB_sync") &&
               glFenceSync && glDeleteSync && glClientWaitSync)
            return true;
#endif
         break;
      case GL_CAPS_MIPMAP:
         {
            static bool extension_queried = false;
            static bool extension         = false;

            if (!extension_queried)
            {
               extension         = gl_query_extension("ARB_framebuffer_object");
               extension_queried = true;
            }

            if (extension)
               return true;
         }
         break;
      case GL_CAPS_VAO:
#ifndef HAVE_OPENGLES
         if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_vertex_array_object"))
            return false;

         if (glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays)
            return true;
#endif
         break;
      case GL_CAPS_FBO:
#if defined(HAVE_PSGL) || defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES3) || defined(HAVE_OPENGLES_3_1) || defined(HAVE_OPENGLES_3_2)
         return true;
#elif defined(HAVE_FBO)
         if (!gl_query_core_context_in_use() && !gl_query_extension("ARB_framebuffer_object")
               && !gl_query_extension("EXT_framebuffer_object"))
            return false;

         if (glGenFramebuffers
               && glBindFramebuffer
               && glFramebufferTexture2D
               && glCheckFramebufferStatus
               && glDeleteFramebuffers
               && glGenRenderbuffers
               && glBindRenderbuffer
               && glFramebufferRenderbuffer
               && glRenderbufferStorage
               && glDeleteRenderbuffers)
            return true;
         break;
#else
         break;
#endif
      case GL_CAPS_ARGB8:
#ifdef HAVE_OPENGLES
         if (gl_query_extension("OES_rgb8_rgba8")
               || gl_query_extension("ARM_argb8"))
            return true;
#else
         /* TODO/FIXME - implement this for non-GLES? */
#endif
         break;
      case GL_CAPS_DEBUG:
         if (gl_query_extension("KHR_debug"))
            return true;
#ifndef HAVE_OPENGLES
         if (gl_query_extension("ARB_debug_output"))
            return true;
#endif
         break;
      case GL_CAPS_PACKED_DEPTH_STENCIL:
         {
            struct retro_hw_render_callback *hwr =
               video_driver_get_hw_context();
            if (major >= 3)
               return true;
            if (hwr->stencil
                  && !gl_query_extension("OES_packed_depth_stencil")
                  && !gl_query_extension("EXT_packed_depth_stencil"))
               return false;
         }
         return true;
      case GL_CAPS_ES2_COMPAT:
#ifndef HAVE_OPENGLES
         /* ATI card detected, skipping check for GL_RGB565 support... */
         if (vendor && renderer && (strstr(vendor, "ATI") || strstr(renderer, "ATI")))
            return false;

         if (gl_query_extension("ARB_ES2_compatibility"))
            return true;
#endif
         break;
      case GL_CAPS_UNPACK_ROW_LENGTH:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;

         /* Extension GL_EXT_unpack_subimage, can copy textures faster
          * than using UNPACK_ROW_LENGTH */
         if (gl_query_extension("GL_EXT_unpack_subimage"))
            return true;
#endif
         break;
      case GL_CAPS_FULL_NPOT_SUPPORT:
         if (major >= 3)
            return true;
#ifdef HAVE_OPENGLES
         if (gl_query_extension("ARB_texture_non_power_of_two") ||
               gl_query_extension("OES_texture_npot"))
            return true;
#else
         {
            GLint max_texture_size = 0;
            GLint max_native_instr = 0;
            /* try to detect actual npot support. might fail for older cards. */
            bool  arb_npot         = gl_query_extension("ARB_texture_non_power_of_two");
            bool  arb_frag_program = gl_query_extension("ARB_fragment_program");

            glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);

#ifdef GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB
            if (arb_frag_program && glGetProgramivARB)
               glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
                     GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &max_native_instr);
#endif

            if (arb_npot && arb_frag_program &&
                  (max_texture_size >= 8192) && (max_native_instr >= 4096))
               return true;
         }
#endif
         break;
      case GL_CAPS_SRGB_FBO_ES3:
#ifdef HAVE_OPENGLES
         if (major >= 3)
            return true;
#else
         break;
#endif
      case GL_CAPS_SRGB_FBO:
#if defined(HAVE_OPENGLES)
         if (major >= 3 || gl_query_extension("EXT_sRGB"))
            return true;
#elif defined(HAVE_FBO)
         if (gl_query_core_context_in_use() ||
               (gl_query_extension("EXT_texture_sRGB")
                && gl_query_extension("ARB_framebuffer_sRGB")))
            return true;
#endif
         break;
      case GL_CAPS_FP_FBO:
         /* GLES - No extensions for float FBO currently. */
#ifndef HAVE_OPENGLES
#ifdef HAVE_FBO
         /* Float FBO is core in 3.2. */
         if (gl_query_core_context_in_use() || gl_query_extension("ARB_texture_float"))
            return true;
#endif
#endif
         break;
      case GL_CAPS_BGRA8888:
#ifdef HAVE_OPENGLES
         /* There are both APPLE and EXT variants. */
         /* Videocore hardware supports BGRA8888 extension, but
          * should be purposefully avoided. */
         if (gl_query_extension("BGRA8888") && !strstr(renderer, "VideoCore"))
            return true;
#else
         /* TODO/FIXME - implement this for non-GLES? */
#endif
         break;
      case GL_CAPS_NONE:
      default:
         break;
   }

   return false;
}