On Mon, Jan 14, 2019 at 08:20:09PM +0000, Emil Velikov wrote: > e aOn Fri, 11 Jan 2019 at 16:34, Silvestrs Timofejevs > <silvestrs.timofej...@imgtec.com> wrote: > > > > 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. > > v3: > > remove unnecessary 'const' qualifiers from the function prototype > > > > Signed-off-by: Silvestrs Timofejevs <silvestrs.timofej...@imgtec.com> > > Reviewed-by: Eric Engestrom <eric.engest...@intel.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); > > + > > _eglGetConfigAttrib is for API level usage. Since we know the attribs > are valid we can use _eglGetConfigKey(). > Thus all the validation (as done in the former) and error checking > here can be dropped. > > Taking it a step further I'd drop the struct and directly use the > values from _eglGetConfigKey(). > > > + 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 }; > > + > char surfstring[32]; > > > + _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); > We don't need to walk through the list twice. Simply pass the config > (to be printed) to _eglPrintConfig()? > Plus we can drop the temporary printMsg all together. The idea is when the _eglChooseConfig function is called, we print all of the configs. If a config is "chosen", then we print its index number at the beginning of the printout string. Example:
all configs: chosen configs: conf0 conf1 conf1 conf4 conf2 conf3 conf4 output: ...................... 0 ...................... ...................... ...................... 1 ...................... To do that we would have to walk the array twice (to print all of the configs, and find out which are chosen to mark them). That seems a little wasteful, but on the other hand this is a debug feature, so being more descriptive is more important (in my opinion). What do you think? > > > + > > + 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; > I'd fold the two functions _eglPrintConfigs and eglPrintConfigDebug. > Might even swap the EGL_CONFIG_DEBUG_OPTION enum with "print_chosen" > or equivalent bool. > > With my nitpicking, the resulting code should be around half the size ;-) > > HTH > Emil Thanks, Silvestrs _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev