Esempio n. 1
0
bool gl_init_hw_render(gl_t *gl, unsigned width, unsigned height)
{
   GLenum status;
   unsigned i;
   bool depth                           = false;
   bool stencil                         = false;
   GLint max_fbo_size                   = 0;
   GLint max_renderbuffer_size          = 0;
   struct retro_hw_render_callback *hwr =
      video_driver_get_hw_context();

   /* We can only share texture objects through contexts.
    * FBOs are "abstract" objects and are not shared. */
   context_bind_hw_render(true);

   RARCH_LOG("[GL]: Initializing HW render (%u x %u).\n", width, height);
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_fbo_size);
   glGetIntegerv(RARCH_GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
   RARCH_LOG("[GL]: Max texture size: %d px, renderbuffer size: %d px.\n",
         max_fbo_size, max_renderbuffer_size);

   if (!gl_check_capability(GL_CAPS_FBO))
      return false;

   RARCH_LOG("[GL]: Supports FBO (render-to-texture).\n");

   glBindTexture(GL_TEXTURE_2D, 0);
   glGenFramebuffers(gl->textures, gl->hw_render_fbo);

   depth   = hwr->depth;
   stencil = hwr->stencil;

#ifdef HAVE_OPENGLES
   if (!gl_check_capability(GL_CAPS_PACKED_DEPTH_STENCIL))
      return false;
   RARCH_LOG("[GL]: Supports Packed depth stencil.\n");
#endif

   if (depth)
   {
      glGenRenderbuffers(gl->textures, gl->hw_render_depth);
      gl->hw_render_depth_init = true;
   }

   for (i = 0; i < gl->textures; i++)
   {
      glBindFramebuffer(RARCH_GL_FRAMEBUFFER, gl->hw_render_fbo[i]);
      glFramebufferTexture2D(RARCH_GL_FRAMEBUFFER,
            RARCH_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl->texture[i], 0);

      if (depth)
      {
         glBindRenderbuffer(RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]);
         glRenderbufferStorage(RARCH_GL_RENDERBUFFER,
               stencil ? RARCH_GL_DEPTH24_STENCIL8 : GL_DEPTH_COMPONENT16,
               width, height);
         glBindRenderbuffer(RARCH_GL_RENDERBUFFER, 0);

         if (stencil)
         {
#if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGLES1) || ((defined(__MACH__) && (defined(__ppc__) || defined(__ppc64__))))
            /* GLES2 is a bit weird, as always.
             * There's no GL_DEPTH_STENCIL_ATTACHMENT like in desktop GL. */
            glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER,
                  RARCH_GL_DEPTH_ATTACHMENT,
                  RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]);
            glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER,
                  RARCH_GL_STENCIL_ATTACHMENT,
                  RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]);
#else
            /* We use ARB FBO extensions, no need to check. */
            glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER,
                  GL_DEPTH_STENCIL_ATTACHMENT,
                  RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]);
