• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         EGLint surfattrs[] = {EGL_WIDTH, kWidth, EGL_HEIGHT, kHeight, EGL_NONE};
102         surface            = eglCreatePbufferSurface(mDisplay, config, surfattrs);
103         EXPECT_TRUE(surface != EGL_NO_SURFACE);
104 
105         EGLint bufferSize = 0;
106         EXPECT_EGL_TRUE(eglGetConfigAttrib(mDisplay, config, EGL_BUFFER_SIZE, &bufferSize));
107 
108         EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, surface, surface, mContext));
109         ASSERT_EGL_SUCCESS() << "eglMakeCurrent failed with Config: " << configId << '\n';
110 
111         // ClearColor RED
112         glClearColor(1.0, 0.0, 0.0, 1.0);
113         glClear(GL_COLOR_BUFFER_BIT);
114         ASSERT_GL_NO_ERROR() << "glClear failed";
115 
116         if (bufferSize > 32)
117         {  // GL_FLOAT configs
118             EXPECT_PIXEL_COLOR32F_EQ(0, 0, kFloatRed);
119         }
120         else
121         {  // GL_UNSIGNED_BYTE configs
122             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
123         }
124 
125         eglDestroySurface(mDisplay, surface);
126         surface = EGL_NO_SURFACE;
127     }
128 }
129 
130 ANGLE_INSTANTIATE_TEST(EGLNoConfigContextTest,
131                        WithNoFixture(ES2_OPENGL()),
132                        WithNoFixture(ES2_VULKAN()),
133                        WithNoFixture(ES3_OPENGL()),
134                        WithNoFixture(ES3_VULKAN()));
135