xref: /aosp_15_r20/external/angle/src/tests/egl_tests/EGLNoConfigContextTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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