#endif
         }
         else
         {
            glFramebufferRenderbuffer(RARCH_GL_FRAMEBUFFER,
                  RARCH_GL_DEPTH_ATTACHMENT,
                  RARCH_GL_RENDERBUFFER, gl->hw_render_depth[i]);
         }
      }

      status = glCheckFramebufferStatus(RARCH_GL_FRAMEBUFFER);
      if (status != RARCH_GL_FRAMEBUFFER_COMPLETE)
      {
         RARCH_ERR("[GL]: Failed to create HW render FBO #%u, error: 0x%u.\n",
               i, (unsigned)status);
         return false;
      }
   }

   gl_bind_backbuffer();
   gl->hw_render_fbo_init = true;

   context_bind_hw_render(false);
   return true;
}
Esempio n. 2
0
static void *android_gfx_ctx_init(video_frame_info_t *video_info, void *video_driver)
{
#ifdef HAVE_OPENGLES
   EGLint n, major, minor;
   EGLint format;
#if 0
   struct retro_hw_render_callback *hwr = video_driver_get_hw_context();
   bool debug = hwr->debug_context;
#endif
   EGLint context_attributes[] = {
      EGL_CONTEXT_CLIENT_VERSION, g_es3 ? 3 : 2,
#if 0
      EGL_CONTEXT_FLAGS_KHR, debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0,
#endif
      EGL_NONE
   };
   EGLint attribs[] = {
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_BLUE_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_RED_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_DEPTH_SIZE, 16,
      EGL_NONE
   };
#endif
   struct android_app *android_app = (struct android_app*)g_android;
   android_ctx_data_t *and  = (android_ctx_data_t*)calloc(1, sizeof(*and));

   if (!android_app || !and)
      return false;

#ifdef HAVE_OPENGLES
   if (g_es3)
      attribs[1] = EGL_OPENGL_ES3_BIT_KHR;
#endif

   switch (android_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_EGL
         RARCH_LOG("Android EGL: GLES version = %d.\n", g_es3 ? 3 : 2);

         if (!egl_init_context(&and->egl, EGL_NONE, EGL_DEFAULT_DISPLAY,
                  &major, &minor, &n, attribs))
         {
            egl_report_error();
            goto error;
         }

         if (!egl_get_native_visual_id(&and->egl, &format))
            goto error;
#endif
         break;
      case GFX_CTX_VULKAN_API:
#ifdef HAVE_VULKAN
         if (!vulkan_context_init(&and->vk, VULKAN_WSI_ANDROID))
            goto error;
#endif
         break;
      case GFX_CTX_NONE:
      default:
         break;
   }

   slock_lock(android_app->mutex);
   if (!android_app->window)
      goto unlock_error;

   switch (android_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
         ANativeWindow_setBuffersGeometry(android_app->window, 0, 0, format);

#ifdef HAVE_EGL
         if (!egl_create_context(&and->egl, context_attributes))
         {
            egl_report_error();
            goto unlock_error;
         }

         if (!egl_create_surface(&and->egl, android_app->window))
            goto unlock_error;
#endif
         break;
      case GFX_CTX_NONE:
      default:
         break;
   }

   slock_unlock(android_app->mutex);
   return and;

unlock_error:
   slock_unlock(android_app->mutex);
error:
   android_gfx_ctx_destroy(and);

   return NULL;
}
Esempio n. 3
0
static void create_gl_context(HWND hwnd, bool *quit)
{
   struct retro_hw_render_callback *hwr = video_driver_get_hw_context();
   bool debug                           = hwr->debug_context;
   bool core_context                    = (win32_major * 1000 + win32_minor) >= 3001;
   win32_hdc                            = GetDC(hwnd);

   setup_pixel_format(win32_hdc);

#ifdef GL_DEBUG
   debug = true;
#endif

   if (win32_hrc)
   {
      RARCH_LOG("[WGL]: Using cached GL context.\n");
      video_driver_set_video_cache_context_ack();
   }
   else
   {
      win32_hrc = wglCreateContext(win32_hdc);

      /* We'll create shared context later if not. */
      if (win32_hrc && !core_context && !debug)
      {
         win32_hw_hrc = wglCreateContext(win32_hdc);
         if (win32_hw_hrc)
         {
            if (!wglShareLists(win32_hrc, win32_hw_hrc))
            {
               RARCH_LOG("[WGL]: Failed to share contexts.\n");
               *quit = true;
            }
         }
         else
            *quit = true;
      }
   }

   if (win32_hrc)
   {
      if (wglMakeCurrent(win32_hdc, win32_hrc))
         g_win32_inited = true;
      else
         *quit          = true;
   }
   else
   {
      *quit        = true;
      return;
   }

   if (core_context || debug)
   {
      int attribs[16];
      int *aptr = attribs;

      if (core_context)
      {
         *aptr++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
         *aptr++ = win32_major;
         *aptr++ = WGL_CONTEXT_MINOR_VERSION_ARB;
         *aptr++ = win32_minor;

         /* Technically, we don't have core/compat until 3.2.
          * Version 3.1 is either compat or not depending
          * on GL_ARB_compatibility.
          */
         if ((win32_major * 1000 + win32_minor) >= 3002)
         {
            *aptr++ = WGL_CONTEXT_PROFILE_MASK_ARB;
            *aptr++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
         }
      }

      if (debug)
      {
         *aptr++ = WGL_CONTEXT_FLAGS_ARB;
         *aptr++ = WGL_CONTEXT_DEBUG_BIT_ARB;
      }

      *aptr = 0;

      if (!pcreate_context)
         pcreate_context = (wglCreateContextAttribsProc)gfx_ctx_wgl_get_proc_address("wglCreateContextAttribsARB");

      if (pcreate_context)
      {
         HGLRC context = pcreate_context(win32_hdc, NULL, attribs);

         if (context)
         {
            wglMakeCurrent(NULL, NULL);
            wglDeleteContext(win32_hrc);
            win32_hrc = context;
            if (!wglMakeCurrent(win32_hdc, win32_hrc))
               *quit = true;
         }
         else
            RARCH_ERR("[WGL]: Failed to create core context. Falling back to legacy context.\n");

         if (win32_use_hw_ctx)
         {
            win32_hw_hrc = pcreate_context(win32_hdc, context, attribs);
            if (!win32_hw_hrc)
            {
               RARCH_ERR("[WGL]: Failed to create shared context.\n");
               *quit = true;
            }
         }
      }
      else
         RARCH_ERR("[WGL]: wglCreateContextAttribsARB not supported.\n");
   }

   {

      const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
      const char *extensions                                 = NULL;

      wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
         gfx_ctx_wgl_get_proc_address("wglGetExtensionsStringARB");
      if (wglGetExtensionsStringARB)
         extensions = wglGetExtensionsStringARB(win32_hdc);
      RARCH_LOG("[WGL] extensions: %s\n", extensions);
      if (wgl_has_extension("WGL_EXT_swap_control_tear", extensions))
      {
         RARCH_LOG("[WGL]: Adaptive VSync supported.\n");
         wgl_adaptive_vsync = true;
      }
   }
}
Esempio n. 4
0
static EGLint *egl_fill_attribs(gfx_ctx_wayland_data_t *wl, EGLint *attr)
{
   switch (wl_api)
   {
#ifdef EGL_KHR_create_context
      case GFX_CTX_OPENGL_API:
      {
         bool debug       = false;
#ifdef HAVE_OPENGL
         unsigned version = wl->egl.major * 1000 + wl->egl.minor;
         bool core        = version >= 3001;
#ifndef GL_DEBUG
         struct retro_hw_render_callback *hwr =
            video_driver_get_hw_context();
#endif

#ifdef GL_DEBUG
         debug            = true;
#else
         debug            = hwr->debug_context;
#endif

         if (core)
         {
            *attr++ = EGL_CONTEXT_MAJOR_VERSION_KHR;
            *attr++ = wl->egl.major;
            *attr++ = EGL_CONTEXT_MINOR_VERSION_KHR;
            *attr++ = wl->egl.minor;
            /* Technically, we don't have core/compat until 3.2.
             * Version 3.1 is either compat or not depending on GL_ARB_compatibility. */
            if (version >= 3002)
            {
               *attr++ = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
               *attr++ = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
            }
         }

         if (debug)
         {
            *attr++ = EGL_CONTEXT_FLAGS_KHR;
            *attr++ = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
         }
#endif

         break;
      }
#endif

      case GFX_CTX_OPENGL_ES_API:
#ifdef HAVE_OPENGLES
         *attr++ = EGL_CONTEXT_CLIENT_VERSION; /* Same as EGL_CONTEXT_MAJOR_VERSION */
         *attr++ = wl->egl.major ? (EGLint)wl->egl.major : 2;
#ifdef EGL_KHR_create_context
         if (wl->egl.minor > 0)
         {
            *attr++ = EGL_CONTEXT_MINOR_VERSION_KHR;
            *attr++ = wl->egl.minor;
         }
#endif
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   *attr = EGL_NONE;
   return attr;
}
Esempio n. 5
0
static void *gl1_gfx_init(const video_info_t *video,
      const input_driver_t **input, void **input_data)
{
   unsigned full_x, full_y;
   gfx_ctx_input_t inp;
   gfx_ctx_mode_t mode;
   void *ctx_data                       = NULL;
   const gfx_ctx_driver_t *ctx_driver   = NULL;
   unsigned win_width = 0, win_height   = 0;
   unsigned temp_width = 0, temp_height = 0;
   settings_t *settings                 = config_get_ptr();
   gl1_t *gl1                           = (gl1_t*)calloc(1, sizeof(*gl1));
   const char *vendor                   = NULL;
   const char *renderer                 = NULL;
   const char *version                  = NULL;
   const char *extensions               = NULL;
   int interval                         = 0;
   struct retro_hw_render_callback *hwr = NULL;

   if (!gl1)
      return NULL;

   *input                               = NULL;
   *input_data                          = NULL;

   gl1_video_width                      = video->width;
   gl1_video_height                     = video->height;
   gl1_rgb32                            = video->rgb32;

   gl1_video_bits                       = video->rgb32 ? 32 : 16;

   if (video->rgb32)
      gl1_video_pitch = video->width * 4;
   else
      gl1_video_pitch = video->width * 2;

   ctx_driver = video_context_driver_init_first(gl1,
         settings->arrays.video_context_driver,
         GFX_CTX_OPENGL_API, 1, 1, false, &ctx_data);

   if (!ctx_driver)
      goto error;

   if (ctx_data)
      gl1->ctx_data = ctx_data;

   gl1->ctx_driver  = ctx_driver;

   video_context_driver_set((const gfx_ctx_driver_t*)ctx_driver);

   RARCH_LOG("[GL1]: Found GL1 context: %s\n", ctx_driver->ident);

   video_context_driver_get_video_size(&mode);

   full_x      = mode.width;
   full_y      = mode.height;
   mode.width  = 0;
   mode.height = 0;

   /* Clear out potential error flags in case we use cached context. */
   glGetError();

   if (string_is_equal(ctx_driver->ident, "null"))
      goto error;

   RARCH_LOG("[GL1]: Detecting screen resolution %ux%u.\n", full_x, full_y);

   win_width   = video->width;
   win_height  = video->height;

   if (video->fullscreen && (win_width == 0) && (win_height == 0))
   {
      win_width  = full_x;
      win_height = full_y;
   }

   mode.width      = win_width;
   mode.height     = win_height;
   mode.fullscreen = video->fullscreen;

   interval = video->swap_interval;

   video_context_driver_swap_interval(&interval);

   if (!video_context_driver_set_video_mode(&mode))
      goto error;

   gl1->fullscreen = video->fullscreen;

   mode.width     = 0;
   mode.height    = 0;

   video_context_driver_get_video_size(&mode);

   temp_width     = mode.width;
   temp_height    = mode.height;
   mode.width     = 0;
   mode.height    = 0;

   /* Get real known video size, which might have been altered by context. */

   if (temp_width != 0 && temp_height != 0)
      video_driver_set_size(&temp_width, &temp_height);

   video_driver_get_size(&temp_width, &temp_height);

   RARCH_LOG("[GL1]: Using resolution %ux%u\n", temp_width, temp_height);

   vendor   = (const char*)glGetString(GL_VENDOR);
   renderer = (const char*)glGetString(GL_RENDERER);
   version  = (const char*)glGetString(GL_VERSION);
   extensions = (const char*)glGetString(GL_EXTENSIONS);

   if (!string_is_empty(version))
      sscanf(version, "%d.%d", &gl1->version_major, &gl1->version_minor);

   if (!string_is_empty(extensions))
      gl1->extensions = string_split(extensions, " ");

   RARCH_LOG("[GL1]: Vendor: %s, Renderer: %s.\n", vendor, renderer);
   RARCH_LOG("[GL1]: Version: %s.\n", version);
   RARCH_LOG("[GL1]: Extensions: %s\n", extensions);

   {
      char device_str[128];

      device_str[0] = '\0';

      if (!string_is_empty(vendor))
      {
         strlcpy(device_str, vendor, sizeof(device_str));
         strlcat(device_str, " ", sizeof(device_str));
      }

      if (!string_is_empty(renderer))
         strlcat(device_str, renderer, sizeof(device_str));

      video_driver_set_gpu_device_string(device_str);

      if (!string_is_empty(version))
         video_driver_set_gpu_api_version_string(version);
   }

   inp.input      = input;
   inp.input_data = input_data;

   video_context_driver_input_driver(&inp);

   if (settings->bools.video_font_enable)
      font_driver_init_osd(gl1, false,
            video->is_threaded,
            FONT_DRIVER_RENDER_OPENGL1_API);

   gl1->smooth = settings->bools.video_smooth;
   gl1->supports_bgra = string_list_find_elem(gl1->extensions, "GL_EXT_bgra");

   glDisable(GL_BLEND);
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_CULL_FACE);
   glDisable(GL_STENCIL_TEST);
   glDisable(GL_SCISSOR_TEST);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glGenTextures(1, &gl1->tex);
   glGenTextures(1, &gl1->menu_tex);

   hwr = video_driver_get_hw_context();

   memcpy(gl1->tex_info.coord, gl1_tex_coords, sizeof(gl1->tex_info.coord));
   gl1->vertex_ptr        = hwr->bottom_left_origin
      ? gl1_vertexes : gl1_vertexes_flipped;
   gl1->textures              = 4;
   gl1->white_color_ptr       = gl1_white_color;
   gl1->coords.vertex         = gl1->vertex_ptr;
   gl1->coords.tex_coord      = gl1->tex_info.coord;
   gl1->coords.color          = gl1->white_color_ptr;
   gl1->coords.lut_tex_coord  = gl1_tex_coords;
   gl1->coords.vertices       = 4;

   RARCH_LOG("[GL1]: Init complete.\n");

   return gl1;

error:
   video_context_driver_destroy();
   if (gl1)
   {
      if (gl1->extensions)
         string_list_free(gl1->extensions);
      free(gl1);
   }
   return NULL;
}
Esempio n. 6
0
/**
 * drivers_init:
 * @flags              : Bitmask of drivers to initialize.
 *
 * Initializes drivers.
 * @flags determines which drivers get initialized.
 **/
