blob: f3b5dac26b47be19d6c2b82f84ded252a4d34ccc [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"
Jamie Madillaf4ffe02017-09-09 23:32:48 -04008#include "test_utils/gl_raii.h"
Geoff Lang0ca42a52015-04-07 13:47:41 -04009
Jamie Madillfa05f602015-05-07 13:47:11 -040010using namespace angle;
Geoff Lang0ca42a52015-04-07 13:47:41 -040011
Geoff Lang0ca42a52015-04-07 13:47:41 -040012class PbufferTest : public ANGLETest
13{
14 protected:
Jamie Madillfa05f602015-05-07 13:47:11 -040015 PbufferTest()
Geoff Lang0ca42a52015-04-07 13:47:41 -040016 {
17 setWindowWidth(512);
18 setWindowHeight(512);
19 setConfigRedBits(8);
20 setConfigGreenBits(8);
21 setConfigBlueBits(8);
22 setConfigAlphaBits(8);
23 }
24
25 virtual void SetUp()
26 {
27 ANGLETest::SetUp();
28
29 const std::string vsSource = SHADER_SOURCE
30 (
31 precision highp float;
32 attribute vec4 position;
33 varying vec2 texcoord;
34
35 void main()
36 {
37 gl_Position = position;
38 texcoord = (position.xy * 0.5) + 0.5;
39 texcoord.y = 1.0 - texcoord.y;
40 }
41 );
42
43 const std::string textureFSSource = SHADER_SOURCE
44 (
45 precision highp float;
46 uniform sampler2D tex;
47 varying vec2 texcoord;
48
49 void main()
50 {
51 gl_FragColor = texture2D(tex, texcoord);
52 }
53 );
54
55 mTextureProgram = CompileProgram(vsSource, textureFSSource);
56 if (mTextureProgram == 0)
57 {
58 FAIL() << "shader compilation failed.";
59 }
60
61 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
62
Geoff Lang1c906c22015-04-10 11:26:17 -040063 EGLWindow *window = getEGLWindow();
64
65 EGLint surfaceType = 0;
66 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE, &surfaceType);
67 mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
68
69 EGLint bindToTextureRGBA = 0;
70 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
71 mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
72
Geoff Lang0ca42a52015-04-07 13:47:41 -040073 const EGLint pBufferAttributes[] =
74 {
Corentin Wallez973402f2015-05-11 13:42:22 -040075 EGL_WIDTH, static_cast<EGLint>(mPbufferSize),
76 EGL_HEIGHT, static_cast<EGLint>(mPbufferSize),
Geoff Lang1c906c22015-04-10 11:26:17 -040077 EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
78 EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
Geoff Lang0ca42a52015-04-07 13:47:41 -040079 EGL_NONE, EGL_NONE,
80 };
81
Geoff Lang0ca42a52015-04-07 13:47:41 -040082 mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
Geoff Lang1c906c22015-04-10 11:26:17 -040083 if (mSupportsPbuffers)
84 {
85 ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
86 ASSERT_EGL_SUCCESS();
87 }
88 else
89 {
90 ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
91 ASSERT_EGL_ERROR(EGL_BAD_MATCH);
92 }
Geoff Lang0ca42a52015-04-07 13:47:41 -040093
Geoff Lang0ca42a52015-04-07 13:47:41 -040094 ASSERT_GL_NO_ERROR();
95 }
96
97 virtual void TearDown()
98 {
99 glDeleteProgram(mTextureProgram);
100
101 EGLWindow *window = getEGLWindow();
102 eglDestroySurface(window->getDisplay(), mPbuffer);
103
104 ANGLETest::TearDown();
105 }
106
107 GLuint mTextureProgram;
108 GLint mTextureUniformLocation;
109
110 const size_t mPbufferSize = 32;
111 EGLSurface mPbuffer;
Geoff Lang1c906c22015-04-10 11:26:17 -0400112 bool mSupportsPbuffers;
113 bool mSupportsBindTexImage;
Geoff Lang0ca42a52015-04-07 13:47:41 -0400114};
115
116// Test clearing a Pbuffer and checking the color is correct
Jamie Madillfa05f602015-05-07 13:47:11 -0400117TEST_P(PbufferTest, Clearing)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400118{
Geoff Lang1c906c22015-04-10 11:26:17 -0400119 if (!mSupportsPbuffers)
120 {
121 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
122 return;
123 }
124
Geoff Lang0ca42a52015-04-07 13:47:41 -0400125 EGLWindow *window = getEGLWindow();
126
127 // Clear the window surface to blue and verify
Jamie Madillfe548342017-06-19 11:13:24 -0400128 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400129 ASSERT_EGL_SUCCESS();
130
131 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
132 glClear(GL_COLOR_BUFFER_BIT);
133 ASSERT_GL_NO_ERROR();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400134 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400135
136 // Apply the Pbuffer and clear it to purple and verify
137 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
138 ASSERT_EGL_SUCCESS();
139
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700140 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400141 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
142 glClear(GL_COLOR_BUFFER_BIT);
143 ASSERT_GL_NO_ERROR();
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700144 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
145 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400146
Corentin Wallez21ce9b02015-05-14 11:50:08 -0400147 // Rebind the window surface and verify that it is still blue
Jamie Madillfe548342017-06-19 11:13:24 -0400148 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400149 ASSERT_EGL_SUCCESS();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400150 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400151}
152
153// Bind the Pbuffer to a texture and verify it renders correctly
Jamie Madillfa05f602015-05-07 13:47:11 -0400154TEST_P(PbufferTest, BindTexImage)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400155{
Geoff Lang1c906c22015-04-10 11:26:17 -0400156 if (!mSupportsPbuffers)
157 {
158 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
159 return;
160 }
161
162 if (!mSupportsBindTexImage)
163 {
164 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
165 return;
166 }
167
Geoff Lang0ca42a52015-04-07 13:47:41 -0400168 EGLWindow *window = getEGLWindow();
169
170 // Apply the Pbuffer and clear it to purple
171 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
172 ASSERT_EGL_SUCCESS();
173
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700174 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400175 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
176 glClear(GL_COLOR_BUFFER_BIT);
177 ASSERT_GL_NO_ERROR();
178
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700179 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
180 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400181
182 // Apply the window surface
Jamie Madillfe548342017-06-19 11:13:24 -0400183 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400184
185 // Create a texture and bind the Pbuffer to it
186 GLuint texture = 0;
187 glGenTextures(1, &texture);
188 glBindTexture(GL_TEXTURE_2D, texture);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
193 EXPECT_GL_NO_ERROR();
194
195 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400196 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Geoff Lang0ca42a52015-04-07 13:47:41 -0400197 ASSERT_EGL_SUCCESS();
198
199 // Draw a quad and verify that it is purple
200 glUseProgram(mTextureProgram);
201 glUniform1i(mTextureUniformLocation, 0);
202
203 drawQuad(mTextureProgram, "position", 0.5f);
204 EXPECT_GL_NO_ERROR();
205
206 // Unbind the texture
207 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
208 ASSERT_EGL_SUCCESS();
209
210 // Verify that purple was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400211 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400212
213 glDeleteTextures(1, &texture);
214}
215
216// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
217// size information is correctly updated.
Jamie Madillfa05f602015-05-07 13:47:11 -0400218TEST_P(PbufferTest, TextureSizeReset)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400219{
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400220 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
221 ANGLE_SKIP_TEST_IF(!mSupportsBindTexImage);
Geoff Lang1c906c22015-04-10 11:26:17 -0400222
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400223 GLTexture texture;
Geoff Lang0ca42a52015-04-07 13:47:41 -0400224 glBindTexture(GL_TEXTURE_2D, texture);
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
227 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
229 EXPECT_GL_NO_ERROR();
230
231 glUseProgram(mTextureProgram);
232 glUniform1i(mTextureUniformLocation, 0);
233
234 // Fill the texture with white pixels
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400235 std::vector<GLColor> whitePixels(mPbufferSize * mPbufferSize, GLColor::white);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700236 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400237 static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE,
238 whitePixels.data());
Geoff Lang0ca42a52015-04-07 13:47:41 -0400239 EXPECT_GL_NO_ERROR();
240
241 // Draw the white texture and verify that the pixels are correct
242 drawQuad(mTextureProgram, "position", 0.5f);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400243 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400244
245 // Bind the EGL surface and draw with it, results are undefined since nothing has
246 // been written to it
247 EGLWindow *window = getEGLWindow();
248 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
249 drawQuad(mTextureProgram, "position", 0.5f);
250 EXPECT_GL_NO_ERROR();
251
252 // Clear the back buffer to a unique color (green)
253 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
254 glClear(GL_COLOR_BUFFER_BIT);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400255 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400256
257 // Unbind the EGL surface and try to draw with the texture again, the texture's size should
258 // now be zero and incomplete so the back buffer should be black
259 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
260 drawQuad(mTextureProgram, "position", 0.5f);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400261 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400262}
Jamie Madillfa05f602015-05-07 13:47:11 -0400263
Jamie Madillbb714f72015-05-20 10:22:18 -0400264// Bind a Pbuffer, redefine the texture, and verify it renders correctly
265TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
266{
267 if (!mSupportsPbuffers)
268 {
269 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
270 return;
271 }
272
273 if (!mSupportsBindTexImage)
274 {
275 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
276 return;
277 }
278
279 EGLWindow *window = getEGLWindow();
280
281 // Apply the Pbuffer and clear it to purple
282 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
283 ASSERT_EGL_SUCCESS();
284
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700285 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Jamie Madillbb714f72015-05-20 10:22:18 -0400286 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
287 glClear(GL_COLOR_BUFFER_BIT);
288 ASSERT_GL_NO_ERROR();
289
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700290 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
291 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400292
293 // Apply the window surface
Jamie Madillfe548342017-06-19 11:13:24 -0400294 window->makeCurrent();
Jamie Madillbb714f72015-05-20 10:22:18 -0400295
296 // Create a texture and bind the Pbuffer to it
297 GLuint texture = 0;
298 glGenTextures(1, &texture);
299 glBindTexture(GL_TEXTURE_2D, texture);
300 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
301 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
304 EXPECT_GL_NO_ERROR();
305
306 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400307 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Jamie Madillbb714f72015-05-20 10:22:18 -0400308 ASSERT_EGL_SUCCESS();
309
310 // Redefine the texture
311 unsigned int pixelValue = 0xFFFF00FF;
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400312 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
313 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]);
Jamie Madillbb714f72015-05-20 10:22:18 -0400314
315 // Draw a quad and verify that it is magenta
316 glUseProgram(mTextureProgram);
317 glUniform1i(mTextureUniformLocation, 0);
318
319 drawQuad(mTextureProgram, "position", 0.5f);
320 EXPECT_GL_NO_ERROR();
321
322 // Verify that magenta was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400323 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400324
325 glDeleteTextures(1, &texture);
326}
327
Jamie Madillfa05f602015-05-07 13:47:11 -0400328// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -0500329ANGLE_INSTANTIATE_TEST(PbufferTest,
330 ES2_D3D9(),
331 ES2_D3D11(),
332 ES2_OPENGL(),
333 ES2_D3D11_WARP(),
334 ES2_D3D11_REFERENCE(),
335 ES2_OPENGLES());