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
156 EGLWindow *window = getEGLWindow();
157
158 // Apply the Pixmap and clear it to purple
159 eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
160 ASSERT_EGL_SUCCESS();
161
162 glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
163 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
164 glClear(GL_COLOR_BUFFER_BIT);
165 ASSERT_GL_NO_ERROR();
166
167 EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
168 0, 255, 255);
169
170 // Apply the window surface
171 window->makeCurrent();
172
173 // Create a texture and bind the pixmap to it
174 GLuint texture = 0;
175 glGenTextures(1, &texture);
176 glBindTexture(GL_TEXTURE_2D, texture);
177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
179 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
181 EXPECT_GL_NO_ERROR();
182
183 eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
184 glViewport(0, 0, getWindowWidth(), getWindowHeight());
185 ASSERT_EGL_SUCCESS();
186
187 // Draw a quad and verify that it is purple
188 glUseProgram(mTextureProgram);
189 glUniform1i(mTextureUniformLocation, 0);
190
191 drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
192 EXPECT_GL_NO_ERROR();
193
194 // Unbind the texture
195 eglReleaseTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
196 ASSERT_EGL_SUCCESS();
197
198 // Verify that purple was drawn
199 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
200
201 glDeleteTextures(1, &texture);
202 }
203
204 // Bind a Pixmap, redefine the texture, and verify it renders correctly
TEST_P(PixmapTest,BindTexImageAndRedefineTexture)205 TEST_P(PixmapTest, BindTexImageAndRedefineTexture)
206 {
207 // Test skipped because pixmaps are not supported or Pixmaps do not support binding to RGBA
208 // textures.
209 ANGLE_SKIP_TEST_IF(!mSupportsPixmaps || !mSupportsBindTexImage);
210
211 EGLWindow *window = getEGLWindow();
212
213 // Apply the Pixmap and clear it to purple
214 eglMakeCurrent(window->getDisplay(), mPixmap, mPixmap, window->getContext());
215 ASSERT_EGL_SUCCESS();
216
217 glViewport(0, 0, static_cast<GLsizei>(mPixmapSize), static_cast<GLsizei>(mPixmapSize));
218 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
219 glClear(GL_COLOR_BUFFER_BIT);
220 ASSERT_GL_NO_ERROR();
221
222 EXPECT_PIXEL_EQ(static_cast<GLint>(mPixmapSize) / 2, static_cast<GLint>(mPixmapSize) / 2, 255,
223 0, 255, 255);
224
225 // Apply the window surface
226 window->makeCurrent();
227
228 // Create a texture and bind the Pixmap to it
229 GLuint texture = 0;
230 glGenTextures(1, &texture);
231 glBindTexture(GL_TEXTURE_2D, texture);
232 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
233 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
236 EXPECT_GL_NO_ERROR();
237
238 eglBindTexImage(window->getDisplay(), mPixmap, EGL_BACK_BUFFER);
239 glViewport(0, 0, getWindowWidth(), getWindowHeight());
240 ASSERT_EGL_SUCCESS();
241
242 // Redefine the texture
243 unsigned int pixelValue = 0xFFFF00FF;
244 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
245 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
246 GL_UNSIGNED_BYTE, &pixelData[0]);
247
248 // Draw a quad and verify that it is magenta
249 glUseProgram(mTextureProgram);
250 glUniform1i(mTextureUniformLocation, 0);
251
252 drawQuad(mTextureProgram, essl31_shaders::PositionAttrib(), 0.5f);
253 EXPECT_GL_NO_ERROR();
254
255 // Verify that magenta was drawn
256 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
257
258 glDeleteTextures(1, &texture);
259 }
260
261 ANGLE_INSTANTIATE_TEST_ES2(PixmapTest);
262