void drivers_init(int flags)
{
   bool video_is_threaded = false;

   if (flags & DRIVER_VIDEO_MASK)
      video_driver_unset_own_driver();
   if (flags & DRIVER_AUDIO_MASK)
      audio_driver_unset_own_driver();
   if (flags & DRIVER_INPUT_MASK)
      input_driver_unset_own_driver();
   if (flags & DRIVER_CAMERA_MASK)
      camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_OWN_DRIVER, NULL);
   if (flags & DRIVER_LOCATION_MASK)
      location_driver_ctl(RARCH_LOCATION_CTL_UNSET_OWN_DRIVER, NULL);
   if (flags & DRIVER_WIFI_MASK)
      wifi_driver_ctl(RARCH_WIFI_CTL_UNSET_OWN_DRIVER, NULL);

#ifdef HAVE_MENU
   /* By default, we want the menu to persist through driver reinits. */
   menu_driver_ctl(RARCH_MENU_CTL_SET_OWN_DRIVER, NULL);
#endif

   if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
      driver_adjust_system_rates();

   if (flags & DRIVER_VIDEO_MASK)
   {
      struct retro_hw_render_callback *hwr =
         video_driver_get_hw_context();

      video_driver_monitor_reset();
      video_driver_init(&video_is_threaded);

      if (!video_driver_is_video_cache_context_ack()
            && hwr->context_reset)
         hwr->context_reset();
      video_driver_unset_video_cache_context_ack();

      rarch_ctl(RARCH_CTL_SET_FRAME_TIME_LAST, NULL);
   }

   if (flags & DRIVER_AUDIO_MASK)
   {
      audio_driver_init();
      audio_driver_new_devices_list();
   }

   /* Only initialize camera driver if we're ever going to use it. */
   if ((flags & DRIVER_CAMERA_MASK) && camera_driver_ctl(RARCH_CAMERA_CTL_IS_ACTIVE, NULL))
      camera_driver_ctl(RARCH_CAMERA_CTL_INIT, NULL);

   /* Only initialize location driver if we're ever going to use it. */
   if ((flags & DRIVER_LOCATION_MASK) && location_driver_ctl(RARCH_LOCATION_CTL_IS_ACTIVE, NULL))
      init_location();

   core_info_init_current_core();

