1 //
2 // Copyright 2019 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 // EGLNoConfigContectTest.cpp:
7 // EGL extension EGL_KHR_no_config_context allows a context to be created
8 // without a config specified. This means all surfaces are compatible.
9 // As a result compatibility checks are circumvented.
10 // This test suite creates and verifies creating a configless context
11 // and then verifies simple rendering to ensure compatibility.
12 //
13
14 #include <gtest/gtest.h>
15
16 #include "test_utils/ANGLETest.h"
17
18 using namespace angle;
19
20 class EGLNoConfigContextTest : public ANGLETest<>
21 {
22 public:
EGLNoConfigContextTest()23 EGLNoConfigContextTest() : mDisplay(EGL_NO_DISPLAY), mContext(EGL_NO_CONTEXT) {}
24
testSetUp()25 void testSetUp() override
26 {
27 int clientVersion = GetParam().majorVersion;
28
29 EGLint dispattrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, GetParam().getRenderer(), EGL_NONE};
30 mDisplay = eglGetPlatformDisplayEXT(
31 EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), dispattrs);
32 EXPECT_TRUE(mDisplay != EGL_NO_DISPLAY);
33 EXPECT_EGL_TRUE(eglInitialize(mDisplay, nullptr, nullptr));
34
35 mExtensionSupported = IsEGLDisplayExtensionEnabled(mDisplay, "EGL_KHR_no_config_context");
36 if (!mExtensionSupported)
37 {
38 return; // Not supported, don't create context
39 }
40
41 EGLint ctxattrs[] = {EGL_CONTEXT_CLIENT_VERSION, clientVersion, EGL_NONE};
42 mContext = eglCreateContext(mDisplay, EGL_NO_CONFIG_KHR, nullptr, ctxattrs);
43 EXPECT_TRUE(mContext != EGL_NO_CONTEXT);
44 }
45
testTearDown()46 void testTearDown() override
47 {
48 if (mDisplay != EGL_NO_DISPLAY)
49 {
50 if (mContext != EGL_NO_CONTEXT)
51 {
52 eglDestroyContext(mDisplay, mContext);
53 mContext = EGL_NO_CONTEXT;
54 }
55 eglTerminate(mDisplay);
56 eglReleaseThread();
57 }
58 ASSERT_EGL_SUCCESS() << "Error during test TearDown";
59 }
60
61 EGLDisplay mDisplay = EGL_NO_DISPLAY;
62 EGLContext mContext = EGL_NO_CONTEXT;
63 bool mExtensionSupported = false;
64 };
65
66 // Check that context has no config.
TEST_P(EGLNoConfigContextTest,QueryConfigID)67 TEST_P(EGLNoConfigContextTest, QueryConfigID)
68 {
69 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
70 EXPECT_TRUE(mDisplay);
71 EXPECT_TRUE(mContext);
72
73 EGLint configId = -1;
74 EXPECT_EGL_TRUE(eglQueryContext(mDisplay, mContext, EGL_CONFIG_ID, &configId));
75 EXPECT_TRUE(configId == 0);
76 ASSERT_EGL_SUCCESS();
77 }
78
79 // Any surface should be eglMakeCurrent compatible with no-config context.
80 // Do a glClear and glReadPixel to verify rendering.
TEST_P(EGLNoConfigContextTest,RenderCheck)81 TEST_P(EGLNoConfigContextTest, RenderCheck)
82 {
83 ANGLE_SKIP_TEST_IF(!mExtensionSupported);
84
85 // Get all the configs
86 EGLint count;
87 EXPECT_EGL_TRUE(eglGetConfigs(mDisplay, nullptr, 0, &count));
88 EXPECT_TRUE(count > 0);
89 std::vector<EGLConfig> configs(count);
90 EXPECT_EGL_TRUE(eglGetConfigs(mDisplay, configs.data(), count, &count));
91
92 // For each config, create PbufferSurface and do a render check
93 EGLSurface surface = EGL_NO_SURFACE;
94 for (auto config : configs)
95 {
96 const uint32_t kWidth = 1;
97 const uint32_t kHeight = 1;
98
99 EGLint configId;
100 EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_CONFIG_ID, &configId));
101
102 EGLint surfaceType;
103 EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_SURFACE_TYPE, &surfaceType));
104 EGLint bufferSize;
105 EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_BUFFER_SIZE, &bufferSize));
106 constexpr int kRGB8BitSize = 24; // RGB8 is 24 bits
107 if (isVulkanRenderer() && bufferSize == kRGB8BitSize &&
108 (surfaceType & EGL_PBUFFER_BIT) != EGL_PBUFFER_BIT)
109 {
110 // Skip this config, since the Vulkan backend doesn't support RGB8 pbuffer surfaces.
111 continue;
112 }
113
114 EGLint surfattrs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE};
115 surface = eglCreatePbufferSurface(mDisplay, config, surfattrs);
116 EXPECT_TRUE(surface != EGL_NO_SURFACE);
117
118 EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, mContext));
119 ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed with Config: " << configId << '\n';
120
121 // ClearColor RED
122 glClearColor(1.0, 0.0, 0.0, 1.0);
123 glClear(GL_COLOR_BUFFER_BIT);
124 ASSERT_GL_NO_ERROR() << "glClear failed";
125
126 if (bufferSize > 32)
127 { // GL_FLOAT configs
128 EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
129 }
130 else
131 { // GL_UNSIGNED_BYTE configs
132 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
133 }
134
135 eglDestroySurface(mDisplay, surface);
136 surface = EGL_NO_SURFACE;
137 }
138 }
139
140 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLNoConfigContextTest);
141 ANGLE_INSTANTIATE_TEST(EGLNoConfigContextTest,
142 WithNoFixture(ES2_OPENGL()),
143 WithNoFixture(ES2_VULKAN()),
144 WithNoFixture(ES3_OPENGL()),
145 WithNoFixture(ES3_VULKAN()));
146