1 //
2 // Copyright 2020 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
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 #include "util/EGLWindow.h"
10 #include "util/OSPixmap.h"
11 #include "util/OSWindow.h"
12
13 #include <iostream>
14
15 using namespace angle;
16
17 class PixmapTest : public ANGLETest
18 {
19 protected:
PixmapTest()20 PixmapTest()
21 {
22 setWindowWidth(512);
23 setWindowHeight(512);
24 setConfigRedBits(8);
25 setConfigGreenBits(8);
26 setConfigBlueBits(8);
27 setConfigAlphaBits(8);
28 }
29
testSetUp()30 void testSetUp() override
31 {
32 mTextureProgram =
33 CompileProgram(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
34 if (mTextureProgram == 0)
35 {
36 FAIL() << "shader compilation failed.";
37 }
38
39 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "u_tex2D");
40 ASSERT_NE(-1, mTextureUniformLocation);
41
42 EGLWindow *window = getEGLWindow();
43
44 EGLint surfaceType = 0;
45 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE,
46 &surfaceType);
47 mSupportsPixmaps = (surfaceType & EGL_PIXMAP_BIT) != 0;
48
49 EGLint bindToTextureRGBA = 0;
50 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA,
51 &bindToTextureRGBA);
52 mSupportsBindTexImage =
53 IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_NOK_texture_from_pixmap") &&
54 (bindToTextureRGBA == EGL_TRUE);
55
56 if (mSupportsPixmaps)
57 {
58 mOSPixmap.reset(CreateOSPixmap());
59
60 OSWindow *osWindow = getOSWindow();
61
62 EGLint nativeVisual = 0;
63 ASSERT_TRUE(eglGetConfigAttrib(window->getDisplay(), window->getConfig(),
64 EGL_NATIVE_VISUAL_ID, &nativeVisual));
65 ASSERT_TRUE(mOSPixmap->initialize(osWindow->getNativeDisplay(), mPixmapSize,
66 mPixmapSize, nativeVisual));
67
68 std::vector<EGLint> attribs;
69 if (mSupportsBindTexImage)
70 {
71 attribs.push_back(EGL_TEXTURE_FORMAT);
72 attribs.push_back(EGL_TEXTURE_RGBA);
73
74 attribs.push_back(EGL_TEXTURE_TARGET);
75 attribs.push_back(EGL_TEXTURE_2D);
76 }
77
78 attribs.push_back(EGL_NONE);
79
80 mPixmap = eglCreatePixmapSurface(window->getDisplay(), window->getConfig(),
81 mOSPixmap->getNativePixmap(), attribs.data());
82 ASSERT_NE(mPixmap, EGL_NO_SURFACE);
83 ASSERT_EGL_SUCCESS();
84 }
85
86 ASSERT_GL_NO_ERROR();
87 }
88
testTearDown()89 void testTearDown() override
90 {
91 glDeleteProgram(mTextureProgram);
92
93 if (mPixmap)
94 {
95 EGLWindow *window = getEGLWindow();
96 eglDestroySurface(window->getDisplay(), mPixmap);
97 }
98
99 mOSPixmap = nullptr;
100 }
101
102 GLuint mTextureProgram;
103 GLint mTextureUniformLocation;
104
105 std::unique_ptr<OSPixmap> mOSPixmap;
106 EGLSurface mPixmap = EGL_NO_SURFACE;
107
108 const size_t mPixmapSize = 32;
109 bool mSupportsPixmaps;
110 bool mSupportsBindTexImage;
111 };
112
113 // Test clearing a Pixmap and checking the color is correct
TEST_P(PixmapTest,Clearing)114 TEST_P(PixmapTest, Clearing)
115 {
116 ANGLE_SKIP_TEST_IF(!mSupportsPixmaps);
117
118 EGLWindow *window = getEGLWindow();
119
120 // Clear the window surface to blue and verify
121 window->makeCurrent();
122 ASSERT_EGL_SUCCESS();
123
124 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
125 glClear(GL_COLOR_BUFFER_BIT);
126 ASSERT_GL_NO_ERROR();
127 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
128
129 // Apply the Pixmap and clear it to purple and verify
130 eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
131 ASSERT_EGL_SUCCESS();
132
133 glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
134 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
135 glClear(GL_COLOR_BUFFER_BIT);
136 ASSERT_GL_NO_ERROR();
137 EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
138 0, 255, 255);
139
140 // Rebind the window surface and verify that it is still blue
141 window->makeCurrent();
142 ASSERT_EGL_SUCCESS();
143 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
144 }
145
146 // Bind the Pixmap to a texture and verify it renders correctly
TEST_P(PixmapTest,BindTexImage)147 TEST_P(PixmapTest, BindTexImage)
148 {
149 // Test skipped because pixmaps are not supported or pixmaps do not support binding to RGBA
150 // textures.
151 ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
152
153 // This test fails flakily on Linux intel when run with many other tests.
154 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel());
155 // http://anglebug.com/5385
156 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
157
158 EGLWindow *window = getEGLWindow();
159
160 // Apply the Pixmap and clear it to purple
161 eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
162 ASSERT_EGL_SUCCESS();
163
164 glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
165 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
166 glClear(GL_COLOR_BUFFER_BIT);
167 ASSERT_GL_NO_ERROR();
168
169 EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
170 0, 255, 255);
171
172 // Apply the window surface
173 window->makeCurrent();
174
175 // Create a texture and bind the pixmap to it
176 GLuint texture = 0;
177 glGenTextures(1, &texture);
178 glBindTexture(GL_TEXTURE_2D, texture);
179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
181 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
183 EXPECT_GL_NO_ERROR();
184
185 eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
186 glViewport(0, 0, getWindowWidth(), getWindowHeight());
187 ASSERT_EGL_SUCCESS();
188
189 // Draw a quad and verify that it is purple
190 glUseProgram(mTextureProgram);
191 glUniform1i(mTextureUniformLocation, 0);
192
193 drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
194 EXPECT_GL_NO_ERROR();
195
196 // Unbind the texture
197 eglReleaseTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
198 ASSERT_EGL_SUCCESS();
199
200 // Verify that purple was drawn
201 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
202
203 glDeleteTextures(1, &texture);
204 }
205
206 // Bind a Pixmap, redefine the texture, and verify it renders correctly
TEST_P(PixmapTest,BindTexImageAndRedefineTexture)207 TEST_P(PixmapTest, BindTexImageAndRedefineTexture)
208 {
209 // Test skipped because pixmaps are not supported or Pixmaps do not support binding to RGBA
210 // textures.
211 ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
212
213 EGLWindow *window = getEGLWindow();
214
215 // Apply the Pixmap and clear it to purple
216 eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
217 ASSERT_EGL_SUCCESS();
218
219 glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
220 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
221 glClear(GL_COLOR_BUFFER_BIT);
222 ASSERT_GL_NO_ERROR();
223
224 EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
225 0, 255, 255);
226
227 // Apply the window surface
228 window->makeCurrent();
229
230 // Create a texture and bind the Pixmap to it
231 GLuint texture = 0;
232 glGenTextures(1, &texture);
233 glBindTexture(GL_TEXTURE_2D, texture);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238 EXPECT_GL_NO_ERROR();
239
240 eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
241 glViewport(0, 0, getWindowWidth(), getWindowHeight());
242 ASSERT_EGL_SUCCESS();
243
244 // Redefine the texture
245 unsigned int pixelValue = 0xFFFF00FF;
246 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
247 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
248 GL_UNSIGNED_BYTE, &pixelData[0]);
249
250 // Draw a quad and verify that it is magenta
251 glUseProgram(mTextureProgram);
252 glUniform1i(mTextureUniformLocation, 0);
253
254 drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
255 EXPECT_GL_NO_ERROR();
256
257 // Verify that magenta was drawn
258 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
259
260 glDeleteTextures(1, &texture);
261 }
262
263 ANGLE_INSTANTIATE_TEST_ES2(PixmapTest);
264