Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 480afb3

Browse files
Show EGL configuration debugging when fail to create surface/context (#19397)
1 parent 8ca6ed6 commit 480afb3

File tree

7 files changed

+666
-61
lines changed

7 files changed

+666
-61
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,9 @@ FILE: ../../../flutter/shell/platform/glfw/platform_handler.h
12141214
FILE: ../../../flutter/shell/platform/glfw/public/flutter_glfw.h
12151215
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc
12161216
FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h
1217+
FILE: ../../../flutter/shell/platform/linux/egl_utils.cc
1218+
FILE: ../../../flutter/shell/platform/linux/egl_utils.h
1219+
FILE: ../../../flutter/shell/platform/linux/egl_utils_test.cc
12171220
FILE: ../../../flutter/shell/platform/linux/fl_basic_message_channel.cc
12181221
FILE: ../../../flutter/shell/platform/linux/fl_basic_message_channel_test.cc
12191222
FILE: ../../../flutter/shell/platform/linux/fl_binary_codec.cc

shell/platform/linux/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ source_set("flutter_linux_sources") {
7676
configs += [ "//flutter/shell/platform/linux/config:gtk" ]
7777

7878
sources = [
79+
"egl_utils.cc",
7980
"fl_basic_message_channel.cc",
8081
"fl_binary_codec.cc",
8182
"fl_binary_messenger.cc",
@@ -138,6 +139,7 @@ executable("flutter_linux_unittests") {
138139
testonly = true
139140

140141
sources = [
142+
"egl_utils_test.cc",
141143
"fl_basic_message_channel_test.cc",
142144
"fl_binary_codec_test.cc",
143145
"fl_binary_messenger_test.cc",

shell/platform/linux/egl_utils.cc

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "egl_utils.h"
6+
7+
#include <EGL/egl.h>
8+
9+
// Converts an EGL decimal value to a string.
10+
static gchar* egl_decimal_to_string(EGLint value) {
11+
return g_strdup_printf("%d", value);
12+
}
13+
14+
// Converts an EGL hexadecimal value to a string.
15+
static gchar* egl_hexadecimal_to_string(EGLint value) {
16+
return g_strdup_printf("0x%x", value);
17+
}
18+
19+
// Converts an EGL enumerated value to a string.
20+
static gchar* egl_enum_to_string(EGLint value) {
21+
if (value == EGL_FALSE)
22+
return g_strdup("EGL_FALSE");
23+
else if (value == EGL_LUMINANCE_BUFFER)
24+
return g_strdup("EGL_LUMINANCE_BUFFER");
25+
else if (value == EGL_NONE)
26+
return g_strdup("EGL_NONE");
27+
else if (value == EGL_NON_CONFORMANT_CONFIG)
28+
return g_strdup("EGL_NON_CONFORMANT_CONFIG");
29+
else if (value == EGL_RGB_BUFFER)
30+
return g_strdup("EGL_RGB_BUFFER");
31+
else if (value == EGL_SLOW_CONFIG)
32+
return g_strdup("EGL_SLOW_CONFIG");
33+
else if (value == EGL_TRANSPARENT_RGB)
34+
return g_strdup("EGL_TRANSPARENT_RGB");
35+
else if (value == EGL_TRUE)
36+
return g_strdup("EGL_TRUE");
37+
else
38+
return nullptr;
39+
}
40+
41+
// Ensures the given bit is not set in a bitfield. Returns TRUE if that bit was
42+
// cleared.
43+
static gboolean clear_bit(EGLint* field, EGLint bit) {
44+
if ((*field & bit) == 0)
45+
return FALSE;
46+
47+
*field ^= bit;
48+
return TRUE;
49+
}
50+
51+
// Converts an EGL renderable type bitfield to a string.
52+
static gchar* egl_renderable_type_to_string(EGLint value) {
53+
EGLint v = value;
54+
g_autoptr(GPtrArray) strings = g_ptr_array_new_with_free_func(g_free);
55+
if (clear_bit(&v, EGL_OPENGL_ES_BIT))
56+
g_ptr_array_add(strings, g_strdup("EGL_OPENGL_ES_BIT"));
57+
if (clear_bit(&v, EGL_OPENVG_BIT))
58+
g_ptr_array_add(strings, g_strdup("EGL_OPENVG_BIT"));
59+
if (clear_bit(&v, EGL_OPENGL_ES2_BIT))
60+
g_ptr_array_add(strings, g_strdup("EGL_OPENGL_ES2_BIT"));
61+
if (clear_bit(&v, EGL_OPENGL_BIT))
62+
g_ptr_array_add(strings, g_strdup("EGL_OPENGL_BIT"));
63+
if (clear_bit(&v, EGL_OPENGL_ES3_BIT))
64+
g_ptr_array_add(strings, g_strdup("EGL_OPENGL_ES3_BIT"));
65+
if (v != 0)
66+
g_ptr_array_add(strings, egl_hexadecimal_to_string(v));
67+
g_ptr_array_add(strings, nullptr);
68+
69+
return g_strjoinv("|", reinterpret_cast<gchar**>(strings->pdata));
70+
}
71+
72+
// Converts an EGL surface type bitfield to a string.
73+
static gchar* egl_surface_type_to_string(EGLint value) {
74+
EGLint v = value;
75+
g_autoptr(GPtrArray) strings = g_ptr_array_new_with_free_func(g_free);
76+
if (clear_bit(&v, EGL_PBUFFER_BIT))
77+
g_ptr_array_add(strings, g_strdup("EGL_PBUFFER_BIT"));
78+
if (clear_bit(&v, EGL_PIXMAP_BIT))
79+
g_ptr_array_add(strings, g_strdup("EGL_PIXMAP_BIT"));
80+
if (clear_bit(&v, EGL_WINDOW_BIT))
81+
g_ptr_array_add(strings, g_strdup("EGL_WINDOW_BIT"));
82+
if (v != 0)
83+
g_ptr_array_add(strings, egl_hexadecimal_to_string(v));
84+
g_ptr_array_add(strings, nullptr);
85+
86+
return g_strjoinv("|", reinterpret_cast<gchar**>(strings->pdata));
87+
}
88+
89+
const gchar* egl_error_to_string(EGLint error) {
90+
switch (error) {
91+
case EGL_SUCCESS:
92+
return "Success";
93+
case EGL_NOT_INITIALIZED:
94+
return "Not Initialized";
95+
case EGL_BAD_ACCESS:
96+
return "Bad Access";
97+
case EGL_BAD_ALLOC:
98+
return "Bad Allocation";
99+
case EGL_BAD_ATTRIBUTE:
100+
return "Bad Attribute";
101+
case EGL_BAD_CONTEXT:
102+
return "Bad Context";
103+
case EGL_BAD_CONFIG:
104+
return "Bad Configuration";
105+
case EGL_BAD_CURRENT_SURFACE:
106+
return "Bad Current Surface";
107+
case EGL_BAD_DISPLAY:
108+
return "Bad Display";
109+
case EGL_BAD_SURFACE:
110+
return "Bad Surface";
111+
case EGL_BAD_MATCH:
112+
return "Bad Match";
113+
case EGL_BAD_PARAMETER:
114+
return "Bad Parameter";
115+
case EGL_BAD_NATIVE_PIXMAP:
116+
return "Bad Native Pixmap";
117+
case EGL_BAD_NATIVE_WINDOW:
118+
return "Bad Native Window";
119+
case EGL_CONTEXT_LOST:
120+
return "Context Lost";
121+
default:
122+
return "Unknown Error";
123+
}
124+
}
125+
126+
gchar* egl_config_to_string(EGLDisplay display, EGLConfig config) {
127+
struct {
128+
EGLint attribute;
129+
const gchar* name;
130+
gchar* (*to_string)(EGLint value);
131+
} config_items[] = {{
132+
EGL_CONFIG_ID,
133+
"EGL_CONFIG_ID",
134+
egl_decimal_to_string,
135+
},
136+
{
137+
EGL_BUFFER_SIZE,
138+
"EGL_BUFFER_SIZE",
139+
egl_decimal_to_string,
140+
},
141+
{
142+
EGL_COLOR_BUFFER_TYPE,
143+
"EGL_COLOR_BUFFER_TYPE",
144+
egl_enum_to_string,
145+
},
146+
{
147+
EGL_TRANSPARENT_TYPE,
148+
"EGL_TRANSPARENT_TYPE",
149+
egl_enum_to_string,
150+
},
151+
{
152+
EGL_LEVEL,
153+
"EGL_LEVEL",
154+
egl_decimal_to_string,
155+
},
156+
{
157+
EGL_RED_SIZE,
158+
"EGL_RED_SIZE",
159+
egl_decimal_to_string,
160+
},
161+
{
162+
EGL_GREEN_SIZE,
163+
"EGL_GREEN_SIZE",
164+
egl_decimal_to_string,
165+
},
166+
{
167+
EGL_BLUE_SIZE,
168+
"EGL_BLUE_SIZE",
169+
egl_decimal_to_string,
170+
},
171+
{
172+
EGL_ALPHA_SIZE,
173+
"EGL_ALPHA_SIZE",
174+
egl_decimal_to_string,
175+
},
176+
{
177+
EGL_DEPTH_SIZE,
178+
"EGL_DEPTH_SIZE",
179+
egl_decimal_to_string,
180+
},
181+
{
182+
EGL_STENCIL_SIZE,
183+
"EGL_STENCIL_SIZE",
184+
egl_decimal_to_string,
185+
},
186+
{
187+
EGL_SAMPLES,
188+
"EGL_SAMPLES",
189+
egl_decimal_to_string,
190+
},
191+
{
192+
EGL_SAMPLE_BUFFERS,
193+
"EGL_SAMPLE_BUFFERS",
194+
egl_decimal_to_string,
195+
},
196+
{
197+
EGL_NATIVE_VISUAL_ID,
198+
"EGL_NATIVE_VISUAL_ID",
199+
egl_hexadecimal_to_string,
200+
},
201+
{
202+
EGL_NATIVE_VISUAL_TYPE,
203+
"EGL_NATIVE_VISUAL_TYPE",
204+
egl_hexadecimal_to_string,
205+
},
206+
{
207+
EGL_NATIVE_RENDERABLE,
208+
"EGL_NATIVE_RENDERABLE",
209+
egl_enum_to_string,
210+
},
211+
{
212+
EGL_CONFIG_CAVEAT,
213+
"EGL_CONFIG_CAVEAT",
214+
egl_enum_to_string,
215+
},
216+
{
217+
EGL_BIND_TO_TEXTURE_RGB,
218+
"EGL_BIND_TO_TEXTURE_RGB",
219+
egl_enum_to_string,
220+
},
221+
{
222+
EGL_BIND_TO_TEXTURE_RGBA,
223+
"EGL_BIND_TO_TEXTURE_RGBA",
224+
egl_enum_to_string,
225+
},
226+
{
227+
EGL_RENDERABLE_TYPE,
228+
"EGL_RENDERABLE_TYPE",
229+
egl_renderable_type_to_string,
230+
},
231+
{
232+
EGL_CONFORMANT,
233+
"EGL_CONFORMANT",
234+
egl_renderable_type_to_string,
235+
},
236+
{
237+
EGL_SURFACE_TYPE,
238+
"EGL_SURFACE_TYPE",
239+
egl_surface_type_to_string,
240+
},
241+
{
242+
EGL_MAX_PBUFFER_WIDTH,
243+
"EGL_MAX_PBUFFER_WIDTH",
244+
egl_decimal_to_string,
245+
},
246+
{
247+
EGL_MAX_PBUFFER_HEIGHT,
248+
"EGL_MAX_PBUFFER_HEIGHT",
249+
egl_decimal_to_string,
250+
},
251+
{
252+
EGL_MAX_PBUFFER_PIXELS,
253+
"EGL_MAX_PBUFFER_PIXELS",
254+
egl_decimal_to_string,
255+
},
256+
{
257+
EGL_MIN_SWAP_INTERVAL,
258+
"EGL_MIN_SWAP_INTERVAL",
259+
egl_decimal_to_string,
260+
},
261+
{
262+
EGL_MAX_SWAP_INTERVAL,
263+
"EGL_MAX_SWAP_INTERVAL",
264+
egl_decimal_to_string,
265+
},
266+
{EGL_NONE, nullptr, nullptr}};
267+
268+
g_autoptr(GPtrArray) strings = g_ptr_array_new_with_free_func(g_free);
269+
for (int i = 0; config_items[i].attribute != EGL_NONE; i++) {
270+
EGLint value;
271+
if (!eglGetConfigAttrib(display, config, config_items[i].attribute, &value))
272+
continue;
273+
g_autofree gchar* value_string = config_items[i].to_string(value);
274+
if (value_string == nullptr)
275+
value_string = egl_hexadecimal_to_string(value);
276+
g_ptr_array_add(
277+
strings, g_strdup_printf("%s=%s", config_items[i].name, value_string));
278+
}
279+
g_ptr_array_add(strings, nullptr);
280+
281+
return g_strjoinv(" ", reinterpret_cast<gchar**>(strings->pdata));
282+
}

shell/platform/linux/egl_utils.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_EGL_UTILS_H_
6+
#define FLUTTER_SHELL_PLATFORM_LINUX_EGL_UTILS_H_
7+
8+
#include <EGL/egl.h>
9+
10+
#include <glib.h>
11+
12+
G_BEGIN_DECLS
13+
14+
/**
15+
* egl_error_to_string:
16+
* @error: an EGL error code.
17+
*
18+
* Converts an egl error code to a human readable string. e.g. "Bad Match".
19+
*
20+
* Returns: an error description.
21+
*/
22+
const gchar* egl_error_to_string(EGLint error);
23+
24+
/**
25+
* egl_config_to_string:
26+
* @display: an EGL display.
27+
* @config: an EGL configuration.
28+
*
29+
* Converts an EGL configuration to a human readable string. e.g.
30+
* "EGL_CONFIG_ID=1 EGL_RED_SIZE=8...".
31+
*
32+
* Returns: a configuration description.
33+
*/
34+
gchar* egl_config_to_string(EGLDisplay display, EGLConfig config);
35+
36+
G_END_DECLS
37+
38+
#endif // FLUTTER_SHELL_PLATFORM_LINUX_EGL_UTILS_H_

0 commit comments

Comments
 (0)