1 //
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 #include "test_utils/gl_raii.h"
13
14 using namespace angle;
15
16 namespace
17 {
18
19 class StateChangeTest : public ANGLETest
20 {
21 protected:
StateChangeTest()22 StateChangeTest()
23 {
24 setWindowWidth(64);
25 setWindowHeight(64);
26 setConfigRedBits(8);
27 setConfigGreenBits(8);
28 setConfigBlueBits(8);
29 setConfigAlphaBits(8);
30
31 // Enable the no error extension to avoid syncing the FBO state on validation.
32 setNoErrorEnabled(true);
33 }
34
SetUp()35 void SetUp() override
36 {
37 ANGLETest::SetUp();
38
39 glGenFramebuffers(1, &mFramebuffer);
40 glGenTextures(2, mTextures.data());
41 glGenRenderbuffers(1, &mRenderbuffer);
42
43 ASSERT_GL_NO_ERROR();
44 }
45
TearDown()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 glDeleteRenderbuffers(1, &mRenderbuffer);
61
62 ANGLETest::TearDown();
63 }
64
65 GLuint mFramebuffer = 0;
66 GLuint mRenderbuffer = 0;
67 std::vector<GLuint> mTextures = {0, 0};
68 };
69
70 class StateChangeTestES3 : public StateChangeTest
71 {
72 protected:
StateChangeTestES3()73 StateChangeTestES3() {}
74 };
75
76 } // anonymous namespace
77
78 // Ensure that CopyTexImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexImage2DSync)79 TEST_P(StateChangeTest, CopyTexImage2DSync)
80 {
81 if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
82 {
83 // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/1291)
84 std::cout << "Test disabled on AMD OpenGL." << std::endl;
85 return;
86 }
87
88 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
89
90 // Init first texture to red
91 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
92 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
93 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
94 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
95 glClear(GL_COLOR_BUFFER_BIT);
96 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
97
98 // Init second texture to green
99 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
100 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
101 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
102 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
103 glClear(GL_COLOR_BUFFER_BIT);
104 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
105
106 // Copy in the red texture to the green one.
107 // CopyTexImage should sync the framebuffer attachment change.
108 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
109 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
110 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
111 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
112
113 ASSERT_GL_NO_ERROR();
114 }
115
116 // Ensure that CopyTexSubImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexSubImage2DSync)117 TEST_P(StateChangeTest, CopyTexSubImage2DSync)
118 {
119 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
120
121 // Init first texture to red
122 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
123 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
124 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
125 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
126 glClear(GL_COLOR_BUFFER_BIT);
127 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
128
129 // Init second texture to green
130 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
131 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
132 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
133 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
134 glClear(GL_COLOR_BUFFER_BIT);
135 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
136
137 // Copy in the red texture to the green one.
138 // CopyTexImage should sync the framebuffer attachment change.
139 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
140 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
141 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
142 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
143
144 ASSERT_GL_NO_ERROR();
145 }
146
147 // Test that Framebuffer completeness caching works when color attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteColorAttachment)148 TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
149 {
150 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
151 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
152 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
153 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
154 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
155
156 // Change the texture at color attachment 0 to be non-color-renderable.
157 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
158 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
159 glCheckFramebufferStatus(GL_FRAMEBUFFER));
160
161 ASSERT_GL_NO_ERROR();
162 }
163
164 // Test that caching works when color attachments change with TexStorage.
TEST_P(StateChangeTest,FramebufferIncompleteWithTexStorage)165 TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
166 {
167 if (!extensionEnabled("GL_EXT_texture_storage"))
168 {
169 std::cout << "Test skipped because TexStorage2DEXT not available." << std::endl;
170 }
171
172 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
173 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
174 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
175 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
176 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
177
178 // Change the texture at color attachment 0 to be non-color-renderable.
179 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
180 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
181 glCheckFramebufferStatus(GL_FRAMEBUFFER));
182
183 ASSERT_GL_NO_ERROR();
184 }
185
186 // Test that caching works when color attachments change with CompressedTexImage2D.
TEST_P(StateChangeTestES3,FramebufferIncompleteWithCompressedTex)187 TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
188 {
189 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
190 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
191 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
192 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
193 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
194
195 // Change the texture at color attachment 0 to be non-color-renderable.
196 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 64, nullptr);
197 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
198 glCheckFramebufferStatus(GL_FRAMEBUFFER));
199
200 ASSERT_GL_NO_ERROR();
201 }
202
203 // Test that caching works when color attachments are deleted.
TEST_P(StateChangeTestES3,FramebufferIncompleteWhenAttachmentDeleted)204 TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
205 {
206 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
207 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
208 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
209 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
210 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
211
212 // Delete the texture at color attachment 0.
213 glDeleteTextures(1, &mTextures[0]);
214 mTextures[0] = 0;
215 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
216 glCheckFramebufferStatus(GL_FRAMEBUFFER));
217
218 ASSERT_GL_NO_ERROR();
219 }
220
221 // Test that Framebuffer completeness caching works when depth attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthAttachment)222 TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
223 {
224 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
225 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
226 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
227 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
228 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
229 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
230 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
231 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
232
233 // Change the texture at color attachment 0 to be non-depth-renderable.
234 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
235 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
236 glCheckFramebufferStatus(GL_FRAMEBUFFER));
237
238 ASSERT_GL_NO_ERROR();
239 }
240
241 // Test that Framebuffer completeness caching works when stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteStencilAttachment)242 TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
243 {
244 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
245 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
246 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
247 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
248 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
249 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
250 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
251 mRenderbuffer);
252 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
253
254 // Change the texture at the stencil attachment to be non-stencil-renderable.
255 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
256 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
257 glCheckFramebufferStatus(GL_FRAMEBUFFER));
258
259 ASSERT_GL_NO_ERROR();
260 }
261
262 // Test that Framebuffer completeness caching works when depth-stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthStencilAttachment)263 TEST_P(StateChangeTest, FramebufferIncompleteDepthStencilAttachment)
264 {
265 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_packed_depth_stencil"))
266 {
267 std::cout << "Test skipped because packed depth+stencil not availble." << std::endl;
268 return;
269 }
270
271 if (IsWindows() && IsIntel() && IsOpenGL())
272 {
273 // TODO(jmadill): Investigate the failure (https://anglebug.com/1388)
274 std::cout << "Test disabled on Windows Intel OpenGL." << std::endl;
275 return;
276 }
277
278 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
279 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
280 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
281 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
282 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
283 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
284 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
285 mRenderbuffer);
286 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
287
288 // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
289 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
290 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
291 glCheckFramebufferStatus(GL_FRAMEBUFFER));
292
293 ASSERT_GL_NO_ERROR();
294 }
295
296 // Ensure that CopyTexSubImage3D syncs framebuffer changes.
TEST_P(StateChangeTestES3,CopyTexSubImage3DSync)297 TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
298 {
299 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
300
301 // Init first texture to red
302 glBindTexture(GL_TEXTURE_3D, mTextures[0]);
303 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
304 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
305 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
306 glClear(GL_COLOR_BUFFER_BIT);
307 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
308
309 // Init second texture to green
310 glBindTexture(GL_TEXTURE_3D, mTextures[1]);
311 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
312 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
313 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
314 glClear(GL_COLOR_BUFFER_BIT);
315 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
316
317 // Copy in the red texture to the green one.
318 // CopyTexImage should sync the framebuffer attachment change.
319 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
320 glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
321 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
322 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
323
324 ASSERT_GL_NO_ERROR();
325 }
326
327 // Ensure that BlitFramebuffer syncs framebuffer changes.
TEST_P(StateChangeTestES3,BlitFramebufferSync)328 TEST_P(StateChangeTestES3, BlitFramebufferSync)
329 {
330 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
331
332 // Init first texture to red
333 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
334 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
335 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
336 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
337 glClear(GL_COLOR_BUFFER_BIT);
338 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
339
340 // Init second texture to green
341 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
342 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
343 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
344 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
345 glClear(GL_COLOR_BUFFER_BIT);
346 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
347
348 // Change to the red textures and blit.
349 // BlitFramebuffer should sync the framebuffer attachment change.
350 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
351 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
352 0);
353 glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
354 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
355 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
356
357 ASSERT_GL_NO_ERROR();
358 }
359
360 // Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
TEST_P(StateChangeTestES3,ReadBufferAndDrawBuffersSync)361 TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
362 {
363 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
364
365 // Initialize two FBO attachments
366 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
367 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
368 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
369 glBindTexture(GL_TEXTURE_2D, mTextures[1]);
370 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
371 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
372
373 // Clear first attachment to red
374 GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
375 glDrawBuffers(2, bufs1);
376 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
377 glClear(GL_COLOR_BUFFER_BIT);
378
379 // Clear second texture to green
380 GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
381 glDrawBuffers(2, bufs2);
382 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
383 glClear(GL_COLOR_BUFFER_BIT);
384
385 // Verify first attachment is red and second is green
386 glReadBuffer(GL_COLOR_ATTACHMENT1);
387 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
388
389 glReadBuffer(GL_COLOR_ATTACHMENT0);
390 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
391
392 ASSERT_GL_NO_ERROR();
393 }
394
395 // Tests calling invalidate on incomplete framebuffers after switching attachments.
396 // Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
TEST_P(StateChangeTestES3,IncompleteRenderbufferAttachmentInvalidateSync)397 TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
398 {
399 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
400 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
401 GLint samples = 0;
402 glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
403 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
404 ASSERT_GL_NO_ERROR();
405
406 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
407 // attached renderbuffer
408 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
409 glCheckFramebufferStatus(GL_FRAMEBUFFER));
410 GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
411 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
412 ASSERT_GL_NO_ERROR();
413
414 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
415 getWindowWidth(), getWindowHeight());
416 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
417 glClear(GL_COLOR_BUFFER_BIT);
418 ASSERT_GL_NO_ERROR();
419
420 GLRenderbuffer renderbuf;
421
422 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
423 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
424 renderbuf.get());
425 ASSERT_GL_NO_ERROR();
426
427 // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
428 // attached renderbuffer
429 // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
430 GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
431 glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
432
433 glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
434 GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
435 EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
436 glClear(GL_DEPTH_BUFFER_BIT);
437 ASSERT_GL_NO_ERROR();
438 }
439
440 class StateChangeRenderTest : public StateChangeTest
441 {
442 protected:
StateChangeRenderTest()443 StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
444
SetUp()445 void SetUp() override
446 {
447 StateChangeTest::SetUp();
448
449 const std::string vertexShaderSource =
450 "attribute vec2 position;\n"
451 "void main() {\n"
452 " gl_Position = vec4(position, 0, 1);\n"
453 "}";
454 const std::string fragmentShaderSource =
455 "uniform highp vec4 uniformColor;\n"
456 "void main() {\n"
457 " gl_FragColor = uniformColor;\n"
458 "}";
459
460 mProgram = CompileProgram(vertexShaderSource, fragmentShaderSource);
461 ASSERT_NE(0u, mProgram);
462
463 glGenRenderbuffers(1, &mRenderbuffer);
464 }
465
TearDown()466 void TearDown() override
467 {
468 glDeleteProgram(mProgram);
469 glDeleteRenderbuffers(1, &mRenderbuffer);
470
471 StateChangeTest::TearDown();
472 }
473
setUniformColor(const GLColor & color)474 void setUniformColor(const GLColor &color)
475 {
476 glUseProgram(mProgram);
477 const Vector4 &normalizedColor = color.toNormalizedVector();
478 GLint uniformLocation = glGetUniformLocation(mProgram, "uniformColor");
479 ASSERT_NE(-1, uniformLocation);
480 glUniform4fv(uniformLocation, 1, normalizedColor.data());
481 }
482
483 GLuint mProgram;
484 GLuint mRenderbuffer;
485 };
486
487 // Test that re-creating a currently attached texture works as expected.
TEST_P(StateChangeRenderTest,RecreateTexture)488 TEST_P(StateChangeRenderTest, RecreateTexture)
489 {
490 if (IsIntel() && IsLinux())
491 {
492 // TODO(cwallez): Fix on Linux Intel drivers (http://anglebug.com/1346)
493 std::cout << "Test disabled on Linux Intel OpenGL." << std::endl;
494 return;
495 }
496
497 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
498
499 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
500 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
501 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
502
503 // Draw with red to the FBO.
504 GLColor red(255, 0, 0, 255);
505 setUniformColor(red);
506 drawQuad(mProgram, "position", 0.5f);
507 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
508
509 // Recreate the texture with green.
510 GLColor green(0, 255, 0, 255);
511 std::vector<GLColor> greenPixels(32 * 32, green);
512 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
513 greenPixels.data());
514 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
515
516 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
517 GLColor blue(0, 0, 255, 255);
518 setUniformColor(blue);
519 drawQuad(mProgram, "position", 0.5f);
520 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
521
522 EXPECT_GL_NO_ERROR();
523 }
524
525 // Test that re-creating a currently attached renderbuffer works as expected.
TEST_P(StateChangeRenderTest,RecreateRenderbuffer)526 TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
527 {
528 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
529
530 glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
531 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
532 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
533
534 // Draw with red to the FBO.
535 GLColor red(255, 0, 0, 255);
536 setUniformColor(red);
537 drawQuad(mProgram, "position", 0.5f);
538 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
539
540 // Recreate the renderbuffer and clear to green.
541 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
542 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
543 glClear(GL_COLOR_BUFFER_BIT);
544 GLColor green(0, 255, 0, 255);
545 EXPECT_PIXEL_COLOR_EQ(0, 0, green);
546
547 // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
548 GLColor blue(0, 0, 255, 255);
549 setUniformColor(blue);
550 drawQuad(mProgram, "position", 0.5f);
551 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
552
553 EXPECT_GL_NO_ERROR();
554 }
555
556 // Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
TEST_P(StateChangeRenderTest,GenerateMipmap)557 TEST_P(StateChangeRenderTest, GenerateMipmap)
558 {
559 glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
560
561 glBindTexture(GL_TEXTURE_2D, mTextures[0]);
562 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
563 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
564 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
565 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
566
567 // Draw once to set the RenderTarget in D3D11
568 GLColor red(255, 0, 0, 255);
569 setUniformColor(red);
570 drawQuad(mProgram, "position", 0.5f);
571 EXPECT_PIXEL_COLOR_EQ(0, 0, red);
572
573 // This will trigger the texture to be re-created on FL9_3.
574 glGenerateMipmap(GL_TEXTURE_2D);
575
576 // Now ensure we don't have a stale render target.
577 GLColor blue(0, 0, 255, 255);
578 setUniformColor(blue);
579 drawQuad(mProgram, "position", 0.5f);
580 EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
581
582 EXPECT_GL_NO_ERROR();
583 }
584
585 ANGLE_INSTANTIATE_TEST(StateChangeTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
586 ANGLE_INSTANTIATE_TEST(StateChangeRenderTest,
587 ES2_D3D9(),
588 ES2_D3D11(),
589 ES2_OPENGL(),
590 ES2_D3D11_FL9_3());
591 ANGLE_INSTANTIATE_TEST(StateChangeTestES3, ES3_D3D11(), ES3_OPENGL());
592