[Mesa-dev] [PATCH v2 3/3] egl: add config debug printout (v2)

Silvestrs Timofejevs silvestrs.timofejevs at imgtec.com
Thu Dec 20 10:02:35 UTC 2018


Feature to print out EGL returned configs for debug purposes.

'eglChooseConfig' and 'eglGetConfigs' debug information printout is
enabled when the log level equals '_EGL_DEBUG'. The configs are
printed, and if any of them are "chosen" they are marked with their
index in the chosen configs array.

v2:
   a) refactor the code in line with Eric's comments
   b) rename function _snprintfStrcat, split it out and put into the
      src/util/u_string.h, make it a separate patch.

Signed-off-by: Silvestrs Timofejevs <silvestrs.timofejevs at imgtec.com>
---
 src/egl/Makefile.sources      |   4 +-
 src/egl/main/eglconfig.c      |  20 +++-
 src/egl/main/eglconfigdebug.c | 265 ++++++++++++++++++++++++++++++++++++++++++
 src/egl/main/eglconfigdebug.h |  55 +++++++++
 src/egl/meson.build           |   2 +
 5 files changed, 341 insertions(+), 5 deletions(-)
 create mode 100644 src/egl/main/eglconfigdebug.c
 create mode 100644 src/egl/main/eglconfigdebug.h

diff --git a/src/egl/Makefile.sources b/src/egl/Makefile.sources
index 0cc5f1b..353a848 100644
--- a/src/egl/Makefile.sources
+++ b/src/egl/Makefile.sources
@@ -28,7 +28,9 @@ LIBEGL_C_FILES := \
 	main/eglsync.c \
 	main/eglsync.h \
 	main/eglentrypoint.h \
-	main/egltypedefs.h
+	main/egltypedefs.h \
+	main/eglconfigdebug.h \
+	main/eglconfigdebug.c
 
 dri2_backend_core_FILES := \
 	drivers/dri2/egl_dri2.c \
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index a346f93..0095dc2 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -40,6 +40,7 @@
 #include "util/macros.h"
 
 #include "eglconfig.h"
+#include "eglconfigdebug.h"
 #include "egldisplay.h"
 #include "eglcurrent.h"
 #include "egllog.h"
@@ -797,14 +798,21 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
                  EGLConfig *configs, EGLint config_size, EGLint *num_configs)
 {
    _EGLConfig criteria;
+   EGLBoolean result;
 
    if (!_eglParseConfigAttribList(&criteria, disp, attrib_list))
       return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
 
-   return _eglFilterConfigArray(disp->Configs,
-         configs, config_size, num_configs,
-         _eglFallbackMatch, _eglFallbackCompare,
-         (void *) &criteria);
+   result = _eglFilterConfigArray(disp->Configs,
+                                  configs, config_size, num_configs,
+                                  _eglFallbackMatch, _eglFallbackCompare,
+                                  (void *) &criteria);
+
+   if (result && (_eglGetLogLevel() == _EGL_DEBUG))
+      eglPrintConfigDebug(drv, disp, configs, *num_configs,
+                          EGL_CONFIG_DEBUG_CHOOSE);
+
+   return result;
 }
 
 
@@ -857,5 +865,9 @@ _eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
    *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
          sizeof(configs[0]), config_size, _eglFlattenConfig);
 
+   if (_eglGetLogLevel() == _EGL_DEBUG)
+      eglPrintConfigDebug(drv, disp, configs, *num_config,
+                          EGL_CONFIG_DEBUG_GET);
+
    return EGL_TRUE;
 }
