From 60781bc6c25997adda83f719675d13a4be50bc21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 24 Jul 2017 17:24:29 +0800 Subject: [PATCH] backends: Add OpenGL ES 3 abstraction layer Add helper functions and macros for managing and drawing OpenGL ES 3. It will be used for blitting framebuffers between multiple GPUs in hybrid GPU systems. https://bugzilla.gnome.org/show_bug.cgi?id=785381 --- src/Makefile.am | 3 + src/backends/meta-gles3-table.h | 36 +++++++ src/backends/meta-gles3.c | 163 ++++++++++++++++++++++++++++++++ src/backends/meta-gles3.h | 83 ++++++++++++++++ 4 files changed, 285 insertions(+) create mode 100644 src/backends/meta-gles3-table.h create mode 100644 src/backends/meta-gles3.c create mode 100644 src/backends/meta-gles3.h diff --git a/src/Makefile.am b/src/Makefile.am index a9642753e..c0d2a6552 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -109,6 +109,9 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ backends/meta-egl.c \ backends/meta-egl.h \ backends/meta-egl-ext.h \ + backends/meta-gles3.c \ + backends/meta-gles3.h \ + backends/meta-gles3-table.h \ backends/meta-gpu.c \ backends/meta-gpu.h \ backends/meta-display-config-shared.h \ diff --git a/src/backends/meta-gles3-table.h b/src/backends/meta-gles3-table.h new file mode 100644 index 000000000..4cc866060 --- /dev/null +++ b/src/backends/meta-gles3-table.h @@ -0,0 +1,36 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * 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. + * + */ + +#ifndef META_GLES3_TABLE_H +#define META_GLES3_TABLE_H + +#include +#include +#include + +typedef struct _MetaGles3Table +{ + void (* glEGLImageTargetTexture2DOES) (GLenum target, + GLeglImageOES image); +} MetaGles3Table; + +#endif /* META_GLES3_TABLE */ diff --git a/src/backends/meta-gles3.c b/src/backends/meta-gles3.c new file mode 100644 index 000000000..f467a8f94 --- /dev/null +++ b/src/backends/meta-gles3.c @@ -0,0 +1,163 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * 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. + * + */ +#include + +#include "config.h" + +#include "backends/meta-gles3.h" + +#include +#include + +#include "backends/meta-gles3-table.h" + +struct _MetaGles3 +{ + GObject parent; + + MetaEgl *egl; + + MetaGles3Table table; +}; + +G_DEFINE_TYPE (MetaGles3, meta_gles3, G_TYPE_OBJECT) + +MetaGles3Table * +meta_gles3_get_table (MetaGles3 *gles3) +{ + return &gles3->table; +} + +void +meta_gles3_ensure_loaded (MetaGles3 *gles3, + gpointer *func, + const char *name) +{ + GError *error = NULL; + + if (*func) + return; + + *func = meta_egl_get_proc_address (gles3->egl, name, &error); + if (!*func) + g_error ("Failed to load GLES3 symbol: %s", error->message); +} + +static const char * +get_gl_error_str (GLenum gl_error) +{ + switch (gl_error) + { + case GL_NO_ERROR: + return "No error has been recorded."; + case GL_INVALID_ENUM: + return "An unacceptable value is specified for an enumerated argument."; + case GL_INVALID_VALUE: + return "A numeric argument is out of range."; + case GL_INVALID_OPERATION: + return "The specified operation is not allowed in the current state."; + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "The framebuffer object is not complete."; + case GL_OUT_OF_MEMORY: + return "There is not enough memory left to execute the command."; + default: + return "Unknown error"; + } +} + +void +meta_gles3_clear_error (MetaGles3 *gles3) +{ + while (TRUE) + { + GLenum gl_error = glGetError (); + + if (gl_error == GL_NO_ERROR) + break; + } +} + +gboolean +meta_gles3_validate (MetaGles3 *gles3, + GError **error) +{ + GLenum gl_error; + + gl_error = glGetError (); + if (gl_error != GL_NO_ERROR) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + get_gl_error_str (gl_error)); + return FALSE; + } + + return TRUE; +} + +gboolean +meta_gles3_has_extensions (MetaGles3 *gles3, + char ***missing_extensions, + char *first_extension, + ...) +{ + va_list var_args; + const char *extensions_str; + gboolean has_extensions; + + extensions_str = (const char *) glGetString (GL_EXTENSIONS); + if (!extensions_str) + { + g_warning ("Failed to get string: %s", get_gl_error_str (glGetError ())); + return FALSE; + } + + va_start (var_args, first_extension); + has_extensions = + meta_extensions_string_has_extensions_valist (extensions_str, + missing_extensions, + first_extension, + var_args); + va_end (var_args); + + return has_extensions; +} + +MetaGles3 * +meta_gles3_new (MetaEgl *egl) +{ + MetaGles3 *gles3; + + gles3 = g_object_new (META_TYPE_GLES3, NULL); + gles3->egl = egl; + + return gles3; +} + +static void +meta_gles3_init (MetaGles3 *gles3) +{ +} + +static void +meta_gles3_class_init (MetaGles3Class *klass) +{ +} diff --git a/src/backends/meta-gles3.h b/src/backends/meta-gles3.h new file mode 100644 index 000000000..6f42be2e0 --- /dev/null +++ b/src/backends/meta-gles3.h @@ -0,0 +1,83 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2017 Red Hat + * + * 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. + * + */ + +#ifndef META_GLES3_H +#define META_GLES3_H + +#include + +#include "backends/meta-egl.h" + +typedef struct _MetaGles3Table MetaGles3Table; + +#define META_TYPE_GLES3 (meta_gles3_get_type ()) +G_DECLARE_FINAL_TYPE (MetaGles3, meta_gles3, META, GLES3, GObject) + +MetaGles3Table * meta_gles3_get_table (MetaGles3 *gles3); + +void meta_gles3_clear_error (MetaGles3 *gles3); + +gboolean meta_gles3_validate (MetaGles3 *gles3, + GError **error); + +void meta_gles3_ensure_loaded (MetaGles3 *gles, + gpointer *func, + const char *name); + +gboolean meta_gles3_has_extensions (MetaGles3 *gles3, + char ***missing_extensions, + char *first_extension, + ...); + +MetaGles3 * meta_gles3_new (MetaEgl *egl); + +#define GLBAS(gles3, func, args) \ +{ \ + GError *_error = NULL; \ + \ + func args; \ + \ + if (!meta_gles3_validate (gles3, &_error)) \ + { \ + g_warning ("%s %s failed: %s", #func, #args, _error->message); \ + g_error_free (_error); \ + } \ +} + +#define GLEXT(gles3, func, args) \ +{ \ + GError *_error = NULL; \ + MetaGles3Table *table; \ + \ + table = meta_gles3_get_table (gles3); \ + meta_gles3_ensure_loaded (gles3, (gpointer *) &table->func, #func); \ + \ + table->func args; \ + \ + if (!meta_gles3_validate (gles3, &_error)) \ + { \ + g_warning ("%s %s failed: %s", #func, #args, _error->message); \ + g_error_free (_error); \ + } \ +} + +#endif /* META_GLES3_H */