#ifdef HAVE_MENU
   if (flags & DRIVER_VIDEO_MASK)
   {
      if (flags & DRIVER_MENU_MASK)
         menu_driver_init(video_is_threaded);
   }
#endif

   if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
   {
      /* Keep non-throttled state as good as possible. */
      if (input_driver_is_nonblock_state())
         driver_set_nonblock_state();
   }

   if (flags & DRIVER_LED_MASK)
   {
      led_driver_init();
   }

   if (flags & DRIVER_MIDI_MASK)
      midi_driver_init();
}
Esempio n. 7
0
static bool gl_raster_font_upload_atlas(gl_raster_t *font)
{
   unsigned i, j;
   GLint  gl_internal                   = GL_LUMINANCE_ALPHA;
   GLenum gl_format                     = GL_LUMINANCE_ALPHA;
   size_t ncomponents                   = 2;
   uint8_t       *tmp                   = NULL;
#if 0
   bool ancient                         = false; /* add a check here if needed */
#endif

#if defined(GL_VERSION_3_0)
   struct retro_hw_render_callback *hwr = video_driver_get_hw_context();
#endif

#if 0
   if (ancient)
   {
      gl_internal = GL_RGBA;
      gl_format   = GL_RGBA;
      ncomponents = 4;
   }
#endif

#if defined(GL_VERSION_3_0)
    if (gl_query_core_context_in_use() ||
        (hwr->context_type == RETRO_HW_CONTEXT_OPENGL &&
         hwr->version_major >= 3))
   {
      GLint swizzle[] = { GL_ONE, GL_ONE, GL_ONE, GL_RED };
      glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);

      gl_internal = GL_R8;
      gl_format   = GL_RED;
      ncomponents = 1;
   }
