1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // EGLDebugTest.cpp:
7 // Tests of EGL_KHR_debug extension
8
9 #include <gtest/gtest.h>
10
11 #include "test_utils/ANGLETest.h"
12 #include "test_utils/angle_test_configs.h"
13 #include "util/EGLWindow.h"
14
15 namespace angle
16 {
17 class EGLDebugTest : public ANGLETest
18 {
19 protected:
testTearDown()20 void testTearDown() override { eglDebugMessageControlKHR(nullptr, nullptr); }
21
hasExtension() const22 bool hasExtension() const { return IsEGLClientExtensionEnabled("EGL_KHR_debug"); }
23
StubCallback(EGLenum error,const char * command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char * message)24 static void EGLAPIENTRY StubCallback(EGLenum error,
25 const char *command,
26 EGLint messageType,
27 EGLLabelKHR threadLabel,
28 EGLLabelKHR objectLabel,
29 const char *message)
30 {}
31
CheckBadBindAPIError(EGLenum error,const char * command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char * message)32 static void EGLAPIENTRY CheckBadBindAPIError(EGLenum error,
33 const char *command,
34 EGLint messageType,
35 EGLLabelKHR threadLabel,
36 EGLLabelKHR objectLabel,
37 const char *message)
38 {
39 EXPECT_STREQ("eglBindAPI", command);
40 ASSERT_EGLENUM_EQ(EGL_BAD_PARAMETER, error);
41 EXPECT_STREQ("Thread", static_cast<const char *>(threadLabel));
42 }
43
EGLAttribToDebugCallback(EGLAttrib attrib)44 static EGLDEBUGPROCKHR EGLAttribToDebugCallback(EGLAttrib attrib)
45 {
46 return reinterpret_cast<EGLDEBUGPROCKHR>(static_cast<uintptr_t>(attrib));
47 }
48
DebugCallbackToEGLAttrib(EGLDEBUGPROCKHR callback)49 static EGLAttrib DebugCallbackToEGLAttrib(EGLDEBUGPROCKHR callback)
50 {
51 return static_cast<EGLAttrib>(reinterpret_cast<intptr_t>(callback));
52 }
53 };
54
55 // Test that the extension is always available (it is implemented in ANGLE's frontend).
TEST_P(EGLDebugTest,ExtensionAlwaysAvailable)56 TEST_P(EGLDebugTest, ExtensionAlwaysAvailable)
57 {
58 ASSERT_TRUE(hasExtension());
59 }
60
61 // Check that the default message filters and callbacks are correct
TEST_P(EGLDebugTest,DefaultParameters)62 TEST_P(EGLDebugTest, DefaultParameters)
63 {
64 ANGLE_SKIP_TEST_IF(!hasExtension());
65
66 EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
67
68 EGLAttrib result = 0;
69
70 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_ERROR_KHR, &result));
71 EXPECT_EGL_TRUE(result);
72
73 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_WARN_KHR, &result));
74 EXPECT_EGL_FALSE(result);
75
76 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_INFO_KHR, &result));
77 EXPECT_EGL_FALSE(result);
78
79 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_CALLBACK_KHR, &result));
80 EXPECT_EQ(nullptr, EGLAttribToDebugCallback(result));
81 }
82
83 // Check that the message control and callback parameters can be set and then queried back
TEST_P(EGLDebugTest,SetMessageControl)84 TEST_P(EGLDebugTest, SetMessageControl)
85 {
86 ANGLE_SKIP_TEST_IF(!hasExtension());
87
88 EGLAttrib controls[] = {
89 EGL_DEBUG_MSG_CRITICAL_KHR,
90 EGL_FALSE,
91 // EGL_DEBUG_MSG_ERROR_KHR left unset
92 EGL_DEBUG_MSG_WARN_KHR,
93 EGL_TRUE,
94 EGL_DEBUG_MSG_INFO_KHR,
95 EGL_FALSE,
96 EGL_NONE,
97 EGL_NONE,
98 };
99
100 EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(&StubCallback, controls));
101
102 EGLAttrib result = 0;
103
104 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_CRITICAL_KHR, &result));
105 EXPECT_EGL_FALSE(result);
106
107 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_ERROR_KHR, &result));
108 EXPECT_EGL_TRUE(result);
109
110 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_WARN_KHR, &result));
111 EXPECT_EGL_TRUE(result);
112
113 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_MSG_INFO_KHR, &result));
114 EXPECT_EGL_FALSE(result);
115
116 EXPECT_EGL_TRUE(eglQueryDebugKHR(EGL_DEBUG_CALLBACK_KHR, &result));
117 EXPECT_EQ(DebugCallbackToEGLAttrib(&StubCallback), result);
118 }
119
120 // Set a thread label and then trigger a callback to verify the callback parameters are correct
TEST_P(EGLDebugTest,CorrectCallbackParameters)121 TEST_P(EGLDebugTest, CorrectCallbackParameters)
122 {
123 ANGLE_SKIP_TEST_IF(!hasExtension());
124
125 EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
126
127 EXPECT_EQ(EGL_SUCCESS, eglLabelObjectKHR(EGL_NO_DISPLAY, EGL_OBJECT_THREAD_KHR, nullptr,
128 const_cast<char *>("Thread")));
129
130 // Enable all messages
131 EGLAttrib controls[] = {
132 EGL_DEBUG_MSG_CRITICAL_KHR,
133 EGL_TRUE,
134 EGL_DEBUG_MSG_ERROR_KHR,
135 EGL_TRUE,
136 EGL_DEBUG_MSG_WARN_KHR,
137 EGL_TRUE,
138 EGL_DEBUG_MSG_INFO_KHR,
139 EGL_TRUE,
140 EGL_NONE,
141 EGL_NONE,
142 };
143
144 EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS),
145 eglDebugMessageControlKHR(&CheckBadBindAPIError, controls));
146
147 // Generate an error and trigger the callback
148 EXPECT_EGL_FALSE(eglBindAPI(0xBADDBADD));
149 }
150
151 // Test that labels can be set and that errors are generated if the wrong object type is used
TEST_P(EGLDebugTest,SetLabel)152 TEST_P(EGLDebugTest, SetLabel)
153 {
154 ANGLE_SKIP_TEST_IF(!hasExtension());
155
156 EGLDisplay display = getEGLWindow()->getDisplay();
157 EGLSurface surface = getEGLWindow()->getSurface();
158
159 EXPECT_EQ(static_cast<EGLint>(EGL_SUCCESS), eglDebugMessageControlKHR(nullptr, nullptr));
160
161 // Display display and object must be equal when setting a display label
162 EXPECT_EQ(
163 static_cast<EGLint>(EGL_SUCCESS),
164 eglLabelObjectKHR(display, EGL_OBJECT_DISPLAY_KHR, display, const_cast<char *>("Display")));
165 EXPECT_NE(static_cast<EGLint>(EGL_SUCCESS),
166 eglLabelObjectKHR(nullptr, EGL_OBJECT_DISPLAY_KHR, getEGLWindow()->getDisplay(),
167 const_cast<char *>("Display")));
168
169 // Set a surface label
170 EXPECT_EQ(
171 static_cast<EGLint>(EGL_SUCCESS),
172 eglLabelObjectKHR(display, EGL_OBJECT_SURFACE_KHR, surface, const_cast<char *>("Surface")));
173 EXPECT_EGL_ERROR(EGL_SUCCESS);
174
175 // Provide a surface but use an image label type
176 EXPECT_EQ(
177 static_cast<EGLint>(EGL_BAD_PARAMETER),
178 eglLabelObjectKHR(display, EGL_OBJECT_IMAGE_KHR, surface, const_cast<char *>("Image")));
179 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
180 }
181
182 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLDebugTest);
183 ANGLE_INSTANTIATE_TEST(EGLDebugTest,
184 ES2_D3D9(),
185 ES2_D3D11(),
186 ES3_D3D11(),
187 ES2_OPENGL(),
188 ES3_OPENGL(),
189 ES2_VULKAN());
190
191 } // namespace angle
192