xref: /aosp_15_r20/external/angle/src/tests/gl_tests/StateChangeTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 #include "util/random_utils.h"
14 
15 #include <thread>
16 
17 using namespace angle;
18 
19 namespace
20 {
21 
22 class StateChangeTest : public ANGLETest<>
23 {
24   protected:
StateChangeTest()25     StateChangeTest()
26     {
27         setWindowWidth(64);
28         setWindowHeight(64);
29         setConfigRedBits(8);
30         setConfigGreenBits(8);
31         setConfigBlueBits(8);
32         setConfigAlphaBits(8);
33         setConfigDepthBits(24);
34         setConfigStencilBits(8);
35 
36         // Enable the no error extension to avoid syncing the FBO state on validation.
37         setNoErrorEnabled(true);
38     }
39 
testSetUp()40     void testSetUp() override
41     {
42         glGenFramebuffers(1, &mFramebuffer);
43         glGenTextures(2, mTextures.data());
44         glGenRenderbuffers(1, &mRenderbuffer);
45 
46         ASSERT_GL_NO_ERROR();
47     }
48 
testTearDown()49     void testTearDown() override
50     {
51         if (mFramebuffer != 0)
52         {
53             glDeleteFramebuffers(1, &mFramebuffer);
54             mFramebuffer = 0;
55         }
56 
57         if (!mTextures.empty())
58         {
59             glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
60             mTextures.clear();
61         }
62 
63         glDeleteRenderbuffers(1, &mRenderbuffer);
64     }
65 
66     GLuint mFramebuffer           = 0;
67     GLuint mRenderbuffer          = 0;
68     std::vector<GLuint> mTextures = {0, 0};
69 };
70 
71 class StateChangeTestES3 : public StateChangeTest
72 {
73   protected:
StateChangeTestES3()74     StateChangeTestES3() {}
75 };
76 
77 class StateChangeTestES31 : public StateChangeTest
78 {
79   protected:
StateChangeTestES31()80     StateChangeTestES31() {}
81 };
82 
83 // Ensure that CopyTexImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexImage2DSync)84 TEST_P(StateChangeTest, CopyTexImage2DSync)
85 {
86     // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/42260302)
87     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
88 
89     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
90 
91     // Init first texture to red
92     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
93     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
94     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
95     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
96     glClear(GL_COLOR_BUFFER_BIT);
97     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
98 
99     // Init second texture to green
100     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
101     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
102     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
103     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
104     glClear(GL_COLOR_BUFFER_BIT);
105     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
106 
107     // Copy in the red texture to the green one.
108     // CopyTexImage should sync the framebuffer attachment change.
109     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
110     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
111     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
112     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
113 
114     ASSERT_GL_NO_ERROR();
115 }
116 
117 // Ensure that CopyTexSubImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexSubImage2DSync)118 TEST_P(StateChangeTest, CopyTexSubImage2DSync)
119 {
120     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
121 
122     // Init first texture to red
123     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
124     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
125     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
126     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
127     glClear(GL_COLOR_BUFFER_BIT);
128     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
129 
130     // Init second texture to green
131     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
132     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
133     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
134     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
135     glClear(GL_COLOR_BUFFER_BIT);
136     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
137 
138     // Copy in the red texture to the green one.
139     // CopyTexImage should sync the framebuffer attachment change.
140     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
141     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
142     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
143     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
144 
145     ASSERT_GL_NO_ERROR();
146 }
147 
148 // Test that Framebuffer completeness caching works when color attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteColorAttachment)149 TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
150 {
151     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
152     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
153     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
154     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
155     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
156 
157     // Change the texture at color attachment 0 to be non-color-renderable.
158     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
159     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
160                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
161 
162     ASSERT_GL_NO_ERROR();
163 }
164 
165 // Test that caching works when color attachments change with TexStorage.
TEST_P(StateChangeTest,FramebufferIncompleteWithTexStorage)166 TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
167 {
168     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
169 
170     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
171     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
172     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
173     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
174     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
175 
176     // Change the texture at color attachment 0 to be non-color-renderable.
177     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
178     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
179                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
180 
181     ASSERT_GL_NO_ERROR();
182 }
183 
184 // Test that caching works when color attachments change with CompressedTexImage2D.
TEST_P(StateChangeTestES3,FramebufferIncompleteWithCompressedTex)185 TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
186 {
187     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/42262497
188     ANGLE_SKIP_TEST_IF(IsMac() && IsDesktopOpenGL());
189 
190     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
191     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
192     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
193     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
194     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
195 
196     // Change the texture at color attachment 0 to be non-color-renderable.
197     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 128, nullptr);
198     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
199                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
200 
201     ASSERT_GL_NO_ERROR();
202 }
203 
204 // Test that caching works when color attachments are deleted.
TEST_P(StateChangeTestES3,FramebufferIncompleteWhenAttachmentDeleted)205 TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
206 {
207     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
208     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
209     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
210     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
211     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
212 
213     // Delete the texture at color attachment 0.
214     glDeleteTextures(1, &mTextures[0]);
215     mTextures[0] = 0;
216     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
217                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
218 
219     ASSERT_GL_NO_ERROR();
220 }
221 
222 // Test that Framebuffer completeness caching works when depth attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthAttachment)223 TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
224 {
225     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
226     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
227     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
228     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
229     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
230     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
231     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
232     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
233 
234     // Change the texture at color attachment 0 to be non-depth-renderable.
235     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
236     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
237                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
238 
239     ASSERT_GL_NO_ERROR();
240 }
241 
242 // Test that Framebuffer completeness caching works when stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteStencilAttachment)243 TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
244 {
245     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
246     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
247     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
248     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
249     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
250     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
251     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
252                               mRenderbuffer);
253     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
254 
255     // Change the texture at the stencil attachment to be non-stencil-renderable.
256     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
257     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
258                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
259 
260     ASSERT_GL_NO_ERROR();
261 }
262 
263 // Test that Framebuffer completeness caching works when depth-stencil attachments change.
TEST_P(StateChangeTestES3,FramebufferIncompleteDepthStencilAttachment)264 TEST_P(StateChangeTestES3, FramebufferIncompleteDepthStencilAttachment)
265 {
266     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
267     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
268     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
269     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
270     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
271     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
272     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
273                               mRenderbuffer);
274     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
275 
276     // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
277     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
278     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
279                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
280 
281     ASSERT_GL_NO_ERROR();
282 }
283 
284 // Test that enabling GL_SAMPLE_ALPHA_TO_COVERAGE doesn't generate errors.
TEST_P(StateChangeTest,AlphaToCoverageEnable)285 TEST_P(StateChangeTest, AlphaToCoverageEnable)
286 {
287     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
288 
289     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
290     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
291     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
292     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
293     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
294     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
295 
296     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
297 
298     // We don't actually care that this does anything, just that it can be enabled without causing
299     // an error.
300     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
301 
302     glUseProgram(greenProgram);
303     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
304     ASSERT_GL_NO_ERROR();
305     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
306 }
307 
308 const char kSimpleAttributeVS[] = R"(attribute vec2 position;
309 attribute vec4 testAttrib;
310 varying vec4 testVarying;
311 void main()
312 {
313     gl_Position = vec4(position, 0, 1);
314     testVarying = testAttrib;
315 })";
316 
317 const char kSimpleAttributeFS[] = R"(precision mediump float;
318 varying vec4 testVarying;
319 void main()
320 {
321     gl_FragColor = testVarying;
322 })";
323 
324 // Tests that using a buffered attribute, then disabling it and using current value, works.
TEST_P(StateChangeTest,DisablingBufferedVertexAttribute)325 TEST_P(StateChangeTest, DisablingBufferedVertexAttribute)
326 {
327     ANGLE_GL_PROGRAM(program, kSimpleAttributeVS, kSimpleAttributeFS);
328     glUseProgram(program);
329     GLint attribLoc   = glGetAttribLocation(program, "testAttrib");
330     GLint positionLoc = glGetAttribLocation(program, "position");
331     ASSERT_NE(-1, attribLoc);
332     ASSERT_NE(-1, positionLoc);
333 
334     // Set up the buffered attribute.
335     std::vector<GLColor> red(6, GLColor::red);
336     GLBuffer attribBuffer;
337     glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
338     glBufferData(GL_ARRAY_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
339     glEnableVertexAttribArray(attribLoc);
340     glVertexAttribPointer(attribLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
341 
342     // Also set the current value to green now.
343     glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
344 
345     // Set up the position attribute as well.
346     setupQuadVertexBuffer(0.5f, 1.0f);
347     glEnableVertexAttribArray(positionLoc);
348     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
349 
350     // Draw with the buffered attribute. Verify red.
351     glDrawArrays(GL_TRIANGLES, 0, 6);
352     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
353 
354     // Draw with the disabled "current value attribute". Verify green.
355     glDisableVertexAttribArray(attribLoc);
356     glDrawArrays(GL_TRIANGLES, 0, 6);
357     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
358 
359     // Verify setting buffer data on the disabled buffer doesn't change anything.
360     std::vector<GLColor> blue(128, GLColor::blue);
361     glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
362     glBufferData(GL_ARRAY_BUFFER, blue.size() * sizeof(GLColor), blue.data(), GL_STATIC_DRAW);
363     glDrawArrays(GL_TRIANGLES, 0, 6);
364     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
365 }
366 
367 // Tests that setting value for a subset of default attributes doesn't affect others.
TEST_P(StateChangeTest,SetCurrentAttribute)368 TEST_P(StateChangeTest, SetCurrentAttribute)
369 {
370     constexpr char kVS[] = R"(attribute vec4 position;
371 attribute mat4 testAttrib;  // Note that this generates 4 attributes
372 varying vec4 testVarying;
373 void main (void)
374 {
375     gl_Position = position;
376 
377     testVarying = position.y < 0.0 ?
378                     position.x < 0.0 ? testAttrib[0] : testAttrib[1] :
379                     position.x < 0.0 ? testAttrib[2] : testAttrib[3];
380 })";
381 
382     ANGLE_GL_PROGRAM(program, kVS, kSimpleAttributeFS);
383     glUseProgram(program);
384     GLint attribLoc   = glGetAttribLocation(program, "testAttrib");
385     GLint positionLoc = glGetAttribLocation(program, "position");
386     ASSERT_NE(-1, attribLoc);
387     ASSERT_NE(-1, positionLoc);
388 
389     // Set the current value of two of the test attributes, while leaving the other two as default.
390     glVertexAttrib4f(attribLoc + 1, 0.0f, 1.0f, 0.0f, 1.0f);
391     glVertexAttrib4f(attribLoc + 2, 0.0f, 0.0f, 1.0f, 1.0f);
392 
393     // Set up the position attribute.
394     setupQuadVertexBuffer(0.5f, 1.0f);
395     glEnableVertexAttribArray(positionLoc);
396     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
397 
398     // Draw and verify the four section in the output:
399     //
400     //  +---------------+
401     //  | Black | Green |
402     //  +-------+-------+
403     //  | Blue  | Black |
404     //  +---------------+
405     //
406     glDrawArrays(GL_TRIANGLES, 0, 6);
407 
408     const int w                            = getWindowWidth();
409     const int h                            = getWindowHeight();
410     constexpr unsigned int kPixelTolerance = 5u;
411     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, kPixelTolerance);
412     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::green, kPixelTolerance);
413     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::blue, kPixelTolerance);
414     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::black, kPixelTolerance);
415 }
416 
417 // Tests that drawing with transform feedback paused, then lines without transform feedback works
418 // without Vulkan validation errors.
TEST_P(StateChangeTestES3,DrawPausedXfbThenNonXfbLines)419 TEST_P(StateChangeTestES3, DrawPausedXfbThenNonXfbLines)
420 {
421     // glTransformFeedbackVaryings for program2 returns GL_INVALID_OPERATION on both Linux and
422     // windows.  http://anglebug.com/42262893
423     ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
424     // http://anglebug.com/42263928
425     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
426 
427     std::vector<std::string> tfVaryings = {"gl_Position"};
428     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, essl1_shaders::vs::Simple(),
429                                         essl1_shaders::fs::Blue(), tfVaryings, GL_SEPARATE_ATTRIBS);
430 
431     GLBuffer xfbBuffer;
432     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
433     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * sizeof(float[4]), nullptr, GL_STATIC_DRAW);
434 
435     GLTransformFeedback xfb;
436     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
437     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
438 
439     glUseProgram(program1);
440     glBeginTransformFeedback(GL_TRIANGLES);
441     glPauseTransformFeedback();
442     glDrawArrays(GL_TRIANGLES, 0, 6);
443 
444     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
445     glUseProgram(program2);
446     glDrawArrays(GL_LINES, 0, 6);
447     glEndTransformFeedback();
448 
449     ASSERT_GL_NO_ERROR();
450 }
451 
452 // Tests that vertex attribute value is preserved across context switches.
TEST_P(StateChangeTest,MultiContextVertexAttribute)453 TEST_P(StateChangeTest, MultiContextVertexAttribute)
454 {
455     EGLWindow *window   = getEGLWindow();
456     EGLDisplay display  = window->getDisplay();
457     EGLConfig config    = window->getConfig();
458     EGLSurface surface  = window->getSurface();
459     EGLContext context1 = window->getContext();
460 
461     // Set up program in primary context
462     ANGLE_GL_PROGRAM(program1, kSimpleAttributeVS, kSimpleAttributeFS);
463     glUseProgram(program1);
464     GLint attribLoc   = glGetAttribLocation(program1, "testAttrib");
465     GLint positionLoc = glGetAttribLocation(program1, "position");
466     ASSERT_NE(-1, attribLoc);
467     ASSERT_NE(-1, positionLoc);
468 
469     // Set up the position attribute in primary context
470     setupQuadVertexBuffer(0.5f, 1.0f);
471     glEnableVertexAttribArray(positionLoc);
472     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
473 
474     // Set primary context attribute to green and draw quad
475     glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
476     glDrawArrays(GL_TRIANGLES, 0, 6);
477     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
478 
479     // Set up and switch to secondary context
480     EGLint contextAttributes[] = {
481         EGL_CONTEXT_MAJOR_VERSION_KHR,
482         GetParam().majorVersion,
483         EGL_CONTEXT_MINOR_VERSION_KHR,
484         GetParam().minorVersion,
485         EGL_NONE,
486     };
487     EGLContext context2 = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
488     ASSERT_NE(context2, EGL_NO_CONTEXT);
489     eglMakeCurrent(display, surface, surface, context2);
490 
491     // Set up program in secondary context
492     ANGLE_GL_PROGRAM(program2, kSimpleAttributeVS, kSimpleAttributeFS);
493     glUseProgram(program2);
494     ASSERT_EQ(attribLoc, glGetAttribLocation(program2, "testAttrib"));
495     ASSERT_EQ(positionLoc, glGetAttribLocation(program2, "position"));
496 
497     // Set up the position attribute in secondary context
498     setupQuadVertexBuffer(0.5f, 1.0f);
499     glEnableVertexAttribArray(positionLoc);
500     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
501 
502     // attribLoc current value should be default - (0,0,0,1)
503     glDrawArrays(GL_TRIANGLES, 0, 6);
504     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
505 
506     // Restore primary context
507     eglMakeCurrent(display, surface, surface, context1);
508     // ReadPixels to ensure context is switched
509     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
510 
511     // Switch to secondary context second time
512     eglMakeCurrent(display, surface, surface, context2);
513     // Check that it still draws black
514     glDrawArrays(GL_TRIANGLES, 0, 6);
515     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
516 
517     // Restore primary context second time
518     eglMakeCurrent(display, surface, surface, context1);
519     // Check if it still draws green
520     glDrawArrays(GL_TRIANGLES, 0, 6);
521     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
522 
523     // Clean up
524     eglDestroyContext(display, context2);
525 }
526 
527 // Ensure that CopyTexSubImage3D syncs framebuffer changes.
TEST_P(StateChangeTestES3,CopyTexSubImage3DSync)528 TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
529 {
530     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
531 
532     // Init first texture to red
533     glBindTexture(GL_TEXTURE_3D, mTextures[0]);
534     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
535     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
536     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
537     glClear(GL_COLOR_BUFFER_BIT);
538     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
539 
540     // Init second texture to green
541     glBindTexture(GL_TEXTURE_3D, mTextures[1]);
542     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
543     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
544     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
545     glClear(GL_COLOR_BUFFER_BIT);
546     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
547 
548     // Copy in the red texture to the green one.
549     // CopyTexImage should sync the framebuffer attachment change.
550     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
551     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
552     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
553     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
554 
555     ASSERT_GL_NO_ERROR();
556 }
557 
558 // Ensure that BlitFramebuffer syncs framebuffer changes.
TEST_P(StateChangeTestES3,BlitFramebufferSync)559 TEST_P(StateChangeTestES3, BlitFramebufferSync)
560 {
561     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
562 
563     // Init first texture to red
564     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
565     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
566     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
567     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
568     glClear(GL_COLOR_BUFFER_BIT);
569     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
570 
571     // Init second texture to green
572     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
573     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
574     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
575     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
576     glClear(GL_COLOR_BUFFER_BIT);
577     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
578 
579     // Change to the red textures and blit.
580     // BlitFramebuffer should sync the framebuffer attachment change.
581     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
582     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
583                            0);
584     glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
585     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
586     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
587 
588     ASSERT_GL_NO_ERROR();
589 }
590 
591 // Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
TEST_P(StateChangeTestES3,ReadBufferAndDrawBuffersSync)592 TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
593 {
594     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
595 
596     // Initialize two FBO attachments
597     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
598     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
599     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
600     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
601     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
602     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
603 
604     // Clear first attachment to red
605     GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
606     glDrawBuffers(2, bufs1);
607     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
608     glClear(GL_COLOR_BUFFER_BIT);
609 
610     // Clear second texture to green
611     GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
612     glDrawBuffers(2, bufs2);
613     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
614     glClear(GL_COLOR_BUFFER_BIT);
615 
616     // Verify first attachment is red and second is green
617     glReadBuffer(GL_COLOR_ATTACHMENT1);
618     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
619 
620     glReadBuffer(GL_COLOR_ATTACHMENT0);
621     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
622 
623     ASSERT_GL_NO_ERROR();
624 }
625 
626 // Tests calling invalidate on incomplete framebuffers after switching attachments.
627 // Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
TEST_P(StateChangeTestES3,IncompleteRenderbufferAttachmentInvalidateSync)628 TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
629 {
630     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
631     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
632     GLint samples = 0;
633     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
634     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
635     ASSERT_GL_NO_ERROR();
636 
637     // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
638     // attached renderbuffer
639     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
640                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
641     GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
642     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
643     ASSERT_GL_NO_ERROR();
644 
645     glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
646                                      getWindowWidth(), getWindowHeight());
647     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
648     glClear(GL_COLOR_BUFFER_BIT);
649     ASSERT_GL_NO_ERROR();
650 
651     GLRenderbuffer renderbuf;
652 
653     glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
654     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuf);
655     ASSERT_GL_NO_ERROR();
656 
657     // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
658     // attached renderbuffer
659     // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
660     GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
661     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
662 
663     glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
664                                      GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
665     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
666     glClear(GL_DEPTH_BUFFER_BIT);
667     ASSERT_GL_NO_ERROR();
668 }
669 
670 class StateChangeRenderTest : public StateChangeTest
671 {
672   protected:
StateChangeRenderTest()673     StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
674 
testSetUp()675     void testSetUp() override
676     {
677         StateChangeTest::testSetUp();
678 
679         constexpr char kVS[] =
680             "attribute vec2 position;\n"
681             "void main() {\n"
682             "    gl_Position = vec4(position, 0, 1);\n"
683             "}";
684         constexpr char kFS[] =
685             "uniform highp vec4 uniformColor;\n"
686             "void main() {\n"
687             "    gl_FragColor = uniformColor;\n"
688             "}";
689 
690         mProgram = CompileProgram(kVS, kFS);
691         ASSERT_NE(0u, mProgram);
692 
693         glGenRenderbuffers(1, &mRenderbuffer);
694     }
695 
testTearDown()696     void testTearDown() override
697     {
698         glDeleteProgram(mProgram);
699         glDeleteRenderbuffers(1, &mRenderbuffer);
700 
701         StateChangeTest::testTearDown();
702     }
703 
setUniformColor(const GLColor & color)704     void setUniformColor(const GLColor &color)
705     {
706         glUseProgram(mProgram);
707         const Vector4 &normalizedColor = color.toNormalizedVector();
708         GLint uniformLocation          = glGetUniformLocation(mProgram, "uniformColor");
709         ASSERT_NE(-1, uniformLocation);
710         glUniform4fv(uniformLocation, 1, normalizedColor.data());
711     }
712 
713     GLuint mProgram;
714     GLuint mRenderbuffer;
715 };
716 
717 // Test that re-creating a currently attached texture works as expected.
TEST_P(StateChangeRenderTest,RecreateTexture)718 TEST_P(StateChangeRenderTest, RecreateTexture)
719 {
720     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
721 
722     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
723     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
724     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
725 
726     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
727     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
728 
729     // Draw with red to the FBO.
730     GLColor red(255, 0, 0, 255);
731     setUniformColor(red);
732     drawQuad(mProgram, "position", 0.5f);
733     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
734 
735     // Recreate the texture with green.
736     GLColor green(0, 255, 0, 255);
737     std::vector<GLColor> greenPixels(32 * 32, green);
738     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
739                  greenPixels.data());
740     EXPECT_PIXEL_COLOR_EQ(0, 0, green);
741 
742     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
743     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
744 
745     // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
746     GLColor blue(0, 0, 255, 255);
747     setUniformColor(blue);
748     drawQuad(mProgram, "position", 0.5f);
749     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
750 
751     EXPECT_GL_NO_ERROR();
752 }
753 
754 // Test that re-creating a currently attached renderbuffer works as expected.
TEST_P(StateChangeRenderTest,RecreateRenderbuffer)755 TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
756 {
757     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
758 
759     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
760     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
761     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
762 
763     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
764     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
765 
766     // Draw with red to the FBO.
767     setUniformColor(GLColor::red);
768     drawQuad(mProgram, "position", 0.5f);
769     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
770 
771     // Recreate the renderbuffer and clear to green.
772     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
773     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
774     glClear(GL_COLOR_BUFFER_BIT);
775     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
776 
777     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
778     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
779 
780     // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
781     setUniformColor(GLColor::blue);
782     drawQuad(mProgram, "position", 0.5f);
783     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
784 
785     EXPECT_GL_NO_ERROR();
786 }
787 
788 // Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
TEST_P(StateChangeRenderTest,GenerateMipmap)789 TEST_P(StateChangeRenderTest, GenerateMipmap)
790 {
791     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
792 
793     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
794     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
795     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
796     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
797     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
798 
799     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
800     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
801 
802     // Draw once to set the RenderTarget in D3D11
803     GLColor red(255, 0, 0, 255);
804     setUniformColor(red);
805     drawQuad(mProgram, "position", 0.5f);
806     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
807 
808     // This may trigger the texture to be re-created internally.
809     glGenerateMipmap(GL_TEXTURE_2D);
810 
811     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
812     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
813 
814     // Now ensure we don't have a stale render target.
815     GLColor blue(0, 0, 255, 255);
816     setUniformColor(blue);
817     drawQuad(mProgram, "position", 0.5f);
818     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
819 
820     EXPECT_GL_NO_ERROR();
821 }
822 
823 // Tests that gl_DepthRange syncs correctly after a change.
TEST_P(StateChangeRenderTest,DepthRangeUpdates)824 TEST_P(StateChangeRenderTest, DepthRangeUpdates)
825 {
826     constexpr char kFragCoordShader[] = R"(void main()
827 {
828     if (gl_DepthRange.near == 0.2)
829     {
830         gl_FragColor = vec4(1, 0, 0, 1);
831     }
832     else if (gl_DepthRange.near == 0.5)
833     {
834         gl_FragColor = vec4(0, 1, 0, 1);
835     }
836     else
837     {
838         gl_FragColor = vec4(0, 0, 1, 1);
839     }
840 })";
841 
842     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
843     glUseProgram(program);
844 
845     const auto &quadVertices = GetQuadVertices();
846 
847     ASSERT_EQ(0, glGetAttribLocation(program, essl1_shaders::PositionAttrib()));
848 
849     GLBuffer vertexBuffer;
850     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
851     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
852                  quadVertices.data(), GL_STATIC_DRAW);
853     glVertexAttribPointer(0u, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
854     glEnableVertexAttribArray(0u);
855 
856     // First, clear.
857     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
858     glClear(GL_COLOR_BUFFER_BIT);
859 
860     // Draw to left half viewport with a first depth range.
861     glDepthRangef(0.2f, 1.0f);
862     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
863     glDrawArrays(GL_TRIANGLES, 0, 6);
864     ASSERT_GL_NO_ERROR();
865 
866     // Draw to right half viewport with a second depth range.
867     glDepthRangef(0.5f, 1.0f);
868     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
869     glDrawArrays(GL_TRIANGLES, 0, 6);
870     ASSERT_GL_NO_ERROR();
871 
872     // Verify left half of the framebuffer is red and right half is green.
873     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() / 2, getWindowHeight(), GLColor::red);
874     EXPECT_PIXEL_RECT_EQ(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight(),
875                          GLColor::green);
876 }
877 
878 class StateChangeRenderTestES3 : public StateChangeRenderTest
879 {};
880 
TEST_P(StateChangeRenderTestES3,InvalidateNonCurrentFramebuffer)881 TEST_P(StateChangeRenderTestES3, InvalidateNonCurrentFramebuffer)
882 {
883     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
884     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
885     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
886     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
887     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
888     glBindTexture(GL_TEXTURE_2D, 0);
889     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
890     ASSERT_GL_NO_ERROR();
891 
892     // Draw with red to the FBO.
893     GLColor red(255, 0, 0, 255);
894     setUniformColor(red);
895     drawQuad(mProgram, "position", 0.5f);
896     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
897 
898     // Go back to default framebuffer, draw green
899     glBindFramebuffer(GL_FRAMEBUFFER, 0);
900     GLColor green(0, 255, 0, 255);
901     setUniformColor(green);
902     drawQuad(mProgram, "position", 0.5f);
903     EXPECT_PIXEL_COLOR_EQ(0, 0, green);
904 
905     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
906 
907     // Invalidate color buffer of FBO
908     GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
909     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
910     ASSERT_GL_NO_ERROR();
911 
912     // Verify drawing blue gives blue.
913     GLColor blue(0, 0, 255, 255);
914     setUniformColor(blue);
915     drawQuad(mProgram, "position", 0.5f);
916     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
917 }
918 
919 // Tests that D3D11 dirty bit updates don't forget about BufferSubData attrib updates.
TEST_P(StateChangeTest,VertexBufferUpdatedAfterDraw)920 TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
921 {
922     constexpr char kVS[] =
923         "attribute vec2 position;\n"
924         "attribute vec4 color;\n"
925         "varying vec4 outcolor;\n"
926         "void main()\n"
927         "{\n"
928         "    gl_Position = vec4(position, 0, 1);\n"
929         "    outcolor = color;\n"
930         "}";
931     constexpr char kFS[] =
932         "varying mediump vec4 outcolor;\n"
933         "void main()\n"
934         "{\n"
935         "    gl_FragColor = outcolor;\n"
936         "}";
937 
938     ANGLE_GL_PROGRAM(program, kVS, kFS);
939     glUseProgram(program);
940 
941     GLint colorLoc = glGetAttribLocation(program, "color");
942     ASSERT_NE(-1, colorLoc);
943     GLint positionLoc = glGetAttribLocation(program, "position");
944     ASSERT_NE(-1, positionLoc);
945 
946     setupQuadVertexBuffer(0.5f, 1.0f);
947     glEnableVertexAttribArray(positionLoc);
948     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
949 
950     GLBuffer colorBuf;
951     glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
952     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
953     glEnableVertexAttribArray(colorLoc);
954 
955     // Fill with green.
956     std::vector<GLColor> colorData(6, GLColor::green);
957     glBufferData(GL_ARRAY_BUFFER, colorData.size() * sizeof(GLColor), colorData.data(),
958                  GL_STATIC_DRAW);
959 
960     // Draw, expect green.
961     glDrawArrays(GL_TRIANGLES, 0, 6);
962     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
963     ASSERT_GL_NO_ERROR();
964 
965     // Update buffer with red.
966     std::fill(colorData.begin(), colorData.end(), GLColor::red);
967     glBufferSubData(GL_ARRAY_BUFFER, 0, colorData.size() * sizeof(GLColor), colorData.data());
968 
969     // Draw, expect red.
970     glDrawArrays(GL_TRIANGLES, 0, 6);
971     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
972     ASSERT_GL_NO_ERROR();
973 }
974 
975 // Tests that drawing after flush without any state change works.
TEST_P(StateChangeTestES3,DrawAfterFlushWithNoStateChange)976 TEST_P(StateChangeTestES3, DrawAfterFlushWithNoStateChange)
977 {
978     // Draw (0.125, 0.25, 0.5, 0.5) once, using additive blend
979     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
980     glUseProgram(drawColor);
981 
982     GLint colorUniformLocation =
983         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
984     ASSERT_NE(colorUniformLocation, -1);
985 
986     GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
987     ASSERT_NE(-1, positionLocation);
988 
989     // Setup VAO
990     const auto &quadVertices = GetQuadVertices();
991 
992     GLBuffer vertexBuffer;
993     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
994     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
995 
996     GLVertexArray vertexArray;
997     glBindVertexArray(vertexArray);
998     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
999     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1000     glEnableVertexAttribArray(positionLocation);
1001     ASSERT_GL_NO_ERROR();
1002 
1003     // Clear and draw
1004     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1005     glClear(GL_COLOR_BUFFER_BIT);
1006 
1007     glEnable(GL_BLEND);
1008     glBlendFunc(GL_ONE, GL_ONE);
1009 
1010     glUniform4f(colorUniformLocation, 0.125f, 0.25f, 0.5f, 0.5f);
1011     glDrawArrays(GL_TRIANGLES, 0, 6);
1012     ASSERT_GL_NO_ERROR();
1013 
1014     // Make sure the work is submitted.
1015     glFinish();
1016 
1017     // Draw again with no state change
1018     glDrawArrays(GL_TRIANGLES, 0, 6);
1019     ASSERT_GL_NO_ERROR();
1020 
1021     // Make sure the pixels have the correct colors.
1022     const int h = getWindowHeight() - 1;
1023     const int w = getWindowWidth() - 1;
1024     const GLColor kExpected(63, 127, 255, 255);
1025 
1026     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1027     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, kExpected, 1);
1028     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, kExpected, 1);
1029     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, kExpected, 1);
1030 }
1031 
1032 // Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
TEST_P(StateChangeTestES3,VertexArrayObjectAndDisabledAttributes)1033 TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes)
1034 {
1035     constexpr char kSingleVS[] = "attribute vec4 position; void main() { gl_Position = position; }";
1036     constexpr char kSingleFS[] = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
1037     ANGLE_GL_PROGRAM(singleProgram, kSingleVS, kSingleFS);
1038 
1039     constexpr char kDualVS[] =
1040         "#version 300 es\n"
1041         "in vec4 position;\n"
1042         "in vec4 color;\n"
1043         "out vec4 varyColor;\n"
1044         "void main()\n"
1045         "{\n"
1046         "    gl_Position = position;\n"
1047         "    varyColor = color;\n"
1048         "}";
1049     constexpr char kDualFS[] =
1050         "#version 300 es\n"
1051         "precision mediump float;\n"
1052         "in vec4 varyColor;\n"
1053         "out vec4 colorOut;\n"
1054         "void main()\n"
1055         "{\n"
1056         "    colorOut = varyColor;\n"
1057         "}";
1058 
1059     ANGLE_GL_PROGRAM(dualProgram, kDualVS, kDualFS);
1060 
1061     // Force consistent attribute locations
1062     constexpr GLint positionLocation = 0;
1063     constexpr GLint colorLocation    = 1;
1064 
1065     glBindAttribLocation(singleProgram, positionLocation, "position");
1066     glBindAttribLocation(dualProgram, positionLocation, "position");
1067     glBindAttribLocation(dualProgram, colorLocation, "color");
1068 
1069     {
1070         glLinkProgram(singleProgram);
1071         GLint linkStatus;
1072         glGetProgramiv(singleProgram, GL_LINK_STATUS, &linkStatus);
1073         ASSERT_NE(linkStatus, 0);
1074     }
1075 
1076     {
1077         glLinkProgram(dualProgram);
1078         GLint linkStatus;
1079         glGetProgramiv(dualProgram, GL_LINK_STATUS, &linkStatus);
1080         ASSERT_NE(linkStatus, 0);
1081     }
1082 
1083     glUseProgram(singleProgram);
1084 
1085     // Initialize position vertex buffer.
1086     const auto &quadVertices = GetQuadVertices();
1087 
1088     GLBuffer vertexBuffer;
1089     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1090     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
1091 
1092     // Initialize a VAO. Draw with single program.
1093     GLVertexArray vertexArray;
1094     glBindVertexArray(vertexArray);
1095     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1096     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1097     glEnableVertexAttribArray(positionLocation);
1098 
1099     // Should draw red.
1100     glDrawArrays(GL_TRIANGLES, 0, 6);
1101     ASSERT_GL_NO_ERROR();
1102     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1103 
1104     // Draw with a green buffer attribute, without the VAO.
1105     glBindVertexArray(0);
1106     glUseProgram(dualProgram);
1107     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1108     glEnableVertexAttribArray(positionLocation);
1109 
1110     std::vector<GLColor> greenColors(6, GLColor::green);
1111     GLBuffer greenBuffer;
1112     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
1113     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, greenColors.data(), GL_STATIC_DRAW);
1114 
1115     glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4, nullptr);
1116     glEnableVertexAttribArray(colorLocation);
1117 
1118     glDrawArrays(GL_TRIANGLES, 0, 6);
1119     ASSERT_GL_NO_ERROR();
1120     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1121 
1122     // Re-bind VAO and try to draw with different program, without changing state.
1123     // Should draw black since current value is not initialized.
1124     glBindVertexArray(vertexArray);
1125     glDrawArrays(GL_TRIANGLES, 0, 6);
1126     ASSERT_GL_NO_ERROR();
1127     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1128 }
1129 
1130 const char kSamplerMetadataVertexShader0[] = R"(#version 300 es
1131 precision mediump float;
1132 out vec4 color;
1133 uniform sampler2D texture;
1134 void main()
1135 {
1136     vec2 size = vec2(textureSize(texture, 0));
1137     color = size.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1138     vec2 pos = vec2(0.0);
1139     switch (gl_VertexID) {
1140         case 0: pos = vec2(-1.0, -1.0); break;
1141         case 1: pos = vec2(3.0, -1.0); break;
1142         case 2: pos = vec2(-1.0, 3.0); break;
1143     };
1144     gl_Position = vec4(pos, 0.0, 1.0);
1145 })";
1146 
1147 const char kSamplerMetadataVertexShader1[] = R"(#version 300 es
1148 precision mediump float;
1149 out vec4 color;
1150 uniform sampler2D texture1;
1151 uniform sampler2D texture2;
1152 void main()
1153 {
1154     vec2 size1 = vec2(textureSize(texture1, 0));
1155     vec2 size2 = vec2(textureSize(texture2, 0));
1156     color = size1.x * size2.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1157     vec2 pos = vec2(0.0);
1158     switch (gl_VertexID) {
1159         case 0: pos = vec2(-1.0, -1.0); break;
1160         case 1: pos = vec2(3.0, -1.0); break;
1161         case 2: pos = vec2(-1.0, 3.0); break;
1162     };
1163     gl_Position = vec4(pos, 0.0, 1.0);
1164 })";
1165 
1166 const char kSamplerMetadataFragmentShader[] = R"(#version 300 es
1167 precision mediump float;
1168 in vec4 color;
1169 out vec4 result;
1170 void main()
1171 {
1172     result = color;
1173 })";
1174 
1175 // Tests that changing an active program invalidates the sampler metadata properly.
TEST_P(StateChangeTestES3,SamplerMetadataUpdateOnSetProgram)1176 TEST_P(StateChangeTestES3, SamplerMetadataUpdateOnSetProgram)
1177 {
1178     // http://anglebug.com/40096654
1179     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1180     GLVertexArray vertexArray;
1181     glBindVertexArray(vertexArray);
1182 
1183     // Create a simple framebuffer.
1184     GLTexture texture1, texture2;
1185     glActiveTexture(GL_TEXTURE0);
1186     glBindTexture(GL_TEXTURE_2D, texture1);
1187     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1188     glActiveTexture(GL_TEXTURE1);
1189     glBindTexture(GL_TEXTURE_2D, texture2);
1190     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 3, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1191 
1192     // Create 2 shader programs differing only in the number of active samplers.
1193     ANGLE_GL_PROGRAM(program1, kSamplerMetadataVertexShader0, kSamplerMetadataFragmentShader);
1194     glUseProgram(program1);
1195     glUniform1i(glGetUniformLocation(program1, "texture"), 0);
1196     ANGLE_GL_PROGRAM(program2, kSamplerMetadataVertexShader1, kSamplerMetadataFragmentShader);
1197     glUseProgram(program2);
1198     glUniform1i(glGetUniformLocation(program2, "texture1"), 0);
1199     glUniform1i(glGetUniformLocation(program2, "texture2"), 0);
1200 
1201     // Draw a solid green color to the framebuffer.
1202     glUseProgram(program1);
1203     glDrawArrays(GL_TRIANGLES, 0, 3);
1204     // Test that our first program is good.
1205     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1206 
1207     // Bind a different program that uses more samplers.
1208     // Draw another quad that depends on the sampler metadata.
1209     glUseProgram(program2);
1210     glDrawArrays(GL_TRIANGLES, 0, 3);
1211     // Flush via ReadPixels and check that it's still green.
1212     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1213 
1214     ASSERT_GL_NO_ERROR();
1215 }
1216 
1217 // Tests that redefining Buffer storage syncs with the Transform Feedback object.
TEST_P(StateChangeTestES3,RedefineTransformFeedbackBuffer)1218 TEST_P(StateChangeTestES3, RedefineTransformFeedbackBuffer)
1219 {
1220     // Create the most simple program possible - simple a passthrough for a float attribute.
1221     constexpr char kVertexShader[] = R"(#version 300 es
1222 in float valueIn;
1223 out float valueOut;
1224 void main()
1225 {
1226     gl_Position = vec4(0, 0, 0, 0);
1227     valueOut = valueIn;
1228 })";
1229 
1230     constexpr char kFragmentShader[] = R"(#version 300 es
1231 out mediump float unused;
1232 void main()
1233 {
1234     unused = 1.0;
1235 })";
1236 
1237     std::vector<std::string> tfVaryings = {"valueOut"};
1238     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, kVertexShader, kFragmentShader, tfVaryings,
1239                                         GL_SEPARATE_ATTRIBS);
1240     glUseProgram(program);
1241 
1242     GLint attribLoc = glGetAttribLocation(program, "valueIn");
1243     ASSERT_NE(-1, attribLoc);
1244 
1245     // Disable rasterization - we're not interested in the framebuffer.
1246     glEnable(GL_RASTERIZER_DISCARD);
1247 
1248     // Initialize a float vertex buffer with 1.0.
1249     std::vector<GLfloat> data1(16, 1.0);
1250     GLsizei size1 = static_cast<GLsizei>(sizeof(GLfloat) * data1.size());
1251 
1252     GLBuffer vertexBuffer;
1253     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1254     glBufferData(GL_ARRAY_BUFFER, size1, data1.data(), GL_STATIC_DRAW);
1255     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1256     glEnableVertexAttribArray(attribLoc);
1257 
1258     ASSERT_GL_NO_ERROR();
1259 
1260     // Initialize a same-sized XFB buffer.
1261     GLBuffer xfbBuffer;
1262     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1263     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size1, nullptr, GL_STATIC_DRAW);
1264 
1265     // Draw with XFB enabled.
1266     GLTransformFeedback xfb;
1267     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1268     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1269 
1270     glBeginTransformFeedback(GL_POINTS);
1271     glDrawArrays(GL_POINTS, 0, 16);
1272     glEndTransformFeedback();
1273 
1274     ASSERT_GL_NO_ERROR();
1275 
1276     // Verify the XFB stage caught the 1.0 attribute values.
1277     void *mapped1     = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size1, GL_MAP_READ_BIT);
1278     GLfloat *asFloat1 = reinterpret_cast<GLfloat *>(mapped1);
1279     std::vector<GLfloat> actualData1(asFloat1, asFloat1 + data1.size());
1280     EXPECT_EQ(data1, actualData1);
1281     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1282 
1283     // Now, reinitialize the XFB buffer to a larger size, and draw with 2.0.
1284     std::vector<GLfloat> data2(128, 2.0);
1285     const GLsizei size2 = static_cast<GLsizei>(sizeof(GLfloat) * data2.size());
1286     glBufferData(GL_ARRAY_BUFFER, size2, data2.data(), GL_STATIC_DRAW);
1287     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size2, nullptr, GL_STATIC_DRAW);
1288 
1289     glBeginTransformFeedback(GL_POINTS);
1290     glDrawArrays(GL_POINTS, 0, 128);
1291     glEndTransformFeedback();
1292 
1293     ASSERT_GL_NO_ERROR();
1294 
1295     // Verify the XFB stage caught the 2.0 attribute values.
1296     void *mapped2     = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size2, GL_MAP_READ_BIT);
1297     GLfloat *asFloat2 = reinterpret_cast<GLfloat *>(mapped2);
1298     std::vector<GLfloat> actualData2(asFloat2, asFloat2 + data2.size());
1299     EXPECT_EQ(data2, actualData2);
1300     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1301 }
1302 
1303 // Variations:
1304 //
1305 // - bool: whether to use WebGL compatibility mode.
1306 using StateChangeTestWebGL2Params = std::tuple<angle::PlatformParameters, bool>;
1307 
StateChangeTestWebGL2Print(const::testing::TestParamInfo<StateChangeTestWebGL2Params> & paramsInfo)1308 std::string StateChangeTestWebGL2Print(
1309     const ::testing::TestParamInfo<StateChangeTestWebGL2Params> &paramsInfo)
1310 {
1311     const StateChangeTestWebGL2Params &params = paramsInfo.param;
1312     std::ostringstream out;
1313 
1314     out << std::get<0>(params);
1315 
1316     if (std::get<1>(params))
1317     {
1318         out << "__WebGLCompatibility";
1319     }
1320 
1321     return out.str();
1322 }
1323 
1324 // State change test verifying both ES3 and WebGL2 specific behaviors.
1325 // Test is parameterized to allow execution with and without WebGL validation.
1326 // Note that this can not inherit from StateChangeTest due to the need to use ANGLETestWithParam.
1327 class StateChangeTestWebGL2 : public ANGLETest<StateChangeTestWebGL2Params>
1328 {
1329   protected:
StateChangeTestWebGL2()1330     StateChangeTestWebGL2()
1331     {
1332         setWindowWidth(kWidth);
1333         setWindowHeight(kHeight);
1334         setConfigRedBits(8);
1335         setConfigGreenBits(8);
1336         setConfigBlueBits(8);
1337         setConfigAlphaBits(8);
1338         if (testing::get<1>(GetParam()))
1339             setWebGLCompatibilityEnabled(true);
1340     }
1341 
1342     struct TestResources
1343     {
1344         GLTexture colorTexture;
1345         GLFramebuffer framebuffer;
1346     };
1347 
setupResources(TestResources & resources)1348     void setupResources(TestResources &resources)
1349     {
1350         glBindTexture(GL_TEXTURE_2D, resources.colorTexture);
1351         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
1352         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1353         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1354         EXPECT_GL_NO_ERROR();
1355 
1356         glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
1357         EXPECT_GL_NO_ERROR();
1358         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
1359                                resources.colorTexture, 0);
1360         EXPECT_GL_NO_ERROR();
1361     }
1362 
1363     // Use a larger window/framebuffer size than 1x1 (though not much larger) to
1364     // increase the chances that random garbage will appear.
1365     static constexpr GLsizei kWidth  = 4;
1366     static constexpr GLsizei kHeight = 4;
1367 };
1368 
1369 // Note: tested multiple other combinations:
1370 //
1371 // - Clearing/drawing to the framebuffer after invalidating, without using a
1372 //   secondary FBO
1373 // - Clearing the framebuffer after invalidating, using a secondary FBO
1374 // - Invalidating after clearing/drawing to the FBO, to verify WebGL's behavior
1375 //   that after invalidation, the framebuffer is either unmodified, or cleared
1376 //   to transparent black
1377 //
1378 // This combination, drawing after invalidating plus copying from the drawn-to
1379 // texture, was the only one which provoked the original bug in the Metal
1380 // backend with the following command line arguments:
1381 //
1382 // MTL_DEBUG_LAYER=1 MTL_DEBUG_LAYER_VALIDATE_LOAD_ACTIONS=1 \
1383 //    MTL_DEBUG_LAYER_VALIDATE_STORE_ACTIONS=1 \
1384 //    MTL_DEBUG_LAYER_VALIDATE_UNRETAINED_RESOURCES=4 \
1385 //    angle_end2end_tests ...
1386 //
1387 // See anglebug.com/42265402.
1388 
TEST_P(StateChangeTestWebGL2,InvalidateThenDrawFBO)1389 TEST_P(StateChangeTestWebGL2, InvalidateThenDrawFBO)
1390 {
1391     GLint origFramebuffer = 0;
1392     glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &origFramebuffer);
1393 
1394     TestResources resources;
1395     setupResources(resources);
1396 
1397     ANGLE_GL_PROGRAM(drawGreen, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
1398 
1399     const GLenum attachment = GL_COLOR_ATTACHMENT0;
1400 
1401     glBindFramebuffer(GL_FRAMEBUFFER, resources.framebuffer);
1402     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1403 
1404     // Clear to red to start.
1405     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1406     glClear(GL_COLOR_BUFFER_BIT);
1407 
1408     // Invalidate framebuffer.
1409     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &attachment);
1410     EXPECT_GL_NO_ERROR();
1411 
1412     // Draw green.
1413     // Important to use a vertex buffer because WebGL doesn't support client-side arrays.
1414     constexpr bool useVertexBuffer = true;
1415     drawQuad(drawGreen, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, useVertexBuffer);
1416     EXPECT_GL_NO_ERROR();
1417 
1418     // Bind original framebuffer.
1419     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, origFramebuffer);
1420     glBindFramebuffer(GL_READ_FRAMEBUFFER, resources.framebuffer);
1421     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
1422     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
1423     EXPECT_GL_NO_ERROR();
1424 
1425     // Blit from user's framebuffer to the window.
1426     //
1427     // This step is crucial to catch bugs in the Metal backend's use of no-op load/store actions.
1428     glBlitFramebuffer(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight, GL_COLOR_BUFFER_BIT,
1429                       GL_NEAREST);
1430     EXPECT_GL_NO_ERROR();
1431 
1432     // Verify results.
1433     glBindFramebuffer(GL_READ_FRAMEBUFFER, origFramebuffer);
1434     EXPECT_GL_NO_ERROR();
1435     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1436 }
1437 
1438 // Simple state change tests for line loop drawing. There is some very specific handling of line
1439 // line loops in Vulkan and we need to test switching between drawElements and drawArrays calls to
1440 // validate every edge cases.
1441 class LineLoopStateChangeTest : public StateChangeTest
1442 {
1443   protected:
LineLoopStateChangeTest()1444     LineLoopStateChangeTest()
1445     {
1446         setWindowWidth(32);
1447         setWindowHeight(32);
1448         setConfigRedBits(8);
1449         setConfigGreenBits(8);
1450         setConfigBlueBits(8);
1451         setConfigAlphaBits(8);
1452     }
1453 
validateSquareAndHourglass() const1454     void validateSquareAndHourglass() const
1455     {
1456         ASSERT_GL_NO_ERROR();
1457 
1458         int quarterWidth  = getWindowWidth() / 4;
1459         int quarterHeight = getWindowHeight() / 4;
1460 
1461         // Bottom left
1462         EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::blue);
1463 
1464         // Top left
1465         EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::blue);
1466 
1467         // Top right
1468         // The last pixel isn't filled on a line loop so we check the pixel right before.
1469         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::blue);
1470 
1471         // dead center to validate the hourglass.
1472         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight * 2, GLColor::blue);
1473 
1474         // Verify line is closed between the 2 last vertices
1475         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::blue);
1476     }
1477 };
1478 
1479 // Draw an hourglass with a drawElements call followed by a square with drawArrays.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawArrays)1480 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
1481 {
1482     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1483     glUseProgram(program);
1484 
1485     // We expect to draw a square with these 4 vertices with a drawArray call.
1486     std::vector<Vector3> vertices;
1487     CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1488                                   getWindowHeight(), &vertices);
1489 
1490     // If we use these indices to draw however, we should be drawing an hourglass.
1491     auto indices = std::vector<GLushort>{0, 2, 1, 3};
1492 
1493     GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1494     ASSERT_NE(-1, mPositionLocation);
1495 
1496     GLBuffer vertexBuffer;
1497     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1498     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1499                  GL_STATIC_DRAW);
1500 
1501     GLBuffer indexBuffer;
1502     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1503     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1504                  GL_STATIC_DRAW);
1505 
1506     glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1507     glEnableVertexAttribArray(mPositionLocation);
1508     glClear(GL_COLOR_BUFFER_BIT);
1509     glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
1510     glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
1511     glDisableVertexAttribArray(mPositionLocation);
1512 
1513     validateSquareAndHourglass();
1514 }
1515 
1516 // Draw line loop using a drawArrays followed by an hourglass with drawElements.
TEST_P(LineLoopStateChangeTest,DrawArraysThenDrawElements)1517 TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
1518 {
1519     // http://anglebug.com/40644657: Seems to fail on older drivers and pass on newer.
1520     // Tested failing on 18.3.3 and passing on 18.9.2.
1521     ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
1522 
1523     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1524     glUseProgram(program);
1525 
1526     // We expect to draw a square with these 4 vertices with a drawArray call.
1527     std::vector<Vector3> vertices;
1528     CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1529                                   getWindowHeight(), &vertices);
1530 
1531     // If we use these indices to draw however, we should be drawing an hourglass.
1532     auto indices = std::vector<GLushort>{0, 2, 1, 3};
1533 
1534     GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1535     ASSERT_NE(-1, mPositionLocation);
1536 
1537     GLBuffer vertexBuffer;
1538     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1539     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1540                  GL_STATIC_DRAW);
1541 
1542     GLBuffer indexBuffer;
1543     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1544     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1545                  GL_STATIC_DRAW);
1546 
1547     glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1548     glEnableVertexAttribArray(mPositionLocation);
1549     glClear(GL_COLOR_BUFFER_BIT);
1550     glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
1551     glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
1552     glDisableVertexAttribArray(mPositionLocation);
1553 
1554     validateSquareAndHourglass();
1555 }
1556 
1557 // Draw a triangle with a drawElements call and a non-zero offset and draw the same
1558 // triangle with the same offset again followed by a line loop with drawElements.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawElements)1559 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawElements)
1560 {
1561     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1562 
1563     glUseProgram(program);
1564 
1565     // Background Red color
1566     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1567     glClear(GL_COLOR_BUFFER_BIT);
1568 
1569     // We expect to draw a triangle with the last three points on the bottom right,
1570     // draw with LineLoop, and then draw a triangle with the same non-zero offset.
1571     auto vertices = std::vector<Vector3>{
1572         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1573 
1574     auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1575 
1576     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1577     ASSERT_NE(-1, positionLocation);
1578 
1579     GLBuffer indexBuffer;
1580     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1581     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1582                  GL_STATIC_DRAW);
1583 
1584     GLBuffer vertexBuffer;
1585     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1586     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1587                  GL_STATIC_DRAW);
1588 
1589     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1590     glEnableVertexAttribArray(positionLocation);
1591 
1592     // Draw a triangle with a non-zero offset on the bottom right.
1593     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1594 
1595     // Draw with LineLoop.
1596     glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, nullptr);
1597 
1598     // Draw the triangle again with the same offset.
1599     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1600 
1601     glDisableVertexAttribArray(positionLocation);
1602 
1603     ASSERT_GL_NO_ERROR();
1604 
1605     int quarterWidth  = getWindowWidth() / 4;
1606     int quarterHeight = getWindowHeight() / 4;
1607 
1608     // Validate the top left point's color.
1609     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::blue);
1610 
1611     // Validate the triangle is drawn on the bottom right.
1612     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1613 
1614     // Validate the triangle is NOT on the top left part.
1615     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1616     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1617 }
1618 
1619 // Simple state change tests, primarily focused on basic object lifetime and dependency management
1620 // with back-ends that don't support that automatically (i.e. Vulkan).
1621 class SimpleStateChangeTest : public ANGLETest<>
1622 {
1623   protected:
1624     static constexpr int kWindowSize = 64;
1625 
SimpleStateChangeTest()1626     SimpleStateChangeTest()
1627     {
1628         setWindowWidth(kWindowSize);
1629         setWindowHeight(kWindowSize);
1630         setConfigRedBits(8);
1631         setConfigGreenBits(8);
1632         setConfigBlueBits(8);
1633         setConfigAlphaBits(8);
1634     }
1635 
1636     void simpleDrawWithBuffer(GLBuffer *buffer);
1637     void simpleDrawWithColor(const GLColor &color);
1638 
1639     using UpdateFunc = std::function<void(GLenum, GLTexture *, GLint, GLint, const GLColor &)>;
1640     void updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc);
1641     void bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture);
1642     void drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty);
1643 };
1644 
1645 class SimpleStateChangeTestES3 : public SimpleStateChangeTest
1646 {
1647   protected:
blendAndVerifyColor(const GLColor32F blendColor,const GLColor expectedColor)1648     void blendAndVerifyColor(const GLColor32F blendColor, const GLColor expectedColor)
1649     {
1650         glEnable(GL_BLEND);
1651         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1652         EXPECT_GL_NO_ERROR();
1653 
1654         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1655         glUseProgram(program);
1656 
1657         GLint colorUniformLocation =
1658             glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1659         ASSERT_NE(colorUniformLocation, -1);
1660 
1661         glUniform4f(colorUniformLocation, blendColor.R, blendColor.G, blendColor.B, blendColor.A);
1662         EXPECT_GL_NO_ERROR();
1663 
1664         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1665         EXPECT_GL_NO_ERROR();
1666         EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 1);
1667     }
1668 };
1669 
1670 class SimpleStateChangeTestES31 : public SimpleStateChangeTestES3
1671 {};
1672 
1673 class SimpleStateChangeTestComputeES31 : public SimpleStateChangeTest
1674 {
1675   protected:
testSetUp()1676     void testSetUp() override
1677     {
1678         glGenFramebuffers(1, &mFramebuffer);
1679         glGenTextures(1, &mTexture);
1680 
1681         glBindTexture(GL_TEXTURE_2D, mTexture);
1682         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
1683         EXPECT_GL_NO_ERROR();
1684 
1685         constexpr char kCS[] = R"(#version 310 es
1686 layout(local_size_x=2, local_size_y=2) in;
1687 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
1688 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
1689 void main()
1690 {
1691     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1692                imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
1693 })";
1694 
1695         mProgram = CompileComputeProgram(kCS);
1696         ASSERT_NE(mProgram, 0u);
1697 
1698         glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1699 
1700         glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
1701         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture,
1702                                0);
1703 
1704         ASSERT_GL_NO_ERROR();
1705     }
1706 
testTearDown()1707     void testTearDown() override
1708     {
1709         if (mFramebuffer != 0)
1710         {
1711             glDeleteFramebuffers(1, &mFramebuffer);
1712             mFramebuffer = 0;
1713         }
1714 
1715         if (mTexture != 0)
1716         {
1717             glDeleteTextures(1, &mTexture);
1718             mTexture = 0;
1719         }
1720         glDeleteProgram(mProgram);
1721     }
1722 
1723     GLuint mProgram;
1724     GLuint mFramebuffer = 0;
1725     GLuint mTexture     = 0;
1726 };
1727 
1728 class ImageES31PPO
1729 {
1730   protected:
ImageES31PPO()1731     ImageES31PPO() : mComputeProg(0), mPipeline(0) {}
1732 
bindProgramPipeline(const GLchar * computeString)1733     void bindProgramPipeline(const GLchar *computeString)
1734     {
1735         mComputeProg = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &computeString);
1736         ASSERT_NE(mComputeProg, 0u);
1737 
1738         // Generate a program pipeline and attach the programs to their respective stages
1739         glGenProgramPipelines(1, &mPipeline);
1740         EXPECT_GL_NO_ERROR();
1741         glUseProgramStages(mPipeline, GL_COMPUTE_SHADER_BIT, mComputeProg);
1742         EXPECT_GL_NO_ERROR();
1743         glBindProgramPipeline(mPipeline);
1744         EXPECT_GL_NO_ERROR();
1745         glActiveShaderProgram(mPipeline, mComputeProg);
1746         EXPECT_GL_NO_ERROR();
1747     }
1748 
1749     GLuint mComputeProg;
1750     GLuint mPipeline;
1751 };
1752 
1753 class SimpleStateChangeTestComputeES31PPO : public ImageES31PPO, public SimpleStateChangeTest
1754 {
1755   protected:
SimpleStateChangeTestComputeES31PPO()1756     SimpleStateChangeTestComputeES31PPO() : ImageES31PPO(), SimpleStateChangeTest() {}
1757 
testTearDown()1758     void testTearDown() override
1759     {
1760         if (mFramebuffer != 0)
1761         {
1762             glDeleteFramebuffers(1, &mFramebuffer);
1763             mFramebuffer = 0;
1764         }
1765 
1766         if (mTexture != 0)
1767         {
1768             glDeleteTextures(1, &mTexture);
1769             mTexture = 0;
1770         }
1771         glDeleteProgramPipelines(1, &mPipeline);
1772     }
1773 
1774     GLuint mFramebuffer = 0;
1775     GLuint mTexture     = 0;
1776 };
1777 
1778 constexpr char kSimpleVertexShader[] = R"(attribute vec2 position;
1779 attribute vec4 color;
1780 varying vec4 vColor;
1781 void main()
1782 {
1783     gl_Position = vec4(position, 0, 1);
1784     vColor = color;
1785 }
1786 )";
1787 
1788 constexpr char kSimpleVertexShaderForPoints[] = R"(attribute vec2 position;
1789 attribute vec4 color;
1790 varying vec4 vColor;
1791 void main()
1792 {
1793     gl_Position = vec4(position, 0, 1);
1794     gl_PointSize = 1.0;
1795     vColor = color;
1796 }
1797 )";
1798 
1799 constexpr char kZeroVertexShaderForPoints[] = R"(void main()
1800 {
1801     gl_Position = vec4(0);
1802     gl_PointSize = 1.0;
1803 }
1804 )";
1805 
1806 constexpr char kSimpleFragmentShader[] = R"(precision mediump float;
1807 varying vec4 vColor;
1808 void main()
1809 {
1810     gl_FragColor = vColor;
1811 }
1812 )";
1813 
simpleDrawWithBuffer(GLBuffer * buffer)1814 void SimpleStateChangeTest::simpleDrawWithBuffer(GLBuffer *buffer)
1815 {
1816     ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
1817     glUseProgram(program);
1818 
1819     GLint colorLoc = glGetAttribLocation(program, "color");
1820     ASSERT_NE(-1, colorLoc);
1821 
1822     glBindBuffer(GL_ARRAY_BUFFER, *buffer);
1823     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1824     glEnableVertexAttribArray(colorLoc);
1825 
1826     drawQuad(program, "position", 0.5f, 1.0f, true);
1827     ASSERT_GL_NO_ERROR();
1828 }
1829 
simpleDrawWithColor(const GLColor & color)1830 void SimpleStateChangeTest::simpleDrawWithColor(const GLColor &color)
1831 {
1832     std::vector<GLColor> colors(6, color);
1833     GLBuffer colorBuffer;
1834     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
1835     glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLColor), colors.data(), GL_STATIC_DRAW);
1836     simpleDrawWithBuffer(&colorBuffer);
1837 }
1838 
1839 // Test that we can do a drawElements call successfully after making a drawArrays call in the same
1840 // frame.
TEST_P(SimpleStateChangeTest,DrawArraysThenDrawElements)1841 TEST_P(SimpleStateChangeTest, DrawArraysThenDrawElements)
1842 {
1843     // http://anglebug.com/40644706
1844     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
1845 
1846     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1847     glUseProgram(program);
1848 
1849     // We expect to draw a triangle with the first 3 points to the left, then another triangle with
1850     // the last 3 vertices using a drawElements call.
1851     auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
1852                                          {-1.0f, 1.0f, 0.0f},
1853                                          {0.0f, 0.0f, 0.0f},
1854                                          {1.0f, 1.0f, 0.0f},
1855                                          {1.0f, -1.0f, 0.0f}};
1856 
1857     // If we use these indices to draw we'll be using the last 2 vertex only to draw.
1858     auto indices = std::vector<GLushort>{2, 3, 4};
1859 
1860     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1861     ASSERT_NE(-1, positionLocation);
1862 
1863     GLBuffer vertexBuffer;
1864     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1865     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1866                  GL_STATIC_DRAW);
1867 
1868     GLBuffer indexBuffer;
1869     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1870     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1871                  GL_STATIC_DRAW);
1872 
1873     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1874     glEnableVertexAttribArray(positionLocation);
1875 
1876     for (int i = 0; i < 10; i++)
1877     {
1878         glClear(GL_COLOR_BUFFER_BIT);
1879         glDrawArrays(GL_TRIANGLES, 0, 3);                             // triangle to the left
1880         glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr);  // triangle to the right
1881         glFinish();
1882     }
1883     glDisableVertexAttribArray(positionLocation);
1884 
1885     ASSERT_GL_NO_ERROR();
1886 
1887     int quarterWidth = getWindowWidth() / 4;
1888     int halfHeight   = getWindowHeight() / 2;
1889 
1890     // Validate triangle to the left
1891     EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::blue);
1892 
1893     // Validate triangle to the right
1894     EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::blue);
1895 }
1896 
1897 // Draw a triangle with drawElements and a non-zero offset and draw the same
1898 // triangle with the same offset followed by binding the same element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElements)1899 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElements)
1900 {
1901     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1902 
1903     glUseProgram(program);
1904 
1905     // Background Red color
1906     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1907     glClear(GL_COLOR_BUFFER_BIT);
1908 
1909     // We expect to draw the triangle with the last three points on the bottom right, and
1910     // rebind the same element buffer and draw with the same indices.
1911     auto vertices = std::vector<Vector3>{
1912         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1913 
1914     auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1915 
1916     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1917     ASSERT_NE(-1, positionLocation);
1918 
1919     GLBuffer indexBuffer;
1920     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1921     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1922                  GL_STATIC_DRAW);
1923 
1924     GLBuffer vertexBuffer;
1925     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1926     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1927                  GL_STATIC_DRAW);
1928 
1929     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1930     glEnableVertexAttribArray(positionLocation);
1931 
1932     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1933 
1934     // Rebind the same element buffer.
1935     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1936 
1937     // Draw the triangle again with the same offset.
1938     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1939 
1940     glDisableVertexAttribArray(positionLocation);
1941 
1942     ASSERT_GL_NO_ERROR();
1943 
1944     int quarterWidth  = getWindowWidth() / 4;
1945     int quarterHeight = getWindowHeight() / 4;
1946 
1947     // Validate the triangle is drawn on the bottom right.
1948     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1949 
1950     // Validate the triangle is NOT on the top left part.
1951     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1952     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1953 }
1954 
1955 // Draw a triangle with drawElements then change the index buffer and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndexBuffer)1956 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndexBuffer)
1957 {
1958     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1959 
1960     glUseProgram(program);
1961 
1962     // Background Red color
1963     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1964     glClear(GL_COLOR_BUFFER_BIT);
1965 
1966     // We expect to draw the triangle with the last three points on the bottom right, and
1967     // rebind the same element buffer and draw with the same indices.
1968     auto vertices = std::vector<Vector3>{
1969         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1970 
1971     auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
1972 
1973     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1974     ASSERT_NE(-1, positionLocation);
1975 
1976     GLint colorUniformLocation =
1977         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1978     ASSERT_NE(colorUniformLocation, -1);
1979 
1980     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1981 
1982     GLBuffer indexBuffer8;
1983     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1984     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1985                  GL_STATIC_DRAW);
1986 
1987     GLBuffer vertexBuffer;
1988     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1989     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1990                  GL_STATIC_DRAW);
1991 
1992     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1993     glEnableVertexAttribArray(positionLocation);
1994 
1995     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1996 
1997     auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
1998 
1999     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2000                  GL_STATIC_DRAW);
2001 
2002     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2003 
2004     // Draw the triangle again with the same offset.
2005     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2006 
2007     glDisableVertexAttribArray(positionLocation);
2008 
2009     ASSERT_GL_NO_ERROR();
2010 
2011     int quarterWidth  = getWindowWidth() / 4;
2012     int quarterHeight = getWindowHeight() / 4;
2013 
2014     // Validate the triangle is drawn on the bottom left.
2015     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2016     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2017 
2018     // Validate the triangle is NOT on the top right part.
2019     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2020 }
2021 
2022 // Draw a triangle with drawElements then change the indices and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndices)2023 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndices)
2024 {
2025     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2026 
2027     glUseProgram(program);
2028 
2029     // Background Red color
2030     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2031     glClear(GL_COLOR_BUFFER_BIT);
2032 
2033     // We expect to draw the triangle with the last three points on the bottom right, and
2034     // rebind the same element buffer and draw with the same indices.
2035     std::vector<Vector3> vertices = {
2036         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2037 
2038     std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
2039 
2040     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2041     ASSERT_NE(-1, positionLocation);
2042 
2043     GLint colorUniformLocation =
2044         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2045     ASSERT_NE(colorUniformLocation, -1);
2046 
2047     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2048 
2049     GLBuffer indexBuffer8;
2050     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2051     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2052                  GL_DYNAMIC_DRAW);
2053 
2054     GLBuffer vertexBuffer;
2055     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2056     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2057                  GL_STATIC_DRAW);
2058 
2059     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2060     glEnableVertexAttribArray(positionLocation);
2061 
2062     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2063 
2064     std::vector<GLubyte> newIndices8 = {2, 3, 0};
2065 
2066     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
2067                     &newIndices8[0]);
2068 
2069     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2070 
2071     // Draw the triangle again with the same offset.
2072     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2073 
2074     glDisableVertexAttribArray(positionLocation);
2075 
2076     ASSERT_GL_NO_ERROR();
2077 
2078     int quarterWidth  = getWindowWidth() / 4;
2079     int quarterHeight = getWindowHeight() / 4;
2080 
2081     // Validate the triangle is drawn on the bottom left.
2082     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2083     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2084 
2085     // Validate the triangle is NOT on the top right part.
2086     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2087 }
2088 
2089 // Draw a triangle with drawElements then change the indices and draw again.  Similar to
2090 // DrawElementsThenDrawElementsNewIndices, but changes the whole index buffer (not just half).  This
2091 // triggers a different path in the Vulkan backend based on the fact that the majority of the buffer
2092 // is being updated.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsWholeNewIndices)2093 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsWholeNewIndices)
2094 {
2095     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2096 
2097     glUseProgram(program);
2098 
2099     // Background Red color
2100     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2101     glClear(GL_COLOR_BUFFER_BIT);
2102 
2103     // We expect to draw the triangle with the last three points on the bottom right, and
2104     // rebind the same element buffer and draw with the same indices.
2105     std::vector<Vector3> vertices = {
2106         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2107 
2108     std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
2109 
2110     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2111     ASSERT_NE(-1, positionLocation);
2112 
2113     GLint colorUniformLocation =
2114         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2115     ASSERT_NE(colorUniformLocation, -1);
2116 
2117     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2118 
2119     GLBuffer indexBuffer8;
2120     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2121     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2122                  GL_DYNAMIC_DRAW);
2123 
2124     GLBuffer vertexBuffer;
2125     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2126     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2127                  GL_STATIC_DRAW);
2128 
2129     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2130     glEnableVertexAttribArray(positionLocation);
2131 
2132     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2133 
2134     std::vector<GLubyte> newIndices8 = {2, 3, 0, 0, 0, 0};
2135 
2136     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
2137                     &newIndices8[0]);
2138 
2139     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2140 
2141     // Draw the triangle again with the same offset.
2142     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2143 
2144     glDisableVertexAttribArray(positionLocation);
2145 
2146     ASSERT_GL_NO_ERROR();
2147 
2148     int quarterWidth  = getWindowWidth() / 4;
2149     int quarterHeight = getWindowHeight() / 4;
2150 
2151     // Validate the triangle is drawn on the bottom left.
2152     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2153     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2154 
2155     // Validate the triangle is NOT on the top right part.
2156     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2157 }
2158 
2159 // Draw a triangle with drawElements and a non-zero offset and draw the same
2160 // triangle with the same offset followed by binding a USHORT element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsUBYTEX2ThenDrawElementsUSHORT)2161 TEST_P(SimpleStateChangeTest, DrawElementsUBYTEX2ThenDrawElementsUSHORT)
2162 {
2163     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2164 
2165     glUseProgram(program);
2166 
2167     // Background Red color
2168     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2169     glClear(GL_COLOR_BUFFER_BIT);
2170 
2171     // We expect to draw the triangle with the last three points on the bottom right, and
2172     // rebind the same element buffer and draw with the same indices.
2173     auto vertices = std::vector<Vector3>{
2174         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2175 
2176     auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
2177 
2178     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2179     ASSERT_NE(-1, positionLocation);
2180 
2181     GLint colorUniformLocation =
2182         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2183     ASSERT_NE(colorUniformLocation, -1);
2184 
2185     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2186 
2187     GLBuffer indexBuffer8;
2188     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2189     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2190                  GL_STATIC_DRAW);
2191 
2192     GLBuffer vertexBuffer;
2193     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2194     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2195                  GL_STATIC_DRAW);
2196 
2197     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2198     glEnableVertexAttribArray(positionLocation);
2199 
2200     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2201 
2202     auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
2203     GLBuffer indexBuffer2nd8;
2204     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2nd8);
2205     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2206                  GL_STATIC_DRAW);
2207     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2208 
2209     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2210 
2211     // Bind the 16bit element buffer.
2212     auto indices16 = std::vector<GLushort>{0, 1, 3, 1, 2, 3};
2213     GLBuffer indexBuffer16;
2214     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2215     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices16.size() * sizeof(GLushort), &indices16[0],
2216                  GL_STATIC_DRAW);
2217 
2218     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2219 
2220     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2221 
2222     // Draw the triangle again with the same offset.
2223     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(0 * sizeof(GLushort)));
2224 
2225     glDisableVertexAttribArray(positionLocation);
2226 
2227     ASSERT_GL_NO_ERROR();
2228 
2229     int quarterWidth  = getWindowWidth() / 4;
2230     int quarterHeight = getWindowHeight() / 4;
2231 
2232     // Validate green triangle is drawn on the bottom.
2233     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::green);
2234 
2235     // Validate white triangle is drawn on the right.
2236     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 3, quarterHeight * 2, GLColor::white);
2237 
2238     // Validate blue triangle is on the top left part.
2239     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::blue);
2240     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2241 }
2242 
2243 // Draw a points use multiple unaligned vertex buffer with same data,
2244 // verify all the rendering results are the same.
TEST_P(SimpleStateChangeTest,DrawRepeatUnalignedVboChange)2245 TEST_P(SimpleStateChangeTest, DrawRepeatUnalignedVboChange)
2246 {
2247     // http://anglebug.com/42263089
2248     ANGLE_SKIP_TEST_IF(isSwiftshader() && (IsWindows() || IsLinux()));
2249 
2250     const int kRepeat = 2;
2251 
2252     // set up VBO, colorVBO is unaligned
2253     GLBuffer positionBuffer;
2254     constexpr size_t posOffset = 0;
2255     const GLfloat posData[]    = {0.5f, 0.5f};
2256     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2257     glBufferData(GL_ARRAY_BUFFER, sizeof(posData), posData, GL_STATIC_DRAW);
2258 
2259     GLBuffer colorBuffers[kRepeat];
2260     constexpr size_t colorOffset                = 1;
2261     const GLfloat colorData[]                   = {0.515f, 0.515f, 0.515f, 1.0f};
2262     constexpr size_t colorBufferSize            = colorOffset + sizeof(colorData);
2263     uint8_t colorDataUnaligned[colorBufferSize] = {0};
2264     memcpy(reinterpret_cast<void *>(colorDataUnaligned + colorOffset), colorData,
2265            sizeof(colorData));
2266     for (uint32_t i = 0; i < kRepeat; i++)
2267     {
2268         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2269         glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorDataUnaligned, GL_STATIC_DRAW);
2270     }
2271 
2272     // set up frame buffer
2273     GLFramebuffer framebuffer;
2274     GLTexture framebufferTexture;
2275     bindTextureToFbo(framebuffer, framebufferTexture);
2276 
2277     // set up program
2278     ANGLE_GL_PROGRAM(program, kSimpleVertexShaderForPoints, kSimpleFragmentShader);
2279     glUseProgram(program);
2280     GLuint colorAttrLocation = glGetAttribLocation(program, "color");
2281     glEnableVertexAttribArray(colorAttrLocation);
2282     GLuint posAttrLocation = glGetAttribLocation(program, "position");
2283     glEnableVertexAttribArray(posAttrLocation);
2284     EXPECT_GL_NO_ERROR();
2285 
2286     // draw and get drawing results
2287     constexpr size_t kRenderSize = kWindowSize * kWindowSize;
2288     std::array<GLColor, kRenderSize> pixelBufs[kRepeat];
2289 
2290     for (uint32_t i = 0; i < kRepeat; i++)
2291     {
2292         glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2293         glClear(GL_COLOR_BUFFER_BIT);
2294 
2295         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2296         glVertexAttribPointer(posAttrLocation, 2, GL_FLOAT, GL_FALSE, 0,
2297                               reinterpret_cast<const void *>(posOffset));
2298         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2299         glVertexAttribPointer(colorAttrLocation, 4, GL_FLOAT, GL_FALSE, 0,
2300                               reinterpret_cast<const void *>(colorOffset));
2301 
2302         glDrawArrays(GL_POINTS, 0, 1);
2303 
2304         // read drawing results
2305         glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
2306                      pixelBufs[i].data());
2307         EXPECT_GL_NO_ERROR();
2308     }
2309 
2310     // verify something is drawn
2311     static_assert(kRepeat >= 2, "More than one repetition required");
2312     std::array<GLColor, kRenderSize> pixelAllBlack{0};
2313     EXPECT_NE(pixelBufs[0], pixelAllBlack);
2314     // verify drawing results are all identical
2315     for (uint32_t i = 1; i < kRepeat; i++)
2316     {
2317         EXPECT_EQ(pixelBufs[i - 1], pixelBufs[i]);
2318     }
2319 }
2320 
2321 // Handles deleting a Buffer when it's being used.
TEST_P(SimpleStateChangeTest,DeleteBufferInUse)2322 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
2323 {
2324     std::vector<GLColor> colorData(6, GLColor::red);
2325 
2326     GLBuffer buffer;
2327     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2328     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * colorData.size(), colorData.data(),
2329                  GL_STATIC_DRAW);
2330 
2331     simpleDrawWithBuffer(&buffer);
2332 
2333     buffer.reset();
2334     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2335 }
2336 
2337 // Tests that resizing a Buffer during a draw works as expected.
TEST_P(SimpleStateChangeTest,RedefineBufferInUse)2338 TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
2339 {
2340     std::vector<GLColor> redColorData(6, GLColor::red);
2341 
2342     GLBuffer buffer;
2343     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2344     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2345                  GL_STATIC_DRAW);
2346 
2347     // Trigger a pull from the buffer.
2348     simpleDrawWithBuffer(&buffer);
2349 
2350     // Redefine the buffer that's in-flight.
2351     std::vector<GLColor> greenColorData(1024, GLColor::green);
2352     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * greenColorData.size(), greenColorData.data(),
2353                  GL_STATIC_DRAW);
2354 
2355     // Trigger the flush and verify the first draw worked.
2356     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2357 
2358     // Draw again and verify the new data is correct.
2359     simpleDrawWithBuffer(&buffer);
2360     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2361 }
2362 
2363 // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest,UpdateBufferInUse)2364 TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
2365 {
2366     std::vector<GLColor> redColorData(6, GLColor::red);
2367 
2368     GLBuffer buffer;
2369     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2370     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2371                  GL_STATIC_DRAW);
2372 
2373     // Trigger a pull from the buffer.
2374     simpleDrawWithBuffer(&buffer);
2375 
2376     // Update the buffer that's in-flight.
2377     std::vector<GLColor> greenColorData(6, GLColor::green);
2378     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * greenColorData.size(),
2379                     greenColorData.data());
2380 
2381     // Trigger the flush and verify the first draw worked.
2382     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2383 
2384     // Draw again and verify the new data is correct.
2385     simpleDrawWithBuffer(&buffer);
2386     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2387 }
2388 
2389 // Tests that deleting an in-flight Texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTest,DeleteTextureInUse)2390 TEST_P(SimpleStateChangeTest, DeleteTextureInUse)
2391 {
2392     std::array<GLColor, 4> colors = {
2393         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2394 
2395     GLTexture tex;
2396     glBindTexture(GL_TEXTURE_2D, tex);
2397     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2398     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2399     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2400 
2401     draw2DTexturedQuad(0.5f, 1.0f, true);
2402     tex.reset();
2403     EXPECT_GL_NO_ERROR();
2404 
2405     int w = getWindowWidth() - 2;
2406     int h = getWindowHeight() - 2;
2407 
2408     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2409     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2410     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2411     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2412 }
2413 
2414 // Tests that modifying a texture parameter in-flight does not cause problems.
TEST_P(SimpleStateChangeTest,ChangeTextureFilterModeBetweenTwoDraws)2415 TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
2416 {
2417     std::array<GLColor, 4> colors = {
2418         {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
2419 
2420     GLTexture tex;
2421     glBindTexture(GL_TEXTURE_2D, tex);
2422     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2423 
2424     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2425     glClear(GL_COLOR_BUFFER_BIT);
2426 
2427     // Draw to the left side of the window only with NEAREST.
2428     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2429     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2430     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2431     draw2DTexturedQuad(0.5f, 1.0f, true);
2432 
2433     // Draw to the right side of the window only with LINEAR.
2434     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2435     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2436     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2437     draw2DTexturedQuad(0.5f, 1.0f, true);
2438     EXPECT_GL_NO_ERROR();
2439 
2440     glViewport(0, 0, getWindowWidth(), getWindowHeight());
2441 
2442     // The first half (left) should be only black followed by plain white.
2443     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2444     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
2445     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
2446     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
2447 
2448     // The second half (right) should be a gradient so we shouldn't find plain black/white in the
2449     // middle.
2450     EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
2451     EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
2452 }
2453 
2454 // Tests that bind the same texture all the time between different draw calls.
TEST_P(SimpleStateChangeTest,RebindTextureDrawAgain)2455 TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
2456 {
2457     GLuint program = get2DTexturedQuadProgram();
2458     glUseProgram(program);
2459 
2460     std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2461 
2462     // Setup the texture
2463     GLTexture tex;
2464     glBindTexture(GL_TEXTURE_2D, tex);
2465     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2466     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2467     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2468 
2469     // Setup the vertex array to draw a quad.
2470     GLint positionLocation = glGetAttribLocation(program, "position");
2471     setupQuadVertexBuffer(1.0f, 1.0f);
2472     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2473     glEnableVertexAttribArray(positionLocation);
2474 
2475     // Draw quad
2476     glDrawArrays(GL_TRIANGLES, 0, 6);
2477     ASSERT_GL_NO_ERROR();
2478 
2479     // Bind again
2480     glBindTexture(GL_TEXTURE_2D, tex);
2481     ASSERT_GL_NO_ERROR();
2482 
2483     // Draw again, should still work.
2484     glDrawArrays(GL_TRIANGLES, 0, 6);
2485     ASSERT_GL_NO_ERROR();
2486 
2487     // Validate whole surface is filled with cyan.
2488     int h = getWindowHeight() - 1;
2489     int w = getWindowWidth() - 1;
2490 
2491     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2492 }
2493 
2494 // Tests that we can draw with a texture, modify the texture with a texSubImage, and then draw again
2495 // correctly.
TEST_P(SimpleStateChangeTest,DrawWithTextureTexSubImageThenDrawAgain)2496 TEST_P(SimpleStateChangeTest, DrawWithTextureTexSubImageThenDrawAgain)
2497 {
2498     GLuint program = get2DTexturedQuadProgram();
2499     ASSERT_NE(0u, program);
2500     glUseProgram(program);
2501 
2502     std::array<GLColor, 4> colors    = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
2503     std::array<GLColor, 4> subColors = {
2504         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
2505 
2506     // Setup the texture
2507     GLTexture tex;
2508     glBindTexture(GL_TEXTURE_2D, tex);
2509     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2510     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2511     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2512 
2513     // Setup the vertex array to draw a quad.
2514     GLint positionLocation = glGetAttribLocation(program, "position");
2515     setupQuadVertexBuffer(1.0f, 1.0f);
2516     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2517     glEnableVertexAttribArray(positionLocation);
2518 
2519     // Draw quad
2520     glDrawArrays(GL_TRIANGLES, 0, 6);
2521     ASSERT_GL_NO_ERROR();
2522 
2523     // Update bottom-half of texture with green.
2524     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
2525     ASSERT_GL_NO_ERROR();
2526 
2527     // Draw again, should still work.
2528     glDrawArrays(GL_TRIANGLES, 0, 6);
2529     ASSERT_GL_NO_ERROR();
2530 
2531     // Validate first half of the screen is red and the bottom is green.
2532     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2533     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4 * 3, GLColor::red);
2534 }
2535 
2536 // Test that we can alternate between textures between different draws.
TEST_P(SimpleStateChangeTest,DrawTextureAThenTextureBThenTextureA)2537 TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
2538 {
2539     GLuint program = get2DTexturedQuadProgram();
2540     glUseProgram(program);
2541 
2542     std::array<GLColor, 4> colorsTex1 = {
2543         {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2544 
2545     std::array<GLColor, 4> colorsTex2 = {
2546         {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
2547 
2548     // Setup the texture
2549     GLTexture tex1;
2550     glBindTexture(GL_TEXTURE_2D, tex1);
2551     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
2552     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2553     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2554 
2555     GLTexture tex2;
2556     glBindTexture(GL_TEXTURE_2D, tex2);
2557     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
2558     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2559     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2560 
2561     // Setup the vertex array to draw a quad.
2562     GLint positionLocation = glGetAttribLocation(program, "position");
2563     setupQuadVertexBuffer(1.0f, 1.0f);
2564     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2565     glEnableVertexAttribArray(positionLocation);
2566 
2567     // Draw quad
2568     glBindTexture(GL_TEXTURE_2D, tex1);
2569     glDrawArrays(GL_TRIANGLES, 0, 6);
2570     ASSERT_GL_NO_ERROR();
2571 
2572     // Bind again, draw again
2573     glBindTexture(GL_TEXTURE_2D, tex2);
2574     glDrawArrays(GL_TRIANGLES, 0, 6);
2575     ASSERT_GL_NO_ERROR();
2576 
2577     // Bind again, draw again
2578     glBindTexture(GL_TEXTURE_2D, tex1);
2579     glDrawArrays(GL_TRIANGLES, 0, 6);
2580 
2581     // Validate whole surface is filled with cyan.
2582     int h = getWindowHeight() - 1;
2583     int w = getWindowWidth() - 1;
2584 
2585     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2586 }
2587 
2588 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
TEST_P(SimpleStateChangeTest,RedefineTextureInUse)2589 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
2590 {
2591     std::array<GLColor, 4> colors = {
2592         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2593 
2594     GLTexture tex;
2595     glBindTexture(GL_TEXTURE_2D, tex);
2596     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2597     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2598     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2599 
2600     // Draw with the first texture.
2601     draw2DTexturedQuad(0.5f, 1.0f, true);
2602 
2603     // Redefine the in-flight texture.
2604     constexpr int kBigSize = 32;
2605     std::vector<GLColor> bigColors;
2606     for (int y = 0; y < kBigSize; ++y)
2607     {
2608         for (int x = 0; x < kBigSize; ++x)
2609         {
2610             bool xComp = x < kBigSize / 2;
2611             bool yComp = y < kBigSize / 2;
2612             if (yComp)
2613             {
2614                 bigColors.push_back(xComp ? GLColor::cyan : GLColor::magenta);
2615             }
2616             else
2617             {
2618                 bigColors.push_back(xComp ? GLColor::yellow : GLColor::white);
2619             }
2620         }
2621     }
2622 
2623     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigColors.data());
2624     EXPECT_GL_NO_ERROR();
2625 
2626     // Verify the first draw had the correct data via ReadPixels.
2627     int w = getWindowWidth() - 2;
2628     int h = getWindowHeight() - 2;
2629 
2630     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2631     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2632     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2633     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2634 
2635     // Draw and verify with the redefined data.
2636     draw2DTexturedQuad(0.5f, 1.0f, true);
2637     EXPECT_GL_NO_ERROR();
2638 
2639     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2640     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::magenta);
2641     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::yellow);
2642     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::white);
2643 }
2644 
2645 // Test updating a Texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTest,UpdateTextureInUse)2646 TEST_P(SimpleStateChangeTest, UpdateTextureInUse)
2647 {
2648     std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2649 
2650     // Set up 2D quad resources.
2651     GLuint program = get2DTexturedQuadProgram();
2652     glUseProgram(program);
2653     ASSERT_EQ(0, glGetAttribLocation(program, "position"));
2654 
2655     const auto &quadVerts = GetQuadVertices();
2656 
2657     GLBuffer vbo;
2658     glBindBuffer(GL_ARRAY_BUFFER, vbo);
2659     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
2660                  GL_STATIC_DRAW);
2661     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2662     glEnableVertexAttribArray(0);
2663 
2664     GLTexture tex;
2665     glBindTexture(GL_TEXTURE_2D, tex);
2666     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
2667     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2668     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2669 
2670     // Draw RGBY to the Framebuffer. The texture is now in-use by GL.
2671     const int w  = getWindowWidth() - 2;
2672     const int h  = getWindowHeight() - 2;
2673     const int w2 = w >> 1;
2674 
2675     glViewport(0, 0, w2, h);
2676     glDrawArrays(GL_TRIANGLES, 0, 6);
2677 
2678     // Update the texture to be YBGR, while the Texture is in-use. Should not affect the draw.
2679     std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
2680     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
2681     ASSERT_GL_NO_ERROR();
2682 
2683     // Draw again to the Framebuffer. The second draw call should use the updated YBGR data.
2684     glViewport(w2, 0, w2, h);
2685     glDrawArrays(GL_TRIANGLES, 0, 6);
2686 
2687     // Check the Framebuffer. Both draws should have completed.
2688     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2689     EXPECT_PIXEL_COLOR_EQ(w2 - 1, 0, GLColor::green);
2690     EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::blue);
2691     EXPECT_PIXEL_COLOR_EQ(w2 - 1, h - 1, GLColor::yellow);
2692 
2693     EXPECT_PIXEL_COLOR_EQ(w2 + 1, 0, GLColor::yellow);
2694     EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::blue);
2695     EXPECT_PIXEL_COLOR_EQ(w2 + 1, h - 1, GLColor::green);
2696     EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::red);
2697     ASSERT_GL_NO_ERROR();
2698 }
2699 
updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)2700 void SimpleStateChangeTest::updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)
2701 {
2702     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2703 
2704     std::vector<GLColor> red(4, GLColor::red);
2705     std::vector<GLColor> green(4, GLColor::green);
2706 
2707     GLTexture renderTarget;
2708     glBindTexture(GL_TEXTURE_2D, renderTarget);
2709     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2710 
2711     GLFramebuffer fbo;
2712     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2713     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2714                            0);
2715     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2716     glViewport(0, 0, 2, 2);
2717     ASSERT_GL_NO_ERROR();
2718 
2719     GLTexture tex;
2720     glBindTexture(GL_TEXTURE_2D, tex);
2721     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2722     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2723     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2724 
2725     // Draw once to flush dirty state bits.
2726     draw2DTexturedQuad(0.5f, 1.0f, true);
2727 
2728     ASSERT_GL_NO_ERROR();
2729 
2730     // Update the (0, 1) pixel to be blue
2731     updateFunc(GL_TEXTURE_2D, &renderTarget, 0, 1, GLColor::blue);
2732 
2733     // Draw green to the right half of the Framebuffer.
2734     glBindTexture(GL_TEXTURE_2D, tex);
2735     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, green.data());
2736     glViewport(1, 0, 1, 2);
2737     draw2DTexturedQuad(0.5f, 1.0f, true);
2738 
2739     // Update the (1, 1) pixel to be yellow
2740     updateFunc(GL_TEXTURE_2D, &renderTarget, 1, 1, GLColor::yellow);
2741 
2742     ASSERT_GL_NO_ERROR();
2743 
2744     // Verify we have a quad with the right colors in the FBO.
2745     std::vector<GLColor> expected = {
2746         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2747     std::vector<GLColor> actual(4);
2748     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2749     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
2750     EXPECT_EQ(expected, actual);
2751 }
2752 
2753 // Tests that TexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,TexSubImageOnTextureBoundToFrambuffer)2754 TEST_P(SimpleStateChangeTest, TexSubImageOnTextureBoundToFrambuffer)
2755 {
2756     // http://anglebug.com/40096654
2757     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2758     auto updateFunc = [](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2759                          const GLColor &color) {
2760         glBindTexture(textureBinding, *tex);
2761         glTexSubImage2D(textureBinding, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2762     };
2763 
2764     updateTextureBoundToFramebufferHelper(updateFunc);
2765 }
2766 
2767 // Tests that CopyTexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,CopyTexSubImageOnTextureBoundToFrambuffer)2768 TEST_P(SimpleStateChangeTest, CopyTexSubImageOnTextureBoundToFrambuffer)
2769 {
2770     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2771 
2772     GLTexture copySource;
2773     glBindTexture(GL_TEXTURE_2D, copySource);
2774     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2775 
2776     GLFramebuffer copyFBO;
2777     glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFBO);
2778     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySource, 0);
2779 
2780     ASSERT_GL_NO_ERROR();
2781     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2782 
2783     auto updateFunc = [&copySource](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2784                                     const GLColor &color) {
2785         glBindTexture(GL_TEXTURE_2D, copySource);
2786         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2787 
2788         glBindTexture(textureBinding, *tex);
2789         glCopyTexSubImage2D(textureBinding, 0, x, y, 0, 0, 1, 1);
2790     };
2791 
2792     updateTextureBoundToFramebufferHelper(updateFunc);
2793 }
2794 
2795 // Tests that the read framebuffer doesn't affect what the draw call thinks the attachments are
2796 // (which is what the draw framebuffer dictates) when a command is issued with the GL_FRAMEBUFFER
2797 // target.
TEST_P(SimpleStateChangeTestES3,ReadFramebufferDrawFramebufferDifferentAttachments)2798 TEST_P(SimpleStateChangeTestES3, ReadFramebufferDrawFramebufferDifferentAttachments)
2799 {
2800     // http://anglebug.com/40096654
2801     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2802 
2803     GLRenderbuffer drawColorBuffer;
2804     glBindRenderbuffer(GL_RENDERBUFFER, drawColorBuffer);
2805     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2806 
2807     GLRenderbuffer drawDepthBuffer;
2808     glBindRenderbuffer(GL_RENDERBUFFER, drawDepthBuffer);
2809     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1);
2810 
2811     GLRenderbuffer readColorBuffer;
2812     glBindRenderbuffer(GL_RENDERBUFFER, readColorBuffer);
2813     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2814 
2815     GLFramebuffer drawFBO;
2816     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2817     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2818                               drawColorBuffer);
2819     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2820                               drawDepthBuffer);
2821     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2822 
2823     GLFramebuffer readFBO;
2824     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2825     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2826                               readColorBuffer);
2827     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2828 
2829     EXPECT_GL_NO_ERROR();
2830 
2831     glClearDepthf(1.0f);
2832     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2833 
2834     // A handful of non-draw calls can sync framebuffer state, such as discard, invalidate,
2835     // invalidateSub and multisamplefv.
2836     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2837     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
2838     EXPECT_GL_NO_ERROR();
2839 
2840     glEnable(GL_DEPTH_TEST);
2841     glDepthFunc(GL_EQUAL);
2842 
2843     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
2844 
2845     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
2846     EXPECT_GL_NO_ERROR();
2847 
2848     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2849     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2850 }
2851 
2852 // Tests that invalidate then copy then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenCopyThenBlend)2853 TEST_P(SimpleStateChangeTestES3, InvalidateThenCopyThenBlend)
2854 {
2855     // Create a framebuffer as the source of copy
2856     const GLColor kSrcData = GLColor::cyan;
2857     GLTexture copySrc;
2858     glBindTexture(GL_TEXTURE_2D, copySrc);
2859     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2860 
2861     GLFramebuffer readFBO;
2862     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2863     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySrc, 0);
2864     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2865 
2866     // Create the framebuffer that will be invalidated
2867     GLTexture renderTarget;
2868     glBindTexture(GL_TEXTURE_2D, renderTarget);
2869     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2870 
2871     GLFramebuffer drawFBO;
2872     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2873     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2874                            0);
2875     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2876 
2877     EXPECT_GL_NO_ERROR();
2878 
2879     // Clear the framebuffer and invalidate it.
2880     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2881     glClear(GL_COLOR_BUFFER_BIT);
2882 
2883     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2884     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2885     EXPECT_GL_NO_ERROR();
2886 
2887     // Copy into the framebuffer's texture.  The framebuffer should now be cyan.
2888     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2889     EXPECT_GL_NO_ERROR();
2890 
2891     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2892     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2893     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2894 }
2895 
2896 // Tests that invalidate then blit then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenBlitThenBlend)2897 TEST_P(SimpleStateChangeTestES3, InvalidateThenBlitThenBlend)
2898 {
2899     // Create a framebuffer as the source of blit
2900     const GLColor kSrcData = GLColor::cyan;
2901     GLTexture blitSrc;
2902     glBindTexture(GL_TEXTURE_2D, blitSrc);
2903     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2904 
2905     GLFramebuffer readFBO;
2906     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2907     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
2908     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2909 
2910     // Create the framebuffer that will be invalidated
2911     GLTexture renderTarget;
2912     glBindTexture(GL_TEXTURE_2D, renderTarget);
2913     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2914 
2915     GLFramebuffer drawFBO;
2916     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2917     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2918                            0);
2919     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2920 
2921     EXPECT_GL_NO_ERROR();
2922 
2923     // Clear the framebuffer and invalidate it.
2924     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2925     glClear(GL_COLOR_BUFFER_BIT);
2926 
2927     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2928     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2929     EXPECT_GL_NO_ERROR();
2930 
2931     // Blit into the framebuffer.  The framebuffer should now be cyan.
2932     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2933     EXPECT_GL_NO_ERROR();
2934 
2935     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2936     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2937     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2938 }
2939 
2940 // Tests that invalidate then generate mipmaps works
TEST_P(SimpleStateChangeTestES3,InvalidateThenGenerateMipmapsThenBlend)2941 TEST_P(SimpleStateChangeTestES3, InvalidateThenGenerateMipmapsThenBlend)
2942 {
2943     // Create a texture on which generate mipmaps would be called
2944     const GLColor kMip0Data[4] = {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan};
2945     const GLColor kMip1Data    = GLColor::blue;
2946     GLTexture texture;
2947     glBindTexture(GL_TEXTURE_2D, texture);
2948     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data);
2949     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kMip1Data);
2950 
2951     // Create the framebuffer that will be invalidated
2952     GLFramebuffer drawFBO;
2953     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2954     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
2955     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2956 
2957     EXPECT_GL_NO_ERROR();
2958 
2959     // Clear the framebuffer and invalidate it.
2960     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2961     glClear(GL_COLOR_BUFFER_BIT);
2962 
2963     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2964     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2965     EXPECT_GL_NO_ERROR();
2966 
2967     // Generate mipmaps
2968     glGenerateMipmap(GL_TEXTURE_2D);
2969 
2970     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2971     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2972     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2973 }
2974 
2975 // Tests that invalidate then upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenUploadThenBlend)2976 TEST_P(SimpleStateChangeTestES3, InvalidateThenUploadThenBlend)
2977 {
2978     // http://anglebug.com/42263445
2979     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2980 
2981     // Create the framebuffer that will be invalidated
2982     GLTexture renderTarget;
2983     glBindTexture(GL_TEXTURE_2D, renderTarget);
2984     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2985 
2986     GLFramebuffer drawFBO;
2987     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2988     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2989                            0);
2990     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2991 
2992     EXPECT_GL_NO_ERROR();
2993 
2994     // Clear the framebuffer and invalidate it.
2995     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2996     glClear(GL_COLOR_BUFFER_BIT);
2997 
2998     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2999     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3000     EXPECT_GL_NO_ERROR();
3001 
3002     // Upload data to it
3003     const GLColor kUploadColor = GLColor::cyan;
3004     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
3005 
3006     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3007     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3008     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3009 }
3010 
3011 // Tests that invalidate then sub upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenSubUploadThenBlend)3012 TEST_P(SimpleStateChangeTestES3, InvalidateThenSubUploadThenBlend)
3013 {
3014     // http://anglebug.com/42263445
3015     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3016 
3017     // Create the framebuffer that will be invalidated
3018     GLTexture renderTarget;
3019     glBindTexture(GL_TEXTURE_2D, renderTarget);
3020     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3021 
3022     GLFramebuffer drawFBO;
3023     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3024     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3025                            0);
3026     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3027 
3028     EXPECT_GL_NO_ERROR();
3029 
3030     // Clear the framebuffer and invalidate it.
3031     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3032     glClear(GL_COLOR_BUFFER_BIT);
3033 
3034     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3035     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3036     EXPECT_GL_NO_ERROR();
3037 
3038     // Upload data to it
3039     const GLColor kUploadColor = GLColor::cyan;
3040     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
3041 
3042     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3043     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3044     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3045 }
3046 
3047 // Tests that invalidate then compute write works
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlend)3048 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlend)
3049 {
3050     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3051     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3052     // http://anglebug.com/42263927
3053     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
3054 
3055     constexpr char kCS[] = R"(#version 310 es
3056 layout(local_size_x=1, local_size_y=1) in;
3057 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
3058 void main()
3059 {
3060     imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
3061 })";
3062 
3063     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3064     glUseProgram(program);
3065     EXPECT_GL_NO_ERROR();
3066 
3067     // Create the framebuffer texture
3068     GLTexture renderTarget;
3069     glBindTexture(GL_TEXTURE_2D, renderTarget);
3070     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
3071     glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3072 
3073     // Write to the texture with compute once.  In the Vulkan backend, this will make sure the image
3074     // is already created with STORAGE usage and avoids recreate later.
3075     glDispatchCompute(1, 1, 1);
3076     EXPECT_GL_NO_ERROR();
3077 
3078     // Needs explicit barrier between compute shader write to FBO access.
3079     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3080 
3081     // Create the framebuffer that will be invalidated
3082     GLFramebuffer drawFBO;
3083     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3084     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3085                            0);
3086     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3087 
3088     EXPECT_GL_NO_ERROR();
3089 
3090     // Clear the framebuffer and invalidate it.
3091     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3092     glClear(GL_COLOR_BUFFER_BIT);
3093 
3094     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3095     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3096     EXPECT_GL_NO_ERROR();
3097 
3098     // Issue a memory barrier before writing to the image again.
3099     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3100 
3101     // Write to it with a compute shader
3102     glDispatchCompute(1, 1, 1);
3103     EXPECT_GL_NO_ERROR();
3104 
3105     // Needs explicit barrier between compute shader write to FBO access.
3106     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3107 
3108     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3109     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3110     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3111 }
3112 
3113 // Tests that invalidate then compute write works inside PPO
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlendPpo)3114 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlendPpo)
3115 {
3116     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3117     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3118     // PPOs are only supported in the Vulkan backend
3119     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
3120 
3121     constexpr char kCS[] = R"(#version 310 es
3122 layout(local_size_x=1, local_size_y=1) in;
3123 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
3124 void main()
3125 {
3126     imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
3127 })";
3128 
3129     GLProgramPipeline pipeline;
3130     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3131     glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
3132     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, program);
3133     EXPECT_GL_NO_ERROR();
3134     glBindProgramPipeline(pipeline);
3135     EXPECT_GL_NO_ERROR();
3136     glUseProgram(0);
3137 
3138     // Create the framebuffer texture
3139     GLTexture renderTarget;
3140     glBindTexture(GL_TEXTURE_2D, renderTarget);
3141     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
3142     glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3143 
3144     // Write to the texture with compute once.  In the Vulkan backend, this will make sure the image
3145     // is already created with STORAGE usage and avoids recreate later.
3146     glDispatchCompute(1, 1, 1);
3147     EXPECT_GL_NO_ERROR();
3148 
3149     // Needs explicit barrier between compute shader write to FBO access.
3150     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3151 
3152     // Create the framebuffer that will be invalidated
3153     GLFramebuffer drawFBO;
3154     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3155     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3156                            0);
3157     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3158 
3159     EXPECT_GL_NO_ERROR();
3160 
3161     // Clear the framebuffer and invalidate it.
3162     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3163     glClear(GL_COLOR_BUFFER_BIT);
3164 
3165     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3166     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3167     EXPECT_GL_NO_ERROR();
3168 
3169     // Issue a memory barrier before writing to the image again.
3170     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3171 
3172     // Write to it with a compute shader
3173     glDispatchCompute(1, 1, 1);
3174     EXPECT_GL_NO_ERROR();
3175 
3176     // Needs explicit barrier between compute shader write to FBO access.
3177     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3178 
3179     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3180     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3181     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3182 }
3183 
3184 // Tests that sub-invalidate then draw works.
TEST_P(SimpleStateChangeTestES3,SubInvalidateThenDraw)3185 TEST_P(SimpleStateChangeTestES3, SubInvalidateThenDraw)
3186 {
3187     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3188     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3189 
3190     // Create the framebuffer that will be invalidated
3191     GLTexture renderTarget;
3192     glBindTexture(GL_TEXTURE_2D, renderTarget);
3193     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3194 
3195     GLFramebuffer drawFBO;
3196     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3197     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3198                            0);
3199     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3200 
3201     EXPECT_GL_NO_ERROR();
3202 
3203     // Clear the framebuffer.
3204     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3205     glClear(GL_COLOR_BUFFER_BIT);
3206 
3207     // Draw into a quarter of the framebuffer, then invalidate that same region.
3208     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3209     glEnable(GL_SCISSOR_TEST);
3210     glScissor(1, 1, 1, 1);
3211     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3212 
3213     // Only invalidate a quarter of the framebuffer.
3214     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3215     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment, 1, 1, 1, 1);
3216     EXPECT_GL_NO_ERROR();
3217 
3218     glDisable(GL_SCISSOR_TEST);
3219 
3220     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3221     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3222     blendAndVerifyColor(GLColor32F(0.0f, 0.0f, 1.0f, 0.5f), GLColor(127, 127, 127, 191));
3223 }
3224 
3225 // Tests that mid-render-pass invalidate then clear works for color buffers.  This test ensures that
3226 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,ColorInvalidateThenClear)3227 TEST_P(SimpleStateChangeTestES3, ColorInvalidateThenClear)
3228 {
3229     // Create the framebuffer that will be invalidated
3230     GLTexture color;
3231     glBindTexture(GL_TEXTURE_2D, color);
3232     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3233 
3234     GLFramebuffer fbo;
3235     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3236     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3237     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3238 
3239     EXPECT_GL_NO_ERROR();
3240 
3241     // Initialize the framebuffer with a draw call.
3242     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3243     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3244 
3245     // Invalidate it.
3246     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3247     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3248 
3249     // Clear the framebuffer.
3250     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3251     glClear(GL_COLOR_BUFFER_BIT);
3252 
3253     // Expect the clear color, ensuring that invalidate wasn't applied after clear.
3254     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3255 }
3256 
3257 // Tests that mid-render-pass invalidate then clear works for depth buffers.  This test ensures that
3258 // the invalidate is undone on draw.
TEST_P(SimpleStateChangeTestES3,DepthInvalidateThenClear)3259 TEST_P(SimpleStateChangeTestES3, DepthInvalidateThenClear)
3260 {
3261     // Create the framebuffer that will be invalidated
3262     GLTexture color;
3263     glBindTexture(GL_TEXTURE_2D, color);
3264     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
3265 
3266     GLRenderbuffer depth;
3267     glBindRenderbuffer(GL_RENDERBUFFER, depth);
3268     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 2, 2);
3269 
3270     GLFramebuffer fbo;
3271     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3272     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3273     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
3274     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3275 
3276     EXPECT_GL_NO_ERROR();
3277 
3278     // Initialize the framebuffer with a draw call.
3279     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3280     glUseProgram(drawColor);
3281     GLint colorUniformLocation =
3282         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
3283     ASSERT_NE(colorUniformLocation, -1);
3284 
3285     glEnable(GL_DEPTH_TEST);
3286     glDepthFunc(GL_ALWAYS);
3287 
3288     glUniform4f(colorUniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3289     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.0f);
3290 
3291     // Invalidate depth.
3292     GLenum invalidateAttachment = GL_DEPTH_ATTACHMENT;
3293     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
3294 
3295     // Clear the framebuffer.
3296     glClearDepthf(0.8f);
3297     glClear(GL_DEPTH_BUFFER_BIT);
3298 
3299     // Expect the draw color.  This breaks the render pass.  Later, the test ensures that invalidate
3300     // of depth wasn't applied after clear.
3301     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3302 
3303     // Blend with depth test and make sure depth is as expected.
3304     glEnable(GL_BLEND);
3305     glBlendFunc(GL_ONE, GL_ONE);
3306 
3307     glDepthFunc(GL_LESS);
3308     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3309     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.59f);
3310 
3311     glDepthFunc(GL_GREATER);
3312     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
3313     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.61f);
3314 
3315     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
3316 }
3317 
3318 // Invalidate an RGB framebuffer and verify that the alpha channel is not destroyed and remains
3319 // valid after a draw call.
TEST_P(SimpleStateChangeTestES3,InvalidateRGBThenDraw)3320 TEST_P(SimpleStateChangeTestES3, InvalidateRGBThenDraw)
3321 {
3322     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3323 
3324     GLTexture texture;
3325     glBindTexture(GL_TEXTURE_2D, texture);
3326     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, getWindowWidth(), getWindowHeight(), 0, GL_RGB,
3327                  GL_UNSIGNED_BYTE, nullptr);
3328 
3329     GLFramebuffer fbo;
3330     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3331     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3332     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3333     ASSERT_GL_NO_ERROR();
3334 
3335     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3336     glClear(GL_COLOR_BUFFER_BIT);
3337     // Verify that clearing alpha is ineffective on an RGB format.
3338     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
3339 
3340     // Invalidate the framebuffer contents.
3341     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3342     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3343 
3344     // Without an explicit clear, draw blue and make sure alpha is unaffected.  If RGB is emulated
3345     // with RGBA, the previous invalidate shouldn't affect the alpha value.
3346     drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
3347     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3348 }
3349 
3350 // Invalidate an RGB framebuffer and verify that the alpha channel is not destroyed, even if the
3351 // color channels may be garbage.
TEST_P(SimpleStateChangeTestES3,DrawAndInvalidateRGBThenVerifyAlpha)3352 TEST_P(SimpleStateChangeTestES3, DrawAndInvalidateRGBThenVerifyAlpha)
3353 {
3354     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3355     glUseProgram(drawColor);
3356     GLint uniformLocation = glGetUniformLocation(drawColor, essl1_shaders::ColorUniform());
3357     ASSERT_NE(uniformLocation, -1);
3358 
3359     const int w = getWindowWidth();
3360     const int h = getWindowHeight();
3361 
3362     GLTexture texture;
3363     glBindTexture(GL_TEXTURE_2D, texture);
3364     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
3365 
3366     GLFramebuffer fbo;
3367     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3368     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3369     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3370     ASSERT_GL_NO_ERROR();
3371 
3372     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3373     glClear(GL_COLOR_BUFFER_BIT);
3374 
3375     glUniform4f(uniformLocation, 0.1f, 0.2f, 0.3f, 0.4f);
3376     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
3377 
3378     // Invalidate the framebuffer contents.
3379     const GLenum discards[] = {GL_COLOR_ATTACHMENT0};
3380     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, discards);
3381 
3382     // Read back the contents of the framebuffer.  The color channels are invalid, but as an RGB
3383     // format, readback should always return 1 in alpha.
3384     std::vector<GLColor> readback(w * h);
3385     glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, readback.data());
3386     for (int y = 0; y < h; ++y)
3387     {
3388         for (int x = 0; x < w; ++x)
3389         {
3390             EXPECT_EQ(readback[y * w + x].A, 255) << x << " " << y;
3391         }
3392     }
3393 }
3394 
3395 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3396 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
3397 {
3398     constexpr int kSize = 16;
3399 
3400     // Create a simple framebuffer.
3401     GLTexture texture;
3402     glBindTexture(GL_TEXTURE_2D, texture);
3403     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3404 
3405     GLFramebuffer framebuffer;
3406     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3407     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3408     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3409 
3410     glViewport(0, 0, kSize, kSize);
3411 
3412     // Draw a solid red color to the framebuffer.
3413     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3414     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3415 
3416     // Delete the framebuffer while the call is in flight.
3417     framebuffer.reset();
3418 
3419     // Make a new framebuffer so we can read back the texture.
3420     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3421     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3422     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3423 
3424     // Flush via ReadPixels and check red was drawn.
3425     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3426     ASSERT_GL_NO_ERROR();
3427 }
3428 
3429 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3430 // buffers too early. The test has 2 textures, we first create a texture and update it with
3431 // multiple updates, but we don't use it right away, we instead draw using another texture
3432 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3433 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3434 {
3435     constexpr int kSize = 64;
3436 
3437     GLuint program = get2DTexturedQuadProgram();
3438     glUseProgram(program);
3439 
3440     std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3441     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3442     GLTexture texture1;
3443     glBindTexture(GL_TEXTURE_2D, texture1);
3444     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3445 
3446     for (int i = 0; i < 100; i++)
3447     {
3448         // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3449         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3450                         greenPixels.data());
3451     }
3452     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3453     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3454 
3455     ASSERT_GL_NO_ERROR();
3456 
3457     GLTexture texture2;
3458     glBindTexture(GL_TEXTURE_2D, texture2);
3459     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3460     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3461     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3462 
3463     // Setup the vertex array to draw a quad.
3464     GLint positionLocation = glGetAttribLocation(program, "position");
3465     setupQuadVertexBuffer(1.0f, 1.0f);
3466     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3467     glEnableVertexAttribArray(positionLocation);
3468 
3469     // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3470     glBindTexture(GL_TEXTURE_2D, texture2);
3471     glDrawArrays(GL_TRIANGLES, 0, 6);
3472     ASSERT_GL_NO_ERROR();
3473     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3474 
3475     // If we now try to draw with texture1, we should trigger the issue.
3476     glBindTexture(GL_TEXTURE_2D, texture1);
3477     glDrawArrays(GL_TRIANGLES, 0, 6);
3478     ASSERT_GL_NO_ERROR();
3479 
3480     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3481 }
3482 
3483 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3484 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3485 {
3486     constexpr int kSize = 16;
3487 
3488     // Create a simple framebuffer.
3489     GLTexture texture;
3490     glBindTexture(GL_TEXTURE_2D, texture);
3491     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3492 
3493     GLFramebuffer framebuffer;
3494     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3495     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3496     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3497 
3498     glViewport(0, 0, kSize, kSize);
3499 
3500     // Draw red to the framebuffer.
3501     simpleDrawWithColor(GLColor::red);
3502 
3503     // Change the framebuffer while the call is in flight to a new texture.
3504     GLTexture otherTexture;
3505     glBindTexture(GL_TEXTURE_2D, otherTexture);
3506     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3507 
3508     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3509     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3510 
3511     // Draw green to the framebuffer. Verify the color.
3512     simpleDrawWithColor(GLColor::green);
3513     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3514 
3515     // Make a new framebuffer so we can read back the first texture and verify red.
3516     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3517     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3518     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3519 
3520     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3521     ASSERT_GL_NO_ERROR();
3522 }
3523 
3524 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3525 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3526 {
3527     GLFramebuffer framebuffer;
3528     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3529 
3530     // Bind a simple 8x8 texture to the framebuffer, draw red.
3531     GLTexture texture;
3532     glBindTexture(GL_TEXTURE_2D, texture);
3533     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3534     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3535 
3536     glViewport(0, 0, 8, 8);
3537     simpleDrawWithColor(GLColor::red);
3538     ASSERT_GL_NO_ERROR();
3539     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3540 
3541     // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3542     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3543     glViewport(0, 0, 32, 32);
3544     simpleDrawWithColor(GLColor::green);
3545     ASSERT_GL_NO_ERROR();
3546     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3547 }
3548 
3549 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3550 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3551 {
3552     // Fails on 431.02 driver. http://anglebug.com/40644697
3553     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3554 
3555     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3556     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3557 
3558     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3559 
3560     GLTexture tex;
3561     glBindTexture(GL_TEXTURE_2D, tex);
3562     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3563     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3564     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3565     ASSERT_GL_NO_ERROR();
3566 
3567     GLFramebuffer fbo;
3568     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3569     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3570     ASSERT_GL_NO_ERROR();
3571     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3572 
3573     glUseProgram(program);
3574 
3575     GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3576     ASSERT_NE(-1, uniLoc);
3577     glUniform1i(uniLoc, 0);
3578 
3579     const int numRowsCols = 2;
3580     const int cellSize    = getWindowWidth() / 2;
3581 
3582     for (int cellY = 0; cellY < numRowsCols; cellY++)
3583     {
3584         for (int cellX = 0; cellX < numRowsCols; cellX++)
3585         {
3586             int seed            = cellX + cellY * numRowsCols;
3587             const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3588 
3589             // Set the texture to a constant color using glClear and a user FBO.
3590             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3591             glClearColor(color[0], color[1], color[2], color[3]);
3592             glClear(GL_COLOR_BUFFER_BIT);
3593 
3594             // Draw a small colored quad to the default FBO using the viewport.
3595             glBindFramebuffer(GL_FRAMEBUFFER, 0);
3596             glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3597             drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3598         }
3599     }
3600 
3601     // Verify the colored quads were drawn correctly despite no flushing.
3602     std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3603     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3604                  pixelData.data());
3605 
3606     ASSERT_GL_NO_ERROR();
3607 
3608     for (int cellY = 0; cellY < numRowsCols; cellY++)
3609     {
3610         for (int cellX = 0; cellX < numRowsCols; cellX++)
3611         {
3612             int seed            = cellX + cellY * numRowsCols;
3613             const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3614 
3615             GLColor expectedColor(color);
3616 
3617             int testN =
3618                 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3619             GLColor actualColor = pixelData[testN];
3620             EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3621         }
3622     }
3623 }
3624 
3625 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3626 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3627 {
3628     // Create a texture with red
3629     const GLColor kInitColor1 = GLColor::red;
3630     GLTexture texture1;
3631     glBindTexture(GL_TEXTURE_2D, texture1);
3632     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3633 
3634     // Create a framebuffer to be cleared
3635     GLTexture texture2;
3636     glBindTexture(GL_TEXTURE_2D, texture2);
3637     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3638 
3639     GLFramebuffer drawFBO;
3640     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3641     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3642     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3643 
3644     EXPECT_GL_NO_ERROR();
3645 
3646     // Clear the framebuffer to green
3647     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3648     glClear(GL_COLOR_BUFFER_BIT);
3649 
3650     // Clear again, but in a way that would be a no-op.  In the Vulkan backend, this will result in
3651     // a framebuffer sync state, which extracts deferred clears.  However, as the clear is actually
3652     // a noop, the deferred clears will remain unflushed.
3653     glClear(0);
3654 
3655     // Change framebuffer's attachment to the other texture.
3656     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3657     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3658 
3659     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3660     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3661     glUseProgram(program);
3662 
3663     glEnable(GL_BLEND);
3664     glBlendFunc(GL_ZERO, GL_ONE);
3665     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3666     EXPECT_GL_NO_ERROR();
3667 
3668     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3669     // to the new attachment, green will be read back.
3670     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3671 
3672     // Attach back to texture2.  It should be cleared to green.
3673     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3674     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3675 }
3676 
3677 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3678 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3679 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3680 {
3681     // Create a texture with red
3682     const GLColor kInitColor1 = GLColor::red;
3683     GLTexture texture1;
3684     glBindTexture(GL_TEXTURE_2D, texture1);
3685     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3686 
3687     // Create a framebuffer to be cleared
3688     GLTexture texture2;
3689     glBindTexture(GL_TEXTURE_2D, texture2);
3690     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3691 
3692     GLFramebuffer drawFBO;
3693     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3694     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3695     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3696 
3697     EXPECT_GL_NO_ERROR();
3698 
3699     // Clear the framebuffer to green
3700     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3701     glClear(GL_COLOR_BUFFER_BIT);
3702 
3703     // Clear again, but in a way that would be a no-op.  In the Vulkan backend, this will result in
3704     // a framebuffer sync state, which extracts deferred clears.  However, as the clear is actually
3705     // a noop, the deferred clears will remain unflushed.
3706     glEnable(GL_SCISSOR_TEST);
3707     glScissor(0, 0, 0, 0);
3708     glClear(GL_COLOR_BUFFER_BIT);
3709     glDisable(GL_SCISSOR_TEST);
3710 
3711     // Change framebuffer's attachment to the other texture.
3712     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3713     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3714 
3715     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3716     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3717     glUseProgram(program);
3718 
3719     glEnable(GL_BLEND);
3720     glBlendFunc(GL_ZERO, GL_ONE);
3721     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3722     EXPECT_GL_NO_ERROR();
3723 
3724     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3725     // to the new attachment, green will be read back.
3726     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3727 
3728     // Attach back to texture2.  It should be cleared to green.
3729     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3730     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3731 }
3732 
3733 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3734 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3735 {
3736     // Create a texture with red
3737     const GLColor kInitColor1 = GLColor::red;
3738     GLTexture texture1;
3739     glBindTexture(GL_TEXTURE_2D, texture1);
3740     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3741 
3742     // Create a framebuffer to be cleared
3743     GLTexture texture2;
3744     glBindTexture(GL_TEXTURE_2D, texture2);
3745     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3746 
3747     GLFramebuffer drawFBO;
3748     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3749     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3750     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3751 
3752     EXPECT_GL_NO_ERROR();
3753 
3754     // Clear the framebuffer to green
3755     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3756     glClear(GL_COLOR_BUFFER_BIT);
3757 
3758     // Issue noop blit.  In the Vulkan backend, this will result in a framebuffer sync state, which
3759     // extracts deferred clears.  However, as the blit is actually a noop, the deferred clears will
3760     // remain unflushed.
3761     GLTexture blitSrc;
3762     glBindTexture(GL_TEXTURE_2D, blitSrc);
3763     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3764 
3765     GLFramebuffer readFBO;
3766     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3767     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3768     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3769 
3770     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3771     EXPECT_GL_NO_ERROR();
3772 
3773     // Change framebuffer's attachment to the other texture.
3774     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3775     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3776 
3777     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3778     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3779     glUseProgram(program);
3780 
3781     glEnable(GL_BLEND);
3782     glBlendFunc(GL_ZERO, GL_ONE);
3783     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3784     EXPECT_GL_NO_ERROR();
3785 
3786     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3787     // to the new attachment, green will be read back.
3788     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3789     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3790 
3791     // Attach back to texture2.  It should be cleared to green.
3792     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3793     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3794 }
3795 
3796 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3797 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3798 {
3799     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3800     glUseProgram(program);
3801 
3802     glClear(GL_COLOR_BUFFER_BIT);
3803     glEnable(GL_CULL_FACE);
3804 
3805     glCullFace(GL_FRONT);
3806 
3807     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3808 
3809     ASSERT_GL_NO_ERROR();
3810 
3811     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3812 
3813     // Disable cull face and redraw, then make sure we have the quad drawn.
3814     glDisable(GL_CULL_FACE);
3815 
3816     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3817 
3818     ASSERT_GL_NO_ERROR();
3819 
3820     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3821 }
3822 
TEST_P(SimpleStateChangeTest,ScissorTest)3823 TEST_P(SimpleStateChangeTest, ScissorTest)
3824 {
3825     // This test validates this order of state changes:
3826     // 1- Set scissor but don't enable it, validate its not used.
3827     // 2- Enable it and validate its working.
3828     // 3- Disable the scissor validate its not used anymore.
3829 
3830     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3831 
3832     glClear(GL_COLOR_BUFFER_BIT);
3833 
3834     // Set the scissor region, but don't enable it yet.
3835     glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3836               getWindowHeight() / 2);
3837 
3838     // Fill the whole screen with a quad.
3839     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3840 
3841     ASSERT_GL_NO_ERROR();
3842 
3843     // Test outside, scissor isnt enabled so its red.
3844     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3845 
3846     // Test inside, red of the fragment shader.
3847     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3848 
3849     // Clear everything and start over with the test enabled.
3850     glClear(GL_COLOR_BUFFER_BIT);
3851     glEnable(GL_SCISSOR_TEST);
3852 
3853     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3854 
3855     ASSERT_GL_NO_ERROR();
3856 
3857     // Test outside the scissor test, pitch black.
3858     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3859 
3860     // Test inside, red of the fragment shader.
3861     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3862 
3863     // Now disable the scissor test, do it again, and verify the region isn't used
3864     // for the scissor test.
3865     glDisable(GL_SCISSOR_TEST);
3866 
3867     // Clear everything and start over with the test enabled.
3868     glClear(GL_COLOR_BUFFER_BIT);
3869 
3870     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3871 
3872     ASSERT_GL_NO_ERROR();
3873 
3874     // Test outside, scissor isnt enabled so its red.
3875     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3876 
3877     // Test inside, red of the fragment shader.
3878     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3879 }
3880 
3881 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3882 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3883 {
3884     constexpr char kPositionUniformVertexShader[] = R"(
3885 precision mediump float;
3886 attribute vec2 position;
3887 uniform vec2 uniPosModifier;
3888 void main()
3889 {
3890     gl_Position = vec4(position + uniPosModifier, 0, 1);
3891 })";
3892 
3893     ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3894     glUseProgram(program);
3895 
3896     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3897     glClear(GL_COLOR_BUFFER_BIT);
3898 
3899     GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3900     ASSERT_NE(posUniformLocation, -1);
3901     GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3902     ASSERT_NE(colorUniformLocation, -1);
3903 
3904     // draw a red quad to the left side.
3905     glUniform2f(posUniformLocation, -0.5, 0.0);
3906     glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3907     drawQuad(program, "position", 0.0f, 0.5f, true);
3908 
3909     // draw a green quad to the right side.
3910     glUniform2f(posUniformLocation, 0.5, 0.0);
3911     glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3912     drawQuad(program, "position", 0.0f, 0.5f, true);
3913 
3914     ASSERT_GL_NO_ERROR();
3915 
3916     // Test the center of the left quad. Should be red.
3917     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3918 
3919     // Test the center of the right quad. Should be green.
3920     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3921 }
3922 
3923 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3924 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3925 {
3926     GLRenderbuffer renderbuffer;
3927     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3928     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3929 
3930     GLFramebuffer framebuffer;
3931     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3932     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3933 
3934     ASSERT_GL_NO_ERROR();
3935     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3936 
3937     ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3938     GLint colorLoc = glGetAttribLocation(program, "color");
3939     ASSERT_NE(-1, colorLoc);
3940 
3941     // Set up and draw red to the left half the screen.
3942     std::vector<GLColor> redData(6, GLColor::red);
3943     GLBuffer vertexBufferRed;
3944     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3945     glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3946     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3947     glEnableVertexAttribArray(colorLoc);
3948 
3949     glViewport(0, 0, 16, 16);
3950     drawQuad(program, "position", 0.5f, 1.0f, true);
3951 
3952     // Immediately redefine the Renderbuffer.
3953     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3954 
3955     // Set up and draw green to the right half of the screen.
3956     std::vector<GLColor> greenData(6, GLColor::green);
3957     GLBuffer vertexBufferGreen;
3958     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3959     glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3960                  GL_STATIC_DRAW);
3961     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3962     glEnableVertexAttribArray(colorLoc);
3963 
3964     glViewport(0, 0, 64, 64);
3965     drawQuad(program, "position", 0.5f, 1.0f, true);
3966 
3967     ASSERT_GL_NO_ERROR();
3968     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3969 }
3970 
3971 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
3972 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)3973 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
3974 {
3975     constexpr size_t kSmallTextureSize = 2;
3976     constexpr size_t kBigTextureSize   = 4;
3977 
3978     // Create 2 textures, one of 2x2 and the other 4x4
3979     GLTexture texture1;
3980     glBindTexture(GL_TEXTURE_2D, texture1);
3981     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
3982                  GL_UNSIGNED_BYTE, nullptr);
3983     ASSERT_GL_NO_ERROR();
3984 
3985     GLTexture texture2;
3986     glBindTexture(GL_TEXTURE_2D, texture2);
3987     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
3988                  GL_UNSIGNED_BYTE, nullptr);
3989     ASSERT_GL_NO_ERROR();
3990 
3991     // A framebuffer for each texture to draw on.
3992     GLFramebuffer framebuffer1;
3993     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3994     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3995     ASSERT_GL_NO_ERROR();
3996     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3997 
3998     GLFramebuffer framebuffer2;
3999     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4000     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
4001     ASSERT_GL_NO_ERROR();
4002     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
4003 
4004     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4005     glUseProgram(program);
4006     GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4007     ASSERT_NE(uniformLocation, -1);
4008 
4009     // Bind to the first framebuffer for drawing.
4010     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
4011 
4012     // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
4013     // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
4014     glScissor(0, 0, 16, 16);
4015     ASSERT_GL_NO_ERROR();
4016 
4017     // Set color to red.
4018     glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
4019     glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
4020 
4021     // Draw a full sized red quad
4022     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4023     ASSERT_GL_NO_ERROR();
4024 
4025     // Bind to the second (bigger) framebuffer
4026     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
4027     glViewport(0, 0, kBigTextureSize, kBigTextureSize);
4028 
4029     ASSERT_GL_NO_ERROR();
4030 
4031     // Set color to green.
4032     glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
4033 
4034     // Draw again and we should fill everything with green and expect everything to be green.
4035     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
4036     ASSERT_GL_NO_ERROR();
4037 
4038     EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
4039 }
4040 
4041 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)4042 TEST_P(SimpleStateChangeTest, RelinkProgram)
4043 {
4044     // http://anglebug.com/40644706
4045     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
4046     const GLuint program = glCreateProgram();
4047 
4048     GLuint vs     = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
4049     GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
4050     GLuint redFs  = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
4051 
4052     glAttachShader(program, vs);
4053     glAttachShader(program, blueFs);
4054 
4055     glLinkProgram(program);
4056     CheckLinkStatusAndReturnProgram(program, true);
4057 
4058     glClear(GL_COLOR_BUFFER_BIT);
4059     std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
4060                                      {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
4061     GLBuffer vertexBuffer;
4062     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4063     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4064                  GL_STATIC_DRAW);
4065     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4066     ASSERT_NE(-1, positionLocation);
4067     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4068     glEnableVertexAttribArray(positionLocation);
4069 
4070     // Draw a blue triangle to the right
4071     glUseProgram(program);
4072     glDrawArrays(GL_TRIANGLES, 0, 3);
4073 
4074     // Relink to draw red to the left
4075     glDetachShader(program, blueFs);
4076     glAttachShader(program, redFs);
4077 
4078     glLinkProgram(program);
4079     CheckLinkStatusAndReturnProgram(program, true);
4080 
4081     glDrawArrays(GL_TRIANGLES, 3, 3);
4082 
4083     ASSERT_GL_NO_ERROR();
4084 
4085     glDisableVertexAttribArray(positionLocation);
4086 
4087     // Verify we drew red and green in the right places.
4088     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
4089     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
4090 
4091     glDeleteShader(vs);
4092     glDeleteShader(blueFs);
4093     glDeleteShader(redFs);
4094     glDeleteProgram(program);
4095 }
4096 
4097 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
4098 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)4099 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
4100 {
4101     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4102     glUseProgram(program);
4103 
4104     const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
4105     EXPECT_NE(-1, uniformLoc);
4106 
4107     // Set color to red.
4108     glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4109 
4110     glClear(GL_COLOR_BUFFER_BIT);
4111     std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
4112     GLBuffer vertexBuffer;
4113     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4114     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
4115                  GL_STATIC_DRAW);
4116     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
4117     ASSERT_NE(-1, positionLocation);
4118     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4119     glEnableVertexAttribArray(positionLocation);
4120 
4121     // Release program while its in use.
4122     glDeleteProgram(program);
4123 
4124     // Draw a red triangle
4125     glDrawArrays(GL_TRIANGLES, 0, 3);
4126 
4127     // Set color to green
4128     glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
4129 
4130     // Draw a green triangle
4131     glDrawArrays(GL_TRIANGLES, 0, 3);
4132 
4133     ASSERT_GL_NO_ERROR();
4134 
4135     glDisableVertexAttribArray(positionLocation);
4136 
4137     glUseProgram(0);
4138 
4139     // Verify we drew red in the end since thats the last draw.
4140     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
4141 }
4142 
4143 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)4144 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
4145 {
4146     // Create a sampler with NEAREST filtering.
4147     GLSampler sampler;
4148     glBindSampler(0, sampler);
4149     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4150     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4151     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4152     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4153     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4154     ASSERT_GL_NO_ERROR();
4155 
4156     // Draw with a program that uses no textures.
4157     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
4158     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
4159     ASSERT_GL_NO_ERROR();
4160     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4161 
4162     // Create a simple texture with four colors and linear filtering.
4163     constexpr GLsizei kSize       = 2;
4164     std::array<GLColor, 4> pixels = {
4165         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4166     GLTexture redTex;
4167     glBindTexture(GL_TEXTURE_2D, redTex);
4168     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4169                  pixels.data());
4170     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4171     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4172     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4173     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4174     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4175 
4176     // Create a program that uses the texture.
4177     constexpr char kVS[] = R"(attribute vec4 position;
4178 varying vec2 texCoord;
4179 void main()
4180 {
4181     gl_Position = position;
4182     texCoord = position.xy * 0.5 + vec2(0.5);
4183 })";
4184 
4185     constexpr char kFS[] = R"(precision mediump float;
4186 varying vec2 texCoord;
4187 uniform sampler2D tex;
4188 void main()
4189 {
4190     gl_FragColor = texture2D(tex, texCoord);
4191 })";
4192 
4193     // Draw. The sampler should override the clamp wrap mode with nearest.
4194     ANGLE_GL_PROGRAM(program2, kVS, kFS);
4195     ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
4196     drawQuad(program2, "position", 0.5f);
4197     ASSERT_GL_NO_ERROR();
4198 
4199     constexpr int kHalfSize = kWindowSize / 2;
4200 
4201     EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4202     EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4203     EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4204     EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4205 }
4206 
4207 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)4208 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
4209 {
4210     // Test overview - Create two separate sampler objects, initially with the same
4211     // sampling args (NEAREST). Bind the same texture object to separate texture units.
4212     // FS samples from two samplers and blends result.
4213     // Bind separate sampler objects to the same texture units as the texture object.
4214     // Render & verify initial results
4215     // Next modify sampler0 to have LINEAR filtering instead of NEAREST
4216     // Render and save results
4217     // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
4218     // Render and verify results are the same as previous
4219 
4220     // Create 2 samplers with NEAREST filtering.
4221     constexpr GLsizei kNumSamplers = 2;
4222     // We create/bind an extra sampler w/o bound tex object for testing purposes
4223     GLSampler samplers[kNumSamplers + 1];
4224     // Set samplers to initially have same state w/ NEAREST filter mode
4225     for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
4226     {
4227         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
4228         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4229         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4230         glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4231         glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4232         glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
4233         glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
4234         glBindSampler(i, samplers[i]);
4235         ASSERT_GL_NO_ERROR();
4236     }
4237 
4238     // Create a simple texture with four colors
4239     constexpr GLsizei kSize       = 2;
4240     std::array<GLColor, 4> pixels = {
4241         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4242     GLTexture rgbyTex;
4243     // Bind same texture object to tex units 0 & 1
4244     glActiveTexture(GL_TEXTURE0);
4245     glBindTexture(GL_TEXTURE_2D, rgbyTex);
4246     glActiveTexture(GL_TEXTURE1);
4247     glBindTexture(GL_TEXTURE_2D, rgbyTex);
4248     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
4249                  pixels.data());
4250 
4251     // Create a program that uses the texture with 2 separate samplers.
4252     constexpr char kFS[] = R"(precision mediump float;
4253 varying vec2 v_texCoord;
4254 uniform sampler2D samp1;
4255 uniform sampler2D samp2;
4256 void main()
4257 {
4258     gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
4259 })";
4260 
4261     // Create program and bind samplers to tex units 0 & 1
4262     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
4263     GLint s1loc = glGetUniformLocation(program, "samp1");
4264     GLint s2loc = glGetUniformLocation(program, "samp2");
4265     glUseProgram(program);
4266     glUniform1i(s1loc, 0);
4267     glUniform1i(s2loc, 1);
4268     // Draw. This first draw is a confidence check and not really necessary for the test
4269     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4270     ASSERT_GL_NO_ERROR();
4271 
4272     constexpr int kHalfSize = kWindowSize / 2;
4273 
4274     // When rendering w/ NEAREST, colors are all maxed out so should still be solid
4275     EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
4276     EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
4277     EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
4278     EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
4279 
4280     // Make first sampler use linear filtering
4281     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4282     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4283 
4284     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4285     ASSERT_GL_NO_ERROR();
4286     // Capture rendered pixel color with s0 linear
4287     std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
4288     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
4289 
4290     // Now restore first sampler & update second sampler
4291     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4292     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4293     glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4294     glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4295 
4296     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
4297     ASSERT_GL_NO_ERROR();
4298     // Capture rendered pixel color w/ s1 linear
4299     std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
4300     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
4301     // Results should be the same regardless of if s0 or s1 is linear
4302     EXPECT_EQ(s0LinearColors, s1LinearColors);
4303 }
4304 
4305 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)4306 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
4307 {
4308     constexpr char kVertexShader[] = R"(attribute vec4 a_position;
4309 attribute vec4 a_color;
4310 varying vec4 v_color;
4311 void main()
4312 {
4313     gl_Position = a_position;
4314     v_color = a_color;
4315 })";
4316 
4317     constexpr char kFragmentShader[] = R"(precision mediump float;
4318 varying vec4 v_color;
4319 void main()
4320 {
4321     gl_FragColor = v_color;
4322 })";
4323 
4324     ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
4325     GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
4326     ASSERT_NE(-1, positionLoc);
4327     GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
4328     ASSERT_NE(-1, colorLoc);
4329 
4330     GLVertexArray VAOS[2];
4331     GLBuffer positionBuffer;
4332     GLBuffer colorBuffer;
4333     const auto quadVertices = GetQuadVertices();
4334 
4335     glBindVertexArray(VAOS[0]);
4336     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4337     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4338                  GL_STATIC_DRAW);
4339     glEnableVertexAttribArray(positionLoc);
4340     glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4341 
4342     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4343     std::vector<GLColor32F> blueColor(6, kFloatBlue);
4344     glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4345                  GL_STATIC_DRAW);
4346     glEnableVertexAttribArray(colorLoc);
4347     glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4348 
4349     glBindVertexArray(0);
4350     glBindBuffer(GL_ARRAY_BUFFER, 0);
4351 
4352     glBindVertexArray(VAOS[1]);
4353     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4354     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4355                  GL_STATIC_DRAW);
4356     glEnableVertexAttribArray(positionLoc);
4357     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4358 
4359     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4360     std::vector<GLColor32F> greenColor(6, kFloatGreen);
4361     glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4362                  GL_STATIC_DRAW);
4363     glEnableVertexAttribArray(colorLoc);
4364     glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4365 
4366     glBindVertexArray(0);
4367     glBindBuffer(GL_ARRAY_BUFFER, 0);
4368 
4369     glUseProgram(mProgram);
4370     ASSERT_GL_NO_ERROR();
4371 
4372     glBindVertexArray(VAOS[1]);
4373     glClear(GL_COLOR_BUFFER_BIT);
4374     glDrawArrays(GL_TRIANGLES, 0, 6);
4375 
4376     // This drawing should not affect the next drawing.
4377     glBindVertexArray(VAOS[0]);
4378     glClear(GL_COLOR_BUFFER_BIT);
4379     glDrawArrays(GL_TRIANGLES, 0, 6);
4380 
4381     glBindVertexArray(VAOS[1]);
4382     glClear(GL_COLOR_BUFFER_BIT);
4383     glDrawArrays(GL_TRIANGLES, 0, 6);
4384 
4385     EXPECT_GL_NO_ERROR();
4386     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4387     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4388     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4389     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4390 
4391     ASSERT_GL_NO_ERROR();
4392 }
4393 
4394 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4395 // correctly.  This requires a memory barrier in between the draw calls which should not be
4396 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4397 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4398 {
4399     // http://anglebug.com/42264124
4400     ANGLE_SKIP_TEST_IF(IsD3D11());
4401 
4402     GLint maxFragmentImageUniforms;
4403     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4404 
4405     ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4406 
4407     // The test uses a GL_R32F framebuffer.
4408     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4409 
4410     constexpr GLsizei kSize = 1;
4411 
4412     GLTexture color;
4413     glBindTexture(GL_TEXTURE_2D, color);
4414     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4415     EXPECT_GL_NO_ERROR();
4416 
4417     GLFramebuffer fbo;
4418     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4419     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4420     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4421     EXPECT_GL_NO_ERROR();
4422 
4423     const float kInitialValue = 0.125f;
4424 
4425     GLTexture texture;
4426     glBindTexture(GL_TEXTURE_2D, texture);
4427     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4428     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4429     EXPECT_GL_NO_ERROR();
4430 
4431     GLFramebuffer readbackFbo;
4432     glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4433     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4434     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4435     EXPECT_GL_NO_ERROR();
4436 
4437     // Create a program that outputs to the image in the fragment shader.
4438     constexpr char kFS[] = R"(#version 310 es
4439 precision mediump float;
4440 layout(r32f, binding = 0) uniform highp image2D dst;
4441 out vec4 colorOut;
4442 void main()
4443 {
4444     vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4445     colorOut = result;
4446 
4447     result.x += 0.193;
4448     imageStore(dst, ivec2(gl_FragCoord.xy), result);
4449 })";
4450 
4451     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4452     glUseProgram(program);
4453 
4454     GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4455     ASSERT_NE(-1, positionLoc);
4456 
4457     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4458     EXPECT_GL_NO_ERROR();
4459 
4460     // Setup the draw so that there's no state change between the draw calls.
4461     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4462     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4463 
4464     GLBuffer posBuffer;
4465     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4466     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4467     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4468     glEnableVertexAttribArray(positionLoc);
4469     EXPECT_GL_NO_ERROR();
4470 
4471     glDrawArrays(GL_TRIANGLES, 0, 6);
4472     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4473     glDrawArrays(GL_TRIANGLES, 0, 6);
4474     EXPECT_GL_NO_ERROR();
4475 
4476     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4477     EXPECT_GL_NO_ERROR();
4478 
4479     // Verify the output of the two draw calls through the image is correct
4480     EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4481                                0.001f);
4482 
4483     // Verify the output of rendering as well
4484     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4485     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4486 }
4487 
4488 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4489 // draw call works correctly.  This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4490 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4491 {
4492     // http://anglebug.com/42264124
4493     ANGLE_SKIP_TEST_IF(IsD3D11());
4494     // http://anglebug.com/42264222
4495     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4496 
4497     GLint maxFragmentImageUniforms;
4498     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4499 
4500     ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4501 
4502     constexpr GLsizei kSize = 1;
4503 
4504     GLTexture color;
4505     glBindTexture(GL_TEXTURE_2D, color);
4506     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4507     EXPECT_GL_NO_ERROR();
4508 
4509     GLFramebuffer fbo;
4510     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4511     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4512     EXPECT_GL_NO_ERROR();
4513 
4514     const GLColor kInitialColor = GLColor::red;
4515 
4516     GLTexture texture;
4517     glBindTexture(GL_TEXTURE_2D, texture);
4518     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4519     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4520                     &kInitialColor);
4521     EXPECT_GL_NO_ERROR();
4522 
4523     GLFramebuffer readbackFbo;
4524     glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4525     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4526     EXPECT_GL_NO_ERROR();
4527 
4528     // Create a program that samples from the texture in the fragment shader.
4529     constexpr char kFSSample[] = R"(#version 310 es
4530 precision mediump float;
4531 uniform sampler2D tex;
4532 out vec4 colorOut;
4533 void main()
4534 {
4535     colorOut = texture(tex, vec2(0));
4536 })";
4537     ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4538 
4539     // Create a program that outputs to the image in the fragment shader.
4540     constexpr char kFSWrite[] = R"(#version 310 es
4541 precision mediump float;
4542 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4543 out vec4 colorOut;
4544 void main()
4545 {
4546     colorOut = vec4(0, 0, 1.0, 0);
4547     imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4548 })";
4549 
4550     ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4551 
4552     glUseProgram(sampleProgram);
4553     GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4554     ASSERT_NE(-1, positionLocSample);
4555 
4556     glUseProgram(writeProgram);
4557     GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4558     ASSERT_NE(-1, positionLocWrite);
4559 
4560     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4561 
4562     // Setup the draw so that there's no state change between the draw calls.
4563     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4564     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4565 
4566     GLBuffer posBuffer;
4567     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4568     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4569     glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4570     glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4571     glEnableVertexAttribArray(positionLocSample);
4572     glEnableVertexAttribArray(positionLocWrite);
4573 
4574     glUseProgram(sampleProgram);
4575     glDrawArrays(GL_TRIANGLES, 0, 6);
4576 
4577     glEnable(GL_BLEND);
4578     glBlendFunc(GL_ONE, GL_ONE);
4579     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4580 
4581     glUseProgram(writeProgram);
4582     glDrawArrays(GL_TRIANGLES, 0, 6);
4583 
4584     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4585     EXPECT_GL_NO_ERROR();
4586 
4587     // Verify the output of the two draw calls through the image is correct
4588     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4589 
4590     // Verify the output of rendering as well
4591     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4592     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4593 }
4594 
4595 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4596 // call works correctly.  This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4597 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4598 {
4599     GLint maxFragmentShaderStorageBlocks;
4600     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4601 
4602     ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4603 
4604     constexpr GLsizei kSize = 1;
4605 
4606     GLTexture color;
4607     glBindTexture(GL_TEXTURE_2D, color);
4608     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4609     EXPECT_GL_NO_ERROR();
4610 
4611     GLFramebuffer fbo;
4612     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4613     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4614     EXPECT_GL_NO_ERROR();
4615 
4616     constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4617     GLBuffer buffer;
4618     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4619     glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4620                  GL_STATIC_DRAW);
4621     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4622 
4623     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4624     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4625 
4626     // Create a program that reads from the ubo in the fragment shader.
4627     constexpr char kFSRead[] = R"(#version 310 es
4628 precision mediump float;
4629 uniform block { vec4 vec; } b;
4630 out vec4 colorOut;
4631 void main()
4632 {
4633     colorOut = b.vec;
4634 })";
4635     ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4636 
4637     // Create a program that outputs to the image in the fragment shader.
4638     constexpr char kFSWrite[] = R"(#version 310 es
4639 precision mediump float;
4640 layout(binding = 0, std430) buffer Output {
4641     vec4 vec;
4642 } b;
4643 out vec4 colorOut;
4644 void main()
4645 {
4646     b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4647     colorOut = vec4(0.125, 0.125, 0.125, 0);
4648 })";
4649 
4650     ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4651 
4652     glUseProgram(readProgram);
4653     GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4654     ASSERT_NE(-1, positionLocRead);
4655 
4656     glUseProgram(writeProgram);
4657     GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4658     ASSERT_NE(-1, positionLocWrite);
4659 
4660     // Setup the draw so that there's no state change between the draw calls.
4661     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4662     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4663 
4664     GLBuffer posBuffer;
4665     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4666     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4667     glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4668     glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4669     glEnableVertexAttribArray(positionLocRead);
4670     glEnableVertexAttribArray(positionLocWrite);
4671 
4672     glUseProgram(readProgram);
4673     glDrawArrays(GL_TRIANGLES, 0, 6);
4674 
4675     glEnable(GL_BLEND);
4676     glBlendFunc(GL_ONE, GL_ONE);
4677     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4678 
4679     glUseProgram(writeProgram);
4680     glDrawArrays(GL_TRIANGLES, 0, 6);
4681 
4682     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4683     EXPECT_GL_NO_ERROR();
4684 
4685     // Verify the output of rendering
4686     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4687 
4688     // Verify the output from the second draw call
4689     const float *ptr = reinterpret_cast<const float *>(
4690         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4691 
4692     EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4693     EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4694     EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4695     EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4696 
4697     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4698 }
4699 
4700 // Tests that writing to an SSBO in the fragment shader before and after a change to the drawbuffers
4701 // still works
TEST_P(SimpleStateChangeTestES31,FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4702 TEST_P(SimpleStateChangeTestES31, FragWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4703 {
4704     GLint maxFragmentShaderStorageBlocks;
4705     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4706 
4707     ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4708 
4709     constexpr GLsizei kSize = 1;
4710 
4711     GLTexture color;
4712     glBindTexture(GL_TEXTURE_2D, color);
4713     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4714     EXPECT_GL_NO_ERROR();
4715 
4716     GLFramebuffer fbo;
4717     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4718     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4719     EXPECT_GL_NO_ERROR();
4720 
4721     constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4722     GLBuffer buffer;
4723     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4724     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4725                  GL_STATIC_DRAW);
4726     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4727 
4728     // Create a program that writes to the SSBO in the fragment shader.
4729     constexpr char kFS[] = R"(#version 310 es
4730 precision mediump float;
4731 layout(binding = 0, std430) buffer Output {
4732     vec4 value;
4733 } b;
4734 out vec4 colorOut;
4735 uniform vec4 value;
4736 void main()
4737 {
4738     b.value = value;
4739     colorOut = vec4(1, 1, 1, 0);
4740 })";
4741 
4742     GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
4743     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
4744 
4745     const GLuint program = glCreateProgram();
4746     glAttachShader(program, vs);
4747     glAttachShader(program, fs);
4748     glLinkProgram(program);
4749     CheckLinkStatusAndReturnProgram(program, true);
4750 
4751     // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4752     glDetachShader(program, vs);
4753     glDetachShader(program, fs);
4754 
4755     glUseProgram(program);
4756     GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4757     ASSERT_NE(-1, positionLoc);
4758     GLint valueLoc = glGetUniformLocation(program, "value");
4759     ASSERT_NE(-1, valueLoc);
4760 
4761     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4762     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4763 
4764     GLBuffer posBuffer;
4765     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4766     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4767     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4768     glEnableVertexAttribArray(positionLoc);
4769 
4770     glUseProgram(program);
4771     constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4772 
4773     glUniform4fv(valueLoc, 1, kValue1);
4774     glDrawArrays(GL_TRIANGLES, 0, 6);
4775     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4776     EXPECT_GL_NO_ERROR();
4777 
4778     // Verify that the program wrote the SSBO correctly.
4779     const float *ptr = reinterpret_cast<const float *>(
4780         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4781 
4782     for (int i = 0; i < 4; ++i)
4783     {
4784         EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4785     }
4786 
4787     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4788 
4789     GLenum drawBuffers[] = {GL_NONE};
4790     glDrawBuffers(1, drawBuffers);
4791 
4792     constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4793     glUniform4fv(valueLoc, 1, kValue2);
4794     glDrawArrays(GL_TRIANGLES, 0, 6);
4795     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4796     EXPECT_GL_NO_ERROR();
4797     // Verify that the program wrote the SSBO correctly.
4798     ptr = reinterpret_cast<const float *>(
4799         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4800 
4801     for (int i = 0; i < 4; ++i)
4802     {
4803         EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4804     }
4805 
4806     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4807 }
4808 
4809 // Tests that writing to an SSBO in the vertex shader before and after a change to the drawbuffers
4810 // still works
TEST_P(SimpleStateChangeTestES31,VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)4811 TEST_P(SimpleStateChangeTestES31, VertWriteSSBOThenChangeDrawbuffersThenWriteSSBO)
4812 {
4813     GLint maxVertexShaderStorageBlocks;
4814     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
4815 
4816     ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks < 1);
4817 
4818     constexpr GLsizei kSize = 1;
4819 
4820     GLTexture color;
4821     glBindTexture(GL_TEXTURE_2D, color);
4822     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4823     EXPECT_GL_NO_ERROR();
4824 
4825     GLFramebuffer fbo;
4826     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4827     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4828     EXPECT_GL_NO_ERROR();
4829 
4830     constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4831     GLBuffer buffer;
4832     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4833     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4834                  GL_STATIC_DRAW);
4835     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4836 
4837     // Create a program that writes to the SSBO in the vertex shader.
4838     constexpr char kVS[] = R"(#version 310 es
4839 in vec4 a_position;
4840 uniform vec4 value;
4841 layout(binding = 0, std430) buffer Output {
4842     vec4 value;
4843 } b;
4844 void main()
4845 {
4846     b.value = value;
4847     gl_Position = a_position;
4848 })";
4849 
4850     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
4851     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, essl31_shaders::fs::Green());
4852 
4853     const GLuint program = glCreateProgram();
4854     glAttachShader(program, vs);
4855     glAttachShader(program, fs);
4856     glLinkProgram(program);
4857     CheckLinkStatusAndReturnProgram(program, true);
4858 
4859     // Detach the shaders, so any draw-time shader rewriting won't be able to use them.
4860     glDetachShader(program, vs);
4861     glDetachShader(program, fs);
4862 
4863     glUseProgram(program);
4864     GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4865     ASSERT_NE(-1, positionLoc);
4866     GLint valueLoc = glGetUniformLocation(program, "value");
4867     ASSERT_NE(-1, valueLoc);
4868 
4869     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4870     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4871 
4872     GLBuffer posBuffer;
4873     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4874     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4875     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4876     glEnableVertexAttribArray(positionLoc);
4877 
4878     glUseProgram(program);
4879     constexpr float kValue1[4] = {0.1f, 0.2f, 0.3f, 0.4f};
4880 
4881     glUniform4fv(valueLoc, 1, kValue1);
4882     glDrawArrays(GL_TRIANGLES, 0, 6);
4883     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4884     EXPECT_GL_NO_ERROR();
4885 
4886     // Verify that the program wrote the SSBO correctly.
4887     const float *ptr = reinterpret_cast<const float *>(
4888         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4889 
4890     for (int i = 0; i < 4; ++i)
4891     {
4892         EXPECT_NEAR(ptr[i], kValue1[i], 0.001);
4893     }
4894 
4895     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4896 
4897     GLenum drawBuffers[] = {GL_NONE};
4898     glDrawBuffers(1, drawBuffers);
4899 
4900     constexpr float kValue2[4] = {0.5f, 0.6f, 0.7f, 0.9f};
4901     glUniform4fv(valueLoc, 1, kValue2);
4902     glDrawArrays(GL_TRIANGLES, 0, 6);
4903     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4904     EXPECT_GL_NO_ERROR();
4905     // Verify that the program wrote the SSBO correctly.
4906     ptr = reinterpret_cast<const float *>(
4907         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4908 
4909     for (int i = 0; i < 4; ++i)
4910     {
4911         EXPECT_NEAR(ptr[i], kValue2[i], 0.001);
4912     }
4913 
4914     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4915 }
4916 
4917 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4918 // call works correctly.  This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4919 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4920 {
4921     // TODO(anglebug.com/42264185): Test is failing since it was introduced on Linux AMD GLES
4922     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4923 
4924     constexpr GLsizei kSize = 1;
4925     const GLColor kInitColor(111, 222, 33, 44);
4926 
4927     GLTexture color;
4928     glBindTexture(GL_TEXTURE_2D, color);
4929     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4930     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4931     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4932     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4933     EXPECT_GL_NO_ERROR();
4934 
4935     GLFramebuffer fbo;
4936     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4937     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4938     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4939     EXPECT_GL_NO_ERROR();
4940 
4941     constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4942     GLBuffer buffer;
4943     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4944     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4945                  GL_STATIC_DRAW);
4946     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4947     EXPECT_GL_NO_ERROR();
4948 
4949     ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4950 
4951     constexpr char kCS[] = R"(#version 310 es
4952 layout(local_size_x=1, local_size_y=1) in;
4953 uniform sampler2D tex;
4954 layout(binding = 0, std430) buffer Output {
4955     vec4 vec;
4956 } b;
4957 void main()
4958 {
4959     b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4960 })";
4961 
4962     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4963     glUseProgram(readProgram);
4964 
4965     glActiveTexture(GL_TEXTURE0);
4966     glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4967 
4968     drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
4969     EXPECT_GL_NO_ERROR();
4970 
4971     glUseProgram(readProgram);
4972     glDispatchCompute(1, 1, 1);
4973 
4974     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4975     EXPECT_GL_NO_ERROR();
4976 
4977     // Verify the output of rendering
4978     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4979 
4980     // Verify the output from the compute shader
4981     const float *ptr = reinterpret_cast<const float *>(
4982         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4983 
4984     EXPECT_EQ(ptr[0], 1.0f);
4985     EXPECT_EQ(ptr[1], 0.0f);
4986     EXPECT_EQ(ptr[2], 0.0f);
4987     EXPECT_EQ(ptr[3], 1.0f);
4988 
4989     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4990 }
4991 
4992 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
4993 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)4994 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
4995 {
4996     // http://anglebug.com/42264223
4997     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
4998 
4999     constexpr GLsizei kSize = 1;
5000 
5001     GLTexture color;
5002     glBindTexture(GL_TEXTURE_2D, color);
5003     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5004     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5005     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5006     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
5007     EXPECT_GL_NO_ERROR();
5008 
5009     GLFramebuffer fbo;
5010     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5011     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
5012     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5013     EXPECT_GL_NO_ERROR();
5014 
5015     // Make sure the update to the texture is effective.
5016     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5017 
5018     // Clear the texture through the framebuffer
5019     glClearColor(0, 1.0f, 0, 1.0f);
5020     glClear(GL_COLOR_BUFFER_BIT);
5021 
5022     constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
5023     GLBuffer buffer;
5024     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
5025     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
5026                  GL_STATIC_DRAW);
5027     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
5028     EXPECT_GL_NO_ERROR();
5029 
5030     constexpr char kCS[] = R"(#version 310 es
5031 layout(local_size_x=1, local_size_y=1) in;
5032 uniform sampler2D tex;
5033 layout(binding = 0, std430) buffer Output {
5034     vec4 vec;
5035 } b;
5036 void main()
5037 {
5038     b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
5039 })";
5040 
5041     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5042     glUseProgram(readProgram);
5043 
5044     glActiveTexture(GL_TEXTURE0);
5045     glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
5046 
5047     glUseProgram(readProgram);
5048     glDispatchCompute(1, 1, 1);
5049 
5050     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5051     EXPECT_GL_NO_ERROR();
5052 
5053     // Verify the clear
5054     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5055 
5056     // Verify the output from the compute shader
5057     const float *ptr = reinterpret_cast<const float *>(
5058         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
5059 
5060     EXPECT_EQ(ptr[0], 0.0f);
5061     EXPECT_EQ(ptr[1], 1.0f);
5062     EXPECT_EQ(ptr[2], 0.0f);
5063     EXPECT_EQ(ptr[3], 1.0f);
5064 
5065     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5066 }
5067 
5068 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
5069 // it in a dispatch call works correctly.  This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)5070 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
5071 {
5072     // http://anglebug.com/42264223
5073     ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
5074 
5075     constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
5076     GLBuffer buffer;
5077     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
5078     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
5079     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
5080 
5081     std::vector<std::string> tfVaryings = {"gl_Position"};
5082     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5083                                         essl3_shaders::fs::Green(), tfVaryings,
5084                                         GL_INTERLEAVED_ATTRIBS);
5085     glUseProgram(program);
5086 
5087     glBeginTransformFeedback(GL_TRIANGLES);
5088     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
5089     glEndTransformFeedback();
5090 
5091     constexpr char kCS[] = R"(#version 310 es
5092 layout(local_size_x=1, local_size_y=1) in;
5093 layout(binding = 0) uniform Input
5094 {
5095     vec4 data[3];
5096 };
5097 layout(binding = 0, std430) buffer Output {
5098     bool pass;
5099 };
5100 void main()
5101 {
5102     pass = data[0] == vec4(-1, 1, 0, 1) &&
5103            data[1] == vec4(-1, -1, 0, 1) &&
5104            data[2] == vec4(1, -1, 0, 1);
5105 })";
5106 
5107     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
5108     glUseProgram(readProgram);
5109 
5110     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
5111 
5112     constexpr GLsizei kResultSize = sizeof(uint32_t);
5113     GLBuffer resultBuffer;
5114     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5115     glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
5116     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
5117 
5118     glDispatchCompute(1, 1, 1);
5119 
5120     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5121     EXPECT_GL_NO_ERROR();
5122 
5123     // Verify the output of rendering
5124     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5125 
5126     // Verify the output from the compute shader
5127     const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
5128         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
5129 
5130     EXPECT_EQ(ptr[0], 1u);
5131 
5132     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5133 }
5134 
5135 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)5136 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
5137 {
5138     std::array<GLColor, 4> colors = {
5139         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5140     GLTexture texRead;
5141     glBindTexture(GL_TEXTURE_2D, texRead);
5142     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5143     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5144     EXPECT_GL_NO_ERROR();
5145 
5146     glUseProgram(mProgram);
5147 
5148     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5149     glDispatchCompute(1, 1, 1);
5150     texRead.reset();
5151 
5152     std::array<GLColor, 4> results;
5153     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5154     EXPECT_GL_NO_ERROR();
5155 
5156     for (int i = 0; i < 4; i++)
5157     {
5158         EXPECT_EQ(colors[i], results[i]);
5159     }
5160 }
5161 
5162 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)5163 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
5164 {
5165     std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5166     GLTexture texRead;
5167     glBindTexture(GL_TEXTURE_2D, texRead);
5168     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5169     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5170 
5171     glUseProgram(mProgram);
5172 
5173     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5174     glDispatchCompute(1, 1, 1);
5175 
5176     // Bind again
5177     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5178     glDispatchCompute(1, 1, 1);
5179     EXPECT_GL_NO_ERROR();
5180 
5181     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5182 }
5183 
5184 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
5185 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)5186 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
5187 {
5188     std::array<GLColor, 4> colors    = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
5189     std::array<GLColor, 4> subColors = {
5190         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
5191 
5192     GLTexture texRead;
5193     glBindTexture(GL_TEXTURE_2D, texRead);
5194     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5195     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5196 
5197     glUseProgram(mProgram);
5198 
5199     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5200     glDispatchCompute(1, 1, 1);
5201 
5202     // Update bottom-half of image texture with green.
5203     glBindTexture(GL_TEXTURE_2D, texRead);
5204     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
5205     ASSERT_GL_NO_ERROR();
5206 
5207     // Dispatch again, should still work.
5208     glDispatchCompute(1, 1, 1);
5209     ASSERT_GL_NO_ERROR();
5210 
5211     // Validate first half of the image is red and the bottom is green.
5212     std::array<GLColor, 4> results;
5213     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5214     EXPECT_GL_NO_ERROR();
5215 
5216     EXPECT_EQ(GLColor::green, results[0]);
5217     EXPECT_EQ(GLColor::green, results[1]);
5218     EXPECT_EQ(GLColor::red, results[2]);
5219     EXPECT_EQ(GLColor::red, results[3]);
5220 }
5221 
5222 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)5223 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
5224 {
5225     std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5226 
5227     GLTexture texRead;
5228     glBindTexture(GL_TEXTURE_2D, texRead);
5229     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5230     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
5231 
5232     glUseProgram(mProgram);
5233 
5234     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5235     glDispatchCompute(1, 1, 1);
5236 
5237     // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
5238     std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
5239     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
5240     ASSERT_GL_NO_ERROR();
5241 
5242     // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
5243     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5244     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
5245     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
5246     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
5247 
5248     // Dispatch again. The second dispatch call should use the updated YBGR data.
5249     glDispatchCompute(1, 1, 1);
5250 
5251     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
5252     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
5253     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
5254     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
5255     ASSERT_GL_NO_ERROR();
5256 }
5257 
5258 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)5259 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
5260 {
5261     std::array<GLColor, 4> colorsTexA = {
5262         {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
5263 
5264     std::array<GLColor, 4> colorsTexB = {
5265         {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
5266 
5267     GLTexture texA;
5268     glBindTexture(GL_TEXTURE_2D, texA);
5269     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5270     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
5271     GLTexture texB;
5272     glBindTexture(GL_TEXTURE_2D, texB);
5273     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5274     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
5275 
5276     glUseProgram(mProgram);
5277 
5278     glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5279     glDispatchCompute(1, 1, 1);
5280 
5281     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5282     glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5283     glDispatchCompute(1, 1, 1);
5284 
5285     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5286     glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5287     glDispatchCompute(1, 1, 1);
5288 
5289     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5290     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
5291     ASSERT_GL_NO_ERROR();
5292 }
5293 
5294 // Tests that glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) after draw works, where the render
5295 // pass is marked as closed.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenStorageWrite)5296 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenStorageWrite)
5297 {
5298     // Create a framebuffer for the purpose of switching FBOs
5299     GLTexture clearColor;
5300     glBindTexture(GL_TEXTURE_2D, clearColor);
5301     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5302 
5303     GLFramebuffer clearFBO;
5304     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, clearFBO);
5305     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, clearColor, 0);
5306     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5307     EXPECT_GL_NO_ERROR();
5308 
5309     constexpr char kCS[] = R"(#version 310 es
5310 layout(local_size_x=1, local_size_y=1) in;
5311 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5312 void main()
5313 {
5314     imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
5315 })";
5316 
5317     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
5318     glUseProgram(program);
5319     EXPECT_GL_NO_ERROR();
5320 
5321     // Create the framebuffer texture
5322     GLTexture renderTarget;
5323     glBindTexture(GL_TEXTURE_2D, renderTarget);
5324     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
5325     glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5326 
5327     // Write to the texture with compute once.  In the Vulkan backend, this will make sure the image
5328     // is already created with STORAGE usage and avoids recreate later.
5329     glDispatchCompute(1, 1, 1);
5330     EXPECT_GL_NO_ERROR();
5331 
5332     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5333 
5334     // Create the framebuffer for this texture
5335     GLFramebuffer drawFBO;
5336     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
5337     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
5338                            0);
5339     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
5340     EXPECT_GL_NO_ERROR();
5341 
5342     // Draw to this framebuffer to start a render pass
5343     ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
5344     drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
5345 
5346     // Change framebuffers and do a clear, making sure the old render pass is marked as closed.  In
5347     // the Vulkan backend, the clear is stashed, so the render pass is kept in the hopes of reviving
5348     // it later.
5349 
5350     glBindFramebuffer(GL_FRAMEBUFFER, clearFBO);
5351     glClear(GL_COLOR_BUFFER_BIT);
5352 
5353     // Issue a memory barrier before writing to the original image again.
5354     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5355 
5356     // Write to it with a compute shader
5357     glDispatchCompute(1, 1, 1);
5358     EXPECT_GL_NO_ERROR();
5359 
5360     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
5361 
5362     // Bind the original framebuffer and verify that the compute shader wrote the correct value.
5363     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
5364     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
5365 }
5366 
5367 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
5368 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)5369 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
5370 {
5371     ANGLE_SKIP_TEST_IF(!IsVulkan());
5372 
5373     glGenFramebuffers(1, &mFramebuffer);
5374     glGenTextures(1, &mTexture);
5375 
5376     glBindTexture(GL_TEXTURE_2D, mTexture);
5377     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5378     EXPECT_GL_NO_ERROR();
5379 
5380     constexpr char kCS[] = R"(#version 310 es
5381 layout(local_size_x=2, local_size_y=2) in;
5382 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
5383 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
5384 void main()
5385 {
5386 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
5387            imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
5388 })";
5389 
5390     bindProgramPipeline(kCS);
5391 
5392     glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
5393 
5394     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
5395     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
5396 
5397     ASSERT_GL_NO_ERROR();
5398 
5399     std::array<GLColor, 4> colors = {
5400         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5401     GLTexture texRead;
5402     glBindTexture(GL_TEXTURE_2D, texRead);
5403     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
5404     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5405     EXPECT_GL_NO_ERROR();
5406 
5407     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
5408     glDispatchCompute(1, 1, 1);
5409     texRead.reset();
5410 
5411     std::array<GLColor, 4> results;
5412     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
5413     EXPECT_GL_NO_ERROR();
5414 
5415     for (int i = 0; i < 4; i++)
5416     {
5417         EXPECT_EQ(colors[i], results[i]);
5418     }
5419 }
5420 
5421 static constexpr char kColorVS[] = R"(attribute vec2 position;
5422 attribute vec4 color;
5423 varying vec4 vColor;
5424 void main()
5425 {
5426     gl_Position = vec4(position, 0, 1);
5427     vColor = color;
5428 })";
5429 
5430 static constexpr char kColorFS[] = R"(precision mediump float;
5431 varying vec4 vColor;
5432 void main()
5433 {
5434     gl_FragColor = vColor;
5435 })";
5436 
5437 class ValidationStateChangeTest : public ANGLETest<>
5438 {
5439   protected:
ValidationStateChangeTest()5440     ValidationStateChangeTest()
5441     {
5442         setWindowWidth(64);
5443         setWindowHeight(64);
5444         setConfigRedBits(8);
5445         setConfigGreenBits(8);
5446         setConfigBlueBits(8);
5447         setConfigAlphaBits(8);
5448     }
5449 };
5450 
5451 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
5452 {
5453   protected:
WebGL2ValidationStateChangeTest()5454     WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5455 };
5456 
5457 class ValidationStateChangeTestES31 : public ANGLETest<>
5458 {};
5459 
5460 class WebGLComputeValidationStateChangeTest : public ANGLETest<>
5461 {
5462   public:
WebGLComputeValidationStateChangeTest()5463     WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
5464 };
5465 
5466 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
5467 {
5468   protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()5469     RobustBufferAccessWebGL2ValidationStateChangeTest()
5470     {
5471         // SwS/OSX GL do not support robustness. Mali does not support it.
5472         if (!isSwiftshader() && !IsMac() && !IsIOS() && !IsARM())
5473         {
5474             setRobustAccess(true);
5475         }
5476     }
5477 };
5478 
5479 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
5480 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)5481 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
5482 {
5483     // Initialize program and set up state.
5484     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5485 
5486     glUseProgram(program);
5487     GLint positionLoc = glGetAttribLocation(program, "position");
5488     ASSERT_NE(-1, positionLoc);
5489     GLint colorLoc = glGetAttribLocation(program, "color");
5490     ASSERT_NE(-1, colorLoc);
5491 
5492     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5493     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5494 
5495     GLBuffer posBuffer;
5496     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5497     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5498 
5499     // Start with position enabled.
5500     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5501     glEnableVertexAttribArray(positionLoc);
5502 
5503     std::vector<GLColor> colorVertices(6, GLColor::blue);
5504     const size_t colorBufferSize = sizeof(GLColor) * 6;
5505 
5506     GLBuffer colorBuffer;
5507     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5508     glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
5509 
5510     // Start with color disabled.
5511     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5512     glDisableVertexAttribArray(colorLoc);
5513 
5514     ASSERT_GL_NO_ERROR();
5515 
5516     // Draw without a mapped buffer. Should succeed.
5517     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5518     glDrawArrays(GL_TRIANGLES, 0, 6);
5519     ASSERT_GL_NO_ERROR();
5520     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5521 
5522     // Map position buffer and draw. Should fail.
5523     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5524     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
5525     ASSERT_GL_NO_ERROR();
5526 
5527     glDrawArrays(GL_TRIANGLES, 0, 6);
5528     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
5529     glUnmapBuffer(GL_ARRAY_BUFFER);
5530 
5531     // Map then enable color buffer. Should fail.
5532     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5533     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
5534     glEnableVertexAttribArray(colorLoc);
5535     ASSERT_GL_NO_ERROR();
5536 
5537     glDrawArrays(GL_TRIANGLES, 0, 6);
5538     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
5539 
5540     // Unmap then draw. Should succeed.
5541     glUnmapBuffer(GL_ARRAY_BUFFER);
5542     ASSERT_GL_NO_ERROR();
5543 
5544     glDrawArrays(GL_TRIANGLES, 0, 6);
5545     ASSERT_GL_NO_ERROR();
5546     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5547 }
5548 
5549 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
5550 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)5551 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
5552 {
5553     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5554 
5555     // Initialize program and set up state.
5556     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5557 
5558     glUseProgram(program);
5559     GLint positionLoc = glGetAttribLocation(program, "position");
5560     ASSERT_NE(-1, positionLoc);
5561     GLint colorLoc = glGetAttribLocation(program, "color");
5562     ASSERT_NE(-1, colorLoc);
5563 
5564     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5565     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5566 
5567     GLBuffer posBuffer;
5568     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5569     glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5570                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5571 
5572     // Start with position enabled.
5573     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5574     glEnableVertexAttribArray(positionLoc);
5575 
5576     std::vector<GLColor> colorVertices(6, GLColor::blue);
5577     const size_t colorBufferSize = sizeof(GLColor) * 6;
5578 
5579     GLBuffer colorBuffer;
5580     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5581     glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5582                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5583 
5584     // Start with color disabled.
5585     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5586     glDisableVertexAttribArray(colorLoc);
5587 
5588     ASSERT_GL_NO_ERROR();
5589 
5590     // Draw without a mapped buffer. Should succeed.
5591     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5592     glDrawArrays(GL_TRIANGLES, 0, 6);
5593     ASSERT_GL_NO_ERROR();
5594     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5595 
5596     // Map position buffer and draw. Should succeed.
5597     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5598     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5599                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5600     ASSERT_GL_NO_ERROR();
5601 
5602     glDrawArrays(GL_TRIANGLES, 0, 6);
5603     ASSERT_GL_NO_ERROR();
5604     glUnmapBuffer(GL_ARRAY_BUFFER);
5605 
5606     // Map then enable color buffer. Should succeed.
5607     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5608     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5609                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5610     glEnableVertexAttribArray(colorLoc);
5611     ASSERT_GL_NO_ERROR();
5612 
5613     glDrawArrays(GL_TRIANGLES, 0, 6);
5614     ASSERT_GL_NO_ERROR();
5615 
5616     // Unmap then draw. Should succeed.
5617     glUnmapBuffer(GL_ARRAY_BUFFER);
5618     ASSERT_GL_NO_ERROR();
5619 
5620     glDrawArrays(GL_TRIANGLES, 0, 6);
5621     ASSERT_GL_NO_ERROR();
5622     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5623 }
5624 
5625 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5626 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5627 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5628 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5629 {
5630     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5631 
5632     // Initialize program and set up state.
5633     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5634 
5635     glUseProgram(program);
5636     GLint positionLoc = glGetAttribLocation(program, "position");
5637     ASSERT_NE(-1, positionLoc);
5638     GLint colorLoc = glGetAttribLocation(program, "color");
5639     ASSERT_NE(-1, colorLoc);
5640 
5641     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5642     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5643 
5644     GLBuffer posBuffer;
5645     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5646     glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5647                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5648 
5649     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5650                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5651 
5652     // Start with position enabled.
5653     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5654     glEnableVertexAttribArray(positionLoc);
5655 
5656     std::vector<GLColor> colorVertices(6, GLColor::blue);
5657     const size_t colorBufferSize = sizeof(GLColor) * 6;
5658 
5659     GLBuffer colorBuffer;
5660     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5661     glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5662                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5663 
5664     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5665                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5666     ASSERT_GL_NO_ERROR();
5667 
5668     // Start with color disabled.
5669     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5670     glDisableVertexAttribArray(colorLoc);
5671 
5672     ASSERT_GL_NO_ERROR();
5673 
5674     // Draw without a mapped buffer. Should succeed.
5675     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5676     glDrawArrays(GL_TRIANGLES, 0, 6);
5677     ASSERT_GL_NO_ERROR();
5678     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5679 
5680     // Unmap then draw. Should succeed.
5681     glUnmapBuffer(GL_ARRAY_BUFFER);
5682     glEnableVertexAttribArray(colorLoc);
5683     ASSERT_GL_NO_ERROR();
5684     glDrawArrays(GL_TRIANGLES, 0, 6);
5685     ASSERT_GL_NO_ERROR();
5686     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5687 }
5688 
5689 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5690 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5691 {
5692     // Seems to trigger a GL error in some edge cases. http://anglebug.com/42261462
5693     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5694 
5695     // Initialize program and set up state.
5696     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5697 
5698     glUseProgram(program);
5699     GLint positionLoc = glGetAttribLocation(program, "position");
5700     ASSERT_NE(-1, positionLoc);
5701     GLint colorLoc = glGetAttribLocation(program, "color");
5702     ASSERT_NE(-1, colorLoc);
5703 
5704     // Create a user vertex array.
5705     GLVertexArray vao;
5706     glBindVertexArray(vao);
5707 
5708     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5709     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5710 
5711     GLBuffer posBuffer;
5712     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5713     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5714 
5715     // Start with position enabled.
5716     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5717     glEnableVertexAttribArray(positionLoc);
5718 
5719     std::vector<GLColor> blueVertices(6, GLColor::blue);
5720     const size_t blueBufferSize = sizeof(GLColor) * 6;
5721 
5722     GLBuffer blueBuffer;
5723     glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5724     glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5725 
5726     // Start with color enabled at an unused binding.
5727     constexpr GLint kUnusedBinding = 3;
5728     ASSERT_NE(colorLoc, kUnusedBinding);
5729     ASSERT_NE(positionLoc, kUnusedBinding);
5730     glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5731     glVertexAttribBinding(colorLoc, kUnusedBinding);
5732     glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5733     glEnableVertexAttribArray(colorLoc);
5734 
5735     // Make binding 'colorLoc' use a mapped buffer.
5736     std::vector<GLColor> greenVertices(6, GLColor::green);
5737     const size_t greenBufferSize = sizeof(GLColor) * 6;
5738     GLBuffer greenBuffer;
5739     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5740     glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5741     glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5742     glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5743 
5744     ASSERT_GL_NO_ERROR();
5745 
5746     // Draw without a mapped buffer. Should succeed.
5747     glDrawArrays(GL_TRIANGLES, 0, 6);
5748     ASSERT_GL_NO_ERROR();
5749     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5750 
5751     // Change divisor with VertexAttribDivisor. Should fail.
5752     glVertexAttribDivisor(colorLoc, 0);
5753     ASSERT_GL_NO_ERROR();
5754     glDrawArrays(GL_TRIANGLES, 0, 6);
5755     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5756 
5757     // Unmap the buffer. Should succeed.
5758     glUnmapBuffer(GL_ARRAY_BUFFER);
5759     glDrawArrays(GL_TRIANGLES, 0, 6);
5760     ASSERT_GL_NO_ERROR();
5761     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5762 }
5763 
5764 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5765 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5766 {
5767     // Initialize program and set up state.
5768     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5769 
5770     glUseProgram(program);
5771     GLint positionLoc = glGetAttribLocation(program, "position");
5772     ASSERT_NE(-1, positionLoc);
5773     GLint colorLoc = glGetAttribLocation(program, "color");
5774     ASSERT_NE(-1, colorLoc);
5775 
5776     // Create a user vertex array.
5777     GLVertexArray vao;
5778     glBindVertexArray(vao);
5779 
5780     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5781     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5782 
5783     GLBuffer posBuffer;
5784     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5785     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5786 
5787     // Start with position enabled.
5788     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5789     glEnableVertexAttribArray(positionLoc);
5790 
5791     std::vector<GLColor> blueVertices(6, GLColor::blue);
5792     const size_t blueBufferSize = sizeof(GLColor) * 6;
5793 
5794     GLBuffer blueBuffer;
5795     glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5796     glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5797 
5798     // Start with color enabled at an unused binding.
5799     constexpr GLint kUnusedBinding = 3;
5800     ASSERT_NE(colorLoc, kUnusedBinding);
5801     ASSERT_NE(positionLoc, kUnusedBinding);
5802     glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5803     glVertexAttribBinding(colorLoc, kUnusedBinding);
5804     glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5805     glEnableVertexAttribArray(colorLoc);
5806 
5807     // Make binding 'colorLoc' use a small buffer.
5808     std::vector<GLColor> greenVertices(6, GLColor::green);
5809     const size_t greenBufferSize = sizeof(GLColor) * 3;
5810     GLBuffer greenBuffer;
5811     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5812     glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5813     glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5814 
5815     ASSERT_GL_NO_ERROR();
5816 
5817     // Draw without a mapped buffer. Should succeed.
5818     glDrawArrays(GL_TRIANGLES, 0, 6);
5819     ASSERT_GL_NO_ERROR();
5820     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5821 
5822     // Change divisor with VertexAttribDivisor. Should fail.
5823     glVertexAttribDivisor(colorLoc, 0);
5824     ASSERT_GL_NO_ERROR();
5825     glDrawArrays(GL_TRIANGLES, 0, 6);
5826     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5827 
5828     // Do a small draw. Should succeed.
5829     glDrawArrays(GL_TRIANGLES, 0, 3);
5830     ASSERT_GL_NO_ERROR();
5831     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5832 }
5833 
5834 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5835 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5836 {
5837     constexpr char kVS[] = R"(#version 300 es
5838 in vec2 position;
5839 void main()
5840 {
5841     gl_Position = vec4(position, 0, 1);
5842 })";
5843 
5844     constexpr char kFS[] = R"(#version 300 es
5845 precision mediump float;
5846 uniform uni { vec4 vec; };
5847 out vec4 color;
5848 void main()
5849 {
5850     color = vec;
5851 })";
5852 
5853     ANGLE_GL_PROGRAM(program, kVS, kFS);
5854     glUseProgram(program);
5855 
5856     GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5857     ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5858 
5859     glUniformBlockBinding(program, blockIndex, 0);
5860 
5861     GLBuffer uniformBuffer;
5862     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5863     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5864     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5865 
5866     const auto &quadVertices = GetQuadVertices();
5867 
5868     GLBuffer positionBuffer;
5869     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5870     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5871                  GL_STATIC_DRAW);
5872 
5873     GLint positionLocation = glGetAttribLocation(program, "position");
5874     ASSERT_NE(-1, positionLocation);
5875 
5876     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5877     glEnableVertexAttribArray(positionLocation);
5878     ASSERT_GL_NO_ERROR();
5879 
5880     // First draw should succeed.
5881     glDrawArrays(GL_TRIANGLES, 0, 6);
5882     ASSERT_GL_NO_ERROR();
5883     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5884 
5885     // Change the uniform block binding. Should fail.
5886     glUniformBlockBinding(program, blockIndex, 1);
5887     ASSERT_GL_NO_ERROR();
5888     glDrawArrays(GL_TRIANGLES, 0, 6);
5889     ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5890 
5891     // Reset to a correct state.
5892     glUniformBlockBinding(program, blockIndex, 0);
5893     glDrawArrays(GL_TRIANGLES, 0, 6);
5894     ASSERT_GL_NO_ERROR();
5895     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5896 
5897     // Change the buffer binding. Should fail.
5898     glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5899     ASSERT_GL_NO_ERROR();
5900     glDrawArrays(GL_TRIANGLES, 0, 6);
5901     ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5902 
5903     // Reset to a correct state.
5904     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5905     glDrawArrays(GL_TRIANGLES, 0, 6);
5906     ASSERT_GL_NO_ERROR();
5907     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5908 
5909     // Resize the buffer to be too small. Should fail.
5910     glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5911     glDrawArrays(GL_TRIANGLES, 0, 6);
5912     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5913 }
5914 
5915 // Tests that redefining attachment storage updates the component type mask
TEST_P(WebGL2ValidationStateChangeTest,AttachmentTypeRedefinition)5916 TEST_P(WebGL2ValidationStateChangeTest, AttachmentTypeRedefinition)
5917 {
5918     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
5919 
5920     GLFramebuffer fb;
5921     glBindFramebuffer(GL_FRAMEBUFFER, fb);
5922 
5923     GLRenderbuffer rb;
5924     glBindRenderbuffer(GL_RENDERBUFFER, rb);
5925     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
5926 
5927     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, 4, 4);
5928     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5929     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5930 
5931     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 4, 4);
5932     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5933     EXPECT_GL_NO_ERROR();
5934     EXPECT_PIXEL_RECT_EQ(0, 0, 4, 4, GLColor::green);
5935 
5936     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8UI, 4, 4);
5937     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
5938     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5939 }
5940 
5941 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5942 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5943 {
5944     // Set up a simple draw from a Texture to a user Framebuffer.
5945     GLuint program = get2DTexturedQuadProgram();
5946     ASSERT_NE(0u, program);
5947     glUseProgram(program);
5948 
5949     GLint posLoc = glGetAttribLocation(program, "position");
5950     ASSERT_NE(-1, posLoc);
5951 
5952     const auto &quadVertices = GetQuadVertices();
5953 
5954     GLBuffer positionBuffer;
5955     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5956     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5957                  GL_STATIC_DRAW);
5958 
5959     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5960     glEnableVertexAttribArray(posLoc);
5961 
5962     constexpr size_t kSize = 2;
5963 
5964     GLTexture colorBufferTexture;
5965     glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5966     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5967     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5968     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5969 
5970     GLFramebuffer framebuffer;
5971     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5972     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5973                            0);
5974     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5975 
5976     std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
5977 
5978     GLTexture greenTexture;
5979     glBindTexture(GL_TEXTURE_2D, greenTexture);
5980     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5981                  greenColor.data());
5982     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5983     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5984 
5985     // Second framebuffer with a feedback loop. Initially unbound.
5986     GLFramebuffer loopedFramebuffer;
5987     glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5988     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
5989     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5990     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5991 
5992     ASSERT_GL_NO_ERROR();
5993 
5994     glDrawArrays(GL_TRIANGLES, 0, 6);
5995     ASSERT_GL_NO_ERROR();
5996     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5997 
5998     // Create a rendering feedback loop. Should fail.
5999     glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
6000     ASSERT_GL_NO_ERROR();
6001     glDrawArrays(GL_TRIANGLES, 0, 6);
6002     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6003 
6004     // Reset to a valid state.
6005     glBindTexture(GL_TEXTURE_2D, greenTexture);
6006     glDrawArrays(GL_TRIANGLES, 0, 6);
6007     ASSERT_GL_NO_ERROR();
6008     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6009 
6010     // Bind a second framebuffer with a feedback loop.
6011     glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
6012     ASSERT_GL_NO_ERROR();
6013     glDrawArrays(GL_TRIANGLES, 0, 6);
6014     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6015 
6016     // Update the framebuffer texture attachment. Should succeed.
6017     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
6018                            0);
6019     glDrawArrays(GL_TRIANGLES, 0, 6);
6020     ASSERT_GL_NO_ERROR();
6021     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6022 }
6023 
6024 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)6025 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
6026 {
6027     // Crashes on 64-bit Android.  http://anglebug.com/42262522
6028     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
6029 
6030     // Set up a program that writes to two outputs: one int and one float.
6031     constexpr char kVS[] = R"(#version 300 es
6032 layout(location = 0) in vec2 position;
6033 out vec2 texCoord;
6034 void main()
6035 {
6036     gl_Position = vec4(position, 0, 1);
6037     texCoord = position * 0.5 + vec2(0.5);
6038 })";
6039 
6040     constexpr char kFS[] = R"(#version 300 es
6041 precision mediump float;
6042 in vec2 texCoord;
6043 layout(location = 0) out vec4 outFloat;
6044 layout(location = 1) out uvec4 outInt;
6045 void main()
6046 {
6047     outFloat = vec4(0, 1, 0, 1);
6048     outInt = uvec4(0, 1, 0, 1);
6049 })";
6050 
6051     ANGLE_GL_PROGRAM(program, kVS, kFS);
6052     glUseProgram(program);
6053 
6054     constexpr GLint kPosLoc = 0;
6055 
6056     const auto &quadVertices = GetQuadVertices();
6057 
6058     GLBuffer positionBuffer;
6059     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
6060     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
6061                  GL_STATIC_DRAW);
6062 
6063     glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6064     glEnableVertexAttribArray(kPosLoc);
6065 
6066     constexpr size_t kSize = 2;
6067 
6068     GLFramebuffer floatFramebuffer;
6069     glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6070 
6071     GLTexture floatTextures[2];
6072     for (int i = 0; i < 2; ++i)
6073     {
6074         glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
6075         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6076                      nullptr);
6077         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6078                                floatTextures[i], 0);
6079         ASSERT_GL_NO_ERROR();
6080     }
6081 
6082     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6083 
6084     GLFramebuffer intFramebuffer;
6085     glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6086 
6087     GLTexture intTextures[2];
6088     for (int i = 0; i < 2; ++i)
6089     {
6090         glBindTexture(GL_TEXTURE_2D, intTextures[i]);
6091         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
6092                      GL_UNSIGNED_BYTE, nullptr);
6093         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
6094                                intTextures[i], 0);
6095         ASSERT_GL_NO_ERROR();
6096     }
6097 
6098     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6099 
6100     ASSERT_GL_NO_ERROR();
6101 
6102     constexpr GLenum kColor0Enabled[]     = {GL_COLOR_ATTACHMENT0, GL_NONE};
6103     constexpr GLenum kColor1Enabled[]     = {GL_NONE, GL_COLOR_ATTACHMENT1};
6104     constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6105 
6106     // Draw float. Should work.
6107     glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
6108     glDrawBuffers(2, kColor0Enabled);
6109 
6110     glDrawArrays(GL_TRIANGLES, 0, 6);
6111     ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6112     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6113 
6114     // Set an invalid component write.
6115     glDrawBuffers(2, kColor0And1Enabled);
6116     ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
6117     glDrawArrays(GL_TRIANGLES, 0, 6);
6118     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6119     // Set all 4 channels of color mask to false. Validate success.
6120     glColorMask(false, false, false, false);
6121     glDrawArrays(GL_TRIANGLES, 0, 6);
6122     EXPECT_GL_NO_ERROR();
6123     glColorMask(false, true, false, false);
6124     glDrawArrays(GL_TRIANGLES, 0, 6);
6125     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6126     glColorMask(true, true, true, true);
6127     glDrawArrays(GL_TRIANGLES, 0, 6);
6128     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6129 
6130     // Restore state.
6131     glDrawBuffers(2, kColor0Enabled);
6132     glDrawArrays(GL_TRIANGLES, 0, 6);
6133     ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
6134     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6135 
6136     // Bind an invalid framebuffer. Validate failure.
6137     glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
6138     ASSERT_GL_NO_ERROR();
6139     glDrawArrays(GL_TRIANGLES, 0, 6);
6140     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
6141 
6142     // Set draw mask to a valid mask. Validate success.
6143     glDrawBuffers(2, kColor1Enabled);
6144     glDrawArrays(GL_TRIANGLES, 0, 6);
6145     ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
6146 }
6147 
6148 // Tests that switching the program properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,IncompatibleDrawFramebufferProgramSwitch)6149 TEST_P(WebGL2ValidationStateChangeTest, IncompatibleDrawFramebufferProgramSwitch)
6150 {
6151     constexpr char kFS0[] = R"(#version 300 es
6152 precision mediump float;
6153 in vec2 texCoord;
6154 out ivec4 color;
6155 void main()
6156 {
6157     color = ivec4(1, 0, 1, 1);
6158 })";
6159     ANGLE_GL_PROGRAM(programInt, essl3_shaders::vs::Simple(), kFS0);
6160 
6161     constexpr char kFS1[] = R"(#version 300 es
6162 precision mediump float;
6163 in vec2 texCoord;
6164 out vec4 color;
6165 void main()
6166 {
6167     color = vec4(0, 1, 0, 1);
6168 })";
6169     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS1);
6170 
6171     constexpr size_t kSize = 2;
6172 
6173     GLFramebuffer fb;
6174     glBindFramebuffer(GL_FRAMEBUFFER, fb);
6175 
6176     GLRenderbuffer rb;
6177     glBindRenderbuffer(GL_RENDERBUFFER, rb);
6178     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6179     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
6180 
6181     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6182 
6183     // Incompatible masked-out draw call
6184     // Implementations may internally disable render targets to avoid runtime failures
6185     glColorMask(false, false, false, false);
6186     drawQuad(programInt, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6187     ASSERT_GL_NO_ERROR();
6188 
6189     // Clear must not be affected
6190     glColorMask(true, true, true, true);
6191     glClearColor(1.0, 0.0, 0.0, 1.0);
6192     glClear(GL_COLOR_BUFFER_BIT);
6193     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::red);
6194 
6195     // Compatible draw call
6196     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6197     ASSERT_GL_NO_ERROR();
6198     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6199 }
6200 
6201 // Tests that updating the render target storage properly syncs the framebuffer implementation
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)6202 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentIncompatibleDrawFramebufferStorageUpdate)
6203 {
6204     constexpr char kFS[] = R"(#version 300 es
6205 precision mediump float;
6206 in vec2 texCoord;
6207 layout(location = 0) out ivec4 colorInt;
6208 layout(location = 1) out vec4 colorFloat;
6209 void main()
6210 {
6211     colorInt = ivec4(1, 0, 1, 1);
6212     colorFloat = vec4(0, 1, 0, 1);
6213 })";
6214 
6215     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6216 
6217     // Explicitly set the program here so that
6218     // drawQuad helpers do not switch it
6219     glUseProgram(program);
6220 
6221     constexpr size_t kSize = 2;
6222 
6223     GLFramebuffer fb;
6224     glBindFramebuffer(GL_FRAMEBUFFER, fb);
6225 
6226     GLRenderbuffer rb0;
6227     glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6228     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6229     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb0);
6230 
6231     GLRenderbuffer rb1;
6232     glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6233     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6234     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rb1);
6235 
6236     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
6237 
6238     constexpr GLenum bufs[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
6239     glDrawBuffers(2, bufs);
6240 
6241     // Incompatible masked-out draw call
6242     // Implementations may internally disable render targets to avoid runtime failures
6243     glColorMask(false, false, false, false);
6244     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6245     ASSERT_GL_NO_ERROR();
6246 
6247     // Redefine storage, swapping numeric types
6248     glBindRenderbuffer(GL_RENDERBUFFER, rb0);
6249     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8I, kSize, kSize);
6250     glBindRenderbuffer(GL_RENDERBUFFER, rb1);
6251     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
6252 
6253     // The same draw call should be valid now
6254     glColorMask(true, true, true, true);
6255     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
6256     ASSERT_GL_NO_ERROR();
6257 
6258     glReadBuffer(GL_COLOR_ATTACHMENT0);
6259     EXPECT_PIXEL_RECT32I_EQ(0, 0, kSize, kSize, GLColor32I(1, 0, 1, 1));
6260 
6261     glReadBuffer(GL_COLOR_ATTACHMENT1);
6262     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
6263 }
6264 
6265 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)6266 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
6267 {
6268     // TODO(anglebug.com/40096690) This fails after the upgrade to the 26.20.100.7870 driver.
6269     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
6270 
6271     constexpr char kFS[] = R"(#version 300 es
6272 precision mediump float;
6273 uniform block { vec4 color; };
6274 out vec4 colorOut;
6275 void main()
6276 {
6277     colorOut = color;
6278 })";
6279 
6280     std::vector<std::string> tfVaryings = {"gl_Position"};
6281     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
6282                                         GL_INTERLEAVED_ATTRIBS);
6283     glUseProgram(program);
6284 
6285     std::vector<Vector4> positionData;
6286     for (const Vector3 &quadVertex : GetQuadVertices())
6287     {
6288         positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6289     }
6290 
6291     GLBuffer arrayBuffer;
6292     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6293     glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6294                  GL_STATIC_DRAW);
6295 
6296     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6297     ASSERT_NE(-1, positionLoc);
6298 
6299     glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6300     glEnableVertexAttribArray(positionLoc);
6301 
6302     EXPECT_GL_NO_ERROR();
6303 
6304     // Set up transform feedback.
6305     GLTransformFeedback transformFeedback;
6306     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6307 
6308     constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6309 
6310     GLBuffer transformFeedbackBuffer;
6311     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6312     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6313     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6314 
6315     // Set up uniform buffer.
6316     GLBuffer uniformBuffer;
6317     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
6318     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
6319     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
6320 
6321     ASSERT_GL_NO_ERROR();
6322 
6323     // Do the draw operation. Should succeed.
6324     glBeginTransformFeedback(GL_TRIANGLES);
6325     glDrawArrays(GL_TRIANGLES, 0, 6);
6326     glEndTransformFeedback();
6327 
6328     ASSERT_GL_NO_ERROR();
6329     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6330 
6331     const GLvoid *mapPointer =
6332         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
6333     ASSERT_GL_NO_ERROR();
6334     ASSERT_NE(nullptr, mapPointer);
6335     const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
6336     std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
6337     EXPECT_EQ(positionData, actualData);
6338     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
6339 
6340     // Draw once to update validation cache.
6341     glBeginTransformFeedback(GL_TRIANGLES);
6342     glDrawArrays(GL_TRIANGLES, 0, 6);
6343 
6344     // Bind transform feedback buffer to another binding point. Should cause a conflict.
6345     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
6346     ASSERT_GL_NO_ERROR();
6347     glDrawArrays(GL_TRIANGLES, 0, 6);
6348     glEndTransformFeedback();
6349     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
6350 
6351     // Reset to valid state.
6352     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
6353     glBeginTransformFeedback(GL_TRIANGLES);
6354     glDrawArrays(GL_TRIANGLES, 0, 6);
6355     glEndTransformFeedback();
6356     ASSERT_GL_NO_ERROR();
6357 
6358     // Simultaneous non-vertex-array binding. Should fail.
6359     glBeginTransformFeedback(GL_TRIANGLES);
6360     glDrawArrays(GL_TRIANGLES, 0, 6);
6361     ASSERT_GL_NO_ERROR();
6362     glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
6363     ASSERT_GL_NO_ERROR();
6364     glDrawArrays(GL_TRIANGLES, 0, 6);
6365     glEndTransformFeedback();
6366     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
6367 }
6368 
6369 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)6370 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
6371 {
6372     // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
6373     // DEPTH_COMPONENT24 is emulated with D32_S8X24.  http://anglebug.com/42262525
6374     ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
6375 
6376     constexpr char kFS[] = R"(#version 300 es
6377 precision mediump float;
6378 uniform sampler2D sampler;
6379 out vec4 colorOut;
6380 void main()
6381 {
6382     colorOut = texture(sampler, vec2(0));
6383 })";
6384 
6385     std::vector<std::string> tfVaryings = {"gl_Position"};
6386     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6387     glUseProgram(program);
6388 
6389     std::array<GLColor, 4> colors = {
6390         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
6391 
6392     GLTexture tex;
6393     glBindTexture(GL_TEXTURE_2D, tex);
6394     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
6395 
6396     const auto &quadVertices = GetQuadVertices();
6397 
6398     GLBuffer arrayBuffer;
6399     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6400     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6401                  GL_STATIC_DRAW);
6402 
6403     GLint samplerLoc = glGetUniformLocation(program, "sampler");
6404     ASSERT_NE(-1, samplerLoc);
6405     glUniform1i(samplerLoc, 0);
6406 
6407     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6408     ASSERT_NE(-1, positionLoc);
6409     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6410     glEnableVertexAttribArray(positionLoc);
6411 
6412     ASSERT_GL_NO_ERROR();
6413 
6414     glDrawArrays(GL_TRIANGLES, 0, 6);
6415     ASSERT_GL_NO_ERROR();
6416 
6417     // TexImage2D should update the sampler format cache.
6418     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
6419                  colors.data());
6420     glDrawArrays(GL_TRIANGLES, 0, 6);
6421     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
6422 
6423     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
6424                  GL_UNSIGNED_INT, colors.data());
6425     glDrawArrays(GL_TRIANGLES, 0, 6);
6426     ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
6427 
6428     // TexParameteri should update the sampler format cache.
6429     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
6430     glDrawArrays(GL_TRIANGLES, 0, 6);
6431     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
6432 }
6433 
6434 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)6435 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
6436 {
6437     std::vector<std::string> tfVaryings = {"gl_Position"};
6438     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
6439                                         essl3_shaders::fs::Red(), tfVaryings,
6440                                         GL_INTERLEAVED_ATTRIBS);
6441     glUseProgram(program);
6442 
6443     std::vector<Vector4> positionData;
6444     for (const Vector3 &quadVertex : GetQuadVertices())
6445     {
6446         positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
6447     }
6448 
6449     GLBuffer arrayBuffer;
6450     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6451     glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
6452                  GL_STATIC_DRAW);
6453 
6454     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6455     ASSERT_NE(-1, positionLoc);
6456 
6457     glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
6458     glEnableVertexAttribArray(positionLoc);
6459 
6460     // Set up transform feedback.
6461     GLTransformFeedback transformFeedback;
6462     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6463 
6464     constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
6465 
6466     GLBuffer transformFeedbackBuffer;
6467     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
6468     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
6469     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
6470 
6471     GLTransformFeedback pointsXFB;
6472     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6473     GLBuffer pointsXFBBuffer;
6474     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
6475     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
6476     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
6477 
6478     // Begin TRIANGLES, switch to paused POINTS, should be valid.
6479     glBeginTransformFeedback(GL_POINTS);
6480     glPauseTransformFeedback();
6481     ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
6482 
6483     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6484     glBeginTransformFeedback(GL_TRIANGLES);
6485     glDrawArrays(GL_TRIANGLES, 0, 6);
6486     EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6487     glDrawArrays(GL_POINTS, 0, 6);
6488     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
6489     glDrawArrays(GL_LINES, 0, 6);
6490     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6491     glPauseTransformFeedback();
6492     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
6493     glResumeTransformFeedback();
6494     glDrawArrays(GL_POINTS, 0, 6);
6495     EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6496     glDrawArrays(GL_TRIANGLES, 0, 6);
6497     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
6498     glDrawArrays(GL_LINES, 0, 6);
6499     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
6500 
6501     glEndTransformFeedback();
6502     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
6503     glEndTransformFeedback();
6504     ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
6505 
6506     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
6507 
6508     glDrawArrays(GL_POINTS, 0, 6);
6509     EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
6510     glDrawArrays(GL_TRIANGLES, 0, 6);
6511     EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
6512     glDrawArrays(GL_LINES, 0, 6);
6513     EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
6514 }
6515 
6516 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)6517 TEST_P(ValidationStateChangeTest, TextureConflict)
6518 {
6519     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
6520 
6521     GLint maxTextures = 0;
6522     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
6523     ANGLE_SKIP_TEST_IF(maxTextures < 2);
6524 
6525     // Set up state.
6526     constexpr GLint kSize = 2;
6527 
6528     std::vector<GLColor> greenData(4, GLColor::green);
6529 
6530     GLTexture textureA;
6531     glBindTexture(GL_TEXTURE_2D, textureA);
6532     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6533                  greenData.data());
6534     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6535     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6536 
6537     glActiveTexture(GL_TEXTURE1);
6538 
6539     GLTexture textureB;
6540     glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
6541     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6542                  GL_UNSIGNED_BYTE, greenData.data());
6543     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6544                  GL_UNSIGNED_BYTE, greenData.data());
6545     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6546                  GL_UNSIGNED_BYTE, greenData.data());
6547     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6548                  GL_UNSIGNED_BYTE, greenData.data());
6549     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6550                  GL_UNSIGNED_BYTE, greenData.data());
6551     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
6552                  GL_UNSIGNED_BYTE, greenData.data());
6553     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6554     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6555 
6556     constexpr char kVS[] = R"(attribute vec2 position;
6557 varying mediump vec2 texCoord;
6558 void main()
6559 {
6560     gl_Position = vec4(position, 0, 1);
6561     texCoord = position * 0.5 + vec2(0.5);
6562 })";
6563 
6564     constexpr char kFS[] = R"(varying mediump vec2 texCoord;
6565 uniform sampler2D texA;
6566 uniform samplerCube texB;
6567 void main()
6568 {
6569     gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
6570 })";
6571 
6572     ANGLE_GL_PROGRAM(program, kVS, kFS);
6573     glUseProgram(program);
6574 
6575     const auto &quadVertices = GetQuadVertices();
6576 
6577     GLBuffer arrayBuffer;
6578     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6579     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
6580                  GL_STATIC_DRAW);
6581 
6582     GLint positionLoc = glGetAttribLocation(program, "position");
6583     ASSERT_NE(-1, positionLoc);
6584 
6585     GLint texALoc = glGetUniformLocation(program, "texA");
6586     ASSERT_NE(-1, texALoc);
6587 
6588     GLint texBLoc = glGetUniformLocation(program, "texB");
6589     ASSERT_NE(-1, texBLoc);
6590 
6591     glUniform1i(texALoc, 0);
6592     glUniform1i(texBLoc, 1);
6593 
6594     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6595     glEnableVertexAttribArray(positionLoc);
6596 
6597     ASSERT_GL_NO_ERROR();
6598 
6599     // First draw. Should succeed.
6600     glDrawArrays(GL_TRIANGLES, 0, 6);
6601     ASSERT_GL_NO_ERROR();
6602     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6603 
6604     // Second draw to ensure all state changes are flushed.
6605     glDrawArrays(GL_TRIANGLES, 0, 6);
6606     ASSERT_GL_NO_ERROR();
6607 
6608     // Make the uniform use an invalid texture binding.
6609     glUniform1i(texBLoc, 0);
6610     glDrawArrays(GL_TRIANGLES, 0, 6);
6611     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6612 }
6613 
6614 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)6615 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
6616 {
6617     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
6618     glUseProgram(program);
6619 
6620     std::array<GLushort, 6> quadIndices = GetQuadIndices();
6621     std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
6622 
6623     GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
6624 
6625     GLBuffer elementArrayBuffer;
6626     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6627     glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
6628 
6629     GLBuffer arrayBuffer;
6630     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6631     glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
6632                  quadVertices.data(), GL_STATIC_DRAW);
6633 
6634     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6635     ASSERT_NE(-1, positionLoc);
6636     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6637     glEnableVertexAttribArray(positionLoc);
6638 
6639     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6640     ASSERT_GL_NO_ERROR();
6641 
6642     void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
6643     ASSERT_NE(nullptr, ptr);
6644 
6645     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6646     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6647 
6648     glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
6649 
6650     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
6651     ASSERT_GL_NO_ERROR();
6652     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6653 }
6654 
6655 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)6656 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
6657 {
6658     constexpr char kFS[] =
6659         "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6660     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6661     glUseProgram(program);
6662     GLint loc = glGetUniformLocation(program, "us");
6663     ASSERT_EQ(0, loc);
6664 
6665     auto quadVertices = GetQuadVertices();
6666     GLint posLoc      = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6667     ASSERT_EQ(0, posLoc);
6668 
6669     GLBuffer buffer;
6670     glBindBuffer(GL_ARRAY_BUFFER, buffer);
6671     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6672                  quadVertices.data(), GL_STATIC_DRAW);
6673     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6674     glEnableVertexAttribArray(posLoc);
6675 
6676     constexpr size_t kSize = 2;
6677     std::vector<GLColor> red(kSize * kSize, GLColor::red);
6678 
6679     GLTexture tex;
6680     glBindTexture(GL_TEXTURE_2D, tex);
6681     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6682     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6683     glUniform1i(loc, 0);
6684 
6685     glDrawArrays(GL_TRIANGLES, 0, 3);
6686     ASSERT_GL_NO_ERROR();
6687     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6688 
6689     // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
6690     GLTexture tex2;
6691     glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
6692     tex2.reset();
6693 
6694     glDrawArrays(GL_TRIANGLES, 0, 3);
6695     ASSERT_GL_NO_ERROR();
6696     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6697 
6698     // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
6699     tex.reset();
6700 
6701     glDrawArrays(GL_TRIANGLES, 0, 3);
6702     ASSERT_GL_NO_ERROR();
6703     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6704 }
6705 
6706 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)6707 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
6708 {
6709     constexpr char kFS[] =
6710         "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
6711     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
6712     glUseProgram(program);
6713     GLint loc = glGetUniformLocation(program, "us");
6714     ASSERT_EQ(0, loc);
6715 
6716     auto quadVertices = GetQuadVertices();
6717     GLint posLoc      = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
6718     ASSERT_EQ(0, posLoc);
6719 
6720     GLBuffer buffer;
6721     glBindBuffer(GL_ARRAY_BUFFER, buffer);
6722     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
6723                  quadVertices.data(), GL_STATIC_DRAW);
6724     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
6725     glEnableVertexAttribArray(posLoc);
6726 
6727     constexpr size_t kSize = 2;
6728     std::vector<GLColor> red(kSize * kSize, GLColor::red);
6729 
6730     GLTexture tex;
6731     glBindTexture(GL_TEXTURE_2D, tex);
6732     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
6733     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6734     glUniform1i(loc, 1);
6735     tex.reset();
6736 
6737     glDrawArrays(GL_TRIANGLES, 0, 3);
6738     ASSERT_GL_NO_ERROR();
6739     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6740 }
6741 
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)6742 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
6743 {
6744     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6745     glBindTexture(GL_TEXTURE_2D, texture);
6746     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
6747                  GL_UNSIGNED_BYTE, nullptr);
6748     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6749     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6750     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6751     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6752 }
6753 
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6754 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6755 {
6756     // Render to an FBO
6757     GLFramebuffer fbo1;
6758     GLTexture texture1;
6759 
6760     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6761     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6762                      essl1_shaders::fs::Texture2D());
6763 
6764     bindTextureToFbo(fbo1, texture1);
6765 
6766     // Clear the surface FBO to initialize it to a known value
6767     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6768     glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
6769     glClear(GL_COLOR_BUFFER_BIT);
6770     ASSERT_GL_NO_ERROR();
6771     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6772     glFlush();
6773 
6774     // Draw to FBO 1 to initialize it to a known value
6775     glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6776 
6777     if (earlyFrontFaceDirty)
6778     {
6779         glEnable(GL_CULL_FACE);
6780         // Make sure we don't cull
6781         glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6782         glFrontFace(frontFace);
6783     }
6784     else
6785     {
6786         glDisable(GL_CULL_FACE);
6787     }
6788 
6789     glUseProgram(greenProgram);
6790     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6791     ASSERT_GL_NO_ERROR();
6792     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6793 
6794     // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6795     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6796     glBindTexture(GL_TEXTURE_2D, texture1);
6797 
6798     glCullFace(GL_BACK);
6799     if (!earlyFrontFaceDirty)
6800     {
6801         // Set the culling we want to test
6802         glEnable(GL_CULL_FACE);
6803         glFrontFace(frontFace);
6804     }
6805 
6806     glUseProgram(textureProgram);
6807     drawQuad(textureProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
6808     ASSERT_GL_NO_ERROR();
6809 
6810     if (frontFace == GL_CCW)
6811     {
6812         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6813     }
6814     else
6815     {
6816         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6817     }
6818 
6819     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6820     glBindTexture(GL_TEXTURE_2D, 0);
6821 }
6822 
6823 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6824 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6825 {
6826     drawToFboWithCulling(GL_CCW, true);
6827 }
6828 
6829 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6830 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6831 {
6832     drawToFboWithCulling(GL_CW, true);
6833 }
6834 
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6835 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6836 {
6837     drawToFboWithCulling(GL_CCW, false);
6838 }
6839 
6840 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6841 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6842 {
6843     drawToFboWithCulling(GL_CW, false);
6844 }
6845 
6846 // Test that vertex attribute translation is still kept after binding it to another buffer then
6847 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6848 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6849 {
6850     // http://anglebug.com/42263918
6851     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6852 
6853     constexpr char kVS[] = R"(attribute vec4 a_position;
6854 attribute float a_attrib;
6855 varying float v_attrib;
6856 void main()
6857 {
6858     v_attrib = a_attrib;
6859     gl_Position = a_position;
6860 })";
6861 
6862     constexpr char kFS[] = R"(precision mediump float;
6863 varying float v_attrib;
6864 void main()
6865 {
6866     gl_FragColor = vec4(v_attrib, 0, 0, 1);
6867 })";
6868 
6869     ANGLE_GL_PROGRAM(program, kVS, kFS);
6870     glBindAttribLocation(program, 0, "a_position");
6871     glBindAttribLocation(program, 1, "a_attrib");
6872     glLinkProgram(program);
6873     glUseProgram(program);
6874     ASSERT_GL_NO_ERROR();
6875 
6876     // Set up color data so red is drawn
6877     std::vector<GLushort> data(1000, 0xffff);
6878 
6879     GLBuffer redBuffer;
6880     glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6881     glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6882     // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6883     glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6884                           reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6885     glBindBuffer(GL_ARRAY_BUFFER, 0);
6886     glEnableVertexAttribArray(1);
6887 
6888     drawQuad(program, "a_position", 0.5f);
6889     // Verify red was drawn
6890     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6891 
6892     glClearColor(0, 1, 0, 1);
6893     glClear(GL_COLOR_BUFFER_BIT);
6894     // Verify that green was drawn
6895     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6896 
6897     // Bind black color buffer to the same attribute with zero offset
6898     std::vector<GLfloat> black(6, 0.0f);
6899     GLBuffer blackBuffer;
6900     glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6901     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6902     glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6903 
6904     drawQuad(program, "a_position", 0.5f);
6905     // Verify black was drawn
6906     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6907 
6908     // Rebind the old buffer & offset
6909     glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6910     // Use offset not multiple of 4 GLushorts
6911     glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6912                           reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6913 
6914     drawQuad(program, "a_position", 0.5f);
6915     // Verify red was drawn
6916     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6917 }
6918 
6919 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6920 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6921 {
6922     constexpr char kVS[] = R"(attribute vec4 a_position;
6923 varying float v_attrib;
6924 uniform float u_value;
6925 void main()
6926 {
6927     v_attrib = u_value;
6928     gl_Position = a_position;
6929 })";
6930 
6931     constexpr char kFS[] = R"(precision mediump float;
6932 varying float v_attrib;
6933 void main()
6934 {
6935     gl_FragColor = vec4(v_attrib, 0, 0, 1);
6936 })";
6937 
6938     ANGLE_GL_PROGRAM(program1, kVS, kFS);
6939     ANGLE_GL_PROGRAM(program2, kVS, kFS);
6940 
6941     // Don't use drawQuad so there's no state changes between the draw calls other than the program
6942     // binding.
6943 
6944     constexpr size_t kProgramCount = 2;
6945     GLuint programs[kProgramCount] = {program1, program2};
6946     for (size_t i = 0; i < kProgramCount; ++i)
6947     {
6948         glUseProgram(programs[i]);
6949         GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6950         ASSERT_NE(uniformLoc, -1);
6951 
6952         glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6953 
6954         // Ensure position is at location 0 in both programs.
6955         GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6956         ASSERT_EQ(positionLocation, 0);
6957     }
6958     ASSERT_GL_NO_ERROR();
6959 
6960     std::array<Vector3, 6> quadVertices = GetQuadVertices();
6961     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6962     glEnableVertexAttribArray(0);
6963 
6964     // Draw once with each so their uniforms are updated.
6965     // The first draw will clear the screen to 255, 0, 0, 255
6966     glUseProgram(program2);
6967     glDrawArrays(GL_TRIANGLES, 0, 6);
6968     // The second draw will clear the screen to 127, 0, 0, 255
6969     glUseProgram(program1);
6970     glDrawArrays(GL_TRIANGLES, 0, 6);
6971 
6972     // Draw with the previous program again, to make sure its default uniforms are bound again.
6973     glUseProgram(program2);
6974     glDrawArrays(GL_TRIANGLES, 0, 6);
6975 
6976     // Verify red was drawn
6977     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6978 }
6979 
6980 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
6981 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)6982 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
6983 {
6984     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6985 
6986     GLBuffer indexBuffer;
6987     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6988     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
6989     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
6990     ASSERT_GL_NO_ERROR();
6991 
6992     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6993 }
6994 
6995 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)6996 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
6997 {
6998     glClearColor(kFloatRed.R, kFloatRed.G, kFloatRed.B, kFloatRed.A);
6999     glClear(GL_COLOR_BUFFER_BIT);
7000     ASSERT_GL_NO_ERROR();
7001     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7002 
7003     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
7004     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7005 
7006     // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7007     glEnable(GL_RASTERIZER_DISCARD);
7008     glUseProgram(greenProgram);
7009     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7010     ASSERT_GL_NO_ERROR();
7011     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7012 
7013     // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
7014     glDisable(GL_RASTERIZER_DISCARD);
7015     glUseProgram(greenProgram);
7016     drawQuad(greenProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7017     ASSERT_GL_NO_ERROR();
7018     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7019 
7020     // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
7021     glEnable(GL_RASTERIZER_DISCARD);
7022     glUseProgram(blueProgram);
7023     drawQuad(blueProgram, std::string(essl1_shaders::PositionAttrib()), 0.0f);
7024     ASSERT_GL_NO_ERROR();
7025     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7026 }
7027 
7028 // Test that early return on binding the same texture is functional
TEST_P(SimpleStateChangeTestES3,BindingSameTexture)7029 TEST_P(SimpleStateChangeTestES3, BindingSameTexture)
7030 {
7031     // Create two 1x1 textures
7032     constexpr GLsizei kSize           = 2;
7033     std::array<GLColor, kSize> colors = {GLColor::yellow, GLColor::cyan};
7034 
7035     GLTexture tex[kSize];
7036     // Bind texture 0 and 1 to active textures 0 and 1 and set data
7037     glActiveTexture(GL_TEXTURE0);
7038     glBindTexture(GL_TEXTURE_2D, tex[0]);
7039     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[0].data());
7040 
7041     glActiveTexture(GL_TEXTURE1);
7042     glBindTexture(GL_TEXTURE_2D, tex[1]);
7043     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors[1].data());
7044 
7045     // Create simple program and query sampler location
7046     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
7047     ASSERT(program.valid());
7048     glUseProgram(program);
7049     GLint textureLocation = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
7050     ASSERT_NE(-1, textureLocation);
7051 
7052     // Draw using active texture 0.
7053     glActiveTexture(GL_TEXTURE0);
7054     glUniform1i(textureLocation, 0);
7055     glBindTexture(GL_TEXTURE_2D, tex[0]);
7056     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7057     ASSERT_GL_NO_ERROR();
7058     EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7059 
7060     // Draw using active texture 1.
7061     glActiveTexture(GL_TEXTURE1);
7062     glUniform1i(textureLocation, 1);
7063     glBindTexture(GL_TEXTURE_2D, tex[1]);
7064     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7065     ASSERT_GL_NO_ERROR();
7066     EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7067 
7068     // Rebind the same texture to texture unit 1 and expect same color
7069     glBindTexture(GL_TEXTURE_2D, tex[1]);
7070     glUniform1i(textureLocation, 1);
7071     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7072     ASSERT_GL_NO_ERROR();
7073     EXPECT_PIXEL_COLOR_EQ(0, 0, colors[1]);
7074 
7075     // Rebind the same texture to texture unit 0 and expect same color
7076     glActiveTexture(GL_TEXTURE0);
7077     glUniform1i(textureLocation, 0);
7078     glBindTexture(GL_TEXTURE_2D, tex[0]);
7079     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7080     ASSERT_GL_NO_ERROR();
7081     EXPECT_PIXEL_COLOR_EQ(0, 0, colors[0]);
7082 }
7083 
7084 // Test that early return on binding the same sampler is functional
TEST_P(SimpleStateChangeTestES3,BindingSameSampler)7085 TEST_P(SimpleStateChangeTestES3, BindingSameSampler)
7086 {
7087     // Create 2 samplers with different filtering.
7088     constexpr GLsizei kNumSamplers = 2;
7089     GLSampler samplers[kNumSamplers];
7090 
7091     // Init sampler0
7092     glBindSampler(0, samplers[0]);
7093     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7094     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7095     ASSERT_GL_NO_ERROR();
7096 
7097     // Init sampler1
7098     glBindSampler(1, samplers[1]);
7099     glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7100     glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7101     ASSERT_GL_NO_ERROR();
7102 
7103     // Create a simple 2x1 texture with black and white colors
7104     std::array<GLColor, 2> colors = {{GLColor::black, GLColor::white}};
7105 
7106     GLTexture tex;
7107     // Bind the same texture to texture units 0 and 1
7108     glActiveTexture(GL_TEXTURE0);
7109     glBindTexture(GL_TEXTURE_2D, tex);
7110     glActiveTexture(GL_TEXTURE1);
7111     glBindTexture(GL_TEXTURE_2D, tex);
7112     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
7113 
7114     // Create a program that uses 2 samplers.
7115     constexpr char kFS[] = R"(precision mediump float;
7116 varying vec2 v_texCoord;
7117 uniform sampler2D baseSampler;
7118 uniform sampler2D overrideSampler;
7119 void main()
7120 {
7121     gl_FragColor = texture2D(baseSampler, v_texCoord);
7122     gl_FragColor = texture2D(overrideSampler, v_texCoord);
7123 })";
7124     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
7125     glUseProgram(program);
7126     GLint baseSamplerLoc     = glGetUniformLocation(program, "baseSampler");
7127     GLint overrideSamplerLoc = glGetUniformLocation(program, "overrideSampler");
7128 
7129     // Bind samplers to texture units 0 and 1
7130     glBindSampler(0, samplers[0]);
7131     glBindSampler(1, samplers[1]);
7132     glUniform1i(baseSamplerLoc, 0);
7133     glUniform1i(overrideSamplerLoc, 1);
7134     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7135     ASSERT_GL_NO_ERROR();
7136     // A gradient should have been rendered since "overrideSampler" has linear filter,
7137     // we should not expect a solid black or white color.
7138     EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::black);
7139     EXPECT_NE(angle::ReadColor(getWindowWidth() / 2, getWindowHeight() / 2), GLColor::white);
7140 
7141     // Switch sampler bindings
7142     glBindSampler(1, samplers[0]);
7143     glBindSampler(0, samplers[1]);
7144     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7145     ASSERT_GL_NO_ERROR();
7146     // Now that "overrideSampler" has nearest filter expect solid colors.
7147     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7148     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7149 
7150     // Rebind the same samplers again and expect same output
7151     glBindSampler(1, samplers[0]);
7152     glBindSampler(0, samplers[1]);
7153     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
7154     ASSERT_GL_NO_ERROR();
7155     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7156     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::white);
7157 }
7158 
7159 // Test that early return on binding the same buffer is functional
TEST_P(SimpleStateChangeTestES3,BindingSameBuffer)7160 TEST_P(SimpleStateChangeTestES3, BindingSameBuffer)
7161 {
7162     GLushort indexData[] = {0, 1, 2, 3};
7163 
7164     GLBuffer elementArrayBuffer;
7165     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7166     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7167 
7168     ANGLE_GL_PROGRAM(program, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
7169     glUseProgram(program);
7170 
7171     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7172 
7173     std::vector<GLColor> colors0(kWindowSize * kWindowSize);
7174     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors0.data());
7175 
7176     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7177     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7178     std::vector<GLColor> colors1(kWindowSize * kWindowSize);
7179     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, colors1.data());
7180 
7181     EXPECT_EQ(colors0, colors1);
7182 }
7183 
7184 class ImageRespecificationTest : public ANGLETest<>
7185 {
7186   protected:
ImageRespecificationTest()7187     ImageRespecificationTest()
7188     {
7189         setWindowWidth(128);
7190         setWindowHeight(128);
7191         setConfigRedBits(8);
7192         setConfigGreenBits(8);
7193         setConfigBlueBits(8);
7194         setConfigAlphaBits(8);
7195         setConfigDepthBits(24);
7196     }
7197 
testSetUp()7198     void testSetUp() override
7199     {
7200         constexpr char kVS[] = R"(precision highp float;
7201 attribute vec4 position;
7202 varying vec2 texcoord;
7203 
7204 void main()
7205 {
7206     gl_Position = position;
7207     texcoord = (position.xy * 0.5) + 0.5;
7208 })";
7209 
7210         constexpr char kFS[] = R"(precision highp float;
7211 uniform sampler2D tex;
7212 varying vec2 texcoord;
7213 
7214 void main()
7215 {
7216     gl_FragColor = texture2D(tex, texcoord);
7217 })";
7218 
7219         mProgram = CompileProgram(kVS, kFS);
7220         ASSERT_NE(0u, mProgram);
7221 
7222         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
7223         ASSERT_NE(-1, mTextureUniformLocation);
7224 
7225         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7226         ASSERT_GL_NO_ERROR();
7227     }
7228 
testTearDown()7229     void testTearDown() override
7230     {
7231         if (mProgram != 0)
7232         {
7233             glDeleteProgram(mProgram);
7234         }
7235     }
7236 
7237     template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)7238     void init2DSourceTexture(GLenum internalFormat,
7239                              GLenum dataFormat,
7240                              GLenum dataType,
7241                              const T *data)
7242     {
7243         glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7244         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7245 
7246         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7247         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7248 
7249         glBindTexture(GL_TEXTURE_2D, 0);
7250     }
7251 
attachTargetTextureToFramebuffer()7252     void attachTargetTextureToFramebuffer()
7253     {
7254         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7255         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
7256                                0);
7257 
7258         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
7259         ASSERT_GL_NO_ERROR();
7260 
7261         glBindFramebuffer(GL_FRAMEBUFFER, 0);
7262     }
7263 
renderToTargetTexture()7264     void renderToTargetTexture()
7265     {
7266         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7267 
7268         glActiveTexture(GL_TEXTURE0);
7269         glBindTexture(GL_TEXTURE_2D, mSourceTexture);
7270 
7271         glUseProgram(mProgram);
7272         glUniform1i(mTextureUniformLocation, 0);
7273 
7274         drawQuad(mProgram, "position", 0.5f);
7275         ASSERT_GL_NO_ERROR();
7276 
7277         glBindFramebuffer(GL_FRAMEBUFFER, 0);
7278         glBindTexture(GL_TEXTURE_2D, 0);
7279         glUseProgram(0);
7280     }
7281 
renderToDefaultFramebuffer(GLColor * expectedData)7282     void renderToDefaultFramebuffer(GLColor *expectedData)
7283     {
7284         glBindFramebuffer(GL_FRAMEBUFFER, 0);
7285         glUseProgram(mProgram);
7286         glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7287         glUniform1i(mTextureUniformLocation, 0);
7288 
7289         glClear(GL_COLOR_BUFFER_BIT);
7290         drawQuad(mProgram, "position", 0.5f);
7291         ASSERT_GL_NO_ERROR();
7292 
7293         EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
7294 
7295         glBindTexture(GL_TEXTURE_2D, 0);
7296         glUseProgram(0);
7297     }
7298 
7299     GLuint mProgram;
7300     GLint mTextureUniformLocation;
7301 
7302     GLTexture mSourceTexture;
7303     GLTexture mTargetTexture;
7304 
7305     GLFramebuffer mFramebuffer;
7306 };
7307 
7308 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)7309 TEST_P(ImageRespecificationTest, Swizzle)
7310 {
7311     GLubyte data[] = {1, 64, 128, 200};
7312     GLColor expectedData(data[0], data[1], data[2], data[3]);
7313 
7314     // Create the source and target texture
7315     init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7316 
7317     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7318     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
7319 
7320     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7321     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7322 
7323     glBindTexture(GL_TEXTURE_2D, 0);
7324 
7325     // Create a framebuffer and the target texture is attached to the framebuffer.
7326     attachTargetTextureToFramebuffer();
7327 
7328     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7329     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7330     glClear(GL_COLOR_BUFFER_BIT);
7331     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7332 
7333     // Render content of source texture to target texture
7334     // This command triggers the creation of -
7335     //     - draw imageviews of the texture
7336     //     - VkFramebuffer object of the framebuffer
7337     renderToTargetTexture();
7338 
7339     // This swizzle operation should cause the read imageviews of the texture to be released
7340     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7341     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
7342     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
7343     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
7344     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
7345     glBindTexture(GL_TEXTURE_2D, 0);
7346 
7347     // Draw using the newly created read imageviews
7348     renderToDefaultFramebuffer(&expectedData);
7349 
7350     // Render content of source texture to target texture, again
7351     renderToTargetTexture();
7352 
7353     // Make sure the content rendered to target texture is correct
7354     renderToDefaultFramebuffer(&expectedData);
7355 }
7356 
7357 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
7358 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)7359 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
7360 {
7361     // This is the specific problem on the Vulkan backend and needs some extensions
7362     ANGLE_SKIP_TEST_IF(
7363         !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
7364         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
7365 
7366     GLubyte data[] = {1, 64, 128, 200};
7367     GLColor expectedData(data[0], data[1], data[2], data[3]);
7368 
7369     // Create the source texture
7370     init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
7371 
7372     // Create the first EGL image to attach the framebuffer through the texture
7373     GLTexture firstTexture;
7374 
7375     glBindTexture(GL_TEXTURE_2D, firstTexture);
7376     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7377 
7378     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7379     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7380 
7381     glBindTexture(GL_TEXTURE_2D, 0);
7382 
7383     EGLWindow *window = getEGLWindow();
7384     EGLint attribs[]  = {
7385         EGL_IMAGE_PRESERVED,
7386         EGL_TRUE,
7387         EGL_NONE,
7388     };
7389     EGLImageKHR firstEGLImage = eglCreateImageKHR(
7390         window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7391         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(firstTexture)), attribs);
7392     ASSERT_EGL_SUCCESS();
7393 
7394     // Create the target texture and attach it to the framebuffer
7395     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7396     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7397 
7398     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7399     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7400 
7401     glBindTexture(GL_TEXTURE_2D, 0);
7402 
7403     attachTargetTextureToFramebuffer();
7404 
7405     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7406 
7407     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
7408     glClear(GL_COLOR_BUFFER_BIT);
7409 
7410     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7411 
7412     // Render content of source texture to target texture
7413     // This command triggers the creation of -
7414     //     - draw imageviews of the texture
7415     //     - VkFramebuffer object of the framebuffer
7416     renderToTargetTexture();
7417 
7418     // Make sure the content rendered to target texture is correct
7419     renderToDefaultFramebuffer(&expectedData);
7420 
7421     // Create the second EGL image
7422     GLTexture secondTexture;
7423 
7424     glBindTexture(GL_TEXTURE_2D, secondTexture);
7425     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7426 
7427     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7428     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7429 
7430     glBindTexture(GL_TEXTURE_2D, 0);
7431 
7432     EGLImageKHR secondEGLImage = eglCreateImageKHR(
7433         window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7434         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(secondTexture)), attribs);
7435     ASSERT_EGL_SUCCESS();
7436 
7437     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7438     // This will release all the imageviews related to the first EGL image
7439     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
7440 
7441     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7442     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7443 
7444     glBindTexture(GL_TEXTURE_2D, 0);
7445 
7446     // Attach the first EGL image to the target texture again
7447     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
7448     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
7449 
7450     // This is for checking this code can deal with the problem even if both ORPHAN and
7451     // COLOR_ATTACHMENT dirty bits are set.
7452     GLTexture tempTexture;
7453 
7454     glBindTexture(GL_TEXTURE_2D, tempTexture);
7455     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
7456 
7457     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7458     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7459 
7460     glBindTexture(GL_TEXTURE_2D, 0);
7461 
7462     // This sets COLOR_ATTACHMENT dirty bit
7463     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
7464     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
7465     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7466 
7467     // The released imageviews related to "secondEGLImage" will be garbage collected
7468     renderToDefaultFramebuffer(&expectedData);
7469 
7470     // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
7471     renderToTargetTexture();
7472 
7473     // Make sure the content rendered to target texture is correct
7474     renderToDefaultFramebuffer(&expectedData);
7475 
7476     // Render content of source texture to target texture
7477     attachTargetTextureToFramebuffer();
7478     renderToTargetTexture();
7479 
7480     // Make sure the content rendered to target texture is correct
7481     renderToDefaultFramebuffer(&expectedData);
7482 
7483     eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
7484     eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
7485 }
7486 
7487 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)7488 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
7489 {
7490     GLushort indexData[] = {0, 1, 2, 3};
7491 
7492     GLBuffer elementArrayBuffer;
7493     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
7494     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
7495 
7496     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7497     glUseProgram(program);
7498 
7499     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
7500 
7501     elementArrayBuffer.reset();
7502 
7503     // Must use a non-0 offset and a multiple of the type size.
7504     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
7505     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7506 }
7507 
7508 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)7509 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
7510 {
7511     // SwiftShader does not currently support robustness.
7512     ANGLE_SKIP_TEST_IF(isSwiftshader());
7513 
7514     // http://anglebug.com/42263447
7515     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
7516 
7517     // no intent to follow up on this failure.
7518     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
7519 
7520     // no intent to follow up on this failure.
7521     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
7522 
7523     // no intent to follow up on this failure.
7524     ANGLE_SKIP_TEST_IF(IsMac());
7525 
7526     // Mali does not support robustness now.
7527     ANGLE_SKIP_TEST_IF(IsARM());
7528 
7529     std::vector<GLubyte> data(48, 1);
7530 
7531     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
7532     glUseProgram(program);
7533 
7534     // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
7535     GLBuffer arrayBuffer;
7536     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
7537     glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
7538     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
7539     glEnableVertexAttribArray(0);
7540     glDrawArrays(GL_TRIANGLES, 0, 3);
7541 
7542     // Then bind a zero size buffer and draw.
7543     GLBuffer secondBuffer;
7544     glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
7545     glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
7546     glDrawArrays(GL_TRIANGLES, 0, 3);
7547 
7548     // Finally delete the original buffer. This triggers the bug.
7549     arrayBuffer.reset();
7550     glDrawArrays(GL_TRIANGLES, 0, 3);
7551     ASSERT_GL_NO_ERROR();
7552 }
7553 
7554 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)7555 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
7556 {
7557     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7558 
7559     glUseProgram(program);
7560 
7561     // Draw with empty buffer. Out of range but valid.
7562     GLBuffer buffer;
7563     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7564     glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
7565 
7566     // Switch VAO. No buffer bound, should be an error.
7567     GLVertexArray vao;
7568     glBindVertexArray(vao);
7569     glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
7570                    reinterpret_cast<const GLvoid *>(0x1000));
7571     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7572 }
7573 
7574 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
7575 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)7576 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
7577 {
7578     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
7579     // bit.
7580     GLBuffer indexBuffer;
7581     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7582 
7583     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7584     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7585 
7586     // Setup vertices.
7587     const std::array<GLfloat, 6> kVertices = {
7588         -1, -1, 3, -1, -1, 3,
7589     };
7590     GLBuffer vertexBuffer;
7591     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7592     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7593     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7594     glEnableVertexAttribArray(0);
7595 
7596     // Create a uniform buffer that will get modified.  This is used to break the render pass.
7597     const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
7598 
7599     GLBuffer ubo;
7600     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
7601     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
7602     glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
7603 
7604     // Set up a program.  The same program is used for all draw calls to avoid state change due to
7605     // program change.
7606     constexpr char kFS[] = R"(#version 300 es
7607 precision mediump float;
7608 uniform block { uint data; } ubo;
7609 uniform uint expect;
7610 uniform vec4 successColor;
7611 out vec4 colorOut;
7612 void main()
7613 {
7614     colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
7615 })";
7616 
7617     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7618     glUseProgram(program);
7619 
7620     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7621     const GLint expectLoc   = glGetUniformLocation(program, "expect");
7622     const GLint successLoc  = glGetUniformLocation(program, "successColor");
7623     ASSERT_NE(-1, positionLoc);
7624     ASSERT_NE(-1, expectLoc);
7625     ASSERT_NE(-1, successLoc);
7626 
7627     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7628     glEnableVertexAttribArray(positionLoc);
7629 
7630     glUniform1ui(expectLoc, kUboData1[0]);
7631     glUniform4f(successLoc, 0, 0, 0, 1);
7632     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7633     EXPECT_GL_NO_ERROR();
7634 
7635     // Then upload data to the UBO so on next use the render pass has to break.  This draw call is
7636     // not indexed.
7637     constexpr GLuint kUboData2 = 0x87654321u;
7638     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
7639 
7640     glEnable(GL_BLEND);
7641     glBlendFunc(GL_ONE, GL_ONE);
7642     glUniform1ui(expectLoc, kUboData2);
7643     glUniform4f(successLoc, 0, 1, 0, 0);
7644     glDrawArrays(GL_TRIANGLES, 0, 3);
7645 
7646     // Issue another draw call that is indexed.  The index buffer should be bound correctly on the
7647     // new render pass.
7648     glUniform4f(successLoc, 0, 0, 1, 0);
7649     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7650     EXPECT_GL_NO_ERROR();
7651 
7652     // Ensure correct rendering.
7653     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7654 }
7655 
7656 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)7657 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
7658 {
7659     // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7660     glClearColor(0, 0, 0, 1);
7661     glClear(GL_COLOR_BUFFER_BIT);
7662     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7663 
7664     GLFramebuffer fbo;
7665     GLTexture texture;
7666 
7667     glBindTexture(GL_TEXTURE_2D, texture);
7668     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7669     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7670     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7671 
7672     glClear(GL_COLOR_BUFFER_BIT);
7673     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7674 
7675     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7676 
7677     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
7678     // bit.
7679     GLBuffer indexBuffer;
7680     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7681 
7682     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7683     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7684 
7685     // Setup vertices.
7686     const std::array<GLfloat, 6> kVertices = {
7687         -1, -1, 3, -1, -1, 3,
7688     };
7689     GLBuffer vertexBuffer;
7690     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7691     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7692     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7693     glEnableVertexAttribArray(0);
7694 
7695     // Set up a program.  The same program is used for all draw calls to avoid state change due to
7696     // program change.
7697     constexpr char kFS[] = R"(#version 300 es
7698 precision mediump float;
7699 uniform vec4 colorIn;
7700 out vec4 colorOut;
7701 void main()
7702 {
7703     colorOut = colorIn;
7704 })";
7705 
7706     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7707     glUseProgram(program);
7708 
7709     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7710     const GLint colorLoc    = glGetUniformLocation(program, "colorIn");
7711     ASSERT_NE(-1, positionLoc);
7712     ASSERT_NE(-1, colorLoc);
7713 
7714     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7715     glEnableVertexAttribArray(positionLoc);
7716 
7717     glUniform4f(colorLoc, 1, 0, 0, 1);
7718     glEnable(GL_BLEND);
7719     glBlendFunc(GL_ONE, GL_ONE);
7720     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7721     EXPECT_GL_NO_ERROR();
7722 
7723     // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7724     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7725     glUniform4f(colorLoc, 0, 1, 0, 0);
7726     glDrawArrays(GL_TRIANGLES, 0, 3);
7727 
7728     glUniform4f(colorLoc, 0, 0, 1, 0);
7729     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7730     EXPECT_GL_NO_ERROR();
7731 
7732     // Ensure correct rendering.
7733     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7734 
7735     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7736     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7737 }
7738 
7739 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
7740 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)7741 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
7742 {
7743     // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
7744     glClearColor(0, 0, 0, 1);
7745     glClear(GL_COLOR_BUFFER_BIT);
7746     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7747 
7748     GLFramebuffer fbo;
7749     GLTexture texture;
7750 
7751     glBindTexture(GL_TEXTURE_2D, texture);
7752     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7753     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
7754     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
7755 
7756     glClear(GL_COLOR_BUFFER_BIT);
7757     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
7758 
7759     glBindFramebuffer(GL_FRAMEBUFFER, 0);
7760 
7761     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
7762     // bit.
7763     GLBuffer indexBuffer;
7764     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7765 
7766     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
7767     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
7768 
7769     // Setup vertices.
7770     const std::array<GLfloat, 6> kVertices = {
7771         -1, -1, 3, -1, -1, 3,
7772     };
7773     GLBuffer vertexBuffer;
7774     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
7775     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
7776     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
7777     glEnableVertexAttribArray(0);
7778 
7779     // Set up a program.  The same program is used for all draw calls to avoid state change due to
7780     // program change.
7781     constexpr char kFS[] = R"(#version 300 es
7782 precision mediump float;
7783 uniform vec4 colorIn;
7784 out vec4 colorOut;
7785 void main()
7786 {
7787     colorOut = colorIn;
7788 })";
7789 
7790     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
7791     glUseProgram(program);
7792 
7793     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
7794     const GLint colorLoc    = glGetUniformLocation(program, "colorIn");
7795     ASSERT_NE(-1, positionLoc);
7796     ASSERT_NE(-1, colorLoc);
7797 
7798     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
7799     glEnableVertexAttribArray(positionLoc);
7800 
7801     glUniform4f(colorLoc, 0, 0, 0, 1);
7802     glEnable(GL_BLEND);
7803     glBlendFunc(GL_ONE, GL_ONE);
7804     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7805     EXPECT_GL_NO_ERROR();
7806 
7807     // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
7808     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7809     glUniform4f(colorLoc, 0, 1, 0, 0);
7810     glDrawArrays(GL_TRIANGLES, 0, 3);
7811 
7812     // In between the two calls, make sure the first render pass is submitted, so the primary
7813     // command buffer is reset.
7814     {
7815         EGLWindow *window          = getEGLWindow();
7816         EGLDisplay dpy             = window->getDisplay();
7817         EGLConfig config           = window->getConfig();
7818         EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
7819         EGLSurface surface         = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
7820         EGLContext ctx             = window->createContext(EGL_NO_CONTEXT, nullptr);
7821         EXPECT_EGL_SUCCESS();
7822         std::thread flushThread = std::thread([&]() {
7823             EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
7824             EXPECT_EGL_SUCCESS();
7825 
7826             glClearColor(1, 0, 0, 1);
7827             glClear(GL_COLOR_BUFFER_BIT);
7828             EXPECT_GL_NO_ERROR();
7829 
7830             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7831         });
7832         flushThread.join();
7833 
7834         eglDestroySurface(dpy, surface);
7835         eglDestroyContext(dpy, ctx);
7836     }
7837 
7838     glUniform4f(colorLoc, 0, 0, 1, 0);
7839     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
7840     EXPECT_GL_NO_ERROR();
7841 
7842     // Ensure correct rendering.
7843     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
7844 }
7845 
7846 // Negative test for EXT_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxEXTNegativeTest)7847 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxEXTNegativeTest)
7848 {
7849     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_primitive_bounding_box"));
7850 
7851     glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7852     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7853 
7854     GLfloat boundingBox[8] = {0};
7855     glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_EXT, boundingBox);
7856     EXPECT_GL_ERROR(GL_INVALID_ENUM);
7857 }
7858 
7859 // Negative test for OES_primitive_bounding_box
TEST_P(SimpleStateChangeTestES31,PrimitiveBoundingBoxOESNegativeTest)7860 TEST_P(SimpleStateChangeTestES31, PrimitiveBoundingBoxOESNegativeTest)
7861 {
7862     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_OES_primitive_bounding_box"));
7863 
7864     glPrimitiveBoundingBoxEXT(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
7865     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
7866 
7867     GLfloat boundingBox[8] = {0};
7868     glGetFloatv(GL_PRIMITIVE_BOUNDING_BOX_OES, boundingBox);
7869     EXPECT_GL_ERROR(GL_INVALID_ENUM);
7870 }
7871 
7872 // Update an element array buffer that is already in use.
TEST_P(SimpleStateChangeTest,UpdateBoundElementArrayBuffer)7873 TEST_P(SimpleStateChangeTest, UpdateBoundElementArrayBuffer)
7874 {
7875     constexpr char kVS[] = R"(attribute vec4 position;
7876 attribute float color;
7877 varying float colorVarying;
7878 void main()
7879 {
7880     gl_Position = position;
7881     colorVarying = color;
7882 })";
7883 
7884     constexpr char kFS[] = R"(precision mediump float;
7885 varying float colorVarying;
7886 void main()
7887 {
7888     if (colorVarying == 1.0)
7889     {
7890         gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
7891     }
7892     else
7893     {
7894         gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
7895     }
7896 })";
7897 
7898     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
7899     glUseProgram(testProgram);
7900 
7901     GLint posLoc = glGetAttribLocation(testProgram, "position");
7902     ASSERT_NE(-1, posLoc);
7903     GLint colorLoc = glGetAttribLocation(testProgram, "color");
7904     ASSERT_NE(-1, colorLoc);
7905 
7906     std::array<GLushort, 6> quadIndices = GetQuadIndices();
7907 
7908     std::vector<GLubyte> indices;
7909     for (GLushort index : quadIndices)
7910     {
7911         indices.push_back(static_cast<GLubyte>(index));
7912     }
7913 
7914     GLBuffer indexBuffer;
7915     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
7916     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(indices[0]), indices.data(),
7917                  GL_STATIC_DRAW);
7918 
7919     std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
7920 
7921     std::vector<Vector3> positionVertices;
7922     for (Vector3 vertex : quadVertices)
7923     {
7924         positionVertices.push_back(vertex);
7925     }
7926     for (Vector3 vertex : quadVertices)
7927     {
7928         positionVertices.push_back(vertex);
7929     }
7930 
7931     GLBuffer positionVertexBuffer;
7932     glBindBuffer(GL_ARRAY_BUFFER, positionVertexBuffer);
7933     glBufferData(GL_ARRAY_BUFFER, positionVertices.size() * sizeof(positionVertices[0]),
7934                  positionVertices.data(), GL_STATIC_DRAW);
7935     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
7936     glEnableVertexAttribArray(posLoc);
7937 
7938     std::vector<float> colorVertices = {1, 1, 1, 1, 0, 0, 0, 0};
7939 
7940     GLBuffer colorVertexBuffer;
7941     glBindBuffer(GL_ARRAY_BUFFER, colorVertexBuffer);
7942     glBufferData(GL_ARRAY_BUFFER, colorVertices.size() * sizeof(colorVertices[0]),
7943                  colorVertices.data(), GL_STATIC_DRAW);
7944     glVertexAttribPointer(colorLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
7945     glEnableVertexAttribArray(colorLoc);
7946 
7947     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7948     ASSERT_GL_NO_ERROR();
7949     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
7950 
7951     indices.clear();
7952     for (GLushort index : quadIndices)
7953     {
7954         indices.push_back(static_cast<GLubyte>(index + 4));
7955     }
7956     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indices.size() * sizeof(indices[0]),
7957                     indices.data());
7958 
7959     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
7960     ASSERT_GL_NO_ERROR();
7961     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
7962 }
7963 
7964 // Covers a bug where we would use a stale cache variable in the Vulkan back-end.
TEST_P(SimpleStateChangeTestES3,DeleteFramebufferBeforeQuery)7965 TEST_P(SimpleStateChangeTestES3, DeleteFramebufferBeforeQuery)
7966 {
7967     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
7968     glUseProgram(testProgram);
7969 
7970     GLFramebuffer fbo;
7971     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
7972 
7973     GLRenderbuffer rbo;
7974     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
7975 
7976     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, 16, 16);
7977     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
7978 
7979     GLfloat floatArray[] = {1, 2, 3, 4};
7980 
7981     GLBuffer buffer;
7982     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
7983     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLfloat) * 4, floatArray, GL_DYNAMIC_COPY);
7984     glDrawElements(GL_TRIANGLE_FAN, 5, GL_UNSIGNED_SHORT, 0);
7985 
7986     fbo.reset();
7987 
7988     GLQuery query2;
7989     glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, query2);
7990 
7991     ASSERT_GL_NO_ERROR();
7992 }
7993 
7994 // Covers an edge case
TEST_P(SimpleStateChangeTestES3,TextureTypeConflictAfterDraw)7995 TEST_P(SimpleStateChangeTestES3, TextureTypeConflictAfterDraw)
7996 {
7997     constexpr char kVS[] = R"(precision highp float;
7998 attribute vec4 a_position;
7999 void main()
8000 {
8001     gl_Position = a_position;
8002 }
8003 )";
8004 
8005     constexpr char kFS[] = R"(precision highp float;
8006 uniform sampler2D u_2d1;
8007 uniform samplerCube u_Cube1;
8008 void main()
8009 {
8010     gl_FragColor = texture2D(u_2d1, vec2(0.0, 0.0)) + textureCube(u_Cube1, vec3(0.0, 0.0, 0.0));
8011 }
8012 )";
8013 
8014     ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
8015     glUseProgram(testProgram);
8016 
8017     GLTexture texture;
8018     glBindTexture(GL_TEXTURE_2D, texture);
8019     glTexStorage2D(GL_TEXTURE_2D, 4, GL_SRGB8, 1268, 614);
8020 
8021     GLint uniformloc = glGetUniformLocation(testProgram, "u_Cube1");
8022     ASSERT_NE(-1, uniformloc);
8023     glUniform1i(uniformloc, 1);
8024 
8025     glDrawArrays(GL_POINTS, 0, 1);
8026     ASSERT_GL_NO_ERROR();
8027 
8028     // Trigger the state update.
8029     glLinkProgram(testProgram);
8030     texture.reset();
8031 
8032     // The texture types are now conflicting, and draws should fail.
8033     glDrawArrays(GL_POINTS, 0, 1);
8034     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8035 }
8036 
8037 // Regression test for a bug where a mutable texture is used with non-zero base level then rebased
8038 // to zero but made incomplete and attached to the framebuffer.  The texture's image is not
8039 // recreated with level 0, leading to errors when drawing to the framebuffer.
TEST_P(SimpleStateChangeTestES3,NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)8040 TEST_P(SimpleStateChangeTestES3, NonZeroBaseMutableTextureThenZeroBaseButIncompleteBug)
8041 {
8042     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8043     glUseProgram(program);
8044 
8045     const std::array<GLColor, 4> kMip0Data = {GLColor::red, GLColor::red, GLColor::red,
8046                                               GLColor::red};
8047     const std::array<GLColor, 2> kMip1Data = {GLColor::green, GLColor::green};
8048 
8049     // Create two textures.
8050     GLTexture immutableTex;
8051     glBindTexture(GL_TEXTURE_2D, immutableTex);
8052     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
8053     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data.data());
8054 
8055     GLTexture mutableTex;
8056     glBindTexture(GL_TEXTURE_2D, mutableTex);
8057     for (uint32_t mip = 0; mip < 2; ++mip)
8058     {
8059         const uint32_t size = 4 >> mip;
8060         glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA8, size, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8061                      mip == 0 ? kMip0Data.data() : kMip1Data.data());
8062     }
8063 
8064     GLFramebuffer fbo;
8065     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8066 
8067     // Sample from the mutable texture at non-zero base level.
8068     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
8069     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8070 
8071     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, immutableTex, 0);
8072     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8073     EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[0]);
8074 
8075     // Rebase the mutable texture to zero, but enable mipmapping which makes it incomplete.
8076     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8077     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
8078 
8079     // Remove feedback loop for good measure.
8080     glBindTexture(GL_TEXTURE_2D, immutableTex);
8081 
8082     // Draw into base zero of the texture.
8083     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mutableTex, 0);
8084     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
8085 
8086     EXPECT_PIXEL_COLOR_EQ(0, 0, kMip1Data[1]);
8087     ASSERT_GL_NO_ERROR();
8088 }
8089 
8090 // Regression test for a bug where the framebuffer binding was not synced during invalidate when a
8091 // clear operation was deferred.
TEST_P(SimpleStateChangeTestES3,ChangeFramebufferThenInvalidateWithClear)8092 TEST_P(SimpleStateChangeTestES3, ChangeFramebufferThenInvalidateWithClear)
8093 {
8094     // Clear the default framebuffer.
8095     glClear(GL_COLOR_BUFFER_BIT);
8096 
8097     // Start rendering to another framebuffer
8098     GLFramebuffer fbo;
8099     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8100 
8101     GLRenderbuffer rbo;
8102     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
8103     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
8104     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
8105 
8106     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
8107     glUseProgram(program);
8108     glDrawArrays(GL_TRIANGLES, 0, 3);
8109 
8110     // Switch back to the default framebuffer
8111     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8112 
8113     // Invalidate it.  Don't invalidate color, as that's the one being cleared.
8114     constexpr GLenum kAttachment = GL_DEPTH;
8115     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8116     EXPECT_GL_NO_ERROR();
8117 }
8118 
8119 // Test that clear / invalidate / clear works.  The invalidate is for a target that's not cleared.
8120 // Regression test for a bug where invalidate() would start a render pass to perform the first
8121 // clear, while the second clear didn't expect a render pass opened without any draw calls in it.
TEST_P(SimpleStateChangeTestES3,ClearColorInvalidateDepthClearColor)8122 TEST_P(SimpleStateChangeTestES3, ClearColorInvalidateDepthClearColor)
8123 {
8124     // Clear color.
8125     glClear(GL_COLOR_BUFFER_BIT);
8126 
8127     // Invalidate depth.
8128     constexpr GLenum kAttachment = GL_DEPTH;
8129     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &kAttachment);
8130     EXPECT_GL_NO_ERROR();
8131 
8132     // Clear color again.
8133     glClear(GL_COLOR_BUFFER_BIT);
8134     ASSERT_GL_NO_ERROR();
8135 }
8136 
8137 // Regression test for a bug where glInvalidateFramebuffer(GL_FRAMEBUFFER, ...) was invalidating
8138 // both the draw and read framebuffers.
TEST_P(SimpleStateChangeTestES3,InvalidateFramebufferShouldntInvalidateReadFramebuffer)8139 TEST_P(SimpleStateChangeTestES3, InvalidateFramebufferShouldntInvalidateReadFramebuffer)
8140 {
8141     // Create an invalid read framebuffer.
8142     GLFramebuffer fbo;
8143     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8144 
8145     GLTexture tex;
8146     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
8147     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, 1, 1, 1);
8148     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, tex, 0, 5);
8149 
8150     // Invalidate using GL_FRAMEBUFFER.  If GL_READ_FRAMEBUFFER was used, validation would fail due
8151     // to the framebuffer not being complete.  A bug here was attempting to invalidate the read
8152     // framebuffer given GL_FRAMEBUFFER anyway.
8153     constexpr std::array<GLenum, 2> kAttachments = {GL_DEPTH, GL_STENCIL};
8154     glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, kAttachments.data());
8155     EXPECT_GL_NO_ERROR();
8156 }
8157 
8158 // Test that respecifies a buffer after we start XFB.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedback)8159 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedback)
8160 {
8161     std::vector<std::string> tfVaryings = {"gl_Position"};
8162     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8163                                         essl3_shaders::fs::Green(), tfVaryings,
8164                                         GL_INTERLEAVED_ATTRIBS);
8165 
8166     glUseProgram(testProgram);
8167     GLBuffer buffer;
8168     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8169     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8170     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8171     glBeginTransformFeedback(GL_TRIANGLES);
8172     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8173     glDrawArrays(GL_TRIANGLES, 0, 6);
8174     glEndTransformFeedback();
8175 }
8176 
8177 // Test a bug angleproject:6998 in TransformFeedback code path by allocating paddingBuffer first and
8178 // then allocate another buffer and then deallocate paddingBuffer and then allocate buffer again.
8179 // This new buffer will be allocated in the space where paddingBuffer was allocated which causing
8180 // XFB generate VVL error.
TEST_P(SimpleStateChangeTestES3,RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)8181 TEST_P(SimpleStateChangeTestES3, RespecifyBufferAfterBeginTransformFeedbackInDeletedPaddingBuffer)
8182 {
8183     std::vector<std::string> tfVaryings = {"gl_Position"};
8184     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl3_shaders::vs::Simple(),
8185                                         essl3_shaders::fs::Green(), tfVaryings,
8186                                         GL_INTERLEAVED_ATTRIBS);
8187     glUseProgram(testProgram);
8188 
8189     GLuint paddingBuffer;
8190     glGenBuffers(1, &paddingBuffer);
8191     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, paddingBuffer);
8192     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 256, nullptr, GL_STREAM_DRAW);
8193 
8194     GLBuffer buffer;
8195     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
8196     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 2 * 7, nullptr, GL_STREAM_DRAW);
8197     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
8198     // Delete padding buffer, expecting the next bufferData call will reuse the space of
8199     // paddingBuffer whose offset is smaller than buffer's offset, which triggers the bug.
8200     glDeleteBuffers(1, &paddingBuffer);
8201     glBeginTransformFeedback(GL_TRIANGLES);
8202     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float) * 3 * 4 * 6, nullptr, GL_STREAM_DRAW);
8203     glDrawArrays(GL_TRIANGLES, 0, 6);
8204     glEndTransformFeedback();
8205 }
8206 
8207 // Regression test for a bug in the Vulkan backend where a draw-based copy after a deferred flush
8208 // would lead to an image view being destroyed too early.
TEST_P(SimpleStateChangeTestES3,DrawFlushThenCopyTexImage)8209 TEST_P(SimpleStateChangeTestES3, DrawFlushThenCopyTexImage)
8210 {
8211     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8212 
8213     // Issue a cheap draw call and a flush
8214     glEnable(GL_SCISSOR_TEST);
8215     glScissor(0, 0, 1, 1);
8216     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8217     glDisable(GL_SCISSOR_TEST);
8218     glFlush();
8219 
8220     constexpr GLsizei kSize = 32;
8221 
8222     // Then an expensive copy tex image
8223     GLTexture texture;
8224     glBindTexture(GL_TEXTURE_3D, texture);
8225     glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGB8, kSize, kSize, kSize);
8226     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, kSize, kSize);
8227     glFlush();
8228     ASSERT_GL_NO_ERROR();
8229 }
8230 
TEST_P(SimpleStateChangeTestES3,DrawFlushThenBlit)8231 TEST_P(SimpleStateChangeTestES3, DrawFlushThenBlit)
8232 {
8233     constexpr GLsizei kSize = 256;
8234     const std::vector<GLColor> data(kSize * kSize, GLColor::red);
8235 
8236     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Green());
8237 
8238     GLFramebuffer fbo;
8239     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8240 
8241     GLTexture readColor;
8242     glBindTexture(GL_TEXTURE_2D, readColor);
8243     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8244                  data.data());
8245     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, readColor, 0);
8246 
8247     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
8248 
8249     // Issue a cheap draw call and a flush
8250     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
8251     glEnable(GL_SCISSOR_TEST);
8252     glScissor(0, 0, 1, 1);
8253     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
8254     glDisable(GL_SCISSOR_TEST);
8255     glFlush();
8256 
8257     // Then an expensive blit
8258     glBlitFramebuffer(0, 0, kSize, kSize, kSize + 2, kSize, 0, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
8259     glFlush();
8260     ASSERT_GL_NO_ERROR();
8261 }
8262 
8263 class VertexAttribArrayStateChangeTest : public ANGLETest<>
8264 {
8265   protected:
VertexAttribArrayStateChangeTest()8266     VertexAttribArrayStateChangeTest()
8267     {
8268         setWindowWidth(128);
8269         setWindowHeight(128);
8270         setConfigRedBits(8);
8271         setConfigGreenBits(8);
8272         setConfigBlueBits(8);
8273         setConfigAlphaBits(8);
8274         setConfigDepthBits(24);
8275     }
8276 
testSetUp()8277     void testSetUp() override
8278     {
8279         constexpr char kVS[] = R"(precision highp float;
8280 attribute vec4 position;
8281 attribute vec4 color;
8282 varying vec4 colorOut;
8283 
8284 void main()
8285 {
8286     gl_Position = position;
8287     colorOut = color;
8288 })";
8289 
8290         constexpr char kFS[] = R"(precision highp float;
8291 varying vec4 colorOut;
8292 
8293 void main()
8294 {
8295     gl_FragColor = colorOut;
8296 })";
8297 
8298         mProgram = CompileProgram(kVS, kFS);
8299         ASSERT_NE(0u, mProgram);
8300 
8301         mPosAttribLocation = glGetAttribLocation(mProgram, "position");
8302         ASSERT_NE(-1, mPosAttribLocation);
8303         mColorAttribLocation = glGetAttribLocation(mProgram, "color");
8304         ASSERT_NE(-1, mColorAttribLocation);
8305 
8306         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
8307         ASSERT_GL_NO_ERROR();
8308 
8309         glGenBuffers(1, &mVertexBuffer);
8310         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8311 
8312         const float posAttribData[] = {
8313             -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8314         };
8315         glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8316 
8317         glBindBuffer(GL_ARRAY_BUFFER, 0);
8318     }
8319 
testTearDown()8320     void testTearDown() override
8321     {
8322         if (mVertexBuffer != 0)
8323         {
8324             glDeleteBuffers(1, &mVertexBuffer);
8325         }
8326 
8327         if (mProgram != 0)
8328         {
8329             glDeleteProgram(mProgram);
8330         }
8331     }
8332 
8333     GLuint mProgram;
8334     GLint mPosAttribLocation;
8335     GLint mColorAttribLocation;
8336     GLuint mVertexBuffer;
8337 };
8338 
TEST_P(VertexAttribArrayStateChangeTest,Basic)8339 TEST_P(VertexAttribArrayStateChangeTest, Basic)
8340 {
8341     glUseProgram(mProgram);
8342     glClear(GL_COLOR_BUFFER_BIT);
8343     glDisable(GL_DEPTH_TEST);
8344     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
8345 
8346     glVertexAttribPointer(mPosAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8347     glEnableVertexAttribArray(mPosAttribLocation);
8348     glDisableVertexAttribArray(mColorAttribLocation);
8349     glVertexAttrib4f(mColorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8350     // Don't try to verify the color of this draw as red here because it might
8351     // hide the bug
8352     glDrawArrays(GL_TRIANGLES, 0, 6);
8353     glVertexAttrib4f(mColorAttribLocation, 0.0f, 1.0f, 0.0f, 1.0f);
8354     glDrawArrays(GL_TRIANGLES, 0, 6);
8355     ASSERT_GL_NO_ERROR();
8356     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8357 
8358     glUseProgram(0);
8359     glBindBuffer(GL_ARRAY_BUFFER, 0);
8360 }
8361 
TEST_P(SimpleStateChangeTestES3,DepthOnlyToColorAttachmentPreservesBlendState)8362 TEST_P(SimpleStateChangeTestES3, DepthOnlyToColorAttachmentPreservesBlendState)
8363 {
8364 
8365     constexpr char kVS[] = R"(precision highp float;
8366 attribute vec4 position;
8367 attribute vec4 color;
8368 varying vec4 colorOut;
8369 
8370 void main()
8371 {
8372     gl_Position = position;
8373     colorOut = color;
8374 })";
8375 
8376     constexpr char kFS[] = R"(precision highp float;
8377 varying vec4 colorOut;
8378 
8379 void main()
8380 {
8381     gl_FragColor = colorOut;
8382 })";
8383 
8384     ANGLE_GL_PROGRAM(program, kVS, kFS);
8385 
8386     GLint posAttribLocation = glGetAttribLocation(program, "position");
8387     ASSERT_NE(-1, posAttribLocation);
8388     GLint colorAttribLocation = glGetAttribLocation(program, "color");
8389     ASSERT_NE(-1, colorAttribLocation);
8390 
8391     GLBuffer vertexBuffer;
8392     GLTexture texture;
8393     GLFramebuffer framebuffer;
8394     GLRenderbuffer depthRenderbuffer;
8395     GLFramebuffer depthFramebuffer;
8396 
8397     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8398 
8399     const float posAttribData[] = {
8400         -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
8401     };
8402     glBufferData(GL_ARRAY_BUFFER, sizeof(posAttribData), posAttribData, GL_STATIC_DRAW);
8403 
8404     glBindBuffer(GL_ARRAY_BUFFER, 0);
8405 
8406     constexpr int kWidth  = 1;
8407     constexpr int kHeight = 1;
8408 
8409     glBindTexture(GL_TEXTURE_2D, texture);
8410     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
8411     glBindTexture(GL_TEXTURE_2D, 0);
8412 
8413     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8414     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8415     glBindFramebuffer(GL_FRAMEBUFFER, 0);
8416 
8417     glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
8418     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);
8419     glBindRenderbuffer(GL_RENDERBUFFER, 0);
8420 
8421     glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8422     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
8423                               depthRenderbuffer);
8424     glBindFramebuffer(GL_FRAMEBUFFER, 0);
8425 
8426     glDisable(GL_DEPTH_TEST);
8427     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
8428     glVertexAttribPointer(posAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
8429     glEnableVertexAttribArray(posAttribLocation);
8430     glDisableVertexAttribArray(colorAttribLocation);
8431     glVertexAttrib4f(colorAttribLocation, 1.0f, 0.0f, 0.0f, 1.0f);
8432 
8433     glUseProgram(program);
8434     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8435     glEnable(GL_BLEND);
8436     glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
8437     glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
8438     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8439     glClear(GL_COLOR_BUFFER_BIT);
8440     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
8441 
8442     glBindFramebuffer(GL_FRAMEBUFFER, depthFramebuffer);
8443     glDrawArrays(GL_TRIANGLES, 0, 6);
8444 
8445     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
8446     glDrawArrays(GL_TRIANGLES, 0, 6);
8447     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
8448 
8449     glBindBuffer(GL_ARRAY_BUFFER, 0);
8450     glBindFramebuffer(GL_FRAMEBUFFER, 0);
8451     glUseProgram(0);
8452 }
8453 
8454 // Tests a bug where we wouldn't update our cached base/max levels in Vulkan.
TEST_P(SimpleStateChangeTestES3,MaxLevelChange)8455 TEST_P(SimpleStateChangeTestES3, MaxLevelChange)
8456 {
8457     // Initialize an immutable texture with 2 levels.
8458     std::vector<GLColor> bluePixels(4, GLColor::blue);
8459 
8460     GLTexture tex;
8461     glBindTexture(GL_TEXTURE_2D, tex);
8462     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8463     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
8464     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8465     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 2, 2);
8466     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, bluePixels.data());
8467     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::yellow);
8468 
8469     // Set up draw resources.
8470     ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
8471     glUseProgram(testProgram);
8472 
8473     GLint posLoc = glGetAttribLocation(testProgram, essl1_shaders::PositionAttrib());
8474     ASSERT_NE(-1, posLoc);
8475 
8476     std::array<Vector3, 6> quadVerts = GetQuadVertices();
8477 
8478     GLBuffer vao;
8479     glBindBuffer(GL_ARRAY_BUFFER, vao);
8480     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
8481                  GL_STATIC_DRAW);
8482     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
8483     glEnableVertexAttribArray(posLoc);
8484 
8485     ASSERT_GL_NO_ERROR();
8486 
8487     // Draw with the 2x2 mip / max level 1.
8488     glViewport(0, 0, 2, 2);
8489     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8490     glDrawArrays(GL_TRIANGLES, 0, 6);
8491 
8492     // Draw with the 1x1 mip / max level 2.
8493     glViewport(2, 0, 1, 1);
8494     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8495     glDrawArrays(GL_TRIANGLES, 0, 6);
8496 
8497     // Draw with the 2x2 mip / max level 1.
8498     glViewport(0, 2, 2, 2);
8499     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8500     glDrawArrays(GL_TRIANGLES, 0, 6);
8501 
8502     // Draw with the 1x1 mip / max level 2.
8503     glViewport(2, 2, 1, 1);
8504     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
8505     glDrawArrays(GL_TRIANGLES, 0, 6);
8506 
8507     ASSERT_GL_NO_ERROR();
8508 
8509     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
8510     EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::yellow);
8511     EXPECT_PIXEL_COLOR_EQ(0, 2, GLColor::blue);
8512     EXPECT_PIXEL_COLOR_EQ(2, 2, GLColor::yellow);
8513 }
8514 
8515 // Tests a bug when removing an element array buffer bound to two vertex arrays.
TEST_P(SimpleStateChangeTestES3,DeleteDoubleBoundBufferAndVertexArray)8516 TEST_P(SimpleStateChangeTestES3, DeleteDoubleBoundBufferAndVertexArray)
8517 {
8518     std::vector<uint8_t> bufData(100, 0);
8519     GLBuffer buffer;
8520     GLVertexArray vao;
8521 
8522     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8523     glBindVertexArray(vao);
8524     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
8525     buffer.reset();
8526     vao.reset();
8527 
8528     glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8529     glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufData.size(), bufData.data(), GL_STATIC_DRAW);
8530     ASSERT_GL_NO_ERROR();
8531 }
8532 
8533 // Tests state change for glLineWidth.
TEST_P(StateChangeTestES3,LineWidth)8534 TEST_P(StateChangeTestES3, LineWidth)
8535 {
8536     // According to the spec, the minimum value for the line width range limits is one.
8537     GLfloat range[2] = {1};
8538     glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8539     EXPECT_GL_NO_ERROR();
8540     EXPECT_GE(range[0], 1.0f);
8541     EXPECT_GE(range[1], 1.0f);
8542 
8543     ANGLE_SKIP_TEST_IF(range[1] < 5.0);
8544 
8545     constexpr char kVS[] = R"(#version 300 es
8546 precision highp float;
8547 uniform float height;
8548 void main()
8549 {
8550     gl_Position = vec4(gl_VertexID == 0 ? -1 : 1, height * 2. - 1., 0, 1);
8551 })";
8552 
8553     constexpr char kFS[] = R"(#version 300 es
8554 precision highp float;
8555 out vec4 colorOut;
8556 uniform vec4 color;
8557 void main()
8558 {
8559     colorOut = color;
8560 })";
8561 
8562     ANGLE_GL_PROGRAM(program, kVS, kFS);
8563     glUseProgram(program);
8564 
8565     GLint heightLoc = glGetUniformLocation(program, "height");
8566     GLint colorLoc  = glGetUniformLocation(program, "color");
8567     ASSERT_NE(-1, heightLoc);
8568     ASSERT_NE(-1, colorLoc);
8569 
8570     glClearColor(0, 0, 0, 1);
8571     glClear(GL_COLOR_BUFFER_BIT);
8572 
8573     const int w                 = getWindowWidth();
8574     const int h                 = getWindowHeight();
8575     const float halfPixelHeight = 0.5 / h;
8576 
8577     glUniform1f(heightLoc, 0.25f + halfPixelHeight);
8578     glUniform4f(colorLoc, 1, 0, 0, 1);
8579     glLineWidth(3);
8580     glDrawArrays(GL_LINES, 0, 2);
8581 
8582     glUniform1f(heightLoc, 0.5f + halfPixelHeight);
8583     glUniform4f(colorLoc, 0, 1, 0, 1);
8584     glLineWidth(5);
8585     glDrawArrays(GL_LINES, 0, 2);
8586 
8587     glUniform1f(heightLoc, 0.75f + halfPixelHeight);
8588     glUniform4f(colorLoc, 0, 0, 1, 1);
8589     glLineWidth(1);
8590     glDrawArrays(GL_LINES, 0, 2);
8591 
8592     EXPECT_PIXEL_RECT_EQ(0, h / 4 - 2, w, 1, GLColor::black);
8593     EXPECT_PIXEL_RECT_EQ(0, h / 4 - 1, w, 3, GLColor::red);
8594     EXPECT_PIXEL_RECT_EQ(0, h / 4 + 2, w, 1, GLColor::black);
8595 
8596     EXPECT_PIXEL_RECT_EQ(0, h / 2 - 3, w, 1, GLColor::black);
8597     EXPECT_PIXEL_RECT_EQ(0, h / 2 - 2, w, 5, GLColor::green);
8598     EXPECT_PIXEL_RECT_EQ(0, h / 2 + 3, w, 1, GLColor::black);
8599 
8600     EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 - 1, w, 1, GLColor::black);
8601     EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4, w, 1, GLColor::blue);
8602     EXPECT_PIXEL_RECT_EQ(0, 3 * h / 4 + 1, w, 1, GLColor::black);
8603 
8604     ASSERT_GL_NO_ERROR();
8605 }
8606 
8607 // Tests state change for out-of-range value for glLineWidth. The expectation
8608 // here is primarily that rendering backends do not crash with invalid line
8609 // width values.
TEST_P(StateChangeTestES3,LineWidthOutOfRangeDoesntCrash)8610 TEST_P(StateChangeTestES3, LineWidthOutOfRangeDoesntCrash)
8611 {
8612     GLfloat range[2] = {1};
8613     glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
8614     EXPECT_GL_NO_ERROR();
8615 
8616     constexpr char kVS[] = R"(#version 300 es
8617 precision highp float;
8618 void main()
8619 {
8620     gl_Position = vec4(gl_VertexID == 0 ? -1.0 : 1.0, -1.0, 0.0, 1.0);
8621 })";
8622 
8623     constexpr char kFS[] = R"(#version 300 es
8624 precision highp float;
8625 out vec4 colorOut;
8626 void main()
8627 {
8628     colorOut = vec4(1.0);
8629 })";
8630 
8631     ANGLE_GL_PROGRAM(program, kVS, kFS);
8632     glUseProgram(program);
8633 
8634     glClearColor(0, 0, 0, 1);
8635     glClear(GL_COLOR_BUFFER_BIT);
8636 
8637     glLineWidth(range[1] + 1.0f);
8638     glDrawArrays(GL_LINES, 0, 2);
8639 
8640     glFinish();
8641 
8642     ASSERT_GL_NO_ERROR();
8643 }
8644 
8645 // Tests state change for glPolygonOffset.
TEST_P(StateChangeTestES3,PolygonOffset)8646 TEST_P(StateChangeTestES3, PolygonOffset)
8647 {
8648     constexpr char kVS[] = R"(#version 300 es
8649 precision highp float;
8650 void main()
8651 {
8652     // gl_VertexID    x    y
8653     //      0        -1   -1
8654     //      1         1   -1
8655     //      2        -1    1
8656     //      3         1    1
8657     int bit0 = gl_VertexID & 1;
8658     int bit1 = gl_VertexID >> 1;
8659     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8660 })";
8661 
8662     constexpr char kFS[] = R"(#version 300 es
8663 precision highp float;
8664 out vec4 colorOut;
8665 uniform vec4 color;
8666 void main()
8667 {
8668     colorOut = color;
8669 })";
8670 
8671     glEnable(GL_POLYGON_OFFSET_FILL);
8672 
8673     ANGLE_GL_PROGRAM(program, kVS, kFS);
8674     glUseProgram(program);
8675 
8676     GLint colorLoc = glGetUniformLocation(program, "color");
8677     ASSERT_NE(-1, colorLoc);
8678 
8679     glClearColor(0, 0, 0, 1);
8680     glClearDepthf(0);
8681     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8682 
8683     glEnable(GL_DEPTH_TEST);
8684     glDepthFunc(GL_ALWAYS);
8685 
8686     // The shader creates a depth slope from left (0) to right (1).
8687     //
8688     // This test issues three draw calls:
8689     //
8690     //           Draw 2 (green): factor width/2, offset 0, depth test: Greater
8691     //          ^     |       __________________
8692     //          |     |    __/__/   __/
8693     //          |     V __/__/   __/  <--- Draw 1 (red): factor width/4, offset 0
8694     //          |    __/__/ ^ __/
8695     //          | __/__/   _|/
8696     //          |/__/   __/ |
8697     //          |/   __/    |
8698     //          | __/    Draw 3 (blue): factor width/2, offset -2, depth test: Less
8699     //          |/
8700     //          |
8701     //          |
8702     //          +------------------------------->
8703     //
8704     // Result:  <----blue-----><-green-><--red-->
8705 
8706     const int w = getWindowWidth();
8707     const int h = getWindowHeight();
8708 
8709     glUniform4f(colorLoc, 1, 0, 0, 1);
8710     glPolygonOffset(getWindowWidth() / 4, 0);
8711     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8712 
8713     glUniform4f(colorLoc, 0, 1, 0, 1);
8714     glPolygonOffset(getWindowWidth() / 2, 0);
8715     glDepthFunc(GL_GREATER);
8716     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8717 
8718     glUniform4f(colorLoc, 0, 0, 1, 1);
8719     glPolygonOffset(getWindowWidth() / 2, -2);
8720     glDepthFunc(GL_LESS);
8721     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8722 
8723     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::blue);
8724     EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 4 - 1, h, GLColor::green);
8725     EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8726 
8727     ASSERT_GL_NO_ERROR();
8728 }
8729 
8730 // Tests state change for glPolygonOffsetClampEXT.
TEST_P(StateChangeTestES3,PolygonOffsetClamp)8731 TEST_P(StateChangeTestES3, PolygonOffsetClamp)
8732 {
8733     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_polygon_offset_clamp"));
8734 
8735     constexpr char kVS[] = R"(#version 300 es
8736 precision highp float;
8737 void main()
8738 {
8739     // gl_VertexID    x    y
8740     //      0        -1   -1
8741     //      1         1   -1
8742     //      2        -1    1
8743     //      3         1    1
8744     int bit0 = gl_VertexID & 1;
8745     int bit1 = gl_VertexID >> 1;
8746     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
8747 })";
8748 
8749     constexpr char kFS[] = R"(#version 300 es
8750 precision highp float;
8751 out vec4 colorOut;
8752 uniform vec4 color;
8753 void main()
8754 {
8755     colorOut = color;
8756 })";
8757 
8758     glEnable(GL_POLYGON_OFFSET_FILL);
8759 
8760     ANGLE_GL_PROGRAM(program, kVS, kFS);
8761     glUseProgram(program);
8762 
8763     GLint colorLoc = glGetUniformLocation(program, "color");
8764     ASSERT_NE(-1, colorLoc);
8765 
8766     glClearColor(0, 0, 0, 1);
8767     glClearDepthf(0);
8768     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8769 
8770     glEnable(GL_DEPTH_TEST);
8771     glDepthFunc(GL_ALWAYS);
8772 
8773     // The shader creates a depth slope from left (0) to right (1).
8774     //
8775     // This test issues two draw calls:
8776     //
8777     //           Draw 2 (green): factor width, offset 0, clamp 0.5, depth test: Greater
8778     //          ^     |       __________________
8779     //          |     |    __/      __/
8780     //          |     V __/      __/  <--- Draw 1 (red): factor width, offset 0, clamp 0.25
8781     //          |    __/      __/
8782     //          | __/      __/
8783     //          |/      __/
8784     //          |    __/
8785     //          | __/
8786     //          |/
8787     //          |
8788     //          |
8789     //          +------------------------------->
8790     //
8791     // Result:  <---------green--------><--red-->
8792 
8793     const int w = getWindowWidth();
8794     const int h = getWindowHeight();
8795 
8796     glUniform4f(colorLoc, 1, 0, 0, 1);
8797     glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.25);
8798     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8799 
8800     glUniform4f(colorLoc, 0, 1, 0, 1);
8801     glPolygonOffsetClampEXT(getWindowWidth(), 0, 0.5);
8802     glDepthFunc(GL_GREATER);
8803     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
8804 
8805     EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::green);
8806     EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
8807 
8808     ASSERT_GL_NO_ERROR();
8809 }
8810 
8811 // Tests state change for glBlendColor.
TEST_P(StateChangeTestES3,BlendColor)8812 TEST_P(StateChangeTestES3, BlendColor)
8813 {
8814     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8815     glUseProgram(program);
8816 
8817     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8818     ASSERT_NE(colorLoc, -1);
8819 
8820     glEnable(GL_BLEND);
8821     glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);
8822     glBlendColor(0.498, 0.498, 0, 1);
8823     glUniform4f(colorLoc, 1, 1, 1, 1);
8824     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8825 
8826     const int w = getWindowWidth();
8827     const int h = getWindowHeight();
8828 
8829     glEnable(GL_SCISSOR_TEST);
8830     glScissor(0, 0, w / 2, h);
8831     glBlendColor(0, 1, 0.498, 1);
8832     glUniform4f(colorLoc, 1, 0.247, 1, 1);
8833     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8834 
8835     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor(0, 63, 127, 255));
8836     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor(127, 127, 0, 255));
8837 
8838     ASSERT_GL_NO_ERROR();
8839 }
8840 
8841 // Tests state change for ref and mask in glStencilFuncSeparate.
TEST_P(StateChangeTestES3,StencilReferenceAndCompareMask)8842 TEST_P(StateChangeTestES3, StencilReferenceAndCompareMask)
8843 {
8844     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8845     glUseProgram(program);
8846 
8847     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8848     ASSERT_NE(colorLoc, -1);
8849 
8850     glClearColor(0, 0, 0, 1);
8851     glClearStencil(0x3A);
8852     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8853 
8854     glEnable(GL_STENCIL_TEST);
8855 
8856     glStencilMaskSeparate(GL_FRONT, 0xF0);
8857     glStencilMaskSeparate(GL_BACK, 0x0F);
8858 
8859     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0xB9, 0x7C);
8860     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8861 
8862     glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x99, 0xAC);
8863     glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_KEEP);
8864 
8865     const int w = getWindowWidth();
8866     const int h = getWindowHeight();
8867 
8868     // Draw front-facing.  Front stencil test should pass, replacing the top bits with 0xB:
8869     //
8870     // Current value of stencil buffer: 0x3A, mask: 0x7C, writing 0xB9
8871     //
8872     //     B9 & 7C == 38 == 3A & 7C
8873     glUniform4f(colorLoc, 1, 0, 0, 1);
8874     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8875 
8876     // Draw back-facing.  Back stencil test should fail, replacing the bottom bits with 0x9:
8877     //
8878     // Current value of stencil buffer: 0xBA, mask: 0xAC, writing 0x99
8879     //
8880     //     99 & AC == 88 != A8 == BA & AC
8881     glFrontFace(GL_CW);
8882     glDisable(GL_CULL_FACE);
8883     glEnable(GL_SCISSOR_TEST);
8884     glScissor(0, 0, w / 2, h);
8885     glUniform4f(colorLoc, 0, 1, 0, 1);
8886     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8887 
8888     // The left half of image should now have a value of B9, the right half should have BA
8889     //
8890     // Change the masks such that if the old masks are used, stencil test would fail, but if the new
8891     // mask is used it would pass.
8892     //
8893     //    Left:  B9 & 7C == 38 != 3C == 3D & 7C
8894     //           B9 & 33 == 31 == 3D & 33
8895     //
8896     //    Right: BA & AC == A8 != 28 == 3A & AC
8897     //           BA & 59 == 18 == 3A & 59
8898     //
8899     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x3D, 0x33);
8900     glStencilFuncSeparate(GL_BACK, GL_EQUAL, 0x3A, 0x59);
8901     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
8902     glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
8903 
8904     glScissor(0, 0, w, h / 2);
8905 
8906     // Draw front-facing, coloring the top-left
8907     glUniform4f(colorLoc, 1, 1, 0, 1);
8908     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8909     glFrontFace(GL_CCW);
8910     glUniform4f(colorLoc, 0, 0, 1, 1);
8911     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8912 
8913     // Verify results
8914     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
8915     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
8916     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
8917     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::red);
8918 
8919     // Verify stencil exactly
8920     glDisable(GL_SCISSOR_TEST);
8921     glStencilFunc(GL_EQUAL, 0xB9, 0xFF);
8922     glUniform4f(colorLoc, 0, 1, 1, 1);
8923     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8924 
8925     glStencilFunc(GL_EQUAL, 0xBA, 0xFF);
8926     glUniform4f(colorLoc, 1, 0, 1, 1);
8927     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8928 
8929     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::cyan);
8930     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
8931 
8932     ASSERT_GL_NO_ERROR();
8933 }
8934 
8935 // Tests state change for mask in glStencilMaskSeparate.
TEST_P(StateChangeTestES3,StencilWriteMask)8936 TEST_P(StateChangeTestES3, StencilWriteMask)
8937 {
8938     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8939     glUseProgram(program);
8940 
8941     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
8942     ASSERT_NE(colorLoc, -1);
8943 
8944     glClearColor(0, 0, 0, 1);
8945     glClearStencil(0x00);
8946     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
8947 
8948     glEnable(GL_STENCIL_TEST);
8949 
8950     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_REPLACE);
8951     glStencilOpSeparate(GL_BACK, GL_REPLACE, GL_KEEP, GL_REPLACE);
8952 
8953     const int w = getWindowWidth();
8954     const int h = getWindowHeight();
8955 
8956     // Draw front-facing to the left half, replacing the top four bits, and back-facing to the right
8957     // half, replacing the bottom four bits.
8958     glStencilMaskSeparate(GL_FRONT, 0xF0);
8959     glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x39, 0xFF);
8960     glStencilMaskSeparate(GL_BACK, 0x0F);
8961     glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x2A, 0xFF);
8962 
8963     glEnable(GL_SCISSOR_TEST);
8964     glScissor(0, 0, w / 2, h);
8965     glUniform4f(colorLoc, 1, 0, 0, 1);
8966     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8967 
8968     glDisable(GL_CULL_FACE);
8969     glFrontFace(GL_CW);
8970     glScissor(w / 2, 0, w / 2, h);
8971     glUniform4f(colorLoc, 0, 1, 0, 1);
8972     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8973 
8974     // Draw back-facing to the top-left quarter, replacing the top two bits, and front-facing to the
8975     // top-right quarter, replacing the bottom two bits.
8976     glStencilMaskSeparate(GL_FRONT, 0xC0);
8977     glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0x81, 0xFF);
8978     glStencilMaskSeparate(GL_BACK, 0x03);
8979     glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x53, 0xFF);
8980 
8981     glScissor(0, 0, w / 2, h / 2);
8982     glUniform4f(colorLoc, 0, 0, 1, 1);
8983     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8984 
8985     glFrontFace(GL_CCW);
8986     glScissor(w / 2, 0, w / 2, h / 2);
8987     glUniform4f(colorLoc, 1, 1, 0, 1);
8988     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8989 
8990     // Verify results
8991     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::blue);
8992     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
8993     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
8994     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
8995 
8996     // Verify stencil exactly.  Stencil has the following values:
8997     //
8998     //    +------+------+
8999     //    |      |      |
9000     //    |  33  |  8A  |
9001     //    |      |      |
9002     //    +------+------+
9003     //    |      |      |
9004     //    |  30  |  0A  |
9005     //    |      |      |
9006     //    +------+------+
9007     //
9008     glDisable(GL_SCISSOR_TEST);
9009     glStencilFunc(GL_EQUAL, 0x33, 0xFF);
9010     glUniform4f(colorLoc, 0, 1, 1, 1);
9011     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9012 
9013     glStencilFunc(GL_EQUAL, 0x8A, 0xFF);
9014     glUniform4f(colorLoc, 1, 0, 1, 1);
9015     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9016 
9017     glStencilFunc(GL_EQUAL, 0x30, 0xFF);
9018     glUniform4f(colorLoc, 1, 1, 1, 1);
9019     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9020 
9021     glStencilFunc(GL_EQUAL, 0x0A, 0xFF);
9022     glUniform4f(colorLoc, 0, 0, 0, 1);
9023     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9024 
9025     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9026     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9027     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9028     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9029 
9030     ASSERT_GL_NO_ERROR();
9031 }
9032 
9033 // Tests that |discard| works with stencil write mask
TEST_P(StateChangeTestES3,StencilWriteMaskVsDiscard)9034 TEST_P(StateChangeTestES3, StencilWriteMaskVsDiscard)
9035 {
9036     constexpr char kVS[] = R"(#version 300 es
9037 precision highp float;
9038 void main()
9039 {
9040     // gl_VertexID    x    y
9041     //      0        -1   -1
9042     //      1         1   -1
9043     //      2        -1    1
9044     //      3         1    1
9045     int bit0 = gl_VertexID & 1;
9046     int bit1 = gl_VertexID >> 1;
9047     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
9048 })";
9049 
9050     constexpr char kFS[] = R"(#version 300 es
9051 precision highp float;
9052 out vec4 colorOut;
9053 uniform vec4 color;
9054 uniform int flag;
9055 void main()
9056 {
9057     if (flag > 0)
9058     {
9059         discard;
9060     }
9061     colorOut = color;
9062 })";
9063 
9064     ANGLE_GL_PROGRAM(program, kVS, kFS);
9065     glUseProgram(program);
9066 
9067     GLint colorLoc = glGetUniformLocation(program, "color");
9068     ASSERT_NE(colorLoc, -1);
9069 
9070     GLint flagLoc = glGetUniformLocation(program, "flag");
9071     ASSERT_NE(flagLoc, -1);
9072 
9073     glEnable(GL_DEPTH_TEST);
9074 
9075     glClearColor(0, 0, 0, 1);
9076     glClearDepthf(1);
9077     glClearStencil(0x00);
9078     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9079 
9080     glDepthFunc(GL_LEQUAL);
9081     glDepthMask(GL_FALSE);
9082     glEnable(GL_STENCIL_TEST);
9083 
9084     // Enable stencil write, but issue a draw call where all fragments are discarded.
9085     glStencilFunc(GL_ALWAYS, 128, 128);
9086     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
9087     glStencilMask(128);
9088 
9089     glUniform4f(colorLoc, 1, 0, 0, 1);
9090     glUniform1i(flagLoc, 1);
9091     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9092 
9093     // At this point, the stencil buffer should be unmodified.  Verify it with another draw call.
9094     glStencilFunc(GL_NOTEQUAL, 128, 128);
9095     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9096     glStencilMask(128);
9097 
9098     glUniform4f(colorLoc, 0, 1, 0, 1);
9099     glUniform1i(flagLoc, 0);
9100     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9101 
9102     const int w = getWindowWidth();
9103     const int h = getWindowHeight();
9104 
9105     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9106 
9107     ASSERT_GL_NO_ERROR();
9108 }
9109 
9110 // Tests state change for glCullFace and glEnable(GL_CULL_FACE) as well as glFrontFace
TEST_P(StateChangeTestES3,CullFaceAndFrontFace)9111 TEST_P(StateChangeTestES3, CullFaceAndFrontFace)
9112 {
9113     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9114     glUseProgram(program);
9115 
9116     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9117     ASSERT_NE(colorLoc, -1);
9118 
9119     glClearColor(0, 0, 0, 1);
9120     glClear(GL_COLOR_BUFFER_BIT);
9121 
9122     const int w = getWindowWidth();
9123     const int h = getWindowHeight();
9124 
9125     // Draw red back-facing.  Face culling is initially disabled
9126     glFrontFace(GL_CW);
9127     glUniform4f(colorLoc, 1, 0, 0, 1);
9128     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9129 
9130     // Draw green back-facing, but enable face culling.  Default cull face is back.
9131     glEnable(GL_CULL_FACE);
9132     glEnable(GL_SCISSOR_TEST);
9133     glScissor(0, 0, w / 2, h / 2);
9134     glUniform4f(colorLoc, 0, 1, 0, 1);
9135     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9136 
9137     // Draw blue front-facing.
9138     glFrontFace(GL_CCW);
9139     glScissor(w / 2, 0, w / 2, h / 2);
9140     glUniform4f(colorLoc, 0, 0, 1, 1);
9141     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9142 
9143     // Draw magenta front-facing, but change cull face to front
9144     glCullFace(GL_FRONT);
9145     glScissor(0, h / 2, w / 2, h / 2);
9146     glUniform4f(colorLoc, 1, 0, 1, 1);
9147     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9148 
9149     // Draw cyan front-facing, with face culling disabled
9150     glDisable(GL_CULL_FACE);
9151     glScissor(w / 2, h / 2, w / 2, h / 2);
9152     glUniform4f(colorLoc, 0, 1, 1, 1);
9153     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9154 
9155     // Draw yellow front-facing, with cull face set to front and back
9156     glEnable(GL_CULL_FACE);
9157     glCullFace(GL_FRONT_AND_BACK);
9158     glDisable(GL_SCISSOR_TEST);
9159     glUniform4f(colorLoc, 1, 1, 0, 1);
9160     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
9161 
9162     // Verify results
9163     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9164     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9165     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::red);
9166     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9167 
9168     ASSERT_GL_NO_ERROR();
9169 }
9170 
9171 // Tests state change for draw primitive mode
TEST_P(StateChangeTestES3,PrimitiveMode)9172 TEST_P(StateChangeTestES3, PrimitiveMode)
9173 {
9174     constexpr char kVS[] = R"(#version 300 es
9175 precision highp float;
9176 
9177 // Hardcoded positions for a number of draw modes, using different vertex offsets.
9178 const vec2 kVertices[35] = vec2[35](
9179     // Two triangle
9180     vec2(-1, -1), vec2(1, -1), vec2(-1, 1),
9181     vec2(-1,  1), vec2(1, -1), vec2( 1, 1),
9182     // A triangle strip with 8 triangles
9183     vec2(   -1, -0.5), vec2(   -1,  0.5),
9184     vec2(-0.75, -0.5), vec2(-0.75,  0.5),
9185     vec2( -0.5, -0.5), vec2( -0.5,  0.5),
9186     vec2(-0.25, -0.5), vec2(-0.25,  0.5),
9187     vec2(    0, -0.5), vec2(    0,  0.5),
9188     // A triangle fan with 4 triangles
9189     vec2(0.5, 0), vec2(1, -0.5), vec2(1, 0.5), vec2(0, 0.5), vec2(0, -0.5), vec2(1, -0.5),
9190     // One line
9191     vec2(-1, -0.49), vec2(1, -0.49),
9192     // One line strip
9193     vec2(-1, 0.51), vec2(0, 0.51), vec2(1, 0.51),
9194     // One line loop
9195     vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99),
9196     // Four points
9197     vec2(-.99, -.99), vec2(0.99, -.99), vec2(0.99, 0.99), vec2(-.99, 0.99)
9198 );
9199 
9200 void main()
9201 {
9202     gl_Position = vec4(kVertices[gl_VertexID], 0, 1);
9203     gl_PointSize = 1.;
9204 })";
9205 
9206     constexpr char kFS[] = R"(#version 300 es
9207 precision highp float;
9208 out vec4 colorOut;
9209 uniform vec4 color;
9210 void main()
9211 {
9212     colorOut = color;
9213 })";
9214 
9215     ANGLE_GL_PROGRAM(program, kVS, kFS);
9216     glUseProgram(program);
9217 
9218     GLint colorLoc = glGetUniformLocation(program, "color");
9219     ASSERT_NE(colorLoc, -1);
9220 
9221     glClearColor(0, 0, 0, 1);
9222     glClear(GL_COLOR_BUFFER_BIT);
9223 
9224     // Draw the following:
9225     //
9226     // 1. Red with two triangles
9227     // 2. Green with a triangle strip
9228     // 3. Blue with a triangle fan
9229     // 4. Yellow with a line
9230     // 5. Cyan with a line strip
9231     // 6. Magenta with a line loop
9232     // 7. White with four points
9233     //
9234     //
9235     //     +---------------------------+  <-- 7: corners
9236     //     |                           |
9237     //     |             1             |
9238     //     |                           |
9239     //     +-------------+-------------+  <-- 5: horizontal line
9240     //     |             |             |
9241     //     |             |             |
9242     //     |             |             |
9243     //     |      2      |      3      |  <-- 6: border around image
9244     //     |             |             |
9245     //     |             |             |
9246     //     |             |             |
9247     //     +-------------+-------------+  <-- 4: horizontal line
9248     //     |                           |
9249     //     |             1             |
9250     //     |                           |
9251     //     +---------------------------+
9252 
9253     glUniform4f(colorLoc, 1, 0, 0, 1);
9254     glDrawArrays(GL_TRIANGLES, 0, 6);
9255 
9256     glUniform4f(colorLoc, 0, 1, 0, 1);
9257     glDrawArrays(GL_TRIANGLE_STRIP, 6, 10);
9258 
9259     glUniform4f(colorLoc, 0, 0, 1, 1);
9260     glDrawArrays(GL_TRIANGLE_FAN, 16, 6);
9261 
9262     glUniform4f(colorLoc, 1, 1, 0, 1);
9263     glDrawArrays(GL_LINES, 22, 2);
9264 
9265     glUniform4f(colorLoc, 0, 1, 1, 1);
9266     glDrawArrays(GL_LINE_STRIP, 24, 3);
9267 
9268     glUniform4f(colorLoc, 1, 0, 1, 1);
9269     glDrawArrays(GL_LINE_LOOP, 27, 4);
9270 
9271     glUniform4f(colorLoc, 1, 1, 1, 1);
9272     glDrawArrays(GL_POINTS, 31, 4);
9273 
9274     const int w = getWindowWidth();
9275     const int h = getWindowHeight();
9276 
9277     // Verify results
9278     EXPECT_PIXEL_RECT_EQ(1, 1, w - 2, h / 4 - 2, GLColor::red);
9279     EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4 + 1, w - 2, h / 4 - 2, GLColor::red);
9280 
9281     EXPECT_PIXEL_RECT_EQ(1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::green);
9282 
9283     EXPECT_PIXEL_RECT_EQ(w / 2 + 1, h / 4 + 1, w / 2 - 2, h / 2 - 2, GLColor::blue);
9284 
9285     EXPECT_PIXEL_RECT_EQ(1, h / 4, w / 2 - 2, 1, GLColor::yellow);
9286 
9287     EXPECT_PIXEL_RECT_EQ(1, 3 * h / 4, w / 2 - 2, 1, GLColor::cyan);
9288 
9289     EXPECT_PIXEL_RECT_EQ(1, 0, w - 2, 1, GLColor::magenta);
9290     EXPECT_PIXEL_RECT_EQ(0, 1, 1, h - 2, GLColor::magenta);
9291     EXPECT_PIXEL_RECT_EQ(w - 1, 1, 1, h - 2, GLColor::magenta);
9292     EXPECT_PIXEL_RECT_EQ(1, h - 1, w - 2, 1, GLColor::magenta);
9293 
9294     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
9295     EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::white);
9296     EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::white);
9297     EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::white);
9298 
9299     ASSERT_GL_NO_ERROR();
9300 }
9301 
9302 // Tests that vertex attributes are correctly bound after a masked clear.  In the Vulkan backend,
9303 // the masked clear is done with an internal shader that doesn't use vertex attributes.
TEST_P(StateChangeTestES3,DrawMaskedClearDraw)9304 TEST_P(StateChangeTestES3, DrawMaskedClearDraw)
9305 {
9306     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9307     glUseProgram(program);
9308 
9309     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9310     ASSERT_NE(colorLoc, -1);
9311 
9312     GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
9313     ASSERT_EQ(0, posAttrib);
9314 
9315     std::array<GLfloat, 3 * 4> positionData = {
9316         -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9317     };
9318 
9319     GLBuffer posBuffer;
9320     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9321     glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9322     glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9323     glEnableVertexAttribArray(posAttrib);
9324 
9325     const int w = getWindowWidth();
9326     const int h = getWindowHeight();
9327 
9328     glClearColor(0, 0, 0, 1);
9329     glClear(GL_COLOR_BUFFER_BIT);
9330 
9331     glEnable(GL_BLEND);
9332     glBlendFunc(GL_ONE, GL_ONE);
9333 
9334     // Draw to red and alpha channels, with garbage in green and blue
9335     glUniform4f(colorLoc, 1, 0.123f, 0.456f, 0.5f);
9336     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9337 
9338     // Clear the green and blue channels
9339     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE);
9340     glClearColor(0.333f, 0.5, 0, 0.888f);
9341     glClear(GL_COLOR_BUFFER_BIT);
9342 
9343     // Blend in to saturate green and alpha
9344     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
9345     glUniform4f(colorLoc, 0, 0.6f, 0, 0.6f);
9346     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9347 
9348     // Verify results
9349     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::yellow);
9350 
9351     ASSERT_GL_NO_ERROR();
9352 }
9353 
9354 // Tests state change for vertex attribute stride
TEST_P(StateChangeTestES3,VertexStride)9355 TEST_P(StateChangeTestES3, VertexStride)
9356 {
9357     constexpr char kVS[] =
9358         R"(#version 300 es
9359 precision mediump float;
9360 in vec4 position;
9361 layout(location = 1) in vec4 test;
9362 layout(location = 5) in vec4 expected;
9363 out vec4 result;
9364 void main(void)
9365 {
9366     gl_Position = position;
9367     if (any(equal(test, vec4(0))) || any(equal(expected, vec4(0))))
9368     {
9369         result = vec4(0);
9370     }
9371     else
9372     {
9373         vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
9374         result = vec4(lessThanEqual(abs(test - expected), threshold));
9375     }
9376 })";
9377 
9378     constexpr char kFS[] =
9379         R"(#version 300 es
9380 precision mediump float;
9381 in vec4 result;
9382 out vec4 colorOut;
9383 void main()
9384 {
9385     colorOut = vec4(greaterThanEqual(result, vec4(0.999)));
9386 })";
9387 
9388     ANGLE_GL_PROGRAM(program, kVS, kFS);
9389     glUseProgram(program);
9390 
9391     // Every draw call consists of 4 vertices.  The vertex attributes are laid out as follows:
9392     //
9393     // Position: No gaps
9394     // test: 4 unorm vertices with stride 20, simultaneously 4 vertices with stride 16
9395     // expected: 4 float vertices with stride 80, simultaneously 4 vertices with stride 48
9396 
9397     const std::array<GLubyte, 7 * 4> kData = {{1,   2,   3,   4,   5,   6,   7,  8,  125, 126,
9398                                                127, 128, 129, 250, 251, 252, 78, 79, 80,  81,
9399                                                155, 156, 157, 158, 20,  21,  22, 23}};
9400 
9401     constexpr size_t kTestStride1     = 20;
9402     constexpr size_t kTestStride2     = 16;
9403     constexpr size_t kExpectedStride1 = 20;
9404     constexpr size_t kExpectedStride2 = 12;
9405 
9406     std::array<GLubyte, kTestStride1 * 3 + 4> testInitData         = {};
9407     std::array<GLfloat, kExpectedStride1 * 3 + 4> expectedInitData = {};
9408 
9409     for (uint32_t vertex = 0; vertex < 7; ++vertex)
9410     {
9411         size_t testOffset     = vertex * kTestStride1;
9412         size_t expectedOffset = vertex * kExpectedStride1;
9413         if (vertex >= 4)
9414         {
9415             testOffset     = (vertex - 3) * kTestStride2;
9416             expectedOffset = (vertex - 3) * kExpectedStride2;
9417         }
9418 
9419         for (uint32_t channel = 0; channel < 4; ++channel)
9420         {
9421             // The strides are chosen such that the two streams don't collide
9422             ASSERT_EQ(testInitData[testOffset + channel], 0);
9423             ASSERT_EQ(expectedInitData[expectedOffset + channel], 0);
9424 
9425             GLubyte data                               = kData[vertex * 4 + channel];
9426             testInitData[testOffset + channel]         = data;
9427             expectedInitData[expectedOffset + channel] = data;
9428         }
9429 
9430         // For the first 4 vertices, expect perfect match (i.e. get white).  For the last 3
9431         // vertices, expect the green channel test to fail (i.e. get magenta).
9432         if (vertex >= 4)
9433         {
9434             expectedInitData[expectedOffset + 1] += 2;
9435         }
9436     }
9437 
9438     std::array<GLfloat, 3 * 4> positionData = {
9439         -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0,
9440     };
9441 
9442     GLBuffer posBuffer;
9443     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9444     glBufferData(GL_ARRAY_BUFFER, sizeof(positionData), positionData.data(), GL_STATIC_DRAW);
9445 
9446     GLBuffer testBuffer;
9447     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9448     glBufferData(GL_ARRAY_BUFFER, sizeof(testInitData), testInitData.data(), GL_STATIC_DRAW);
9449 
9450     GLBuffer expectedBuffer;
9451     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9452     glBufferData(GL_ARRAY_BUFFER, sizeof(expectedInitData), expectedInitData.data(),
9453                  GL_STATIC_DRAW);
9454 
9455     GLint posAttrib = glGetAttribLocation(program, "position");
9456     ASSERT_EQ(0, posAttrib);
9457     GLint testAttrib = glGetAttribLocation(program, "test");
9458     ASSERT_EQ(1, testAttrib);
9459     GLint expectedAttrib = glGetAttribLocation(program, "expected");
9460     ASSERT_EQ(5, expectedAttrib);
9461 
9462     const int w = getWindowWidth();
9463     const int h = getWindowHeight();
9464 
9465     glClearColor(0, 0, 0, 1);
9466     glClear(GL_COLOR_BUFFER_BIT);
9467 
9468     glEnableVertexAttribArray(posAttrib);
9469     glEnableVertexAttribArray(testAttrib);
9470     glEnableVertexAttribArray(expectedAttrib);
9471 
9472     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
9473     glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
9474     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9475     glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride1 * sizeof(GLubyte),
9476                           nullptr);
9477     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9478     glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride1 * sizeof(GLfloat),
9479                           nullptr);
9480 
9481     glEnable(GL_SCISSOR_TEST);
9482     glScissor(0, 0, w / 2, h);
9483     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9484 
9485     glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
9486     glVertexAttribPointer(testAttrib, 4, GL_UNSIGNED_BYTE, GL_FALSE, kTestStride2 * sizeof(GLubyte),
9487                           nullptr);
9488     glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer);
9489     glVertexAttribPointer(expectedAttrib, 4, GL_FLOAT, GL_FALSE, kExpectedStride2 * sizeof(GLfloat),
9490                           nullptr);
9491 
9492     glScissor(w / 2, 0, w / 2, h);
9493     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
9494 
9495     // Verify results
9496     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h, GLColor::white);
9497     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h, GLColor::magenta);
9498 
9499     ASSERT_GL_NO_ERROR();
9500 }
9501 
9502 // Tests state change for vertex attribute format
TEST_P(StateChangeTestES3,VertexFormat)9503 TEST_P(StateChangeTestES3, VertexFormat)
9504 {
9505     constexpr char kVS[] = R"(precision highp float;
9506 attribute vec3 position;
9507 attribute vec4 color;
9508 varying vec4 colorOut;
9509 
9510 void main()
9511 {
9512     gl_Position = vec4(position, 1.0);
9513     colorOut = color;
9514 })";
9515 
9516     constexpr char kFS[] = R"(precision highp float;
9517 varying vec4 colorOut;
9518 
9519 void main()
9520 {
9521     gl_FragColor = colorOut;
9522 })";
9523 
9524     ANGLE_GL_PROGRAM(program, kVS, kFS);
9525     glUseProgram(program);
9526 
9527     GLint positionLoc = glGetAttribLocation(program, "position");
9528     ASSERT_NE(positionLoc, -1);
9529     GLint colorLoc = glGetAttribLocation(program, "color");
9530     ASSERT_NE(colorLoc, -1);
9531 
9532     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
9533     glClear(GL_COLOR_BUFFER_BIT);
9534 
9535     std::vector<Vector4> colorAttribDataFloat(6, Vector4(255.0f, 0.0f, 0.0f, 255.0f));
9536     std::vector<GLColor> colorAttribDataUnsignedByte(6, GLColor::green);
9537 
9538     // Setup position attribute
9539     std::array<Vector3, 6> quadVertices = GetQuadVertices();
9540     GLBuffer vertexLocationBuffer;
9541     glBindBuffer(GL_ARRAY_BUFFER, vertexLocationBuffer);
9542     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
9543     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
9544     glEnableVertexAttribArray(positionLoc);
9545 
9546     // Setup color attribute with float data
9547     GLBuffer floatBuffer;
9548     glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
9549     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector4) * 6, colorAttribDataFloat.data(), GL_STATIC_DRAW);
9550     glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
9551     glEnableVertexAttribArray(colorLoc);
9552 
9553     // Draw red using float attribute
9554     glDrawArrays(GL_TRIANGLES, 0, 6);
9555     ASSERT_GL_NO_ERROR();
9556     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
9557 
9558     // Setup color attribute with unsigned byte data
9559     GLBuffer unsignedByteBuffer;
9560     glBindBuffer(GL_ARRAY_BUFFER, unsignedByteBuffer);
9561     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, colorAttribDataUnsignedByte.data(),
9562                  GL_STATIC_DRAW);
9563     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
9564     glEnableVertexAttribArray(colorLoc);
9565 
9566     // Draw green using unsigned byte attribute
9567     glDrawArrays(GL_TRIANGLES, 0, 6);
9568     ASSERT_GL_NO_ERROR();
9569     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
9570 
9571     glUseProgram(0);
9572     glBindBuffer(GL_ARRAY_BUFFER, 0);
9573 }
9574 
9575 // Tests state change for depth test, write and function
TEST_P(StateChangeTestES3,DepthTestWriteAndFunc)9576 TEST_P(StateChangeTestES3, DepthTestWriteAndFunc)
9577 {
9578     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9579     glUseProgram(program);
9580 
9581     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9582     ASSERT_NE(colorLoc, -1);
9583 
9584     const int w = getWindowWidth();
9585     const int h = getWindowHeight();
9586 
9587     glClearColor(0, 0, 0, 1);
9588     glClearDepthf(0.5);
9589     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9590 
9591     // Initialize the depth buffer:
9592     glEnable(GL_DEPTH_TEST);
9593     glDepthMask(GL_TRUE);
9594     glDepthFunc(GL_ALWAYS);
9595 
9596     glEnable(GL_SCISSOR_TEST);
9597     glScissor(0, 0, w / 2, h / 2);
9598     glUniform4f(colorLoc, 0, 0, 0, 1);
9599     drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9600     glScissor(w / 2, 0, w / 2, h / 2);
9601     drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9602     glScissor(0, h / 2, w / 2, h / 2);
9603     drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9604     glScissor(w / 2, h / 2, w / 2, h / 2);
9605     drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9606 
9607     glDisable(GL_SCISSOR_TEST);
9608     glDisable(GL_DEPTH_TEST);
9609     glDepthMask(GL_FALSE);
9610     glUniform4f(colorLoc, 1, 0, 0, 1);
9611     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9612 
9613     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9614 
9615     // Make draw calls that test depth or not, write depth or not, and use different functions
9616 
9617     // Write green to one half
9618     glEnable(GL_DEPTH_TEST);
9619     glDepthFunc(GL_LESS);
9620     glUniform4f(colorLoc, 0, 1, 0, 1);
9621     drawQuad(program, essl1_shaders::PositionAttrib(), 0.35f);
9622 
9623     // Write blue to another half
9624     glDepthFunc(GL_GREATER);
9625     glUniform4f(colorLoc, 0, 0, 1, 1);
9626     drawQuad(program, essl1_shaders::PositionAttrib(), -0.15f);
9627 
9628     // Write yellow to a corner, overriding depth
9629     glDepthMask(GL_TRUE);
9630     glUniform4f(colorLoc, 1, 1, 0, 1);
9631     drawQuad(program, essl1_shaders::PositionAttrib(), -0.6f);
9632 
9633     // Write magenta to another corner, overriding depth
9634     glDepthFunc(GL_LESS);
9635     glUniform4f(colorLoc, 1, 0, 1, 1);
9636     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
9637 
9638     // No-op write
9639     glDepthFunc(GL_NEVER);
9640     glUniform4f(colorLoc, 0, 1, 1, 1);
9641     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9642 
9643     // Verify results
9644     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::yellow);
9645     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::blue);
9646     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9647     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::magenta);
9648 
9649     // Verify the depth buffer
9650     glDepthMask(GL_FALSE);
9651     glDepthFunc(GL_LESS);
9652     glUniform4f(colorLoc, 1, 0, 0, 1);
9653     drawQuad(program, essl1_shaders::PositionAttrib(), -0.61f);
9654     glUniform4f(colorLoc, 0, 0, 0, 1);
9655     drawQuad(program, essl1_shaders::PositionAttrib(), -0.59f);
9656 
9657     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9658     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9659     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9660     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9661 
9662     glDepthFunc(GL_GREATER);
9663     glUniform4f(colorLoc, 0, 1, 1, 1);
9664     drawQuad(program, essl1_shaders::PositionAttrib(), 0.51f);
9665     glUniform4f(colorLoc, 0, 0, 0, 1);
9666     drawQuad(program, essl1_shaders::PositionAttrib(), 0.49f);
9667 
9668     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9669     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
9670     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
9671     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::cyan);
9672 
9673     glDepthFunc(GL_LESS);
9674     glUniform4f(colorLoc, 0, 1, 0, 1);
9675     drawQuad(program, essl1_shaders::PositionAttrib(), -0.21f);
9676     glUniform4f(colorLoc, 1, 1, 1, 1);
9677     drawQuad(program, essl1_shaders::PositionAttrib(), -0.19f);
9678 
9679     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::black);
9680     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::green);
9681     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9682     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9683 
9684     glDepthFunc(GL_GREATER);
9685     glUniform4f(colorLoc, 0, 0, 1, 1);
9686     drawQuad(program, essl1_shaders::PositionAttrib(), 0.41f);
9687     glUniform4f(colorLoc, 1, 0, 1, 1);
9688     drawQuad(program, essl1_shaders::PositionAttrib(), 0.39f);
9689 
9690     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::magenta);
9691     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9692     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::blue);
9693     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::white);
9694 
9695     ASSERT_GL_NO_ERROR();
9696 }
9697 
9698 // Tests state change for depth test while depth write is enabled
TEST_P(StateChangeTestES3,DepthTestToggleWithDepthWrite)9699 TEST_P(StateChangeTestES3, DepthTestToggleWithDepthWrite)
9700 {
9701     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9702     glUseProgram(program);
9703 
9704     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9705     ASSERT_NE(colorLoc, -1);
9706 
9707     const int w = getWindowWidth();
9708     const int h = getWindowHeight();
9709 
9710     glClearColor(0, 0, 0, 1);
9711     glClearDepthf(0.5);
9712     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9713 
9714     // Enable depth write, but keep depth test disabled.  Internally, depth write may be disabled
9715     // because of the depth test.
9716     glDisable(GL_DEPTH_TEST);
9717     glDepthMask(GL_TRUE);
9718     glDepthFunc(GL_LESS);
9719 
9720     // Draw with a different depth, but because depth test is disabled, depth is not actually
9721     // changed.
9722     glUniform4f(colorLoc, 1, 0, 0, 1);
9723     drawQuad(program, essl1_shaders::PositionAttrib(), -0.3f);
9724 
9725     // Enable depth test, but don't change state otherwise.  The following draw must change depth.
9726     glEnable(GL_DEPTH_TEST);
9727 
9728     glUniform4f(colorLoc, 0, 1, 0, 1);
9729     drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9730 
9731     // Verify that depth was changed in the last draw call.
9732     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
9733 
9734     glDepthFunc(GL_GREATER);
9735     glUniform4f(colorLoc, 0, 0, 1, 1);
9736     drawQuad(program, essl1_shaders::PositionAttrib(), -0.1f);
9737     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
9738     ASSERT_GL_NO_ERROR();
9739 }
9740 
9741 // Tests state change for stencil test and function
TEST_P(StateChangeTestES3,StencilTestAndFunc)9742 TEST_P(StateChangeTestES3, StencilTestAndFunc)
9743 {
9744     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9745     glUseProgram(program);
9746 
9747     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9748     ASSERT_NE(colorLoc, -1);
9749 
9750     const int w = getWindowWidth();
9751     const int h = getWindowHeight();
9752 
9753     glClearColor(0, 0, 0, 1);
9754     glClearDepthf(0.5);
9755     glClearStencil(0x55);
9756     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
9757 
9758     // Initialize the depth and stencil buffers
9759     glEnable(GL_DEPTH_TEST);
9760     glDepthMask(GL_TRUE);
9761     glDepthFunc(GL_ALWAYS);
9762 
9763     glEnable(GL_STENCIL_TEST);
9764     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
9765 
9766     glEnable(GL_SCISSOR_TEST);
9767     glScissor(0, 0, w / 2, h / 2);
9768     glUniform4f(colorLoc, 0, 0, 0, 1);
9769     glStencilFunc(GL_ALWAYS, 0x3E, 0xFF);
9770     drawQuad(program, essl1_shaders::PositionAttrib(), -0.8f);
9771     glScissor(w / 2, 0, w / 2, h / 2);
9772     glStencilFunc(GL_ALWAYS, 0xA7, 0xFF);
9773     drawQuad(program, essl1_shaders::PositionAttrib(), -0.2f);
9774     glScissor(0, h / 2, w / 2, h / 2);
9775     glStencilFunc(GL_ALWAYS, 0x6C, 0xFF);
9776     drawQuad(program, essl1_shaders::PositionAttrib(), 0.4f);
9777     glScissor(w / 2, h / 2, w / 2, h / 2);
9778     glStencilFunc(GL_ALWAYS, 0x5B, 0xFF);
9779     drawQuad(program, essl1_shaders::PositionAttrib(), 0.6f);
9780 
9781     glDisable(GL_SCISSOR_TEST);
9782     glDisable(GL_DEPTH_TEST);
9783     glDisable(GL_STENCIL_TEST);
9784     glDepthMask(GL_FALSE);
9785     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
9786     glUniform4f(colorLoc, 1, 0, 0, 1);
9787     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9788 
9789     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9790 
9791     // Make draw calls that manipulate stencil and use different functions and ops.
9792 
9793     // Current color/depth/stencil in the four sections of the image:
9794     //
9795     //     red/-0.8/3E    red/-0.2/A7
9796     //     red/ 0.4/6C    red/0.6/5B
9797     //
9798     glEnable(GL_DEPTH_TEST);
9799     glDepthFunc(GL_LESS);
9800     glEnable(GL_STENCIL_TEST);
9801     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x2C, 0x2C);
9802     glStencilOpSeparate(GL_FRONT, GL_INCR, GL_DECR, GL_INVERT);
9803     glStencilFuncSeparate(GL_BACK, GL_GREATER, 0x7B, 0xFF);
9804     glStencilOpSeparate(GL_BACK, GL_INCR, GL_ZERO, GL_REPLACE);
9805 
9806     // Draw green front-facing to get:
9807     //
9808     //       red/-0.8/3D    red/-0.2/A8
9809     //     green/ 0.4/93    red/ 0.6/5C
9810     //
9811     glUniform4f(colorLoc, 0, 1, 0, 1);
9812     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9813 
9814     // Draw blue back-facing to get:
9815     //
9816     //       red/-0.8/00    red/-0.2/A9
9817     //     green/ 0.4/94   blue/ 0.6/7B
9818     //
9819     glFrontFace(GL_CW);
9820     glUniform4f(colorLoc, 0, 0, 1, 1);
9821     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9822 
9823     glStencilFuncSeparate(GL_FRONT, GL_LEQUAL, 0x42, 0x42);
9824     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_INCR_WRAP);
9825     glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0x00, 0x00);
9826     glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_INVERT);
9827 
9828     // Draw yellow back-facing to get:
9829     //
9830     //    yellow/-0.8/FF yellow/-0.2/56
9831     //     green/ 0.4/95   blue/ 0.6/7C
9832     //
9833     glDepthFunc(GL_GREATER);
9834     glUniform4f(colorLoc, 1, 1, 0, 1);
9835     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9836 
9837     // Draw cyan front-facing to get:
9838     //
9839     //      cyan/-0.8/00 yellow/-0.2/55
9840     //     green/ 0.4/95   blue/ 0.6/7C
9841     //
9842     glFrontFace(GL_CCW);
9843     glUniform4f(colorLoc, 0, 1, 1, 1);
9844     drawQuad(program, essl1_shaders::PositionAttrib(), -0.5);
9845 
9846     // No-op draw
9847     glStencilFuncSeparate(GL_FRONT, GL_NEVER, 0x00, 0x00);
9848     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INVERT, GL_INVERT);
9849     glUniform4f(colorLoc, 1, 0, 1, 1);
9850     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9851 
9852     // Verify results
9853     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::cyan);
9854     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9855     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9856     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9857 
9858     // Verify the stencil buffer
9859     glDisable(GL_DEPTH_TEST);
9860     glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP);
9861     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x00, 0xFF);
9862     glUniform4f(colorLoc, 1, 0, 0, 1);
9863     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9864 
9865     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9866     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::yellow);
9867     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9868     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9869 
9870     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x55, 0xFF);
9871     glUniform4f(colorLoc, 1, 0, 1, 1);
9872     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9873 
9874     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9875     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9876     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::green);
9877     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9878 
9879     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x95, 0xFF);
9880     glUniform4f(colorLoc, 1, 1, 1, 1);
9881     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9882 
9883     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9884     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9885     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9886     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::blue);
9887 
9888     glStencilFuncSeparate(GL_FRONT, GL_EQUAL, 0x7C, 0xFF);
9889     glUniform4f(colorLoc, 0, 0, 0, 1);
9890     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9891 
9892     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
9893     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::magenta);
9894     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::white);
9895     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::black);
9896 
9897     ASSERT_GL_NO_ERROR();
9898 }
9899 
9900 // Tests state change for rasterizer discard
TEST_P(StateChangeTestES3,RasterizerDiscard)9901 TEST_P(StateChangeTestES3, RasterizerDiscard)
9902 {
9903     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
9904     glUseProgram(program);
9905 
9906     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
9907     ASSERT_NE(colorLoc, -1);
9908 
9909     const int w = getWindowWidth();
9910     const int h = getWindowHeight();
9911 
9912     glClearColor(0, 0, 0, 0);
9913     glClear(GL_COLOR_BUFFER_BIT);
9914 
9915     glEnable(GL_BLEND);
9916     glBlendFunc(GL_ONE, GL_ONE);
9917 
9918     // Start a render pass and issue three draw calls with the middle one having rasterizer discard
9919     // enabled.
9920     glUniform4f(colorLoc, 1, 0, 0, 0);
9921     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9922 
9923     glEnable(GL_RASTERIZER_DISCARD);
9924 
9925     glUniform4f(colorLoc, 0, 1, 1, 0);
9926     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9927 
9928     glDisable(GL_RASTERIZER_DISCARD);
9929 
9930     glUniform4f(colorLoc, 0, 0, 0, 1);
9931     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9932 
9933     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9934 
9935     // Enable rasterizer discard and make sure the state is effective.
9936     glEnable(GL_RASTERIZER_DISCARD);
9937 
9938     glUniform4f(colorLoc, 0, 1, 0, 1);
9939     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9940 
9941     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::red);
9942 
9943     // Start a render pass and issue three draw calls with the first and last ones having rasterizer
9944     // discard enabled.
9945     glUniform4f(colorLoc, 0, 1, 0, 0);
9946     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9947 
9948     glDisable(GL_RASTERIZER_DISCARD);
9949 
9950     glUniform4f(colorLoc, 0, 0, 1, 0);
9951     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9952 
9953     glEnable(GL_RASTERIZER_DISCARD);
9954 
9955     glUniform4f(colorLoc, 0, 1, 0, 1);
9956     drawQuad(program, essl1_shaders::PositionAttrib(), 0);
9957 
9958     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::magenta);
9959 
9960     ASSERT_GL_NO_ERROR();
9961 }
9962 
9963 // Tests state change for GL_POLYGON_OFFSET_FILL.
TEST_P(StateChangeTestES3,PolygonOffsetFill)9964 TEST_P(StateChangeTestES3, PolygonOffsetFill)
9965 {
9966     constexpr char kVS[] = R"(#version 300 es
9967 precision highp float;
9968 void main()
9969 {
9970     // gl_VertexID    x    y
9971     //      0        -1   -1
9972     //      1         1   -1
9973     //      2        -1    1
9974     //      3         1    1
9975     int bit0 = gl_VertexID & 1;
9976     int bit1 = gl_VertexID >> 1;
9977     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
9978 })";
9979 
9980     constexpr char kFS[] = R"(#version 300 es
9981 precision highp float;
9982 out vec4 colorOut;
9983 uniform vec4 color;
9984 void main()
9985 {
9986     colorOut = color;
9987 })";
9988 
9989     ANGLE_GL_PROGRAM(program, kVS, kFS);
9990     glUseProgram(program);
9991 
9992     GLint colorLoc = glGetUniformLocation(program, "color");
9993     ASSERT_NE(-1, colorLoc);
9994 
9995     glClearColor(0, 0, 0, 1);
9996     glClearDepthf(0);
9997     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9998 
9999     // The shader creates a depth slope from left (0) to right (1).
10000     //
10001     // This test issues three draw calls:
10002     //
10003     //
10004     //           Draw 3 (blue): factor width/2, enabled, depth test: Greater
10005     //          ^     |       __________________
10006     //          |     |    __/      __/      __/
10007     //          |     V __/      __/      __/
10008     //          |    __/      __/      __/
10009     //          | __/      __/      __/
10010     //          |/      __/^     __/
10011     //          |    __/   |  __/   <--- Draw 2: factor width/2, disabled, depth test: Greater
10012     //          | __/      _\/
10013     //          |/      __/  \
10014     //          |    __/      Draw 1 (red): factor width/4, enabled
10015     //          | __/
10016     //          +/------------------------------>
10017     //
10018     // Result:  <-------magenta-------><--red-->
10019 
10020     glEnable(GL_BLEND);
10021     glBlendFunc(GL_ONE, GL_ONE);
10022 
10023     glEnable(GL_DEPTH_TEST);
10024     glDepthFunc(GL_ALWAYS);
10025 
10026     glEnable(GL_POLYGON_OFFSET_FILL);
10027 
10028     const int w = getWindowWidth();
10029     const int h = getWindowHeight();
10030 
10031     glUniform4f(colorLoc, 1, 0, 0, 1);
10032     glPolygonOffset(getWindowWidth() / 4, 0);
10033     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10034 
10035     glUniform4f(colorLoc, 0, 1, 0, 1);
10036     glPolygonOffset(getWindowWidth() / 2, 0);
10037     glDepthFunc(GL_GREATER);
10038     glDisable(GL_POLYGON_OFFSET_FILL);
10039     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10040 
10041     glUniform4f(colorLoc, 0, 0, 1, 1);
10042     glEnable(GL_POLYGON_OFFSET_FILL);
10043     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10044 
10045     EXPECT_PIXEL_RECT_EQ(0, 0, 3 * w / 4 - 1, h, GLColor::magenta);
10046     EXPECT_PIXEL_RECT_EQ(3 * w / 4 + 1, 0, w / 4 - 1, h, GLColor::red);
10047 
10048     ASSERT_GL_NO_ERROR();
10049 }
10050 
10051 // Tests state change for GL_PRIMITIVE_RESTART.
TEST_P(StateChangeTestES3,PrimitiveRestart)10052 TEST_P(StateChangeTestES3, PrimitiveRestart)
10053 {
10054     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10055     glUseProgram(program);
10056 
10057     GLint colorLoc = glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
10058     ASSERT_NE(colorLoc, -1);
10059 
10060     GLint posAttrib = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
10061     ASSERT_EQ(0, posAttrib);
10062 
10063     // Arrange the vertices as such:
10064     //
10065     //     1      3      4
10066     //      +-----+-----+
10067     //      |     |     |
10068     //      |     |     |
10069     //      |     |     |
10070     //      |     |     |
10071     //      |     |     |
10072     //      |     |     |
10073     //      +-----+-----+
10074     //     0      2     FF
10075     //
10076     // Drawing a triangle strip, without primitive restart, the whole framebuffer is rendered, while
10077     // with primitive restart only the left half is.
10078     std::vector<Vector3> positionData(256, {0, 0, 0});
10079 
10080     positionData[0]    = Vector3(-1, -1, 0);
10081     positionData[1]    = Vector3(-1, 1, 0);
10082     positionData[2]    = Vector3(0, -1, 0);
10083     positionData[3]    = Vector3(0, 1, 0);
10084     positionData[0xFF] = Vector3(1, -1, 0);
10085     positionData[4]    = Vector3(1, 1, 0);
10086 
10087     constexpr std::array<GLubyte, 6> indices = {0, 1, 2, 3, 0xFF, 4};
10088 
10089     GLBuffer posBuffer;
10090     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
10091     glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(positionData[0]),
10092                  positionData.data(), GL_STATIC_DRAW);
10093     glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
10094     glEnableVertexAttribArray(posAttrib);
10095 
10096     GLBuffer indexBuffer;
10097     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
10098     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
10099 
10100     const int w = getWindowWidth();
10101     const int h = getWindowHeight();
10102 
10103     glClearColor(0, 0, 0, 1);
10104     glClear(GL_COLOR_BUFFER_BIT);
10105 
10106     glEnable(GL_BLEND);
10107     glBlendFunc(GL_ONE, GL_ONE);
10108 
10109     // Draw red with primitive restart enabled
10110     glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10111     glUniform4f(colorLoc, 1, 0, 0, 0);
10112     glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10113 
10114     // Draw green with primitive restart disabled
10115     glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10116     glUniform4f(colorLoc, 0, 1, 0, 1);
10117     glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10118 
10119     // Draw blue with primitive restart enabled again
10120     glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10121     glUniform4f(colorLoc, 0, 0, 1, 0);
10122     glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE, nullptr);
10123 
10124     // Verify results
10125     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2 - 1, h, GLColor::white);
10126     EXPECT_PIXEL_RECT_EQ(w / 2 + 1, 0, w / 2 - 1, h, GLColor::green);
10127 
10128     ASSERT_GL_NO_ERROR();
10129 }
10130 
10131 // Tests that primitive restart for patches can be queried when tessellation shaders are available,
10132 // and that its value is independent of whether primitive restart is enabled.
TEST_P(StateChangeTestES31,PrimitiveRestartForPatchQuery)10133 TEST_P(StateChangeTestES31, PrimitiveRestartForPatchQuery)
10134 {
10135     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
10136 
10137     glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10138     GLint primitiveRestartForPatchesWhenEnabled = -1;
10139     glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10140                   &primitiveRestartForPatchesWhenEnabled);
10141     ASSERT_GL_NO_ERROR();
10142     EXPECT_GE(primitiveRestartForPatchesWhenEnabled, 0);
10143 
10144     glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
10145     GLint primitiveRestartForPatchesWhenDisabled = -1;
10146     glGetIntegerv(GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED,
10147                   &primitiveRestartForPatchesWhenDisabled);
10148     ASSERT_GL_NO_ERROR();
10149     EXPECT_GE(primitiveRestartForPatchesWhenDisabled, 0);
10150 
10151     EXPECT_EQ(primitiveRestartForPatchesWhenEnabled, primitiveRestartForPatchesWhenDisabled);
10152 }
10153 
10154 // Tests state change for GL_COLOR_LOGIC_OP and glLogicOp.
TEST_P(StateChangeTestES3,LogicOp)10155 TEST_P(StateChangeTestES3, LogicOp)
10156 {
10157     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_logic_op"));
10158 
10159     constexpr char kVS[] = R"(#version 300 es
10160 precision highp float;
10161 void main()
10162 {
10163     // gl_VertexID    x    y
10164     //      0        -1   -1
10165     //      1         1   -1
10166     //      2        -1    1
10167     //      3         1    1
10168     int bit0 = gl_VertexID & 1;
10169     int bit1 = gl_VertexID >> 1;
10170     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10171 })";
10172 
10173     constexpr char kFS[] = R"(#version 300 es
10174 precision highp float;
10175 out vec4 colorOut;
10176 uniform vec4 color;
10177 void main()
10178 {
10179     colorOut = color;
10180 })";
10181 
10182     ANGLE_GL_PROGRAM(program, kVS, kFS);
10183     glUseProgram(program);
10184 
10185     GLint colorLoc = glGetUniformLocation(program, "color");
10186     ASSERT_NE(-1, colorLoc);
10187 
10188     glClearColor(0, 0, 0, 1);
10189     glClearDepthf(0);
10190     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10191 
10192     auto unorm8 = [](uint8_t value) { return (value + 0.1f) / 255.0f; };
10193 
10194     constexpr uint8_t kInitRed   = 0xA4;
10195     constexpr uint8_t kInitGreen = 0x1E;
10196     constexpr uint8_t kInitBlue  = 0x97;
10197     constexpr uint8_t kInitAlpha = 0x65;
10198 
10199     // Initialize with logic op enabled, but using the default GL_COPY op.
10200     glEnable(GL_COLOR_LOGIC_OP_ANGLE);
10201 
10202     glUniform4f(colorLoc, unorm8(kInitRed), unorm8(kInitGreen), unorm8(kInitBlue),
10203                 unorm8(kInitAlpha));
10204     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10205 
10206     // Set logic op to GL_XOR and draw again.
10207     glLogicOpANGLE(GL_LOGIC_OP_XOR_ANGLE);
10208 
10209     constexpr uint8_t kXorRed   = 0x4C;
10210     constexpr uint8_t kXorGreen = 0x7D;
10211     constexpr uint8_t kXorBlue  = 0xB3;
10212     constexpr uint8_t kXorAlpha = 0x0F;
10213 
10214     glUniform4f(colorLoc, unorm8(kXorRed), unorm8(kXorGreen), unorm8(kXorBlue), unorm8(kXorAlpha));
10215     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10216 
10217     // Set logic op to GL_INVERT and draw again.
10218     glLogicOpANGLE(GL_LOGIC_OP_INVERT_ANGLE);
10219     glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10220     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10221 
10222     const int w = getWindowWidth();
10223     const int h = getWindowHeight();
10224 
10225     // Verify results
10226     const GLColor kExpect(static_cast<uint8_t>(~(kInitRed ^ kXorRed)),
10227                           static_cast<uint8_t>(~(kInitGreen ^ kXorGreen)),
10228                           static_cast<uint8_t>(~(kInitBlue ^ kXorBlue)),
10229                           static_cast<uint8_t>(~(kInitAlpha ^ kXorAlpha)));
10230     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, kExpect);
10231 
10232     // Render again with logic op enabled, this time with GL_COPY_INVERTED
10233     glLogicOpANGLE(GL_LOGIC_OP_COPY_INVERTED_ANGLE);
10234     glUniform4f(colorLoc, 0.123f, 0.234f, 0.345f, 0.456f);
10235     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10236 
10237     // Disable logic op and render again
10238     glDisable(GL_COLOR_LOGIC_OP_ANGLE);
10239     glUniform4f(colorLoc, 0, 1, 0, 1);
10240     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10241 
10242     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
10243     ASSERT_GL_NO_ERROR();
10244 }
10245 
10246 // Test for a bug with the VK_EXT_graphics_pipeline_library implementation in a scenario such as
10247 // this:
10248 //
10249 // - Use blend function A, draw  <-- a new pipeline is created
10250 // - Use blend function B, draw  <-- a new pipeline is created,
10251 //                                   new transition from A to B
10252 // - Switch to program 2
10253 // - Use blend function A, draw  <-- a new pipeline is created
10254 // - Switch to program 1
10255 // -                       draw  <-- the first pipeline is retrieved from cache,
10256 //                                   new transition from B to A
10257 // - Use blend function B, draw  <-- the second pipeline is retrieved from transition
10258 // - Switch to program 3
10259 // -                       draw  <-- a new pipeline is created
10260 //
10261 // With graphics pipeline library, the fragment output partial pipeline changes as follows:
10262 //
10263 // - Use blend function A, draw  <-- a new fragment output pipeline is created
10264 // - Use blend function B, draw  <-- a new fragment output pipeline is created,
10265 //                                   new transition from A to B
10266 // - Switch to program 2
10267 // - Use blend function A, draw  <-- the first fragment output pipeline is retrieved from cache
10268 // - Switch to program 1
10269 // -                       draw  <-- the first monolithic pipeline is retrieved from cache
10270 // - Use blend function B, draw  <-- the second monolithic pipeline is retrieved from transition
10271 // - Switch to program 3
10272 // -                       draw  <-- the second fragment output pipeline is retrieved from cache
10273 //
10274 // The bug was that the dirty blend state was discarded when the monolithic pipeline was retrieved
10275 // through the transition graph, and the last draw call used a stale fragment output pipeline (from
10276 // the last draw call with function A)
10277 //
TEST_P(StateChangeTestES3,FragmentOutputStateChangeAfterCachedPipelineTransition)10278 TEST_P(StateChangeTestES3, FragmentOutputStateChangeAfterCachedPipelineTransition)
10279 {
10280     // Program 1
10281     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10282     // Program 2
10283     ANGLE_GL_PROGRAM(drawColor2, essl3_shaders::vs::Simple(), R"(#version 300 es
10284 precision mediump float;
10285 out vec4 colorOut;
10286 uniform vec4 colorIn;
10287 void main()
10288 {
10289     colorOut = colorIn;
10290 }
10291 )");
10292     // Program 3
10293     ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10294 
10295     glUseProgram(drawColor2);
10296     GLint color2UniformLocation = glGetUniformLocation(drawColor2, "colorIn");
10297     ASSERT_NE(color2UniformLocation, -1);
10298 
10299     glUseProgram(drawColor);
10300     GLint colorUniformLocation =
10301         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
10302     ASSERT_NE(colorUniformLocation, -1);
10303 
10304     glEnable(GL_BLEND);
10305     glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10306     glClearColor(0, 0, 0, 0);
10307     glClear(GL_COLOR_BUFFER_BIT);
10308     // Framebuffer color is now (0, 0, 0, 0)
10309 
10310     glUniform4f(colorUniformLocation, 0, 0, 1, 0.25f);
10311     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10312     // Framebuffer color is now (0, 0, 0.25, 0.25*0.25)
10313 
10314     glBlendFunc(GL_ONE, GL_ONE);
10315     glUniform4f(colorUniformLocation, 0, 0, 0.25, 0.5 - 0.0625);
10316     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10317     // Framebuffer color is now (0, 0, 0.5, 0.5)
10318 
10319     // Draw with a different program, but same fragment output state.  The fragment output pipeline
10320     // is retrieved from cache.
10321     glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10322     glUseProgram(drawColor2);
10323     glUniform4f(color2UniformLocation, 1, 0, 0, 0.5);
10324     drawQuad(drawColor2, essl1_shaders::PositionAttrib(), 0.5f);
10325     // Framebuffer color is now (0.5, 0, 0.25, 0.5)
10326 
10327     // Draw with the original program and the first fragment output state, so it's retrieved from
10328     // cache.
10329     glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
10330     glUseProgram(drawColor);
10331     glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25);
10332     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10333     // Framebuffer color is now (0.25, 0, 0.25, 0.25+0.25*0.25)
10334 
10335     // Change to the second fragment output state, so it's retrieved through the transition graph.
10336     glBlendFunc(GL_ONE, GL_ONE);
10337     glUniform4f(colorUniformLocation, 0, 0, 0.5, 0.25 - 0.25 * 0.25);
10338     drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
10339     // Framebuffer color is now (0.25, 0, 0.75, 0.5)
10340 
10341     // Draw with the third program, not changing the fragment output state.
10342     drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.5f);
10343     // Framebuffer color is now (0.25, 1, 0.75, 1)
10344 
10345     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(64, 255, 192, 255), 1);
10346     ASSERT_GL_NO_ERROR();
10347 }
10348 
10349 // Tests a specific case for multiview and queries.
TEST_P(SimpleStateChangeTestES3,MultiviewAndQueries)10350 TEST_P(SimpleStateChangeTestES3, MultiviewAndQueries)
10351 {
10352     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OVR_multiview"));
10353 
10354     ANGLE_GL_PROGRAM(prog, kZeroVertexShaderForPoints, essl1_shaders::fs::Red());
10355     glUseProgram(prog);
10356 
10357     const int PRE_QUERY_CNT = 63;
10358 
10359     GLQuery qry;
10360     GLTexture tex;
10361     GLFramebuffer fb;
10362     GLFramebuffer fb2;
10363     glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10364     for (int i = 0; i < PRE_QUERY_CNT; i++)
10365     {
10366         glDrawArrays(GL_POINTS, 0, 1);
10367 
10368         GLColor color;
10369         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
10370     }
10371     glEndQuery(GL_ANY_SAMPLES_PASSED);
10372     glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
10373     glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
10374     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 2, 2, 2);
10375     glBindFramebuffer(GL_FRAMEBUFFER, fb);
10376     glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 0, 2);
10377     glClear(GL_COLOR_BUFFER_BIT);
10378     glBindFramebuffer(GL_FRAMEBUFFER, fb2);
10379     glBeginQuery(GL_ANY_SAMPLES_PASSED, qry);
10380 }
10381 
10382 // Tests a bug related to an ordering of certain commands.
TEST_P(SimpleStateChangeTestES3,ClearQuerySwapClear)10383 TEST_P(SimpleStateChangeTestES3, ClearQuerySwapClear)
10384 {
10385     glClear(GL_COLOR_BUFFER_BIT);
10386     {
10387         GLQuery query;
10388         glBeginQuery(GL_ANY_SAMPLES_PASSED, query);
10389         glEndQuery(GL_ANY_SAMPLES_PASSED);
10390     }
10391     swapBuffers();
10392     glClear(GL_COLOR_BUFFER_BIT);
10393 }
10394 
10395 // Tests a bug around sampler2D swap and uniform locations.
TEST_P(StateChangeTestES3,SamplerSwap)10396 TEST_P(StateChangeTestES3, SamplerSwap)
10397 {
10398     constexpr char kVS[] = R"(#version 300 es
10399 precision highp float;
10400 void main()
10401 {
10402     // gl_VertexID    x    y
10403     //      0        -1   -1
10404     //      1         1   -1
10405     //      2        -1    1
10406     //      3         1    1
10407     int bit0 = gl_VertexID & 1;
10408     int bit1 = gl_VertexID >> 1;
10409     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10410 })";
10411 
10412     constexpr char kFS1[] = R"(#version 300 es
10413 precision highp float;
10414 uniform sampler2D A;
10415 uniform sampler2D B;
10416 out vec4 colorOut;
10417 void main()
10418 {
10419     float a = texture(A, vec2(0)).x;
10420     float b = texture(B, vec2(0)).x;
10421     colorOut = vec4(a, b, 0, 1);
10422 })";
10423 
10424     constexpr char kFS2[] = R"(#version 300 es
10425 precision highp float;
10426 uniform sampler2D B;
10427 uniform sampler2D A;
10428 const vec2 multiplier = vec2(0.5, 0.5);
10429 out vec4 colorOut;
10430 void main()
10431 {
10432     float a = texture(A, vec2(0)).x;
10433     float b = texture(B, vec2(0)).x;
10434     colorOut = vec4(a, b, 0, 1);
10435 })";
10436 
10437     ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10438     ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10439 
10440     const GLColor kColorA(123, 0, 0, 0);
10441     const GLColor kColorB(157, 0, 0, 0);
10442 
10443     GLTexture texA;
10444     glActiveTexture(GL_TEXTURE0);
10445     glBindTexture(GL_TEXTURE_2D, texA);
10446     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10447     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10448 
10449     GLTexture texB;
10450     glActiveTexture(GL_TEXTURE1);
10451     glBindTexture(GL_TEXTURE_2D, texB);
10452     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10453     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10454     EXPECT_GL_NO_ERROR();
10455 
10456     glUseProgram(prog1);
10457     glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10458     glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10459 
10460     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10461 
10462     const GLColor kExpect(kColorA.R, kColorB.R, 0, 255);
10463 
10464     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10465     ASSERT_GL_NO_ERROR();
10466 
10467     // The same with the second program that has sampler2D (definitions) swapped which should have
10468     // no effect on the result.
10469     glUseProgram(prog2);
10470     glUniform1i(glGetUniformLocation(prog2, "A"), 0);
10471     glUniform1i(glGetUniformLocation(prog2, "B"), 1);
10472 
10473     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10474 
10475     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10476     ASSERT_GL_NO_ERROR();
10477 }
10478 
10479 // Tests a bug around sampler2D reordering and uniform locations.
TEST_P(StateChangeTestES3,SamplerReordering)10480 TEST_P(StateChangeTestES3, SamplerReordering)
10481 {
10482     constexpr char kVS[] = R"(#version 300 es
10483 precision highp float;
10484 void main()
10485 {
10486     // gl_VertexID    x    y
10487     //      0        -1   -1
10488     //      1         1   -1
10489     //      2        -1    1
10490     //      3         1    1
10491     int bit0 = gl_VertexID & 1;
10492     int bit1 = gl_VertexID >> 1;
10493     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
10494 })";
10495 
10496     constexpr char kFS1[] = R"(#version 300 es
10497 precision highp float;
10498 uniform sampler2D A;
10499 uniform sampler2D B;
10500 //uniform vec2 multiplier;
10501 const vec2 multiplier = vec2(0.5, 0.5);
10502 out vec4 colorOut;
10503 void main()
10504 {
10505     float a = texture(A, vec2(0)).x;
10506     float b = texture(B, vec2(0)).x;
10507     colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10508 })";
10509 
10510     constexpr char kFS2[] = R"(#version 300 es
10511 precision highp float;
10512 uniform sampler2D S;
10513 uniform sampler2D P;
10514 //uniform vec2 multiplier;
10515 const vec2 multiplier = vec2(0.5, 0.5);
10516 out vec4 colorOut;
10517 void main()
10518 {
10519     float a = texture(P, vec2(0)).x;
10520     float b = texture(S, vec2(0)).x;
10521     colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10522 })";
10523 
10524     constexpr char kFS3[] = R"(#version 300 es
10525 precision highp float;
10526 uniform sampler2D R;
10527 uniform sampler2D S;
10528 //uniform vec2 multiplier;
10529 const vec2 multiplier = vec2(0.5, 0.5);
10530 out vec4 colorOut;
10531 void main()
10532 {
10533     float a = texture(R, vec2(0)).x;
10534     float b = texture(S, vec2(0)).x;
10535     colorOut = vec4(vec2(a, b) * multiplier, 0, 1);
10536 })";
10537 
10538     ANGLE_GL_PROGRAM(prog1, kVS, kFS1);
10539     ANGLE_GL_PROGRAM(prog2, kVS, kFS2);
10540     ANGLE_GL_PROGRAM(prog3, kVS, kFS3);
10541 
10542     const GLColor kColorA(123, 0, 0, 0);
10543     const GLColor kColorB(157, 0, 0, 0);
10544 
10545     GLTexture texA;
10546     glActiveTexture(GL_TEXTURE0);
10547     glBindTexture(GL_TEXTURE_2D, texA);
10548     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10549     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorA);
10550 
10551     GLTexture texB;
10552     glActiveTexture(GL_TEXTURE1);
10553     glBindTexture(GL_TEXTURE_2D, texB);
10554     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
10555     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kColorB);
10556     EXPECT_GL_NO_ERROR();
10557 
10558     glUseProgram(prog1);
10559     glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10560     glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10561 
10562     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10563 
10564     glUseProgram(prog2);
10565     glUniform1i(glGetUniformLocation(prog2, "S"), 0);
10566     glUniform1i(glGetUniformLocation(prog2, "P"), 1);
10567 
10568     glEnable(GL_BLEND);
10569     glBlendFunc(GL_ONE, GL_ONE);
10570     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10571 
10572     constexpr float kXMultiplier = 0.5;
10573     constexpr float kYMultiplier = 0.5;
10574 
10575     const GLColor kExpect(static_cast<uint8_t>((kColorA.R + kColorB.R) * kXMultiplier),
10576                           static_cast<uint8_t>((kColorA.R + kColorB.R) * kYMultiplier), 0, 255);
10577 
10578     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10579     ASSERT_GL_NO_ERROR();
10580 
10581     // Do the same thing again, but with the second shader having its samplers specified in the
10582     // opposite order.  The difference between kFS2 and kFS3 is that S is now the second
10583     // declaration, and P is renamed to R.  The reason for the rename is that even if the samplers
10584     // get sorted by name, they would still result in the two shaders declaring them in different
10585     // orders.
10586     glDisable(GL_BLEND);
10587 
10588     glUseProgram(prog1);
10589     glUniform1i(glGetUniformLocation(prog1, "A"), 0);
10590     glUniform1i(glGetUniformLocation(prog1, "B"), 1);
10591 
10592     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10593 
10594     glUseProgram(prog3);
10595     glUniform1i(glGetUniformLocation(prog3, "S"), 0);
10596     glUniform1i(glGetUniformLocation(prog3, "R"), 1);
10597 
10598     glEnable(GL_BLEND);
10599     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
10600 
10601     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpect, 1);
10602     ASSERT_GL_NO_ERROR();
10603 }
10604 
10605 // Test that switching FBO attachments affects sample coverage
TEST_P(StateChangeTestES3,SampleCoverageFramebufferAttachmentSwitch)10606 TEST_P(StateChangeTestES3, SampleCoverageFramebufferAttachmentSwitch)
10607 {
10608     // Keep this state unchanged during the test
10609     glEnable(GL_SAMPLE_COVERAGE);
10610     glSampleCoverage(0.0f, false);
10611 
10612     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
10613 
10614     GLFramebuffer fbo;
10615     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10616 
10617     GLRenderbuffer rbo;
10618     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10619     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10620 
10621     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10622     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10623 
10624     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10625     ASSERT_GL_NO_ERROR();
10626 
10627     // Sample coverage must have no effect
10628     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10629 
10630     GLRenderbuffer rboMS;
10631     glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10632     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10633 
10634     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10635     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10636 
10637     glClearColor(1, 0, 0, 1);
10638     glClear(GL_COLOR_BUFFER_BIT);
10639     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10640     ASSERT_GL_NO_ERROR();
10641 
10642     // Use a temporary FBO to resolve
10643     {
10644         GLFramebuffer fboResolve;
10645         glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10646 
10647         GLRenderbuffer rboResolve;
10648         glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10649         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10650 
10651         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10652                                   rboResolve);
10653         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10654 
10655         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10656         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10657         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10658         ASSERT_GL_NO_ERROR();
10659 
10660         // Nothing was drawn because of zero coverage
10661         glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10662         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10663     }
10664 
10665     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10666 
10667     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10668     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10669 
10670     glClearColor(0, 0, 1, 1);
10671     glClear(GL_COLOR_BUFFER_BIT);
10672     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10673 
10674     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10675     ASSERT_GL_NO_ERROR();
10676 
10677     // Sample coverage must have no effect
10678     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
10679 }
10680 
10681 // Test that switching FBO attachments affects alpha-to-coverage
TEST_P(StateChangeTestES3,AlphaToCoverageFramebufferAttachmentSwitch)10682 TEST_P(StateChangeTestES3, AlphaToCoverageFramebufferAttachmentSwitch)
10683 {
10684     // Keep this state unchanged during the test
10685     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
10686 
10687     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
10688     glUseProgram(program);
10689     glUniform4f(glGetUniformLocation(program, essl1_shaders::ColorUniform()), 0, 1, 0, 0);
10690 
10691     GLFramebuffer fbo;
10692     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10693 
10694     GLRenderbuffer rbo;
10695     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10696     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, 1, 1);
10697 
10698     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10699     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10700 
10701     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10702     ASSERT_GL_NO_ERROR();
10703 
10704     // A2C must have no effect
10705     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10706 
10707     GLRenderbuffer rboMS;
10708     glBindRenderbuffer(GL_RENDERBUFFER, rboMS);
10709     glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, 1, 1);
10710 
10711     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboMS);
10712     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10713 
10714     glClearColor(1, 0, 0, 1);
10715     glClear(GL_COLOR_BUFFER_BIT);
10716     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10717     ASSERT_GL_NO_ERROR();
10718 
10719     // Use a temporary FBO to resolve
10720     {
10721         GLFramebuffer fboResolve;
10722         glBindFramebuffer(GL_FRAMEBUFFER, fboResolve);
10723 
10724         GLRenderbuffer rboResolve;
10725         glBindRenderbuffer(GL_RENDERBUFFER, rboResolve);
10726         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
10727 
10728         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
10729                                   rboResolve);
10730         ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10731 
10732         glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
10733         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboResolve);
10734         glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
10735         ASSERT_GL_NO_ERROR();
10736 
10737         // Nothing was drawn because of zero alpha
10738         glBindFramebuffer(GL_READ_FRAMEBUFFER, fboResolve);
10739         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
10740     }
10741 
10742     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10743 
10744     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10745     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10746 
10747     glClearColor(0, 0, 1, 1);
10748     glClear(GL_COLOR_BUFFER_BIT);
10749     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
10750 
10751     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
10752     ASSERT_GL_NO_ERROR();
10753 
10754     // A2C must have no effect
10755     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
10756 }
10757 
10758 // Test that switching FBO attachments affects depth test
TEST_P(StateChangeTestES3,DepthTestFramebufferAttachmentSwitch)10759 TEST_P(StateChangeTestES3, DepthTestFramebufferAttachmentSwitch)
10760 {
10761     // Keep this state unchanged during the test
10762     glEnable(GL_DEPTH_TEST);
10763     glDepthMask(GL_TRUE);
10764     glDepthFunc(GL_GREATER);
10765 
10766     constexpr char kVS[] = R"(#version 300 es
10767 precision highp float;
10768 uniform float u_depth;
10769 void main()
10770 {
10771     // gl_VertexID    x    y
10772     //      0        -1   -1
10773     //      1         1   -1
10774     //      2        -1    1
10775     //      3         1    1
10776     int bit0 = gl_VertexID & 1;
10777     int bit1 = gl_VertexID >> 1;
10778     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, u_depth * 2. - 1., 1);
10779 })";
10780 
10781     constexpr char kFS[] = R"(#version 300 es
10782 uniform mediump vec4 u_color;
10783 out mediump vec4 color;
10784 void main(void)
10785 {
10786     color = u_color;
10787 })";
10788 
10789     ANGLE_GL_PROGRAM(program, kVS, kFS);
10790     glUseProgram(program);
10791     GLint depthUni = glGetUniformLocation(program, "u_depth");
10792     GLint colorUni = glGetUniformLocation(program, "u_color");
10793 
10794     constexpr uint32_t kWidth  = 17;
10795     constexpr uint32_t kHeight = 23;
10796 
10797     GLRenderbuffer rbo;
10798     glBindRenderbuffer(GL_RENDERBUFFER, rbo);
10799     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10800 
10801     GLRenderbuffer depthStencil;
10802     glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
10803     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kWidth, kHeight);
10804 
10805     GLFramebuffer fbo;
10806     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10807     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
10808     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10809                               depthStencil);
10810     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10811 
10812     glEnable(GL_BLEND);
10813     glBlendFunc(GL_ONE, GL_ONE);
10814 
10815     glClearColor(0, 0, 0, 0);
10816     glClearDepthf(0);
10817     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
10818     ASSERT_GL_NO_ERROR();
10819 
10820     // Draw with the depth buffer attached, set depth to 0.5.  Should succeed and the color buffer
10821     // becomes red.
10822     glUniform4f(colorUni, 1, 0, 0, 0);
10823     glUniform1f(depthUni, 0.5);
10824     glDrawArrays(GL_TRIANGLES, 0, 6);
10825 
10826     // Detach the depth buffer and draw with a smaller depth.  Should still succeed because there is
10827     // no depth buffer test against.  Green should be added.
10828     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
10829     glUniform4f(colorUni, 0, 0.2, 0, 0.6);
10830     glUniform1f(depthUni, 0.3);
10831     glDrawArrays(GL_TRIANGLES, 0, 6);
10832     // Higher depth should also pass
10833     glUniform1f(depthUni, 0.9);
10834     glDrawArrays(GL_TRIANGLES, 0, 6);
10835 
10836     // Reattach the depth buffer and draw with a depth in between.  Should fail the depth.  Blue
10837     // should not be added.
10838     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10839                               depthStencil);
10840     glUniform4f(colorUni, 0, 0, 1, 1);
10841     glUniform1f(depthUni, 0.4);
10842     glDrawArrays(GL_TRIANGLES, 0, 6);
10843 
10844     // Reattach the depth buffer and draw with a depth larger than 0.5.  Should pass the depth test.
10845     // Blue should be added.
10846     glUniform4f(colorUni, 0, 0.8, 0, 0);
10847     glUniform1f(depthUni, 0.6);
10848     glDrawArrays(GL_TRIANGLES, 0, 6);
10849 
10850     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10851     ASSERT_GL_NO_ERROR();
10852 }
10853 
10854 // Test that switching FBO attachments affects blend state
TEST_P(StateChangeTestES3,BlendFramebufferAttachmentSwitch)10855 TEST_P(StateChangeTestES3, BlendFramebufferAttachmentSwitch)
10856 {
10857     // Keep this state unchanged during the test
10858     glEnable(GL_BLEND);
10859     glBlendFunc(GL_ONE, GL_ONE);
10860 
10861     constexpr char kVS[] = R"(#version 300 es
10862 precision highp float;
10863 void main()
10864 {
10865     // gl_VertexID    x    y
10866     //      0        -1   -1
10867     //      1         1   -1
10868     //      2        -1    1
10869     //      3         1    1
10870     int bit0 = gl_VertexID & 1;
10871     int bit1 = gl_VertexID >> 1;
10872     gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, 0, 1);
10873 })";
10874 
10875     constexpr char kFS[] = R"(#version 300 es
10876 uniform mediump vec4 u_color;
10877 layout(location=0) out mediump vec4 color0;
10878 layout(location=1) out mediump vec4 color1;
10879 void main(void)
10880 {
10881     color0 = u_color;
10882     color1 = u_color;
10883 })";
10884 
10885     ANGLE_GL_PROGRAM(program, kVS, kFS);
10886     glUseProgram(program);
10887     GLint colorUni = glGetUniformLocation(program, "u_color");
10888 
10889     constexpr uint32_t kWidth  = 17;
10890     constexpr uint32_t kHeight = 23;
10891 
10892     GLRenderbuffer color0;
10893     glBindRenderbuffer(GL_RENDERBUFFER, color0);
10894     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10895 
10896     GLRenderbuffer color1;
10897     glBindRenderbuffer(GL_RENDERBUFFER, color1);
10898     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kWidth, kHeight);
10899 
10900     GLFramebuffer fbo;
10901     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10902     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10903     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10904 
10905     constexpr GLenum kDrawBuffers[2] = {
10906         GL_COLOR_ATTACHMENT0,
10907         GL_COLOR_ATTACHMENT1,
10908     };
10909     glDrawBuffers(2, kDrawBuffers);
10910 
10911     // Clear the first attachment to transparent green
10912     glClearColor(0, 1, 0, 0);
10913     glClear(GL_COLOR_BUFFER_BIT);
10914 
10915     // Clear the second attachment to transparent blue
10916     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10917     glClearColor(0, 0, 1, 0);
10918     glClear(GL_COLOR_BUFFER_BIT);
10919     ASSERT_GL_NO_ERROR();
10920 
10921     // Draw with only one attachment.  Attachment 0 is now transparent yellow-ish.
10922     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color0);
10923     glUniform4f(colorUni, 0.6, 0, 0, 0);
10924     glDrawArrays(GL_TRIANGLES, 0, 6);
10925 
10926     // Attach the second renderbuffer and draw to both.  Attachment 0 is now yellow-ish, while
10927     // attachment 1 is blue.
10928     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, color1);
10929     glUniform4f(colorUni, 0, 0, 0, 1);
10930     glDrawArrays(GL_TRIANGLES, 0, 6);
10931 
10932     // Detach the second renderbuffer again and draw.  Attachment 0 is now yellow.
10933     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, 0);
10934     glUniform4f(colorUni, 0.6, 0, 0, 0);
10935     glDrawArrays(GL_TRIANGLES, 0, 6);
10936 
10937     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
10938     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color1);
10939     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::blue);
10940     ASSERT_GL_NO_ERROR();
10941 }
10942 
10943 // Tests state change for sample shading.
TEST_P(StateChangeTestES31,SampleShading)10944 TEST_P(StateChangeTestES31, SampleShading)
10945 {
10946     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
10947     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_variables"));
10948 
10949     constexpr GLsizei kSize        = 1;
10950     constexpr GLsizei kSampleCount = 4;
10951 
10952     // Create a single sampled texture and framebuffer for verifying results
10953     GLFramebuffer fbo;
10954     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
10955 
10956     GLTexture texture;
10957     glBindTexture(GL_TEXTURE_2D, texture);
10958     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
10959     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
10960     ASSERT_GL_NO_ERROR();
10961     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10962 
10963     // Create a multisampled texture and framebuffer.
10964     GLFramebuffer msaaFBO;
10965     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
10966 
10967     GLTexture msaaTexture;
10968     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaTexture);
10969     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, kSampleCount, GL_RGBA8, kSize, kSize,
10970                               false);
10971     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
10972                            msaaTexture, 0);
10973     ASSERT_GL_NO_ERROR();
10974     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
10975 
10976     // Create a fragment shader whose _resolved_ output is different based on whether sample shading
10977     // is enabled or not, but which doesn't use gl_SampleID (which implicitly enables sample
10978     // shading).
10979     //
10980     // This is done by non-linearly transforming a varying, resulting in a different color average
10981     // based on the location in which the varying is sampled.  The framebuffer is 1x1 and the vertex
10982     // shader outputs the following triangle:
10983     //
10984     //      (-3, 3)
10985     //        |\
10986     //        |  \
10987     //        |    \
10988     //        |      \
10989     //        |        \
10990     //        |          \
10991     //        +-----------+ <----- position evaluates as (1, 1)
10992     //        |       X   | \
10993     //        |  W        |   \
10994     //        |     C     |     \
10995     //        |        Z  |       \
10996     //        |   Y       |         \
10997     //        +-----------+-----------\
10998     //      (-1, -1)                (3, -1)
10999     //
11000     // The varying |gradient| is output as position.  This means that:
11001     //
11002     // - At the center of the pixel (C), the |gradient| value is (0,0)
11003     // - At sample positions W, X, Y and Z, the |gradient| has 0.75 and 0.25 (positive or negative)
11004     //   in its components.  Most importantly, its length^2 (i.e. gradient.gradient) is:
11005     //
11006     //       0.25^2 + 0.75^2 = 0.625
11007     //
11008     // The fragment shader outputs gradient.gradient + (0.1, 0) as color.  Without sample shading,
11009     // this outputs (0.1, 0, 0, 1) in the color.  With sample shading, it outputs
11010     // (0.725, 0.625, 0, 1) (for all samples).  By using additive blending, we can verify that when
11011     // only sample shading state is modified, that sample shading is indeed toggled.
11012     //
11013     constexpr char kVS[] = R"(#version 300 es
11014 
11015 out mediump vec2 gradient;
11016 
11017 void main()
11018 {
11019     vec2 position = vec2(-1, -1);
11020     if (gl_VertexID == 1)
11021         position = vec2(3, -1);
11022     else if (gl_VertexID == 2)
11023         position = vec2(-1, 3);
11024 
11025     gradient = position;
11026     gl_Position = vec4(position, 0, 1);
11027 })";
11028 
11029     constexpr char kFS[] = R"(#version 300 es
11030 
11031 in mediump vec2 gradient;
11032 out mediump vec4 color;
11033 
11034 uniform mediump vec2 offset;
11035 
11036 void main()
11037 {
11038     mediump float len = dot(gradient, gradient);
11039     color = vec4(vec2(len, len) + offset, 0, 1);
11040 })";
11041 
11042     ANGLE_GL_PROGRAM(program, kVS, kFS);
11043     glUseProgram(program);
11044     GLint offsetLoc = glGetUniformLocation(program, "offset");
11045     ASSERT_NE(offsetLoc, -1);
11046 
11047     glClearColor(0, 0, 0, 0);
11048     glClear(GL_COLOR_BUFFER_BIT);
11049 
11050     glEnable(GL_BLEND);
11051     glBlendFunc(GL_ONE, GL_ONE);
11052 
11053     glViewport(0, 0, kSize, kSize);
11054 
11055     // Issue 2 draw calls, with sample shading enabled then disabled.
11056     glUniform2f(offsetLoc, 0.1f, 0);
11057 
11058     glEnable(GL_SAMPLE_SHADING_OES);
11059     glMinSampleShadingOES(1.0f);
11060     glDrawArrays(GL_TRIANGLES, 0, 3);
11061     glDisable(GL_SAMPLE_SHADING_OES);
11062     glDrawArrays(GL_TRIANGLES, 0, 3);
11063 
11064     // Verify results
11065     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11066     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11067     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11068     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(210, 159, 0, 255), 1);
11069 
11070     // Do the same test in opposite order (sample shading disabled first, then enabled).
11071     glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
11072 
11073     glUniform2f(offsetLoc, 0, 0.1f);
11074 
11075     glClear(GL_COLOR_BUFFER_BIT);
11076     glDrawArrays(GL_TRIANGLES, 0, 3);
11077     glEnable(GL_SAMPLE_SHADING_OES);
11078     glDrawArrays(GL_TRIANGLES, 0, 3);
11079 
11080     // Verify results
11081     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
11082     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_LINEAR);
11083     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
11084     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(159, 210, 0, 255), 1);
11085 
11086     ASSERT_GL_NO_ERROR();
11087 }
11088 
11089 // Tests value change for MinSampleShadingOES.
TEST_P(StateChangeTestES31,MinSampleShadingOES)11090 TEST_P(StateChangeTestES31, MinSampleShadingOES)
11091 {
11092     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_sample_shading"));
11093     ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_sample_variables"));
11094 
11095     GLfloat value = 0.0f;
11096     glEnable(GL_SAMPLE_SHADING_OES);
11097     EXPECT_GL_TRUE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11098     glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11099     ASSERT_EQ(value, 0);  // initial value should be 0.
11100 
11101     glDisable(GL_SAMPLE_SHADING_OES);
11102     glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11103     ASSERT_EQ(value, 0);
11104 
11105     glMinSampleShadingOES(0.5);
11106     EXPECT_GL_FALSE(glIsEnabled(GL_SAMPLE_SHADING_OES));
11107     glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11108     ASSERT_EQ(value, 0.5);
11109 
11110     glMinSampleShadingOES(1.5);
11111     glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11112     ASSERT_EQ(value, 1);  // clamped to 1.
11113 
11114     glMinSampleShadingOES(-0.5);
11115     glGetFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &value);
11116     ASSERT_EQ(value, 0);  // clamped to 0.
11117 }
11118 
11119 // Tests state changes with uniform block binding.
TEST_P(StateChangeTestES3,UniformBlockBinding)11120 TEST_P(StateChangeTestES3, UniformBlockBinding)
11121 {
11122     constexpr char kVS[] = R"(#version 300 es
11123 void main()
11124 {
11125     vec2 pos = vec2(0.0);
11126     switch (gl_VertexID) {
11127         case 0: pos = vec2(-1.0, -1.0); break;
11128         case 1: pos = vec2(3.0, -1.0); break;
11129         case 2: pos = vec2(-1.0, 3.0); break;
11130     };
11131     gl_Position = vec4(pos, 0.0, 1.0);
11132 })";
11133     constexpr char kFS[] = R"(#version 300 es
11134 out mediump vec4 colorOut;
11135 
11136 layout(std140) uniform buffer { mediump vec4 color; };
11137 
11138 void main()
11139 {
11140     colorOut = color;
11141 })";
11142 
11143     ANGLE_GL_PROGRAM(program, kVS, kFS);
11144     glUseProgram(program);
11145     const GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
11146 
11147     // Create buffers bound to bindings 1 and 2
11148     constexpr std::array<float, 4> kRed              = {1, 0, 0, 1};
11149     constexpr std::array<float, 4> kTransparentGreen = {0, 1, 0, 0};
11150     GLBuffer red, transparentGreen;
11151     glBindBuffer(GL_UNIFORM_BUFFER, red);
11152     glBufferData(GL_UNIFORM_BUFFER, sizeof(kRed), kRed.data(), GL_STATIC_DRAW);
11153     glBindBuffer(GL_UNIFORM_BUFFER, transparentGreen);
11154     glBufferData(GL_UNIFORM_BUFFER, sizeof(kTransparentGreen), kTransparentGreen.data(),
11155                  GL_STATIC_DRAW);
11156 
11157     glBindBufferBase(GL_UNIFORM_BUFFER, 1, transparentGreen);
11158     glBindBufferBase(GL_UNIFORM_BUFFER, 2, red);
11159     glUniformBlockBinding(program, uniformBufferIndex, 2);
11160 
11161     // Issue a draw call.  The buffer should be transparent green now
11162     glClearColor(0, 0, 0, 0);
11163     glClear(GL_COLOR_BUFFER_BIT);
11164     glEnable(GL_BLEND);
11165     glBlendFunc(GL_ONE, GL_ONE);
11166 
11167     glUseProgram(program);
11168     glDrawArrays(GL_TRIANGLES, 0, 3);
11169 
11170     // Change the binding
11171     glUniformBlockBinding(program, uniformBufferIndex, 1);
11172     ASSERT_GL_NO_ERROR();
11173 
11174     // Draw again, it should accumulate blue and the buffer should become magenta.
11175     glDrawArrays(GL_TRIANGLES, 0, 3);
11176 
11177     // Verify results
11178     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
11179     ASSERT_GL_NO_ERROR();
11180 }
11181 
11182 // Tests that viewport changes within a render pass are correct. WebGPU sets a default viewport,
11183 // cover the omission of setViewport in the backend.
TEST_P(StateChangeTest,ViewportChangeWithinRenderPass)11184 TEST_P(StateChangeTest, ViewportChangeWithinRenderPass)
11185 {
11186     glClearColor(0, 0, 0, 0);
11187     glClear(GL_COLOR_BUFFER_BIT);
11188 
11189     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11190     glUseProgram(program);
11191     GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11192 
11193     glViewport(0, 0, 10, 10);
11194     glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11195     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11196 
11197     glViewport(0, 0, getWindowWidth(), getWindowHeight());  // "default" size
11198     glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11199     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11200 
11201     // Verify that the first draw is covered by the second "full" draw
11202     EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11203     EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11204 
11205     // Go the other way, start with a full size viewport and change it to 10x10 for the second draw
11206     glViewport(0, 0, getWindowWidth(), getWindowHeight());  // "default" size
11207     glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11208     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11209 
11210     glViewport(0, 0, 10, 10);
11211     glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11212     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11213 
11214     // Verify that the first draw is covered by the second "full" draw
11215     EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11216     EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11217 }
11218 
11219 // Tests that scissor changes within a render pass are correct. WebGPU sets a default scissor, cover
11220 // the omission of setScissorRect in the backend.
TEST_P(StateChangeTest,ScissortChangeWithinRenderPass)11221 TEST_P(StateChangeTest, ScissortChangeWithinRenderPass)
11222 {
11223     glClearColor(0, 0, 0, 0);
11224     glClear(GL_COLOR_BUFFER_BIT);
11225     glEnable(GL_SCISSOR_TEST);
11226 
11227     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
11228     glUseProgram(program);
11229     GLint colorLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
11230 
11231     glScissor(0, 0, 10, 10);
11232     glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11233     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11234 
11235     glScissor(0, 0, getWindowWidth(), getWindowHeight());  // "default" size
11236     glUniform4f(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
11237     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11238 
11239     // Verify that the first draw is covered by the second "full" draw
11240     EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::green);
11241     EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::green);
11242 
11243     // Go the other way, start with a full size scissor and change it to 10x10 for the second draw
11244     glScissor(0, 0, getWindowWidth(), getWindowHeight());  // "default" size
11245     glUniform4f(colorLoc, 0.0f, 0.0f, 1.0f, 1.0f);
11246     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11247 
11248     glScissor(0, 0, 10, 10);
11249     glUniform4f(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
11250     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
11251 
11252     // Verify that the first draw is covered by the second "full" draw
11253     EXPECT_PIXEL_COLOR_EQ(5, 5, GLColor::red);
11254     EXPECT_PIXEL_COLOR_EQ(12, 12, GLColor::blue);
11255 }
11256 
11257 }  // anonymous namespace
11258 
11259 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
11260 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
11261 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
11262 
11263 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
11264 ANGLE_INSTANTIATE_TEST_ES3_AND(
11265     StateChangeTestES3,
11266     ES3_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11267     ES3_VULKAN().disable(Feature::UseDepthWriteEnableDynamicState),
11268     ES3_VULKAN()
11269         .disable(Feature::SupportsExtendedDynamicState)
11270         .disable(Feature::SupportsExtendedDynamicState2),
11271     ES3_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11272     ES3_VULKAN()
11273         .disable(Feature::SupportsExtendedDynamicState2)
11274         .disable(Feature::SupportsGraphicsPipelineLibrary),
11275     ES3_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11276     ES3_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11277 
11278 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES31);
11279 ANGLE_INSTANTIATE_TEST_ES31_AND(
11280     StateChangeTestES31,
11281     ES31_VULKAN().disable(Feature::SupportsIndexTypeUint8),
11282     ES31_VULKAN()
11283         .disable(Feature::SupportsExtendedDynamicState)
11284         .disable(Feature::SupportsExtendedDynamicState2),
11285     ES31_VULKAN().disable(Feature::SupportsExtendedDynamicState2),
11286     ES31_VULKAN()
11287         .disable(Feature::SupportsExtendedDynamicState2)
11288         .disable(Feature::SupportsGraphicsPipelineLibrary),
11289     ES31_VULKAN().disable(Feature::UseVertexInputBindingStrideDynamicState),
11290     ES31_VULKAN().disable(Feature::UsePrimitiveRestartEnableDynamicState));
11291 
11292 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestWebGL2);
11293 ANGLE_INSTANTIATE_TEST_COMBINE_1(StateChangeTestWebGL2,
11294                                  StateChangeTestWebGL2Print,
11295                                  testing::Bool(),
11296                                  ANGLE_ALL_TEST_PLATFORMS_ES3);
11297 
11298 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
11299 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
11300 
11301 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
11302 
11303 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
11304 ANGLE_INSTANTIATE_TEST_ES3_AND(SimpleStateChangeTestES3,
11305                                ES3_VULKAN().enable(Feature::AllocateNonZeroMemory));
11306 
11307 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
11308 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
11309 
11310 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
11311 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
11312 
11313 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
11314 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
11315 
11316 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
11317 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
11318 
11319 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
11320 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
11321 
11322 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
11323 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
11324 
11325 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
11326 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
11327 
11328 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
11329 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
11330 
11331 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
11332 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
11333 
11334 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttribArrayStateChangeTest);
11335 ANGLE_INSTANTIATE_TEST_ES3(VertexAttribArrayStateChangeTest);
11336