#endif

   tmp = (uint8_t*)calloc(font->tex_height, font->tex_width * ncomponents);

   if (!tmp)
      return false;

   for (i = 0; i < font->atlas->height; ++i)
   {
      const uint8_t *src = &font->atlas->buffer[i * font->atlas->width];
      uint8_t       *dst = &tmp[i * font->tex_width * ncomponents];

      switch (ncomponents)
      {
         case 1:
            memcpy(dst, src, font->atlas->width);
            break;
         case 2:
            for (j = 0; j < font->atlas->width; ++j)
            {
               *dst++ = 0xff;
               *dst++ = *src++;
            }
            break;
         case 4:
            for (j = 0; j < font->atlas->width; ++j)
            {
               *dst++ = 0xff;
               *dst++ = 0xff;
               *dst++ = 0xff;
               *dst++ = *src++;
            }
            break;
         default:
            RARCH_ERR("Unsupported number of components: %u\n",
                  (unsigned)ncomponents);
            free(tmp);
            return false;
      }
   }

   glTexImage2D(GL_TEXTURE_2D, 0, gl_internal, font->tex_width, font->tex_height,
         0, gl_format, GL_UNSIGNED_BYTE, tmp);

   free(tmp);

   return true;
}
Esempio n. 8
0
/**
 * init_drivers:
 * @flags              : Bitmask of drivers to initialize.
 *
 * Initializes drivers.
 * @flags determines which drivers get initialized.
 **/
