blob: 19a174a8bcb942156b06f0d1ba85978f8dcb6e84 [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
Olli Etuahoa20af6d2017-09-18 13:32:29 +030029 const std::string vsSource =
30 R"(precision highp float;
Geoff Lang0ca42a52015-04-07 13:47:41 -040031 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;
Olli Etuahoa20af6d2017-09-18 13:32:29 +030039 })";
Geoff Lang0ca42a52015-04-07 13:47:41 -040040
Olli Etuahoa20af6d2017-09-18 13:32:29 +030041 const std::string textureFSSource =
42 R"(precision highp float;
Geoff Lang0ca42a52015-04-07 13:47:41 -040043 uniform sampler2D tex;
44 varying vec2 texcoord;
45
46 void main()
47 {
48 gl_FragColor = texture2D(tex, texcoord);
Olli Etuahoa20af6d2017-09-18 13:32:29 +030049 })";
Geoff Lang0ca42a52015-04-07 13:47:41 -040050
51 mTextureProgram = CompileProgram(vsSource, textureFSSource);
52 if (mTextureProgram == 0)
53 {
54 FAIL() << "shader compilation failed.";
55 }
56
57 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
58
Geoff Lang1c906c22015-04-10 11:26:17 -040059 EGLWindow *window = getEGLWindow();
60
61 EGLint surfaceType = 0;
62 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE, &surfaceType);
63 mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
64
65 EGLint bindToTextureRGBA = 0;
66 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
67 mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
68
Geoff Lang0ca42a52015-04-07 13:47:41 -040069 const EGLint pBufferAttributes[] =
70 {
Corentin Wallez973402f2015-05-11 13:42:22 -040071 EGL_WIDTH, static_cast<EGLint>(mPbufferSize),
72 EGL_HEIGHT, static_cast<EGLint>(mPbufferSize),
Geoff Lang1c906c22015-04-10 11:26:17 -040073 EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
74 EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
Geoff Lang0ca42a52015-04-07 13:47:41 -040075 EGL_NONE, EGL_NONE,
76 };
77
Geoff Lang0ca42a52015-04-07 13:47:41 -040078 mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
Geoff Lang1c906c22015-04-10 11:26:17 -040079 if (mSupportsPbuffers)
80 {
81 ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
82 ASSERT_EGL_SUCCESS();
83 }
84 else
85 {
86 ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
87 ASSERT_EGL_ERROR(EGL_BAD_MATCH);
88 }
Geoff Lang0ca42a52015-04-07 13:47:41 -040089
Geoff Lang0ca42a52015-04-07 13:47:41 -040090 ASSERT_GL_NO_ERROR();
91 }
92
93 virtual void TearDown()
94 {
95 glDeleteProgram(mTextureProgram);
96
97 EGLWindow *window = getEGLWindow();
98 eglDestroySurface(window->getDisplay(), mPbuffer);
99
100 ANGLETest::TearDown();
101 }
102
103 GLuint mTextureProgram;
104 GLint mTextureUniformLocation;
105
106 const size_t mPbufferSize = 32;
107 EGLSurface mPbuffer;
Geoff Lang1c906c22015-04-10 11:26:17 -0400108 bool mSupportsPbuffers;
109 bool mSupportsBindTexImage;
Geoff Lang0ca42a52015-04-07 13:47:41 -0400110};
111
112// Test clearing a Pbuffer and checking the color is correct
Jamie Madillfa05f602015-05-07 13:47:11 -0400113TEST_P(PbufferTest, Clearing)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400114{
Geoff Lang1c906c22015-04-10 11:26:17 -0400115 if (!mSupportsPbuffers)
116 {
117 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
118 return;
119 }
120
Geoff Lang0ca42a52015-04-07 13:47:41 -0400121 EGLWindow *window = getEGLWindow();
122
123 // Clear the window surface to blue and verify
Jamie Madillfe548342017-06-19 11:13:24 -0400124 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400125 ASSERT_EGL_SUCCESS();
126
127 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
128 glClear(GL_COLOR_BUFFER_BIT);
129 ASSERT_GL_NO_ERROR();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400130 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400131
132 // Apply the Pbuffer and clear it to purple and verify
133 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
134 ASSERT_EGL_SUCCESS();
135
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700136 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400137 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
138 glClear(GL_COLOR_BUFFER_BIT);
139 ASSERT_GL_NO_ERROR();
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700140 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
141 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400142
Corentin Wallez21ce9b02015-05-14 11:50:08 -0400143 // Rebind the window surface and verify that it is still blue
Jamie Madillfe548342017-06-19 11:13:24 -0400144 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400145 ASSERT_EGL_SUCCESS();
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400146 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400147}
148
149// Bind the Pbuffer to a texture and verify it renders correctly
Jamie Madillfa05f602015-05-07 13:47:11 -0400150TEST_P(PbufferTest, BindTexImage)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400151{
Geoff Lang1c906c22015-04-10 11:26:17 -0400152 if (!mSupportsPbuffers)
153 {
154 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
155 return;
156 }
157
158 if (!mSupportsBindTexImage)
159 {
160 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
161 return;
162 }
163
Geoff Lang0ca42a52015-04-07 13:47:41 -0400164 EGLWindow *window = getEGLWindow();
165
166 // Apply the Pbuffer and clear it to purple
167 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
168 ASSERT_EGL_SUCCESS();
169
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700170 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Geoff Lang0ca42a52015-04-07 13:47:41 -0400171 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
172 glClear(GL_COLOR_BUFFER_BIT);
173 ASSERT_GL_NO_ERROR();
174
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700175 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
176 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400177
178 // Apply the window surface
Jamie Madillfe548342017-06-19 11:13:24 -0400179 window->makeCurrent();
Geoff Lang0ca42a52015-04-07 13:47:41 -0400180
181 // Create a texture and bind the Pbuffer to it
182 GLuint texture = 0;
183 glGenTextures(1, &texture);
184 glBindTexture(GL_TEXTURE_2D, texture);
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
189 EXPECT_GL_NO_ERROR();
190
191 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400192 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Geoff Lang0ca42a52015-04-07 13:47:41 -0400193 ASSERT_EGL_SUCCESS();
194
195 // Draw a quad and verify that it is purple
196 glUseProgram(mTextureProgram);
197 glUniform1i(mTextureUniformLocation, 0);
198
199 drawQuad(mTextureProgram, "position", 0.5f);
200 EXPECT_GL_NO_ERROR();
201
202 // Unbind the texture
203 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
204 ASSERT_EGL_SUCCESS();
205
206 // Verify that purple was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400207 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400208
209 glDeleteTextures(1, &texture);
210}
211
212// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
213// size information is correctly updated.
Jamie Madillfa05f602015-05-07 13:47:11 -0400214TEST_P(PbufferTest, TextureSizeReset)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400215{
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400216 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
217 ANGLE_SKIP_TEST_IF(!mSupportsBindTexImage);
Geoff Lang1c906c22015-04-10 11:26:17 -0400218
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400219 GLTexture texture;
Geoff Lang0ca42a52015-04-07 13:47:41 -0400220 glBindTexture(GL_TEXTURE_2D, texture);
221 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
222 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
223 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
224 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
225 EXPECT_GL_NO_ERROR();
226
227 glUseProgram(mTextureProgram);
228 glUniform1i(mTextureUniformLocation, 0);
229
230 // Fill the texture with white pixels
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400231 std::vector<GLColor> whitePixels(mPbufferSize * mPbufferSize, GLColor::white);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700232 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400233 static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE,
234 whitePixels.data());
Geoff Lang0ca42a52015-04-07 13:47:41 -0400235 EXPECT_GL_NO_ERROR();
236
237 // Draw the white texture and verify that the pixels are correct
238 drawQuad(mTextureProgram, "position", 0.5f);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400240
241 // Bind the EGL surface and draw with it, results are undefined since nothing has
242 // been written to it
243 EGLWindow *window = getEGLWindow();
244 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
245 drawQuad(mTextureProgram, "position", 0.5f);
246 EXPECT_GL_NO_ERROR();
247
248 // Clear the back buffer to a unique color (green)
249 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
250 glClear(GL_COLOR_BUFFER_BIT);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400251 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400252
253 // Unbind the EGL surface and try to draw with the texture again, the texture's size should
254 // now be zero and incomplete so the back buffer should be black
255 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
256 drawQuad(mTextureProgram, "position", 0.5f);
Jamie Madillaf4ffe02017-09-09 23:32:48 -0400257 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
Geoff Lang0ca42a52015-04-07 13:47:41 -0400258}
Jamie Madillfa05f602015-05-07 13:47:11 -0400259
Jamie Madillbb714f72015-05-20 10:22:18 -0400260// Bind a Pbuffer, redefine the texture, and verify it renders correctly
261TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
262{
263 if (!mSupportsPbuffers)
264 {
265 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
266 return;
267 }
268
269 if (!mSupportsBindTexImage)
270 {
271 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
272 return;
273 }
274
275 EGLWindow *window = getEGLWindow();
276
277 // Apply the Pbuffer and clear it to purple
278 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
279 ASSERT_EGL_SUCCESS();
280
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700281 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
Jamie Madillbb714f72015-05-20 10:22:18 -0400282 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
283 glClear(GL_COLOR_BUFFER_BIT);
284 ASSERT_GL_NO_ERROR();
285
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700286 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
287 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400288
289 // Apply the window surface
Jamie Madillfe548342017-06-19 11:13:24 -0400290 window->makeCurrent();
Jamie Madillbb714f72015-05-20 10:22:18 -0400291
292 // Create a texture and bind the Pbuffer to it
293 GLuint texture = 0;
294 glGenTextures(1, &texture);
295 glBindTexture(GL_TEXTURE_2D, texture);
296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
300 EXPECT_GL_NO_ERROR();
301
302 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400303 glViewport(0, 0, getWindowWidth(), getWindowHeight());
Jamie Madillbb714f72015-05-20 10:22:18 -0400304 ASSERT_EGL_SUCCESS();
305
306 // Redefine the texture
307 unsigned int pixelValue = 0xFFFF00FF;
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400308 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
309 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]);
Jamie Madillbb714f72015-05-20 10:22:18 -0400310
311 // Draw a quad and verify that it is magenta
312 glUseProgram(mTextureProgram);
313 glUniform1i(mTextureUniformLocation, 0);
314
315 drawQuad(mTextureProgram, "position", 0.5f);
316 EXPECT_GL_NO_ERROR();
317
318 // Verify that magenta was drawn
Corentin Wallezf3357ee2015-07-22 14:10:19 -0400319 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
Jamie Madillbb714f72015-05-20 10:22:18 -0400320
321 glDeleteTextures(1, &texture);
322}
323
Jamie Madillfa05f602015-05-07 13:47:11 -0400324// 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 -0500325ANGLE_INSTANTIATE_TEST(PbufferTest,
326 ES2_D3D9(),
327 ES2_D3D11(),
328 ES2_OPENGL(),
329 ES2_D3D11_WARP(),
330 ES2_D3D11_REFERENCE(),
331 ES2_OPENGLES());