blob: cc086ed5e5a736f02e32e2b9517f70c110104e67 [file] [log] [blame]
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001//
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// StateChangeTest:
7// Specifically designed for an ANGLE implementation of GL, these tests validate that
8// ANGLE's dirty bits systems don't get confused by certain sequences of state changes.
9//
10
11#include "test_utils/ANGLETest.h"
12
13using namespace angle;
14
15namespace
16{
17
18class StateChangeTest : public ANGLETest
19{
20 protected:
21 StateChangeTest() : mFramebuffer(0)
22 {
23 setWindowWidth(64);
24 setWindowHeight(64);
25 setConfigRedBits(8);
26 setConfigGreenBits(8);
27 setConfigBlueBits(8);
28 setConfigAlphaBits(8);
29
30 // Enable the no error extension to avoid syncing the FBO state on validation.
31 setNoErrorEnabled(true);
32 }
33
34 void SetUp() override
35 {
36 ANGLETest::SetUp();
37
38 glGenFramebuffers(1, &mFramebuffer);
39
40 mTextures.resize(2, 0);
41 glGenTextures(2, mTextures.data());
42
43 ASSERT_GL_NO_ERROR();
44 }
45
46 void TearDown() override
47 {
48 if (mFramebuffer != 0)
49 {
50 glDeleteFramebuffers(1, &mFramebuffer);
51 mFramebuffer = 0;
52 }
53
54 if (!mTextures.empty())
55 {
56 glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
57 mTextures.clear();
58 }
59
60 ANGLETest::TearDown();
61 }
62
63 GLuint mFramebuffer;
64 std::vector<GLuint> mTextures;
65};
66
67class StateChangeTestES3 : public StateChangeTest
68{
69 protected:
70 StateChangeTestES3() {}
71};
72
73} // anonymous namespace
74
75// Ensure that CopyTexImage2D syncs framebuffer changes.
76TEST_P(StateChangeTest, CopyTexImage2DSync)
77{
Jamie Madill7208f692016-02-29 10:47:35 -050078 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
Geoff Lang5103f4c2016-01-26 11:40:18 -050079 {
80 // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/1291)
81 std::cout << "Test disabled on AMD OpenGL." << std::endl;
82 return;
83 }
84
Jamie Madill60ec6ea2016-01-22 15:27:19 -050085 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
86
87 // Init first texture to red
88 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
89 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
90 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
91 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
92 glClear(GL_COLOR_BUFFER_BIT);
93 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
94
95 // Init second texture to green
96 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
97 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
98 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
99 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
100 glClear(GL_COLOR_BUFFER_BIT);
101 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
102
103 // Copy in the red texture to the green one.
104 // CopyTexImage should sync the framebuffer attachment change.
105 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
106 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
107 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
108 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
109
110 ASSERT_GL_NO_ERROR();
111}
112
113// Ensure that CopyTexSubImage2D syncs framebuffer changes.
114TEST_P(StateChangeTest, CopyTexSubImage2DSync)
115{
116 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
117
118 // Init first texture to red
119 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
120 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
121 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
122 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
123 glClear(GL_COLOR_BUFFER_BIT);
124 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
125
126 // Init second texture to green
127 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
128 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
129 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
130 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
131 glClear(GL_COLOR_BUFFER_BIT);
132 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
133
134 // Copy in the red texture to the green one.
135 // CopyTexImage should sync the framebuffer attachment change.
136 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
137 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
138 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
139 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
140
141 ASSERT_GL_NO_ERROR();
142}
143
144// Ensure that CopyTexSubImage3D syncs framebuffer changes.
145TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
146{
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500147 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
148
149 // Init first texture to red
150 glBindTexture(GL_TEXTURE_3D, mTextures[0]);
151 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
152 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
153 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
154 glClear(GL_COLOR_BUFFER_BIT);
155 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
156
157 // Init second texture to green
158 glBindTexture(GL_TEXTURE_3D, mTextures[1]);
159 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
160 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
161 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
162 glClear(GL_COLOR_BUFFER_BIT);
163 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
164
165 // Copy in the red texture to the green one.
166 // CopyTexImage should sync the framebuffer attachment change.
167 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
168 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
169 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
170 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
171
172 ASSERT_GL_NO_ERROR();
173}
174
175// Ensure that BlitFramebuffer syncs framebuffer changes.
176TEST_P(StateChangeTestES3, BlitFramebufferSync)
177{
178 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
179
180 // Init first texture to red
181 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
182 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
183 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
184 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
185 glClear(GL_COLOR_BUFFER_BIT);
186 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
187
188 // Init second texture to green
189 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
190 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
191 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
192 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
193 glClear(GL_COLOR_BUFFER_BIT);
194 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
195
196 // Change to the red textures and blit.
197 // BlitFramebuffer should sync the framebuffer attachment change.
198 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
199 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
200 0);
201 glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
202 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
203 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
204
205 ASSERT_GL_NO_ERROR();
206}
207
208// Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
209TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
210{
211 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
212
213 // Initialize two FBO attachments
214 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
215 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
216 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
217 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
218 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
219 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
220
221 // Clear first attachment to red
222 GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
223 glDrawBuffers(2, bufs1);
224 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
225 glClear(GL_COLOR_BUFFER_BIT);
226
227 // Clear second texture to green
228 GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
229 glDrawBuffers(2, bufs2);
230 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
231 glClear(GL_COLOR_BUFFER_BIT);
232
233 // Verify first attachment is red and second is green
234 glReadBuffer(GL_COLOR_ATTACHMENT1);
235 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
236
237 glReadBuffer(GL_COLOR_ATTACHMENT0);
238 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
239
240 ASSERT_GL_NO_ERROR();
241}
242
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500243class StateChangeRenderTest : public StateChangeTest
244{
245 protected:
246 StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
247
248 void SetUp() override
249 {
250 StateChangeTest::SetUp();
251
252 const std::string vertexShaderSource =
253 "attribute vec2 position;\n"
254 "void main() {\n"
255 " gl_Position = vec4(position, 0, 1);\n"
256 "}";
257 const std::string fragmentShaderSource =
258 "uniform highp vec4 uniformColor;\n"
259 "void main() {\n"
260 " gl_FragColor = uniformColor;\n"
261 "}";
262
263 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
264 ASSERT_NE(0u, mProgram);
265
266 glGenRenderbuffers(1, &mRenderbuffer);
267 }
268
269 void TearDown() override
270 {
271 glDeleteProgram(mProgram);
272 glDeleteRenderbuffers(1, &mRenderbuffer);
273
274 StateChangeTest::TearDown();
275 }
276
277 void setUniformColor(const GLColor &color)
278 {
279 glUseProgram(mProgram);
280 const Vector4 &normalizedColor = color.toNormalizedVector();
281 GLint uniformLocation = glGetUniformLocation(mProgram, "uniformColor");
282 ASSERT_NE(-1, uniformLocation);
283 glUniform4fv(uniformLocation, 1, normalizedColor.data());
284 }
285
286 GLuint mProgram;
287 GLuint mRenderbuffer;
288};
289
290// Test that re-creating a currently attached texture works as expected.
291TEST_P(StateChangeRenderTest, RecreateTexture)
292{
293 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
294
295 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
296 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
297 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
298
299 // Draw with red to the FBO.
300 GLColor red(255, 0, 0, 255);
301 setUniformColor(red);
302 drawQuad(mProgram, "position", 0.5f);
303 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
304
305 // Recreate the texture with green.
306 GLColor green(0, 255, 0, 255);
307 std::vector<GLColor> greenPixels(32 * 32, green);
308 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
309 greenPixels.data());
310 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
311
312 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
313 GLColor blue(0, 0, 255, 255);
314 setUniformColor(blue);
315 drawQuad(mProgram, "position", 0.5f);
316 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
317
318 EXPECT_GL_NO_ERROR();
319}
320
321// Test that re-creating a currently attached renderbuffer works as expected.
322TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
323{
324 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
325
326 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
327 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
328 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
329
330 // Draw with red to the FBO.
331 GLColor red(255, 0, 0, 255);
332 setUniformColor(red);
333 drawQuad(mProgram, "position", 0.5f);
334 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
335
336 // Recreate the renderbuffer and clear to green.
337 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
338 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
339 glClear(GL_COLOR_BUFFER_BIT);
340 GLColor green(0, 255, 0, 255);
341 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
342
343 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
344 GLColor blue(0, 0, 255, 255);
345 setUniformColor(blue);
346 drawQuad(mProgram, "position", 0.5f);
347 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
348
349 EXPECT_GL_NO_ERROR();
350}
351
352// Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
353TEST_P(StateChangeRenderTest, GenerateMipmap)
354{
355 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
356
357 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
358 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
359 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
360 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
361 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
362
363 // Draw once to set the RenderTarget in D3D11
364 GLColor red(255, 0, 0, 255);
365 setUniformColor(red);
366 drawQuad(mProgram, "position", 0.5f);
367 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
368
369 // This will trigger the texture to be re-created on FL9_3.
370 glGenerateMipmap(GL_TEXTURE_2D);
371
372 // Now ensure we don't have a stale render target.
373 GLColor blue(0, 0, 255, 255);
374 setUniformColor(blue);
375 drawQuad(mProgram, "position", 0.5f);
376 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
377
378 EXPECT_GL_NO_ERROR();
379}
380
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500381ANGLE_INSTANTIATE_TEST(StateChangeTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500382ANGLE_INSTANTIATE_TEST(StateChangeRenderTest,
383 ES2_D3D9(),
384 ES2_D3D11(),
385 ES2_OPENGL(),
386 ES2_D3D11_FL9_3());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500387ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());