static void init_drivers(int flags)
{
   if (flags & DRIVER_VIDEO)
      video_driver_unset_own_driver();
   if (flags & DRIVER_AUDIO)
      audio_driver_unset_own_driver();
   if (flags & DRIVER_INPUT)
      input_driver_unset_own_driver();
   if (flags & DRIVER_CAMERA)
      camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_OWN_DRIVER, NULL);
   if (flags & DRIVER_LOCATION)
      location_driver_ctl(RARCH_LOCATION_CTL_UNSET_OWN_DRIVER, NULL);

#ifdef HAVE_MENU
   /* By default, we want the menu to persist through driver reinits. */
   menu_driver_ctl(RARCH_MENU_CTL_SET_OWN_DRIVER, NULL);
#endif

   if (flags & (DRIVER_VIDEO | DRIVER_AUDIO))
      driver_adjust_system_rates();

   if (flags & DRIVER_VIDEO)
   {
      struct retro_hw_render_callback *hwr =
         video_driver_get_hw_context();

      video_driver_monitor_reset();
      video_driver_init();

      if (!video_driver_is_video_cache_context_ack()
            && hwr->context_reset)
         hwr->context_reset();
      video_driver_unset_video_cache_context_ack();

      runloop_ctl(RUNLOOP_CTL_SET_FRAME_TIME_LAST, NULL);
   }

   if (flags & DRIVER_AUDIO)
   {
      audio_driver_init();
      audio_driver_new_devices_list();
   }

   /* Only initialize camera driver if we're ever going to use it. */
   if ((flags & DRIVER_CAMERA) && camera_driver_ctl(RARCH_CAMERA_CTL_IS_ACTIVE, NULL))
      camera_driver_ctl(RARCH_CAMERA_CTL_INIT, NULL);

   /* Only initialize location driver if we're ever going to use it. */
   if ((flags & DRIVER_LOCATION) && location_driver_ctl(RARCH_LOCATION_CTL_IS_ACTIVE, NULL))
      init_location();

#ifdef HAVE_MENU
   if (flags & DRIVER_MENU)
   {
      menu_driver_ctl(RARCH_MENU_CTL_INIT, NULL);
      menu_driver_ctl(RARCH_MENU_CTL_CONTEXT_RESET, NULL);
   }