diff --git a/src/egl/main/eglconfigdebug.c b/src/egl/main/eglconfigdebug.c
new file mode 100644
index 0000000..0617c99
--- /dev/null
+++ b/src/egl/main/eglconfigdebug.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2017 Imagination Technologies.
+ * All Rights Reserved.
+ *
+ * Based on eglinfo, which has copyright:
+ * Copyright (C) 2005  Brian Paul   All Rights Reserved.
+ *
+ * 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
+ * BRIAN PAUL 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "eglarray.h"
+#include "eglconfig.h"
+#include "eglconfigdebug.h"
+#include "egldisplay.h"
+#include "egllog.h"
+#include "egltypedefs.h"
+#include "util/macros.h"
+#include "util/u_string.h"
+
+/* Max debug message length */
+#define CONFIG_DEBUG_MSG_MAX 1000
+
+/*
+ * These are X visual types, so if you're running eglinfo under
+ * something not X, they probably don't make sense.
+ */
+static const char *const vnames[] = { "SG", "GS", "SC", "PC", "TC", "DC" };
+
+struct _printAttributes {
+   EGLint id, size, level;
+   EGLint red, green, blue, alpha;
+   EGLint depth, stencil;
+   EGLint renderable, surfaces;
+   EGLint vid, vtype, caveat, bindRgb, bindRgba;
+   EGLint samples, sampleBuffers;
+   char surfString[32];
+};
+
+static void
+_printHeaderFormat(void)
+{
+   /*
+    * EGL configuration output legend:
+    *
+    * chosen --------------- eglChooseConfig returned config priority,
+    *                        only relevant when eglChooseConfig is called.
+    * id ------------------- EGL_CONFIG_ID
+    * bfsz ----------------- EGL_BUFFER_SIZE
+    * lvl ------------------ EGL_LEVEL
+    *
+    * colourbuffer
+    * r -------------------- EGL_RED_SIZE
+    * g -------------------- EGL_GREEN_SIZE
+    * b -------------------- EGL_BLUE_SIZE
+    * a -------------------- EGL_ALPHA_SIZE
+    * dpth ----------------- EGL_DEPTH_SIZE
+    * stcl ----------------- EGL_STENCIL_SIZE
+    *
+    * multisample
+    * ns ------------------- EGL_SAMPLES
+    * b -------------------- EGL_SAMPLE_BUFFERS
+    * visid ---------------- EGL_NATIVE_VISUAL_ID/EGL_NATIVE_VISUAL_TYPE
+    * caveat --------------- EGL_CONFIG_CAVEAT
+    * bind ----------------- EGL_BIND_TO_TEXTURE_RGB/EGL_BIND_TO_TEXTURE_RGBA
+    *
+    * renderable
+    * gl, es, es2, es3, vg - EGL_RENDERABLE_TYPE
+    *
+    * supported
+    * surfaces ------------- EGL_SURFACE_TYPE
+    */
+   _eglLog(_EGL_DEBUG, "---------------");
+   _eglLog(_EGL_DEBUG, "Configurations:");
+   _eglLog(_EGL_DEBUG, "cho       bf lv colourbuffer dp st  ms           vis  cav  bi     renderable           supported");
+   _eglLog(_EGL_DEBUG, "sen    id sz  l  r  g  b  a  th cl ns b           id  eat  nd  gl es es2 es3 vg         surfaces");
+   _eglLog(_EGL_DEBUG, "---------------");
+}
+
+static void
+_eglGetConfigAttrs(_EGLDriver *const drv, _EGLDisplay *const dpy,
+                   _EGLConfig *const conf, struct _printAttributes *const attr)
+{
+   EGLBoolean success = EGL_TRUE;
+
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_CONFIG_ID, &attr->id);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_BUFFER_SIZE, &attr->size);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_LEVEL, &attr->level);
+
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_RED_SIZE, &attr->red);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_GREEN_SIZE, &attr->green);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_BLUE_SIZE, &attr->blue);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_ALPHA_SIZE, &attr->alpha);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_DEPTH_SIZE, &attr->depth);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_STENCIL_SIZE, &attr->stencil);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_NATIVE_VISUAL_ID, &attr->vid);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_NATIVE_VISUAL_TYPE, &attr->vtype);
+
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_CONFIG_CAVEAT, &attr->caveat);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_BIND_TO_TEXTURE_RGB, &attr->bindRgb);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_BIND_TO_TEXTURE_RGBA, &attr->bindRgba);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_RENDERABLE_TYPE, &attr->renderable);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_SURFACE_TYPE, &attr->surfaces);
+
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_SAMPLES, &attr->samples);
+   success &= _eglGetConfigAttrib(drv, dpy, conf, EGL_SAMPLE_BUFFERS, &attr->sampleBuffers);
+
+   if (!success)
+      _eglLog(_EGL_DEBUG, "%s: config ID = %d, could not obtain all attributes",
+              __func__, conf->ConfigID);
+}
+
+static void
+_eglPrintConfig(_EGLDriver *const drv, _EGLDisplay *const dpy,
+                _EGLConfig *const conf, char *const printMsg)
+{
+   struct _printAttributes attr = { 0 };
+
+   _eglGetConfigAttrs(drv, dpy, conf, &attr);
+
+   if (attr.surfaces & EGL_WINDOW_BIT)
+      strcat(attr.surfString, "win,");
+   if (attr.surfaces & EGL_PBUFFER_BIT)
+      strcat(attr.surfString, "pb,");
+   if (attr.surfaces & EGL_PIXMAP_BIT)
+      strcat(attr.surfString, "pix,");
+   if (attr.surfaces & EGL_STREAM_BIT_KHR)
+      strcat(attr.surfString, "str,");
+   if (attr.surfaces & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
+      strcat(attr.surfString, "prsv");
+   if (strlen(attr.surfString) > 0)
+      attr.surfString[strlen(attr.surfString) - 1] = 0;
+
+   STATIC_ASSERT(sizeof(attr.surfString) >= sizeof("win,pb,pix,str,prsv"));
+
+   util_strnappend(printMsg, CONFIG_DEBUG_MSG_MAX,
+                   "0x%03x %2d %2d %2d %2d %2d %2d  %2d %2d %2d%2d 0x%08x%2s     ",
+                   attr.id, attr.size, attr.level,
+                   attr.red, attr.green, attr.blue, attr.alpha,
+                   attr.depth, attr.stencil,
+                   attr.samples, attr.sampleBuffers, attr.vid,
+                   attr.vtype < 6 ? vnames[attr.vtype] : "--");
+
+   util_strnappend(printMsg, CONFIG_DEBUG_MSG_MAX,
+                   "%c  %c   %c  %c   %c   %c   %c %15s",
+                   (attr.caveat != EGL_NONE) ? 'y' : ' ',
+                   (attr.bindRgba) ? 'a' : (attr.bindRgb) ? 'y' : ' ',
+                   (attr.renderable & EGL_OPENGL_BIT) ? 'y' : ' ',
+                   (attr.renderable & EGL_OPENGL_ES_BIT) ? 'y' : ' ',
+                   (attr.renderable & EGL_OPENGL_ES2_BIT) ? 'y' : ' ',
+                   (attr.renderable & EGL_OPENGL_ES3_BIT) ? 'y' : ' ',
+                   (attr.renderable & EGL_OPENVG_BIT) ? 'y' : ' ',
+                   attr.surfString);
+
+   _eglLog(_EGL_DEBUG, printMsg);
+}
+
+static void
+_eglWriteChosenConfigOrderNum(_EGLConfig *const config,
+                              _EGLConfig *const *const chosenConfigs,
+                              const EGLint numConfigs, char *const printMsg)
+{
+   const char padding[] = "   ";
+
+   if (chosenConfigs == NULL) {
+      util_strnappend(printMsg, CONFIG_DEBUG_MSG_MAX, "%s ", &padding[0]);
+      return;
+   }
+
+   /* Find a match, write its order number and return */
+   for (EGLint i = 0; i < numConfigs; i++) {
+      if (config == chosenConfigs[i]) {
+         util_strnappend(printMsg, CONFIG_DEBUG_MSG_MAX, "%*d ",
+                         strlen(padding), i);
+         return;
+      }
+   }
+
+   util_strnappend(printMsg, CONFIG_DEBUG_MSG_MAX, "%s ", &padding[0]);
+}
+
+static void
+_eglPrintConfigs(_EGLDriver *const drv, _EGLDisplay *const dpy,
+                 EGLConfig *const configs, const EGLint numConfigs,
+                 const enum EGL_CONFIG_DEBUG_OPTION printOption)
+{
+   EGLint numConfigsToPrint;
+   _EGLConfig **configsToPrint;
+   _EGLConfig **chosenConfigs;
+   char *printMsg;
+
+   printMsg = malloc(CONFIG_DEBUG_MSG_MAX);
+   if (!printMsg) {
+      _eglLog(_EGL_DEBUG, "%s: failed to allocate the print message", __func__);
+      return;
+   }
+
+   /*
+    * If the printout request came from the 'eglChooseConfig', all
+    * configs are printed, and the "chosen" configs are marked.
+    */
+   if (printOption == EGL_CONFIG_DEBUG_CHOOSE) {
+      configsToPrint = (_EGLConfig **) dpy->Configs->Elements;
+      numConfigsToPrint = dpy->Configs->Size;
+      chosenConfigs = (_EGLConfig **) configs;
+   } else {
+      assert(printOption == EGL_CONFIG_DEBUG_GET);
+      configsToPrint = (_EGLConfig **) configs;
+      numConfigsToPrint = numConfigs;
+      chosenConfigs = NULL;
+   }
+
+   _printHeaderFormat();
+   for (EGLint i = 0; i < numConfigsToPrint; i++) {
+      _EGLConfig *configToPrint = configsToPrint[i];
+
+      /* "clear" message */
+      printMsg[0] = '\0';
+
+      _eglWriteChosenConfigOrderNum(configToPrint, chosenConfigs, numConfigs,
+                                    printMsg);
+
+      _eglPrintConfig(drv, dpy, configToPrint, printMsg);
+   }
+
+   free(printMsg);
+}
+
+void eglPrintConfigDebug(_EGLDriver *const drv, _EGLDisplay *const dpy,
+                         EGLConfig *const configs, const EGLint numConfigs,
+                         const enum EGL_CONFIG_DEBUG_OPTION printOption)
+{
+   if (!numConfigs || !configs) {
+      _eglLog(_EGL_DEBUG, "%s: nothing to print", __func__);
+      return;
+   }
+
+   switch (printOption) {
+   case EGL_CONFIG_DEBUG_CHOOSE:
+   case EGL_CONFIG_DEBUG_GET:
+      _eglPrintConfigs(drv, dpy, configs, numConfigs, printOption);
+      return;
+   }
+
+   _eglLog(_EGL_DEBUG, "%s: bad debug option", __func__);
+}
diff --git a/src/egl/main/eglconfigdebug.h b/src/egl/main/eglconfigdebug.h
new file mode 100644
index 0000000..8be6223
--- /dev/null
+++ b/src/egl/main/eglconfigdebug.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+ * Copyright 2017 Imagination Technologies.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 (including the
+ * next paragraph) 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.
+ *
+ **************************************************************************/
+
+#ifndef EGLCONFIGDEBUG_INCLUDED
+#define EGLCONFIGDEBUG_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "egltypedefs.h"
+
+/**
+ * Config printout options.
+ */
+enum EGL_CONFIG_DEBUG_OPTION {
+   EGL_CONFIG_DEBUG_CHOOSE,
+   EGL_CONFIG_DEBUG_GET,
+};
+
+/**
+ * Print the list of configs and the associated attributes.
+ */
+void eglPrintConfigDebug(_EGLDriver *const drv, _EGLDisplay *const dpy,
+                         EGLConfig *const configs, EGLint numConfigs,
+                         enum EGL_CONFIG_DEBUG_OPTION printOption);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EGLCONFIGDEBUG_INCLUDED */
diff --git a/src/egl/meson.build b/src/egl/meson.build
index 89bac2c..47ac2c8 100644
--- a/src/egl/meson.build
+++ b/src/egl/meson.build
@@ -31,6 +31,8 @@ files_egl = files(
   'main/eglapi.h',
   'main/eglarray.c',
   'main/eglarray.h',
+  'main/eglconfigdebug.c',
+  'main/eglconfigdebug.h',
   'main/eglconfig.c',
   'main/eglconfig.h',
   'main/eglcontext.c',
-- 
2.7.4



More information about the mesa-dev mailing list