blob: 0f8ea6106693d0dd6a2ca15b095d6dd38651a868 [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 Wallez9cb95832015-05-11 10:21:48 -07007#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 {
74 EGL_WIDTH, mPbufferSize,
75 EGL_HEIGHT, 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();
133 EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 0, 0, 255, 255);
134
135 // Apply the Pbuffer and clear it to purple and verify
136 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
137 ASSERT_EGL_SUCCESS();
138
139 glViewport(0, 0, mPbufferSize, mPbufferSize);
140 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
141 glClear(GL_COLOR_BUFFER_BIT);
142 ASSERT_GL_NO_ERROR();
143 EXPECT_PIXEL_EQ(mPbufferSize / 2, mPbufferSize / 2, 255, 0, 255, 255);
144
145 // Rebind the window serfance and verify that it is still blue
146 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
147 ASSERT_EGL_SUCCESS();
148 EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 0, 0, 255, 255);
149}
150
151// Bind the Pbuffer to a texture and verify it renders correctly
Jamie Madillfa05f602015-05-07 13:47:11 -0400152TEST_P(PbufferTest, BindTexImage)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400153{
Geoff Lang1c906c22015-04-10 11:26:17 -0400154 if (!mSupportsPbuffers)
155 {
156 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
157 return;
158 }
159
160 if (!mSupportsBindTexImage)
161 {
162 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
163 return;
164 }
165
Geoff Lang0ca42a52015-04-07 13:47:41 -0400166 EGLWindow *window = getEGLWindow();
167
168 // Apply the Pbuffer and clear it to purple
169 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
170 ASSERT_EGL_SUCCESS();
171
172 glViewport(0, 0, mPbufferSize, mPbufferSize);
173 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
174 glClear(GL_COLOR_BUFFER_BIT);
175 ASSERT_GL_NO_ERROR();
176
177 EXPECT_PIXEL_EQ(mPbufferSize / 2, mPbufferSize / 2, 255, 0, 255, 255);
178
179 // Apply the window surface
180 eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
181
182 // Create a texture and bind the Pbuffer to it
183 GLuint texture = 0;
184 glGenTextures(1, &texture);
185 glBindTexture(GL_TEXTURE_2D, texture);
186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
190 EXPECT_GL_NO_ERROR();
191
192 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
193 glViewport(0, 0, window->getWidth(), window->getHeight());
194 ASSERT_EGL_SUCCESS();
195
196 // Draw a quad and verify that it is purple
197 glUseProgram(mTextureProgram);
198 glUniform1i(mTextureUniformLocation, 0);
199
200 drawQuad(mTextureProgram, "position", 0.5f);
201 EXPECT_GL_NO_ERROR();
202
203 // Unbind the texture
204 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
205 ASSERT_EGL_SUCCESS();
206
207 // Verify that purple was drawn
208 EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 255, 0, 255, 255);
209
210 glDeleteTextures(1, &texture);
211}
212
213// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
214// size information is correctly updated.
Jamie Madillfa05f602015-05-07 13:47:11 -0400215TEST_P(PbufferTest, TextureSizeReset)
Geoff Lang0ca42a52015-04-07 13:47:41 -0400216{
Geoff Lang1c906c22015-04-10 11:26:17 -0400217 if (!mSupportsPbuffers)
218 {
219 std::cout << "Test skipped because Pbuffers are not supported." << std::endl;
220 return;
221 }
222
223 if (!mSupportsBindTexImage)
224 {
225 std::cout << "Test skipped because Pbuffer does not support binding to RGBA textures." << std::endl;
226 return;
227 }
228
Geoff Lang0ca42a52015-04-07 13:47:41 -0400229 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 glUseProgram(mTextureProgram);
239 glUniform1i(mTextureUniformLocation, 0);
240
241 // Fill the texture with white pixels
242 std::vector<GLubyte> whitePixels(mPbufferSize * mPbufferSize * 4, 255);
243 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mPbufferSize, mPbufferSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixels[0]);
244 EXPECT_GL_NO_ERROR();
245
246 // Draw the white texture and verify that the pixels are correct
247 drawQuad(mTextureProgram, "position", 0.5f);
248 EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
249
250 // Bind the EGL surface and draw with it, results are undefined since nothing has
251 // been written to it
252 EGLWindow *window = getEGLWindow();
253 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
254 drawQuad(mTextureProgram, "position", 0.5f);
255 EXPECT_GL_NO_ERROR();
256
257 // Clear the back buffer to a unique color (green)
258 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
259 glClear(GL_COLOR_BUFFER_BIT);
260 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
261
262 // Unbind the EGL surface and try to draw with the texture again, the texture's size should
263 // now be zero and incomplete so the back buffer should be black
264 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
265 drawQuad(mTextureProgram, "position", 0.5f);
266 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
267}
Jamie Madillfa05f602015-05-07 13:47:11 -0400268
269// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
270ANGLE_INSTANTIATE_TEST(PbufferTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_D3D11_WARP(), ES2_D3D11_REFERENCE());