#endif

   if (flags & (DRIVER_VIDEO | DRIVER_AUDIO))
   {
      /* Keep non-throttled state as good as possible. */
      if (input_driver_is_nonblock_state())
         driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL);
   }
}
Esempio n. 9
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;
}
Esempio n. 10
0
enum rarch_shader_type video_shader_get_type_from_ext(
      const char *ext, bool *is_preset)
{
   enum gfx_ctx_api api = video_context_driver_get_api();

   if (string_is_empty(ext))
      return RARCH_SHADER_NONE;

   if (strlen(ext) > 1 && ext[0] == '.')
      ext++;

   *is_preset           = false;

   if (
         string_is_equal_case_insensitive(ext, "cg")
         )
   {
      switch (api)
      {
         case GFX_CTX_DIRECT3D9_API:
            return RARCH_SHADER_CG;
         case GFX_CTX_OPENGL_API:
         case GFX_CTX_OPENGL_ES_API:
            {
               struct retro_hw_render_callback *hwr =
                  video_driver_get_hw_context();
               if (hwr)
               {
                  switch (hwr->context_type)
                  {
                     case RETRO_HW_CONTEXT_OPENGLES2:
                     case RETRO_HW_CONTEXT_OPENGL_CORE:
                     case RETRO_HW_CONTEXT_OPENGLES3:
                        return RARCH_SHADER_NONE;
                     default:
                        break;
                  }
               }
            }
            return RARCH_SHADER_CG;
         default:
            break;
      }
   }
   if (
         string_is_equal_case_insensitive(ext, "cgp")
         )
   {
      *is_preset = true;
      switch (api)
      {
         case GFX_CTX_DIRECT3D9_API:
            return RARCH_SHADER_CG;
         case GFX_CTX_OPENGL_API:
         case GFX_CTX_OPENGL_ES_API:
            {
               struct retro_hw_render_callback *hwr =
                  video_driver_get_hw_context();
               if (hwr)
               {
                  switch (hwr->context_type)
                  {
                     case RETRO_HW_CONTEXT_OPENGLES2:
                     case RETRO_HW_CONTEXT_OPENGL_CORE:
                     case RETRO_HW_CONTEXT_OPENGLES3:
                        return RARCH_SHADER_NONE;
                     default:
                        break;
                  }
               }
            }
            return RARCH_SHADER_CG;
         default:
            break;
      }
   }
   if (
         string_is_equal_case_insensitive(ext, "glsl")
         )
   {
      switch (api)
      {
         case GFX_CTX_OPENGL_API:
         case GFX_CTX_OPENGL_ES_API:
            return RARCH_SHADER_GLSL;
         default:
            break;
      }
   }
   if (
         string_is_equal_case_insensitive(ext, "glslp")
         )
   {
      *is_preset = true;
      switch (api)
      {
         case GFX_CTX_OPENGL_API:
         case GFX_CTX_OPENGL_ES_API:
            return RARCH_SHADER_GLSL;
         default:
            break;
      }
   }
   if (
         string_is_equal_case_insensitive(ext, "slang")
         )
   {
      switch (api)
      {
         case GFX_CTX_DIRECT3D10_API:
         case GFX_CTX_DIRECT3D11_API:
         case GFX_CTX_DIRECT3D12_API:
         case GFX_CTX_GX2_API:
         case GFX_CTX_VULKAN_API:
         case GFX_CTX_METAL_API:
            return RARCH_SHADER_SLANG;
         default:
            break;
      }
   }
   if (
         string_is_equal_case_insensitive(ext, "slangp")
         )
   {
      *is_preset = true;

      switch (api)
      {
         case GFX_CTX_DIRECT3D10_API:
         case GFX_CTX_DIRECT3D11_API:
         case GFX_CTX_DIRECT3D12_API:
         case GFX_CTX_GX2_API:
         case GFX_CTX_VULKAN_API:
         case GFX_CTX_METAL_API:
            return RARCH_SHADER_SLANG;
         default:
            break;
      }
   }

   return RARCH_SHADER_NONE;
}
Esempio n. 11
0
static void *gfx_ctx_x_init(video_frame_info_t *video_info, void *data)
{
   int nelements           = 0;
   int major               = 0;
   int minor               = 0;
#ifdef HAVE_OPENGL
   static const int visual_attribs[] = {
      GLX_X_RENDERABLE     , True,
      GLX_DRAWABLE_TYPE    , GLX_WINDOW_BIT,
      GLX_RENDER_TYPE      , GLX_RGBA_BIT,
      GLX_DOUBLEBUFFER     , True,
      GLX_RED_SIZE         , 8,
      GLX_GREEN_SIZE       , 8,
      GLX_BLUE_SIZE        , 8,
      GLX_ALPHA_SIZE       , 8,
      GLX_DEPTH_SIZE       , 0,
      GLX_STENCIL_SIZE     , 0,
      GLX_SAMPLE_BUFFERS   , 0,
      GLX_SAMPLES          , 0,
      None
   };
   GLXFBConfig *fbcs       = NULL;
#endif
   gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)
      calloc(1, sizeof(gfx_ctx_x_data_t));
