Skip to content
Snippets Groups Projects
Commit 5416fd09 authored by Jeremy Whiting's avatar Jeremy Whiting Committed by Jeremy Whiting
Browse files

GL and GLES helpers initial commit.

In order to check opengl and gles on linux desktop for multiple
architectures build check-gl|gles] with architecture prefix.
Modifications from upstream sources include:
Removing kernel parameter checks for gnome.fallback, just run no need
to check for fallbacks.
Removing blacklisted renderer list support, no need for our use case.
Removing dependency on gtk+ and gdk.
Removing dependency on epoxy.
parent fc7cd7f6
No related branches found
No related tags found
1 merge request!3GL and GLES helpers initial commit.
Copyright © 2019 Collabora Ltd. Copyright © 2019 Collabora Ltd.
SPDX-License-Identifier: MIT SPDX-License-Identifier: MIT and GPL-2.0-or-later
Permission is hereby granted, free of charge, to any person obtaining See individual source files for details.
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included The shared library is under the MIT/X11 license:
in all copies or substantial portions of the Software.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Separate helper executables in the helpers/ directory are under various
licenses including MIT/X11 and GPL-2.0-or-later.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* check-gl - OpenGL functional check helper for steam-runtime-tools
* Based on gnome-session-check-accelerated-gl-helper from gnome-session.
*
* Copyright (C) 2019 Collabora Ltd.
* Copyright (C) 2010 Novell, Inc.
* Copyright (C) 2006-2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author:
* Vincent Untz <vuntz@gnome.org>
*
* Most of the code comes from desktop-effects [1], released under GPLv2+.
* desktop-effects was written by:
* Soren Sandmann <sandmann@redhat.com>
*
* [1] http://git.fedorahosted.org/git/?p=desktop-effects.git;a=blob_plain;f=desktop-effects.c;hb=HEAD
*/
/*
* Here's the rationale behind this helper, quoting Owen, in his mail to the
* release team:
* (http://mail.gnome.org/archives/release-team/2010-June/msg00079.html)
*
* """
* There are some limits to what we can do here automatically without
* knowing anything about the driver situation on the system. The basic
* problem is that there are all sorts of suck:
*
* * No GL at all. This typically only happens if a system is
* misconfigured.
*
* * Only software GL. This one is easy to detect. We have code in
* the Fedora desktop-effects tool, etc.
*
* * GL that isn't featureful enough. (Tiny texture size limits, no
* texture-from-pixmap, etc.) Possible to detect with more work, but
* largely a fringe case.
*
* * Buggy GL. This isn't possible to detect. Except for the case where
* all GL programs crash. For that reason, we probably don't want
* gnome-session to directly try and do any GL detection; better to
* use a helper binary.
*
* * Horribly slow hardware GL. We could theoretically develop some sort
* of benchmark, but it's a tricky area. And how slow is too slow?
* """
*
* Some other tools are doing similar checks:
* - desktop-effects (Fedora Config Tool) [1]
* - drak3d (Mandriva Config Tool) [2]
* - compiz-manager (Compiz wrapper) [3]
*
* [1] http://git.fedorahosted.org/git/?p=desktop-effects.git;a=blob_plain;f=desktop-effects.c;hb=HEAD
* [2] http://svn.mandriva.com/cgi-bin/viewvc.cgi/soft/drak3d/trunk/lib/Xconfig/glx.pm?view=markup
* [3] http://git.compiz.org/fusion/misc/compiz-manager/tree/compiz-manager
*/
/* for strcasestr */
#define _GNU_SOURCE
#include <ctype.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <regex.h>
#ifdef __FreeBSD__
#include <kenv.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xcomposite.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include "gnome-session-check-accelerated-common.h"
#define SIZE_UNSET 0
#define SIZE_ERROR -1
static int max_texture_size = SIZE_UNSET;
static int max_renderbuffer_size = SIZE_UNSET;
static gboolean has_llvmpipe = FALSE;
static inline void
_print_error (const char *str)
{
fprintf (stderr, "gnome-session-is-accelerated: %s\n", str);
}
static gboolean
_is_comment (const char *line)
{
while (*line && isspace(*line))
line++;
if (*line == '#' || *line == '\0')
return TRUE;
return FALSE;
}
static gboolean
_is_gl_renderer_blacklisted (const char *renderer)
{
return FALSE;
#if 0
FILE *blacklist;
char *line = NULL;
size_t line_len = 0;
gboolean ret = TRUE;
blacklist = fopen(PKGDATADIR "/hardware-compatibility", "r");
if (blacklist == NULL)
goto out;
while (getline (&line, &line_len, blacklist) != -1) {
int whitelist = 0;
const char *re_str;
regex_t re;
int status;
if (line == NULL)
break;
/* Drop trailing \n */
line[strlen(line) - 1] = '\0';
if (_is_comment (line)) {
free (line);
line = NULL;
continue;
}
if (line[0] == '+')
whitelist = 1;
else if (line[0] == '-')
whitelist = 0;
else {
_print_error ("Invalid syntax in this line for hardware compatibility:");
_print_error (line);
free (line);
line = NULL;
continue;
}
re_str = line + 1;
if (regcomp (&re, re_str, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) {
_print_error ("Cannot use this regular expression for hardware compatibility:");
_print_error (re_str);
} else {
status = regexec (&re, renderer, 0, NULL, 0);
regfree(&re);
if (status == 0) {
if (whitelist)
ret = FALSE;
goto out;
}
}
free (line);
line = NULL;
}
ret = FALSE;
out:
if (line != NULL)
free (line);
if (blacklist != NULL)
fclose (blacklist);
return ret;
#endif
}
static char *
_get_hardware_gl (Display *display)
{
int screen;
Window root;
XVisualInfo *visual = NULL;
GLXContext context = NULL;
XSetWindowAttributes cwa = { 0 };
Window window = None;
char *renderer = NULL;
int attrlist[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
None
};
screen = DefaultScreen (display);
root = RootWindow (display, screen);
visual = glXChooseVisual (display, screen, attrlist);
if (!visual)
goto out;
context = glXCreateContext (display, visual, NULL, True);
if (!context)
goto out;
cwa.colormap = XCreateColormap (display, root,
visual->visual, AllocNone);
cwa.background_pixel = 0;
cwa.border_pixel = 0;
window = XCreateWindow (display, root,
0, 0, 1, 1, 0,
visual->depth, InputOutput, visual->visual,
CWColormap | CWBackPixel | CWBorderPixel,
&cwa);
if (!glXMakeCurrent (display, window, context))
goto out;
renderer = g_strdup ((const char *) glGetString (GL_RENDERER));
if (_is_gl_renderer_blacklisted (renderer)) {
g_clear_pointer (&renderer, g_free);
goto out;
}
if (renderer && strcasestr (renderer, "llvmpipe"))
has_llvmpipe = TRUE;
/* we need to get the max texture and renderbuffer sizes while we have
* a context, but we'll check their values later */
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
if (glGetError() != GL_NO_ERROR)
max_texture_size = SIZE_ERROR;
glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE_EXT, &max_renderbuffer_size);
if (glGetError() != GL_NO_ERROR)
max_renderbuffer_size = SIZE_ERROR;
out:
glXMakeCurrent (display, None, None);
if (context)
glXDestroyContext (display, context);
if (window)
XDestroyWindow (display, window);
if (cwa.colormap)
XFreeColormap (display, cwa.colormap);
return renderer;
}
static gboolean
_has_extension (const char *extension_list,
const char *extension)
{
char **extensions;
guint i;
gboolean ret;
g_return_val_if_fail (extension != NULL, TRUE);
/* Extension_list is one big string, containing extensions
* separated by spaces. */
if (extension_list == NULL)
return FALSE;
ret = FALSE;
extensions = g_strsplit (extension_list, " ", -1);
if (extensions == NULL)
return FALSE;
for (i = 0; extensions[i] != NULL; i++) {
if (g_str_equal (extensions[i], extension)) {
ret = TRUE;
break;
}
}
g_strfreev (extensions);
return ret;
}
static gboolean
_display_has_extension (Display *display, const char *extension)
{
int screen;
const char *server_extensions;
const char *client_extensions;
gboolean ret = FALSE;
screen = DefaultScreen (display);
server_extensions = glXQueryServerString (display, screen,
GLX_EXTENSIONS);
if (!_has_extension (server_extensions,
extension))
goto out;
client_extensions = glXGetClientString (display, GLX_EXTENSIONS);
if (!_has_extension (client_extensions,
extension))
goto out;
ret = TRUE;
out:
return ret;
}
static gboolean print_renderer = FALSE;
static const GOptionEntry entries[] = {
{ "print-renderer", 'p', 0, G_OPTION_ARG_NONE, &print_renderer, "Print GL renderer name", NULL },
{ NULL },
};
int
main (int argc, char **argv)
{
Display *display = NULL;
int ret = HELPER_NO_ACCEL;
GOptionContext *context;
GError *error = NULL;
char *renderer = NULL;
setlocale (LC_ALL, "");
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_error ("Can't parse command line: %s\n", error->message);
g_error_free (error);
goto out;
}
display = XOpenDisplay (NULL);
if (!display) {
_print_error ("No X display.");
goto out;
}
renderer = _get_hardware_gl (display);
if (!renderer) {
_print_error ("No hardware 3D support.");
goto out;
}
ret = has_llvmpipe ? HELPER_SOFTWARE_RENDERING : HELPER_ACCEL;
if (print_renderer)
g_print ("%s", renderer);
out:
if (display)
XCloseDisplay (display);
g_free (renderer);
return ret;
}
/*
* check-gles OpenGLES functional check helper for steam-runtime-tools
* Based on gnome-session-check-accelerated-gles-heper from gnome-session.
*
* Copyright (C) 2019 Collabora Ltd.
* Copyright (C) 2016 Endless Mobile, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author:
* Cosimo Cecchi <cosimo@endlessm.com>
*/
/* for strcasestr */
#define _GNU_SOURCE
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include "gnome-session-check-accelerated-common.h"
static char *
get_gles_renderer (void)
{
/* Select GLESv2 config */
EGLint attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 1,
EGL_GREEN_SIZE, 1,
EGL_BLUE_SIZE, 1,
EGL_NONE
};
EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
gboolean egl_inited = FALSE;
Display *display;
Window win = None;
EGLContext egl_ctx = NULL;
EGLDisplay egl_dpy = NULL;
EGLSurface egl_surf = NULL;
char *renderer = NULL;
display = XOpenDisplay (NULL);
egl_dpy = eglGetDisplay (display);
if (!egl_dpy) {
g_warning ("eglGetDisplay() failed");
goto out;
}
EGLint egl_major, egl_minor;
if (!eglInitialize (egl_dpy, &egl_major, &egl_minor)) {
g_warning ("eglInitialize() failed");
goto out;
}
egl_inited = TRUE;
EGLint num_configs;
EGLConfig config;
if (!eglChooseConfig (egl_dpy, attribs, &config, 1, &num_configs)) {
g_warning ("Failed to get EGL configuration");
goto out;
}
EGLint vid;
if (!eglGetConfigAttrib (egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
g_warning ("Failed to get EGL visual");
goto out;
}
/* The X window visual must match the EGL config */
XVisualInfo *vis_info, vis_template;
int num_visuals;
vis_template.visualid = vid;
vis_info = XGetVisualInfo (display, VisualIDMask, &vis_template, &num_visuals);
if (!vis_info) {
g_warning ("Failed to get X visual");
goto out;
}
XSetWindowAttributes attr;
attr.colormap = XCreateColormap (display, DefaultRootWindow (display),
vis_info->visual, AllocNone);
win = XCreateWindow (display, DefaultRootWindow (display),
0, 0, /* x, y */
1, 1, /* width, height */
0, /* border_width */
vis_info->depth, InputOutput,
vis_info->visual, CWColormap, &attr);
XFree (vis_info);
eglBindAPI (EGL_OPENGL_ES_API);
egl_ctx = eglCreateContext (egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs);
if (!egl_ctx) {
g_warning ("Failed to create EGL context");
goto out;
}
egl_surf = eglCreateWindowSurface (egl_dpy, config, win, NULL);
if (!egl_surf) {
g_warning ("Failed to create EGL surface");
goto out;
}
if (!eglMakeCurrent (egl_dpy, egl_surf, egl_surf, egl_ctx)) {
g_warning ("eglMakeCurrent() failed");
goto out;
}
renderer = g_strdup ((const char *) glGetString (GL_RENDERER));
out:
if (egl_ctx)
eglDestroyContext (egl_dpy, egl_ctx);
if (egl_surf)
eglDestroySurface (egl_dpy, egl_surf);
if (egl_inited)
eglTerminate (egl_dpy);
if (win != None)
XDestroyWindow (display, win);
return renderer;
}
static gboolean print_renderer = FALSE;
static const GOptionEntry entries[] = {
{ "print-renderer", 'p', 0, G_OPTION_ARG_NONE, &print_renderer, "Print EGL renderer name", NULL },
{ NULL },
};
int
main (int argc,
char **argv)
{
char *renderer = NULL;
GOptionContext *context;
int ret = HELPER_NO_ACCEL;
GError *error = NULL;
setlocale (LC_ALL, "");
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error)) {
g_error ("Can't parse command line: %s\n", error->message);
g_error_free (error);
goto out;
}
renderer = get_gles_renderer ();
if (renderer != NULL) {
if (print_renderer)
g_print ("%s", renderer);
if (strcasestr (renderer, "llvmpipe"))
ret = HELPER_SOFTWARE_RENDERING;
else
ret = HELPER_ACCEL;
}
out:
return ret;
}
/* -*- mode:c; c-basic-offset: 8; indent-tabs-mode: nil; -*- */
/* Tool to set the property _GNOME_SESSION_ACCELERATED on the root window */
/*
* Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author:
* Frederic Crozat <fcrozat@suse.com>
*/
/* Exit value for helper */
#define HELPER_ACCEL 0
#define HELPER_NO_ACCEL 1
#define HELPER_SOFTWARE_RENDERING 2
...@@ -31,4 +31,37 @@ executable( ...@@ -31,4 +31,37 @@ executable(
) )
) )
glib_dep = dependency('glib-2.0')
x11_dep = dependency('x11')
executable(
multiarch + '-check-gl',
'check-gl.c',
install : true,
install_dir : join_paths(
get_option('libexecdir'),
'steam-runtime-tools-' + api_major,
),
dependencies : [ glib_dep,
x11_dep,
dependency('gl'),
dependency('xcomposite')
]
)
executable(
multiarch + '-check-gles',
'check-gles.c',
install : true,
install_dir : join_paths(
get_option('libexecdir'),
'steam-runtime-tools-' + api_major,
),
dependencies: [ glib_dep,
x11_dep,
dependency('egl'),
dependency('glesv2')
]
)
# vim:set sw=2 sts=2 et: # vim:set sw=2 sts=2 et:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment