opengl: loop through highest available versions to find a working one, only do hwapi check on glx/wgl for now

This commit is contained in:
Brad Parker 2019-08-05 10:46:17 -04:00
parent 22a62363b3
commit 7479245875
3 changed files with 168 additions and 43 deletions

View File

@ -242,7 +242,7 @@ static void create_gl_context(HWND hwnd, bool *quit)
if (core_context || debug)
{
int attribs[16];
int attribs[16] = {0};
int *aptr = attribs;
if (core_context)
@ -274,29 +274,71 @@ static void create_gl_context(HWND hwnd, bool *quit)
if (!pcreate_context)
pcreate_context = (wglCreateContextAttribsProc)gfx_ctx_wgl_get_proc_address("wglCreateContextAttribsARB");
/* In order to support the core info "required_hw_api" field correctly, we should try to init the highest available
* version GL context possible. This means trying successively lower versions until it works, because GL has
* no facility for determining the highest possible supported version.
*/
if (pcreate_context)
{
HGLRC context = pcreate_context(win32_hdc, NULL, attribs);
int i;
int gl_versions[][2] = {{4, 6}, {4, 3}, {4, 0}, {3, 3}, {3, 2}, {0, 0}};
int gl_version_rows = ARRAY_SIZE(gl_versions);
int (*versions)[2];
int version_rows = 0;
HGLRC context = NULL;
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");
versions = gl_versions;
version_rows = gl_version_rows;
if (win32_use_hw_ctx)
/* try each version, starting with the highest first */
for (i = 0; i < version_rows; i++)
{
win32_hw_hrc = pcreate_context(win32_hdc, context, attribs);
if (!win32_hw_hrc)
if (versions[i][0] == 0 && versions[i][1] == 0)
{
RARCH_ERR("[WGL]: Failed to create shared context.\n");
*quit = true;
/* use the actual requested version last */
versions[i][0] = win32_major;
versions[i][1] = win32_minor;
}
attribs[1] = versions[i][0];
attribs[3] = versions[i][1];
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;
break;
}
}
else
continue;
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;
break;
}
}
break;
}
if (!context)
{
RARCH_ERR("[WGL]: Failed to create core context. Falling back to legacy context.\n");
*quit = true;
}
}
else
@ -725,7 +767,7 @@ static bool gfx_ctx_wgl_suppress_screensaver(void *data, bool enable)
}
static bool gfx_ctx_wgl_get_metrics(void *data,
enum display_metric_types type, float *value)
enum display_metric_types type, float *value)
{
return win32_get_metrics(data, type, value);
}

View File

