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 <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "util/macros.h"
32 #include "eglarray.h"
33 #include "eglconfig.h"
34 #include "eglconfigdebug.h"
35 #include "egldisplay.h"
36 #include "egllog.h"
37 #include "egltypedefs.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 */
46 static const char *const vnames[] = {"SG", "GS", "SC", "PC", "TC", "DC"};
47
48 static void
_printHeaderFormat(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 /* clang-format off */
82 _eglLog(_EGL_DEBUG, "---------------");
83 _eglLog(_EGL_DEBUG, "Configurations:");
84 _eglLog(_EGL_DEBUG, "cho bf lv colourbuffer dp st ms vis cav bi renderable supported");
85 _eglLog(_EGL_DEBUG, "sen id sz l r g b a th cl ns b id eat nd gl es es2 es3 vg surfaces");
86 _eglLog(_EGL_DEBUG, "---------------");
87 /* clang-format on */
88 }
89
90 /* Append a formatted string to the buffer, up to the buffer size */
91 static inline void
_strnAppend(char * const buf,const int bufSize,const char * fmt,...)92 _strnAppend(char *const buf, const int bufSize, const char *fmt, ...)
93 {
94 int maxAllowed;
95 va_list args;
96 size_t bufLen = strlen(buf);
97
98 maxAllowed = bufSize - bufLen;
99 assert(maxAllowed >= 0);
100
101 va_start(args, fmt);
102 (void)vsnprintf(&buf[bufLen], maxAllowed, fmt, args);
103 va_end(args);
104 }
105
106 static void
_eglPrintConfig(_EGLConfig * const conf,const int chosenIndex)107 _eglPrintConfig(_EGLConfig *const conf, const int chosenIndex)
108 {
109 const char padding[] = " ";
110 char printMsg[CONFIG_DEBUG_MSG_MAX] = "";
111 char surfString[32] = "";
112 EGLint renderable, surfaces, vtype, bindRgb, bindRgba;
113
114 vtype = conf->NativeVisualType;
115 surfaces = conf->SurfaceType;
116
117 STATIC_ASSERT(sizeof(surfString) >= sizeof("win,pb,pix,str,prsv"));
118
119 if (surfaces & EGL_WINDOW_BIT)
120 strcat(surfString, "win,");
121 if (surfaces & EGL_PBUFFER_BIT)
122 strcat(surfString, "pb,");
123 if (surfaces & EGL_PIXMAP_BIT)
124 strcat(surfString, "pix,");
125 if (surfaces & EGL_STREAM_BIT_KHR)
126 strcat(surfString, "str,");
127 if (surfaces & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
128 strcat(surfString, "prsv");
129
130 /* If one of chosen configs, print its index in the returned config array */
131 if (chosenIndex >= 0)
132 _strnAppend(printMsg, sizeof(printMsg), "%*d ", strlen(padding),
133 chosenIndex);
134 else
135 _strnAppend(printMsg, sizeof(printMsg), "%s ", &padding[0]);
136
137 _strnAppend(printMsg, sizeof(printMsg),
138 "0x%03x %2d %2d %2d %2d %2d %2d %2d %2d %2d%2d 0x%08x%2s ",
139 conf->ConfigID, conf->BufferSize, conf->Level, conf->RedSize,
140 conf->GreenSize, conf->BlueSize, conf->AlphaSize,
141 conf->DepthSize, conf->StencilSize, conf->Samples,
142 conf->SampleBuffers, conf->NativeVisualID,
143 vtype < 6 ? vnames[vtype] : "--");
144
145 bindRgb = conf->BindToTextureRGB;
146 bindRgba = conf->BindToTextureRGBA;
147 renderable = conf->RenderableType;
148
149 _strnAppend(printMsg, sizeof(printMsg),
150 "%c %c %c %c %c %c %c %15s",
151 (conf->ConfigCaveat != EGL_NONE) ? 'y' : ' ',
152 (bindRgba) ? 'a'
153 : (bindRgb) ? 'y'
154 : ' ',
155 (renderable & EGL_OPENGL_BIT) ? 'y' : ' ',
156 (renderable & EGL_OPENGL_ES_BIT) ? 'y' : ' ',
157 (renderable & EGL_OPENGL_ES2_BIT) ? 'y' : ' ',
158 (renderable & EGL_OPENGL_ES3_BIT) ? 'y' : ' ',
159 (renderable & EGL_OPENVG_BIT) ? 'y' : ' ', surfString);
160
161 _eglLog(_EGL_DEBUG, printMsg);
162 }
163
164 void
eglPrintConfigDebug(const _EGLDisplay * const disp,const EGLConfig * const configs,const EGLint numConfigs,const EGLBoolean printChosen)165 eglPrintConfigDebug(const _EGLDisplay *const disp,
166 const EGLConfig *const configs, const EGLint numConfigs,
167 const EGLBoolean printChosen)
168 {
169 EGLint numConfigsToPrint;
170 _EGLConfig **configsToPrint;
171 _EGLConfig **chosenConfigs;
172
173 if (!numConfigs || !configs) {
174 _eglLog(_EGL_DEBUG, "%s: nothing to print", __func__);
175 return;
176 }
177
178 /*
179 * If the printout request came from the 'eglChooseConfig', all
180 * configs are printed, and the "chosen" configs are marked.
181 */
182 if (printChosen) {
183 configsToPrint = (_EGLConfig **)disp->Configs->Elements;
184 numConfigsToPrint = disp->Configs->Size;
185 chosenConfigs = (_EGLConfig **)configs;
186 } else {
187 configsToPrint = (_EGLConfig **)configs;
188 numConfigsToPrint = numConfigs;
189 chosenConfigs = NULL;
190 }
191
192 _printHeaderFormat();
193 for (EGLint i = 0; i < numConfigsToPrint; i++) {
194 _EGLConfig *configToPrint = configsToPrint[i];
195 EGLint chosenIndex = -1;
196
197 /* See if the current config to print is one of the chosen configs */
198 if (chosenConfigs)
199 for (EGLint j = 0; j < numConfigs; j++)
200 if (configToPrint == chosenConfigs[j])
201 chosenIndex = j;
202
203 _eglPrintConfig(configToPrint, chosenIndex);
204 }
205 }
206