blob: ab08078c9dcfa202f1ef85daa44b646d64d36a76 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
2// Copyright 2015 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
Corentin Wallezd3970de2015-05-14 11:07:48 -04007#include "test_utils/ANGLETest.h"
Geoff Lang0ca42a52015-04-07 13:47:41 -04008
Jamie Madillfa05f602015-05-07 13:47:11 -04009using namespace angle;
Geoff Lang0ca42a52015-04-07 13:47:41 -040010
Geoff Lang0ca42a52015-04-07 13:47:41 -040011class PbufferTest : public ANGLETest
12{
13 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040014 PbufferTest()
Geoff Lang0ca42a52015-04-07 13:47:41 -040015 {
16 setWindowWidth(512);
17 setWindowHeight(512);
18 setConfigRedBits(8);
19 setConfigGreenBits(8);
20 setConfigBlueBits(8);
21 setConfigAlphaBits(8);
22 }
23
24 virtual void SetUp()
25 {
26 ANGLETest::SetUp();
27
28 const std::string vsSource = SHADER_SOURCE
29 (
30 precision highp float;
31 attribute vec4 position;
32 varying vec2 texcoord;
33
34 void main()
35 {
36 gl_Position = position;
37 texcoord = (position.xy * 0.5) + 0.5;
38 texcoord.y = 1.0 - texcoord.y;
39 }
40 );
41
42 const std::string textureFSSource = SHADER_SOURCE
43 (
44 precision highp float;
45 uniform sampler2D tex;
46 varying vec2 texcoord;
47
48 void main()
49 {
50 gl_FragColor = texture2D(tex, texcoord);
51 }
52 );
53
54 mTextureProgram = CompileProgram(vsSource, textureFSSource);
55 if (mTextureProgram == 0)
56 {
57 FAIL() << "shader compilation failed.";
58 }
59
60 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
61
Geoff Lang1c906c22015-04-10 11:26:17 -040062 EGLWindow *window = getEGLWindow();
63
64 EGLint surfaceType = 0;
65 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE, &surfaceType);
66 mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
67
68 EGLint bindToTextureRGBA = 0;
69 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
70 mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
71
Geoff Lang0ca42a52015-04-07 13:47:41 -040072 const EGLint pBufferAttributes[] =
73 {
Corentin Wallez973402f2015-05-11 13:42:22 -040074 EGL_WIDTH, static_cast<EGLint>(mPbufferSize),
75 EGL_HEIGHT, static_cast<EGLint>(mPbufferSize),
Geoff Lang1c906c22015-04-10 11:26:17 -040076 EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
77 EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
Geoff Lang0ca42a52015-04-07 13:47:41 -040078 EGL_NONE, EGL_NONE,
79 };
80
Geoff Lang0ca42a52015-04-07 13:47:41 -040081 mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
Geoff Lang1c906c22015-04-10 11:26:17 -040082 if (mSupportsPbuffers)
83 {
84 ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
85 ASSERT_EGL_SUCCESS();
86 }
87 else
88 {
89 ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
90 ASSERT_EGL_ERROR(EGL_BAD_MATCH);
91 }
Geoff Lang0ca42a52015-04-07 13:47:41 -040092
Geoff Lang0ca42a52015-04-07 13:47:41 -040093 ASSERT_GL_NO_ERROR();
94 }
95
96 virtual void TearDown()
97 {
98 glDeleteProgram(mTextureProgram);
99
100 EGLWindow *window = getEGLWindow();
101 eglDestroySurface(window->getDisplay(), mPbuffer);
102
103 ANGLETest::TearDown();
104 }
105
106 GLuint mTextureProgram;
107 GLint mTextureUniformLocation;
108
109 const size_t mPbufferSize = 32;
110 EGLSurface mPbuffer;
Geoff Lang1c906c22015-04-10 11:26:17 -0400111 bool mSupportsPbuffers;
112 bool mSupportsBindTexImage;
Geoff Lang0ca42a52015-04-07 13:47:41 -0400113};
114
115// Test clearing a Pbuffer and checking the color is correct
Jamie Madillfa05f602015-05-07 13:47:11 -0400116TEST_P(PbufferTest, Clearing)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400117{
Geoff Lang1c906c22015-04-10 11:26:17 -0400118 if (!mSupportsPbuffers)
119 {
120 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
121 return;
122 }
123
Geoff Lang0ca42a52015-04-07 13:47:41 -0400124 EGLWindow *window = getEGLWindow();
125
126 // Clear the window surface to blue and verify
127 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
128 ASSERT_EGL_SUCCESS();
129
130 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
131 glClear(GL_COLOR_BUFFER_BIT);
132 ASSERT_GL_NO_ERROR();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400133 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400134
135 // Apply the Pbuffer and clear it to purple and verify
136 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
137 ASSERT_EGL_SUCCESS();
138
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700139 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400140 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
141 glClear(GL_COLOR_BUFFER_BIT);
142 ASSERT_GL_NO_ERROR();
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700143 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
144 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400145
Corentin Wallez21ce9b02015-05-14 11:50:08 -0400146 // Rebind the window surface and verify that it is still blue
Geoff Lang0ca42a52015-04-07 13:47:41 -0400147 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
148 ASSERT_EGL_SUCCESS();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400149 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400150}
151
152// Bind the Pbuffer to a texture and verify it renders correctly
Jamie Madillfa05f602015-05-07 13:47:11 -0400153TEST_P(PbufferTest, BindTexImage)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400154{
Geoff Lang1c906c22015-04-10 11:26:17 -0400155 if (!mSupportsPbuffers)
156 {
157 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
158 return;
159 }
160
161 if (!mSupportsBindTexImage)
162 {
163 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
164 return;
165 }
166
Geoff Lang0ca42a52015-04-07 13:47:41 -0400167 EGLWindow *window = getEGLWindow();
168
169 // Apply the Pbuffer and clear it to purple
170 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
171 ASSERT_EGL_SUCCESS();
172
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700173 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400174 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
175 glClear(GL_COLOR_BUFFER_BIT);
176 ASSERT_GL_NO_ERROR();
177
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700178 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
179 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400180
181 // Apply the window surface
182 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
183
184 // Create a texture and bind the Pbuffer to it
185 GLuint texture = 0;
186 glGenTextures(1, &texture);
187 glBindTexture(GL_TEXTURE_2D, texture);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
192 EXPECT_GL_NO_ERROR();
193
194 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400195 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Geoff Lang0ca42a52015-04-07 13:47:41 -0400196 ASSERT_EGL_SUCCESS();
197
198 // Draw a quad and verify that it is purple
199 glUseProgram(mTextureProgram);
200 glUniform1i(mTextureUniformLocation, 0);
201
202 drawQuad(mTextureProgram, "position", 0.5f);
203 EXPECT_GL_NO_ERROR();
204
205 // Unbind the texture
206 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
207 ASSERT_EGL_SUCCESS();
208
209 // Verify that purple was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400210 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400211
212 glDeleteTextures(1, &texture);
213}
214
215// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
216// size information is correctly updated.
Jamie Madillfa05f602015-05-07 13:47:11 -0400217TEST_P(PbufferTest, TextureSizeReset)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400218{
Geoff Lang1c906c22015-04-10 11:26:17 -0400219 if (!mSupportsPbuffers)
220 {
221 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
222 return;
223 }
224
225 if (!mSupportsBindTexImage)
226 {
227 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
228 return;
229 }
230
Geoff Lang0ca42a52015-04-07 13:47:41 -0400231 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 glUseProgram(mTextureProgram);
241 glUniform1i(mTextureUniformLocation, 0);
242
243 // Fill the texture with white pixels
244 std::vector<GLubyte> whitePixels(mPbufferSize * mPbufferSize * 4, 255);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700245 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
246 static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixels[0]);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400247 EXPECT_GL_NO_ERROR();
248
249 // Draw the white texture and verify that the pixels are correct
250 drawQuad(mTextureProgram, "position", 0.5f);
251 EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
252
253 // Bind the EGL surface and draw with it, results are undefined since nothing has
254 // been written to it
255 EGLWindow *window = getEGLWindow();
256 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
257 drawQuad(mTextureProgram, "position", 0.5f);
258 EXPECT_GL_NO_ERROR();
259
260 // Clear the back buffer to a unique color (green)
261 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
262 glClear(GL_COLOR_BUFFER_BIT);
263 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
264
265 // Unbind the EGL surface and try to draw with the texture again, the texture's size should
266 // now be zero and incomplete so the back buffer should be black
267 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
268 drawQuad(mTextureProgram, "position", 0.5f);
269 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
270}
Jamie Madillfa05f602015-05-07 13:47:11 -0400271
Jamie Madillbb714f72015-05-20 10:22:18 -0400272// Bind a Pbuffer, redefine the texture, and verify it renders correctly
273TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
274{
275 if (!mSupportsPbuffers)
276 {
277 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
278 return;
279 }
280
281 if (!mSupportsBindTexImage)
282 {
283 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
284 return;
285 }
286
287 EGLWindow *window = getEGLWindow();
288
289 // Apply the Pbuffer and clear it to purple
290 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
291 ASSERT_EGL_SUCCESS();
292
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700293 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Jamie Madillbb714f72015-05-20 10:22:18 -0400294 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
295 glClear(GL_COLOR_BUFFER_BIT);
296 ASSERT_GL_NO_ERROR();
297
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700298 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
299 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400300
301 // Apply the window surface
302 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
303
304 // Create a texture and bind the Pbuffer to it
305 GLuint texture = 0;
306 glGenTextures(1, &texture);
307 glBindTexture(GL_TEXTURE_2D, texture);
308 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
312 EXPECT_GL_NO_ERROR();
313
314 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400315 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Jamie Madillbb714f72015-05-20 10:22:18 -0400316 ASSERT_EGL_SUCCESS();
317
318 // Redefine the texture
319 unsigned int pixelValue = 0xFFFF00FF;
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400320 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
321 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]);
Jamie Madillbb714f72015-05-20 10:22:18 -0400322
323 // Draw a quad and verify that it is magenta
324 glUseProgram(mTextureProgram);
325 glUniform1i(mTextureUniformLocation, 0);
326
327 drawQuad(mTextureProgram, "position", 0.5f);
328 EXPECT_GL_NO_ERROR();
329
330 // Verify that magenta was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400331 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400332
333 glDeleteTextures(1, &texture);
334}
335
Jamie Madillfa05f602015-05-07 13:47:11 -0400336// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
337ANGLE_INSTANTIATE_TEST(PbufferTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_D3D11_WARP(), ES2_D3D11_REFERENCE());