#ifndef GL_DEBUG
   struct retro_hw_render_callback *hwr =
      video_driver_get_hw_context();
#endif

   if (!x)
      return NULL;

   current_context_data = x;

   XInitThreads();

   if (!x11_connect())
      goto error;


   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
      case GFX_CTX_OPENGL_ES_API:
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
         glXQueryVersion(g_x11_dpy, &major, &minor);

         /* GLX 1.3+ minimum required. */
         if ((major * 1000 + minor) < 1003)
            goto error;

         glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
            glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");

#ifdef GL_DEBUG
         x->g_debug = true;
#else
         x->g_debug = hwr->debug_context;
#endif

         /* Have to use ContextAttribs */
#ifdef HAVE_OPENGLES2
         x->g_core_es      = true;
         x->g_core_es_core = true;
#else
         x->g_core_es      = (g_major * 1000 + g_minor) >= 3001;
         x->g_core_es_core = (g_major * 1000 + g_minor) >= 3002;
#endif

         if ((x->g_core_es || x->g_debug) && !glx_create_context_attribs)
            goto error;

         fbcs = glXChooseFBConfig(g_x11_dpy, DefaultScreen(g_x11_dpy),
               visual_attribs, &nelements);

         if (!fbcs)
            goto error;

         if (!nelements)
         {
            XFree(fbcs);
            goto error;
         }

         x->g_fbc = fbcs[0];
         XFree(fbcs);
#endif
         break;
      case GFX_CTX_VULKAN_API:
#ifdef HAVE_VULKAN
         /* Use XCB WSI since it's the most supported WSI over legacy Xlib. */
         if (!vulkan_context_init(&x->vk, VULKAN_WSI_XCB))
            goto error;
#endif
         break;

      case GFX_CTX_NONE:
      default:
         break;
   }

   switch (x_api)
   {
      case GFX_CTX_OPENGL_API:
#ifdef HAVE_OPENGL
	 if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear"))
	 {
            RARCH_LOG("[GLX]: GLX_EXT_swap_control_tear supported.\n");
	    x_adaptive_vsync = true;
	 }
         if (GLXExtensionSupported(g_x11_dpy, "GLX_OML_sync_control") &&
             GLXExtensionSupported(g_x11_dpy, "GLX_MESA_swap_control")
            )
         {
            RARCH_LOG("[GLX]: GLX_OML_sync_control and GLX_MESA_swap_control supported, using better swap control method...\n");

            x->swap_mode         = 1;

            glXGetSyncValuesOML  = (GLXGETSYNCVALUESOMLPROC)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML");
            glXGetMscRateOML     = (GLXGETMSCRATEOMLPROC)glXGetProcAddress((unsigned char *)"glXGetMscRateOML");
            glXSwapBuffersMscOML = (GLXSWAPBUFFERSMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML");
            glXWaitForMscOML     = (GLXWAITFORMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForMscOML");
            glXWaitForSbcOML     = (GLXWAITFORSBCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML");

            glXGetSyncValuesOML(g_x11_dpy, g_x11_win, &x->ust, &x->msc, &x->sbc);

#if 0
            RARCH_LOG("[GLX]: UST: %d, MSC: %d, SBC: %d\n", x->ust, x->msc, x->sbc);
#endif
         }
#endif
         break;
      default:
         break;
   }

   return x;

error:
   if (x)
   {
      gfx_ctx_x_destroy_resources(x);
      free(x);
   }
   g_x11_screen = 0;

   return NULL;
}