OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "testing/gmock/include/gmock/gmock.h" | 5 #include "testing/gmock/include/gmock/gmock.h" |
6 #include "testing/gtest/include/gtest/gtest.h" | 6 #include "testing/gtest/include/gtest/gtest.h" |
7 | 7 |
8 #include <EGL/egl.h> | 8 #include <EGL/egl.h> |
9 #include <GLES2/gl2.h> | |
10 | 9 |
11 // This file tests EGL basic interface for command_buffer_gles2, the mode of | 10 // This file tests EGL basic interface for command_buffer_gles2, the mode of |
12 // command buffer where the code is compiled as a standalone dynamic library and | 11 // command buffer where the code is compiled as a standalone dynamic library and |
13 // exposed through EGL API. | 12 // exposed through EGL API. |
14 namespace gpu { | 13 namespace gpu { |
15 | 14 |
16 using testing::Test; | 15 using testing::Test; |
17 | 16 |
18 TEST_F(Test, BasicEGLInitialization) { | 17 TEST_F(Test, BasicEGLInitialization) { |
19 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | 18 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
20 ASSERT_NE(display, EGL_NO_DISPLAY); | 19 ASSERT_NE(display, EGL_NO_DISPLAY); |
21 | 20 |
22 // Test for no crash even though passing nullptrs for major, minor. | 21 // Test for no crash even though passing nullptrs for major, minor. |
23 EGLBoolean success = eglInitialize(display, nullptr, nullptr); | 22 EGLBoolean success = eglInitialize(display, nullptr, nullptr); |
24 ASSERT_TRUE(success); | 23 ASSERT_TRUE(success); |
25 | 24 |
26 EGLint major = 0; | 25 EGLint major = 0; |
27 EGLint minor = 0; | 26 EGLint minor = 0; |
28 success = eglInitialize(display, &major, &minor); | 27 success = eglInitialize(display, &major, &minor); |
29 ASSERT_TRUE(success); | 28 ASSERT_TRUE(success); |
30 ASSERT_EQ(major, 1); | 29 ASSERT_EQ(major, 1); |
31 ASSERT_EQ(minor, 4); | 30 ASSERT_EQ(minor, 4); |
32 | 31 |
33 success = eglTerminate(display); | 32 success = eglTerminate(display); |
34 ASSERT_TRUE(success); | 33 ASSERT_TRUE(success); |
35 } | 34 } |
36 | 35 |
37 class TestContext { | 36 } // namespace gpu |
38 public: | |
39 TestContext() { | |
40 display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
41 | |
42 eglInitialize(display_, nullptr, nullptr); | |
43 | |
44 static const EGLint configAttribs[] = { | |
45 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, | |
46 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
47 EGL_RED_SIZE, 8, | |
48 EGL_GREEN_SIZE, 8, | |
49 EGL_BLUE_SIZE, 8, | |
50 EGL_ALPHA_SIZE, 8, | |
51 EGL_NONE | |
52 }; | |
53 EGLint numConfigs; | |
54 EGLConfig config; | |
55 eglChooseConfig(display_, configAttribs, &config, 1, &numConfigs); | |
56 | |
57 static const EGLint surfaceAttribs[] = { | |
58 EGL_WIDTH, 1, | |
59 EGL_HEIGHT, 1, | |
60 EGL_NONE | |
61 }; | |
62 surface_ = eglCreatePbufferSurface(display_, config, surfaceAttribs); | |
63 | |
64 static const EGLint contextAttribs[] = { | |
65 EGL_CONTEXT_CLIENT_VERSION, 2, | |
66 EGL_NONE | |
67 }; | |
68 context_ = eglCreateContext(display_, config, nullptr, contextAttribs); | |
69 } | |
70 | |
71 ~TestContext() { | |
72 eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
73 eglDestroyContext(display_, context_); | |
74 eglDestroySurface(display_, surface_); | |
75 eglTerminate(display_); | |
76 } | |
77 | |
78 bool IsValid() const { | |
79 return display_ != EGL_NO_DISPLAY && | |
80 context_ != EGL_NO_CONTEXT && | |
81 surface_ != EGL_NO_SURFACE; | |
82 } | |
83 | |
84 void TestCallGL() { | |
85 eglMakeCurrent(display_, surface_, surface_, context_); | |
86 | |
87 typedef GL_APICALL void GL_APIENTRY (*glEnableProc)(GLenum); | |
88 | |
89 auto address = eglGetProcAddress("glEnable"); | |
90 auto* glEnable = reinterpret_cast<glEnableProc>(address); | |
91 glEnable(GL_BLEND); | |
92 } | |
93 | |
94 private: | |
95 TestContext(const TestContext&) = delete; | |
96 TestContext& operator=(const TestContext&) = delete; | |
97 | |
98 private: | |
99 EGLDisplay display_; | |
100 EGLContext context_; | |
101 EGLSurface surface_; | |
102 }; | |
103 | |
104 // Test case for a workaround for an issue in gles2_conform_support. | |
105 // | |
106 // The problem is that every call to eglGetDisplay(EGL_DEFAULT_DISPLAY) | |
107 // returns a new display object and the construction of each display | |
108 // calls to establish a thread local store variable in where to store the | |
109 // current command buffer context. | |
110 // Likewise the destructor of display calls to free the same tls variable. | |
111 // | |
112 // When skia (nanobench) uses multiple instances of command buffer | |
113 // based contexts and one display is destroyed the TLS variable | |
114 // is also destroyed and subsequent command buffer GL calls using another | |
115 // context instance end up accessing free'ed TLS variable. | |
116 // | |
117 // Note that technically there's also a problem in SkCommandBufferContext | |
118 // since it calls eglTerminate for each display, but this is because | |
119 // the current command buffer egl implementation requires this. | |
120 // Overall this functionality is not aligned with the EGL spefication. | |
121 // | |
122 // This testcase tests that we can create multiple command buffer contexts | |
123 // and dispose them without affecting the other. | |
124 TEST(Test, MultipleDisplays) { | |
125 TestContext first; | |
126 ASSERT_TRUE(first.IsValid()); | |
127 | |
128 first.TestCallGL(); | |
129 | |
130 { | |
131 TestContext second; | |
132 ASSERT_TRUE(second.IsValid()); | |
133 | |
134 second.TestCallGL(); | |
135 } | |
136 | |
137 first.TestCallGL(); | |
138 } | |
139 | |
140 } // namespace gpu | |
141 | |
OLD | NEW |