@ -176,6 +176,19 @@ static int GLXExtensionSupported(Display *dpy, const char *extension)
}
#endif
static int x_gl_version_error_handler(Display *dpy, XErrorEvent *event)
{
(void)dpy;
if (event->error_code == BadMatch && event->request_code == 151 && event->minor_code == 34)
{
RARCH_WARN("[GLX]: Version %d.%d not supported, trying a lower version.\n", g_major, g_minor);
return 0;
}
exit(1);
}
static int x_nul_handler(Display *dpy, XErrorEvent *event)
{
(void)dpy;
@ -816,7 +829,7 @@ static bool gfx_ctx_x_set_video_mode(void *data,
{
if (x->g_core_es || x->g_debug)
{
int attribs[16];
int attribs[16] = {0};
int *aptr = attribs;
if (x->g_core_es)
@ -848,18 +861,75 @@ static bool gfx_ctx_x_set_video_mode(void *data,
}
*aptr = None;
x->g_ctx = glx_create_context_attribs(g_x11_dpy,
x->g_fbc, NULL, True, attribs);
if (x->g_use_hw_ctx)
/* silently ignore failures when requesting GL versions that are too high */
old_handler = XSetErrorHandler(x_gl_version_error_handler);
/* In order to support the core info "required_hw_api" field correctly, we should try to init the highest available
* version GL context possible. This means trying successively lower versions until it works, because GL has
* no facility for determining the highest possible supported version.
*/
{
RARCH_LOG("[GLX]: Creating shared HW context.\n");
x->g_hw_ctx = glx_create_context_attribs(g_x11_dpy,
x->g_fbc, x->g_ctx, True, attribs);
int i;
int gl_versions[][2] = {{4, 6}, {4, 3}, {4, 0}, {3, 3}, {3, 2}, {0, 0}};
#ifdef HAVE_OPENGLES3
int gles_versions[][2] = {{3, 2}, {3, 1}, {3, 0}, {0, 0}};
#else
int gles_versions[][2] = {{2, 1}, {2, 0}, {1, 1}, {1, 0}, {0, 0}};
#endif
int gl_version_rows = ARRAY_SIZE(gl_versions);
int gles_version_rows = ARRAY_SIZE(gles_versions);
int (*versions)[2];
int version_rows = 0;
if (!x->g_hw_ctx)
RARCH_ERR("[GLX]: Failed to create new shared context.\n");
if (x_api == GFX_CTX_OPENGL_API)
{
versions = gl_versions;
version_rows = gl_version_rows;
}
else if (x_api == GFX_CTX_OPENGL_ES_API)
{
versions = gles_versions;
version_rows = gles_version_rows;
}
/* try each version, starting with the highest first */
for (i = 0; i < version_rows; i++)
{
if (versions[i][0] == 0 && versions[i][1] == 0)
{
/* use the actual requested version last */
versions[i][0] = g_major;
versions[i][1] = g_minor;
}
attribs[1] = versions[i][0];
attribs[3] = versions[i][1];
x->g_ctx = glx_create_context_attribs(g_x11_dpy,
x->g_fbc, NULL, True, attribs);
if (!x->g_ctx)
continue;
if (x->g_use_hw_ctx)
{
RARCH_LOG("[GLX]: Creating shared HW context.\n");
x->g_hw_ctx = glx_create_context_attribs(g_x11_dpy,
x->g_fbc, x->g_ctx, True, attribs);
if (!x->g_hw_ctx)
RARCH_ERR("[GLX]: Failed to create new shared context.\n");
}
g_major = versions[i][0];
g_minor = versions[i][1];
break;
}
}
XSetErrorHandler(old_handler);
}
else
{

View File

@ -584,33 +584,46 @@ static void content_load_init_wrap(
**/
static bool content_load(content_ctx_info_t *info)
{
unsigned i;
unsigned i = 0;
int rarch_argc = 0;
char *rarch_argv[MAX_ARGS] = {NULL};
char *argv_copy [MAX_ARGS] = {NULL};
char **rarch_argv_ptr = (char**)info->argv;
int *rarch_argc_ptr = (int*)&info->argc;
struct rarch_main_wrap *wrap_args;
core_info_t core_info = {0};
core_info_list_t *core_info_list = NULL;
struct rarch_main_wrap *wrap_args = NULL;
core_info_t core_info = {0};
core_info_list_t *core_info_list = NULL;
gfx_ctx_ident_t ident_info = {0};
core_info_get_list(&core_info_list);
video_context_driver_get_ident(&ident_info);
if (core_info_list)
/* only check for supported hw api on X11/GLX and Windows since that is where it is currently implemented */
#ifdef HAVE_X11
if (!string_is_empty(ident_info.ident) && string_is_equal(ident_info.ident, "x"))
#else
#if defined(_WIN32) && !defined(_XBOX)
if (!string_is_empty(ident_info.ident) && string_is_equal(ident_info.ident, "wgl"))
#endif
#endif
{
if (core_info_list_get_info(core_info_list, &core_info, path_get(RARCH_PATH_CORE)))
core_info_get_list(&core_info_list);
if (core_info_list)
{
if (!core_info_hw_api_supported(&core_info))
if (core_info_list_get_info(core_info_list, &core_info, path_get(RARCH_PATH_CORE)))
{
RARCH_ERR("This core is not compatible with the current video driver.\n");
runloop_msg_queue_push(
msg_hash_to_str(MSG_INCOMPATIBLE_CORE_FOR_VIDEO_DRIVER),
100, 250, true, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return false;
if (!core_info_hw_api_supported(&core_info))
{
RARCH_ERR("This core is not compatible with the current video driver.\n");
runloop_msg_queue_push(
msg_hash_to_str(MSG_INCOMPATIBLE_CORE_FOR_VIDEO_DRIVER),
100, 250, true, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return false;
}
else
RARCH_LOG("This core is compatible with the current video driver.\n");
}
else
RARCH_LOG("This core is compatible with the current video driver.\n");
}
}