1/* 2 * Copyright 2019 Imagination Technologies. 3 * All Rights Reserved. 4 * 5 * Based on eglinfo, which has copyright: 6 * Copyright (C) 2005 Brian Paul All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26#include <stdlib.h> 27#include <string.h> 28#include <stdio.h> 29#include <stdarg.h> 30 31#include "eglarray.h" 32#include "eglconfig.h" 33#include "eglconfigdebug.h" 34#include "egldisplay.h" 35#include "egllog.h" 36#include "egltypedefs.h" 37#include "util/macros.h" 38 39/* Max debug message length */ 40#define CONFIG_DEBUG_MSG_MAX 1000 41 42/* 43 * These are X visual types, so if you're running eglinfo under 44 * something not X, they probably don't make sense. 45 */ 46static const char *const vnames[] = { "SG", "GS", "SC", "PC", "TC", "DC" }; 47 48static void 49_printHeaderFormat(void) 50{ 51 /* 52 * EGL configuration output legend: 53 * 54 * chosen --------------- eglChooseConfig returned config priority, 55 * only relevant when eglChooseConfig is called. 56 * id ------------------- EGL_CONFIG_ID 57 * bfsz ----------------- EGL_BUFFER_SIZE 58 * lvl ------------------ EGL_LEVEL 59 * 60 * colourbuffer 61 * r -------------------- EGL_RED_SIZE 62 * g -------------------- EGL_GREEN_SIZE 63 * b -------------------- EGL_BLUE_SIZE 64 * a -------------------- EGL_ALPHA_SIZE 65 * dpth ----------------- EGL_DEPTH_SIZE 66 * stcl ----------------- EGL_STENCIL_SIZE 67 * 68 * multisample 69 * ns ------------------- EGL_SAMPLES 70 * b -------------------- EGL_SAMPLE_BUFFERS 71 * visid ---------------- EGL_NATIVE_VISUAL_ID/EGL_NATIVE_VISUAL_TYPE 72 * caveat --------------- EGL_CONFIG_CAVEAT 73 * bind ----------------- EGL_BIND_TO_TEXTURE_RGB/EGL_BIND_TO_TEXTURE_RGBA 74 * 75 * renderable 76 * gl, es, es2, es3, vg - EGL_RENDERABLE_TYPE 77 * 78 * supported 79 * surfaces ------------- EGL_SURFACE_TYPE 80 */ 81 _eglLog(_EGL_DEBUG, "---------------"); 82 _eglLog(_EGL_DEBUG, "Configurations:"); 83 _eglLog(_EGL_DEBUG, "cho bf lv colourbuffer dp st ms vis cav bi renderable supported"); 84 _eglLog(_EGL_DEBUG, "sen id sz l r g b a th cl ns b id eat nd gl es es2 es3 vg surfaces"); 85 _eglLog(_EGL_DEBUG, "---------------"); 86} 87 88/* Append a formatted string to the buffer, up to the buffer size */ 89static inline void 90_strnAppend(char *const buf, const int bufSize, const char *fmt, ...) 91{ 92 int maxAllowed; 93 va_list args; 94 size_t bufLen = strlen(buf); 95 96 maxAllowed = bufSize - bufLen; 97 assert(maxAllowed >= 0); 98 99 va_start(args, fmt); 100 (void) vsnprintf(&buf[bufLen], maxAllowed, fmt, args); 101 va_end(args); 102} 103 104static void 105_eglPrintConfig(_EGLConfig *const conf, const int chosenIndex) 106{ 107 const char padding[] = " "; 108 char printMsg[CONFIG_DEBUG_MSG_MAX] = ""; 109 char surfString[32] = ""; 110 EGLint renderable, surfaces, vtype, bindRgb, bindRgba; 111 112 vtype = conf->NativeVisualType; 113 surfaces = conf->SurfaceType; 114 115 STATIC_ASSERT(sizeof(surfString) >= sizeof("win,pb,pix,str,prsv")); 116 117 if (surfaces & EGL_WINDOW_BIT) 118 strcat(surfString, "win,"); 119 if (surfaces & EGL_PBUFFER_BIT) 120 strcat(surfString, "pb,"); 121 if (surfaces & EGL_PIXMAP_BIT) 122 strcat(surfString, "pix,"); 123 if (surfaces & EGL_STREAM_BIT_KHR) 124 strcat(surfString, "str,"); 125 if (surfaces & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) 126 strcat(surfString, "prsv"); 127 128 /* If one of chosen configs, print its index in the returned config array */ 129 if (chosenIndex >= 0) 130 _strnAppend(printMsg, sizeof(printMsg), "%*d ", strlen(padding), 131 chosenIndex); 132 else 133 _strnAppend(printMsg, sizeof(printMsg), "%s ", &padding[0]); 134 135 _strnAppend(printMsg, sizeof(printMsg), 136 "0x%03x %2d %2d %2d %2d %2d %2d %2d %2d %2d%2d 0x%08x%2s ", 137 conf->ConfigID, conf->BufferSize, conf->Level, 138 conf->RedSize, conf->GreenSize, conf->BlueSize, conf->AlphaSize, 139 conf->DepthSize, conf->StencilSize, 140 conf->Samples, conf->SampleBuffers, conf->NativeVisualID, 141 vtype < 6 ? vnames[vtype] : "--"); 142 143 bindRgb = conf->BindToTextureRGB; 144 bindRgba = conf->BindToTextureRGBA; 145 renderable = conf->RenderableType; 146 147 _strnAppend(printMsg, sizeof(printMsg), 148 "%c %c %c %c %c %c %c %15s", 149 (conf->ConfigCaveat != EGL_NONE) ? 'y' : ' ', 150 (bindRgba) ? 'a' : (bindRgb) ? 'y' : ' ', 151 (renderable & EGL_OPENGL_BIT) ? 'y' : ' ', 152 (renderable & EGL_OPENGL_ES_BIT) ? 'y' : ' ', 153 (renderable & EGL_OPENGL_ES2_BIT) ? 'y' : ' ', 154 (renderable & EGL_OPENGL_ES3_BIT) ? 'y' : ' ', 155 (renderable & EGL_OPENVG_BIT) ? 'y' : ' ', 156 surfString); 157 158 _eglLog(_EGL_DEBUG, printMsg); 159} 160 161void eglPrintConfigDebug(const _EGLDisplay *const disp, 162 const EGLConfig *const configs, 163 const EGLint numConfigs, const EGLBoolean printChosen) 164{ 165 EGLint numConfigsToPrint; 166 _EGLConfig **configsToPrint; 167 _EGLConfig **chosenConfigs; 168 169 if (!numConfigs || !configs) { 170 _eglLog(_EGL_DEBUG, "%s: nothing to print", __func__); 171 return; 172 } 173 174 /* 175 * If the printout request came from the 'eglChooseConfig', all 176 * configs are printed, and the "chosen" configs are marked. 177 */ 178 if (printChosen) { 179 configsToPrint = (_EGLConfig **) disp->Configs->Elements; 180 numConfigsToPrint = disp->Configs->Size; 181 chosenConfigs = (_EGLConfig **) configs; 182 } else { 183 configsToPrint = (_EGLConfig **) configs; 184 numConfigsToPrint = numConfigs; 185 chosenConfigs = NULL; 186 } 187 188 _printHeaderFormat(); 189 for (EGLint i = 0; i < numConfigsToPrint; i++) { 190 _EGLConfig *configToPrint = configsToPrint[i]; 191 EGLint chosenIndex = -1; 192 193 /* See if the current config to print is one of the chosen configs */ 194 if (chosenConfigs) 195 for (EGLint j = 0; j < numConfigs; j++) 196 if (configToPrint == chosenConfigs[j]) 197 chosenIndex = j; 198 199 _eglPrintConfig(configToPrint, chosenIndex); 200 } 201} 202