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 
34         // Enable the no error extension to avoid syncing the FBO state on validation.
35         setNoErrorEnabled(true);
36     }
37 
testSetUp()38     void testSetUp() override
39     {
40         glGenFramebuffers(1, &mFramebuffer);
41         glGenTextures(2, mTextures.data());
42         glGenRenderbuffers(1, &mRenderbuffer);
43 
44         ASSERT_GL_NO_ERROR();
45     }
46 
testTearDown()47     void testTearDown() override
48     {
49         if (mFramebuffer != 0)
50         {
51             glDeleteFramebuffers(1, &mFramebuffer);
52             mFramebuffer = 0;
53         }
54 
55         if (!mTextures.empty())
56         {
57             glDeleteTextures(static_cast<GLsizei>(mTextures.size()), mTextures.data());
58             mTextures.clear();
59         }
60 
61         glDeleteRenderbuffers(1, &mRenderbuffer);
62     }
63 
64     GLuint mFramebuffer           = 0;
65     GLuint mRenderbuffer          = 0;
66     std::vector<GLuint> mTextures = {0, 0};
67 };
68 
69 class StateChangeTestES3 : public StateChangeTest
70 {
71   protected:
StateChangeTestES3()72     StateChangeTestES3() {}
73 };
74 
75 // Ensure that CopyTexImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexImage2DSync)76 TEST_P(StateChangeTest, CopyTexImage2DSync)
77 {
78     // TODO(geofflang): Fix on Linux AMD drivers (http://anglebug.com/1291)
79     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
80 
81     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
82 
83     // Init first texture to red
84     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
85     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
86     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
87     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
88     glClear(GL_COLOR_BUFFER_BIT);
89     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
90 
91     // Init second texture to green
92     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
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[1], 0);
95     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
96     glClear(GL_COLOR_BUFFER_BIT);
97     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
98 
99     // Copy in the red texture to the green one.
100     // CopyTexImage should sync the framebuffer attachment change.
101     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
102     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 16, 16, 0);
103     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
104     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
105 
106     ASSERT_GL_NO_ERROR();
107 }
108 
109 // Ensure that CopyTexSubImage2D syncs framebuffer changes.
TEST_P(StateChangeTest,CopyTexSubImage2DSync)110 TEST_P(StateChangeTest, CopyTexSubImage2DSync)
111 {
112     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
113 
114     // Init first texture to red
115     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
116     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
117     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
118     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
119     glClear(GL_COLOR_BUFFER_BIT);
120     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
121 
122     // Init second texture to green
123     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
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[1], 0);
126     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
127     glClear(GL_COLOR_BUFFER_BIT);
128     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
129 
130     // Copy in the red texture to the green one.
131     // CopyTexImage should sync the framebuffer attachment change.
132     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
133     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 16, 16);
134     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
135     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
136 
137     ASSERT_GL_NO_ERROR();
138 }
139 
140 // Test that Framebuffer completeness caching works when color attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteColorAttachment)141 TEST_P(StateChangeTest, FramebufferIncompleteColorAttachment)
142 {
143     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
144     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
145     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
146     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
147     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
148 
149     // Change the texture at color attachment 0 to be non-color-renderable.
150     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 16, 16, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
151     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
152                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
153 
154     ASSERT_GL_NO_ERROR();
155 }
156 
157 // Test that caching works when color attachments change with TexStorage.
TEST_P(StateChangeTest,FramebufferIncompleteWithTexStorage)158 TEST_P(StateChangeTest, FramebufferIncompleteWithTexStorage)
159 {
160     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
161 
162     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
163     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
164     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
165     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
166     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
167 
168     // Change the texture at color attachment 0 to be non-color-renderable.
169     glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ALPHA8_EXT, 16, 16);
170     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
171                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
172 
173     ASSERT_GL_NO_ERROR();
174 }
175 
176 // Test that caching works when color attachments change with CompressedTexImage2D.
TEST_P(StateChangeTestES3,FramebufferIncompleteWithCompressedTex)177 TEST_P(StateChangeTestES3, FramebufferIncompleteWithCompressedTex)
178 {
179     // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
180     ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
181 
182     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
183     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
184     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
185     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
186     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
187 
188     // Change the texture at color attachment 0 to be non-color-renderable.
189     glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, 16, 16, 0, 128, nullptr);
190     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
191                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
192 
193     ASSERT_GL_NO_ERROR();
194 }
195 
196 // Test that caching works when color attachments are deleted.
TEST_P(StateChangeTestES3,FramebufferIncompleteWhenAttachmentDeleted)197 TEST_P(StateChangeTestES3, FramebufferIncompleteWhenAttachmentDeleted)
198 {
199     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
200     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
201     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
202     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
203     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
204 
205     // Delete the texture at color attachment 0.
206     glDeleteTextures(1, &mTextures[0]);
207     mTextures[0] = 0;
208     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
209                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
210 
211     ASSERT_GL_NO_ERROR();
212 }
213 
214 // Test that Framebuffer completeness caching works when depth attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteDepthAttachment)215 TEST_P(StateChangeTest, FramebufferIncompleteDepthAttachment)
216 {
217     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
218     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
219     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
220     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
221     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
222     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 16, 16);
223     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderbuffer);
224     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
225 
226     // Change the texture at color attachment 0 to be non-depth-renderable.
227     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
228     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
229                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
230 
231     ASSERT_GL_NO_ERROR();
232 }
233 
234 // Test that Framebuffer completeness caching works when stencil attachments change.
TEST_P(StateChangeTest,FramebufferIncompleteStencilAttachment)235 TEST_P(StateChangeTest, FramebufferIncompleteStencilAttachment)
236 {
237     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
238     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
239     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
240     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
241     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
242     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, 16, 16);
243     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
244                               mRenderbuffer);
245     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
246 
247     // Change the texture at the stencil attachment to be non-stencil-renderable.
248     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
249     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
250                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
251 
252     ASSERT_GL_NO_ERROR();
253 }
254 
255 // Test that Framebuffer completeness caching works when depth-stencil attachments change.
TEST_P(StateChangeTestES3,FramebufferIncompleteDepthStencilAttachment)256 TEST_P(StateChangeTestES3, FramebufferIncompleteDepthStencilAttachment)
257 {
258     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
259     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
260     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
261     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
262     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
263     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
264     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
265                               mRenderbuffer);
266     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
267 
268     // Change the texture the depth-stencil attachment to be non-depth-stencil-renderable.
269     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
270     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
271                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
272 
273     ASSERT_GL_NO_ERROR();
274 }
275 
276 // Test that enabling GL_SAMPLE_ALPHA_TO_COVERAGE doesn't generate errors.
TEST_P(StateChangeTest,AlphaToCoverageEnable)277 TEST_P(StateChangeTest, AlphaToCoverageEnable)
278 {
279     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
280 
281     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
282     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
283     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
286     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
287 
288     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
289 
290     // We don't actually care that this does anything, just that it can be enabled without causing
291     // an error.
292     glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
293 
294     glUseProgram(greenProgram);
295     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
296     ASSERT_GL_NO_ERROR();
297     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
298 }
299 
300 const char kSimpleAttributeVS[] = R"(attribute vec2 position;
301 attribute vec4 testAttrib;
302 varying vec4 testVarying;
303 void main()
304 {
305     gl_Position = vec4(position, 0, 1);
306     testVarying = testAttrib;
307 })";
308 
309 const char kSimpleAttributeFS[] = R"(precision mediump float;
310 varying vec4 testVarying;
311 void main()
312 {
313     gl_FragColor = testVarying;
314 })";
315 
316 // Tests that using a buffered attribute, then disabling it and using current value, works.
TEST_P(StateChangeTest,DisablingBufferedVertexAttribute)317 TEST_P(StateChangeTest, DisablingBufferedVertexAttribute)
318 {
319     ANGLE_GL_PROGRAM(program, kSimpleAttributeVS, kSimpleAttributeFS);
320     glUseProgram(program);
321     GLint attribLoc   = glGetAttribLocation(program, "testAttrib");
322     GLint positionLoc = glGetAttribLocation(program, "position");
323     ASSERT_NE(-1, attribLoc);
324     ASSERT_NE(-1, positionLoc);
325 
326     // Set up the buffered attribute.
327     std::vector<GLColor> red(6, GLColor::red);
328     GLBuffer attribBuffer;
329     glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
330     glBufferData(GL_ARRAY_BUFFER, red.size() * sizeof(GLColor), red.data(), GL_STATIC_DRAW);
331     glEnableVertexAttribArray(attribLoc);
332     glVertexAttribPointer(attribLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
333 
334     // Also set the current value to green now.
335     glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
336 
337     // Set up the position attribute as well.
338     setupQuadVertexBuffer(0.5f, 1.0f);
339     glEnableVertexAttribArray(positionLoc);
340     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
341 
342     // Draw with the buffered attribute. Verify red.
343     glDrawArrays(GL_TRIANGLES, 0, 6);
344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
345 
346     // Draw with the disabled "current value attribute". Verify green.
347     glDisableVertexAttribArray(attribLoc);
348     glDrawArrays(GL_TRIANGLES, 0, 6);
349     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
350 
351     // Verify setting buffer data on the disabled buffer doesn't change anything.
352     std::vector<GLColor> blue(128, GLColor::blue);
353     glBindBuffer(GL_ARRAY_BUFFER, attribBuffer);
354     glBufferData(GL_ARRAY_BUFFER, blue.size() * sizeof(GLColor), blue.data(), GL_STATIC_DRAW);
355     glDrawArrays(GL_TRIANGLES, 0, 6);
356     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
357 }
358 
359 // Tests that setting value for a subset of default attributes doesn't affect others.
TEST_P(StateChangeTest,SetCurrentAttribute)360 TEST_P(StateChangeTest, SetCurrentAttribute)
361 {
362     constexpr char kVS[] = R"(attribute vec4 position;
363 attribute mat4 testAttrib;  // Note that this generates 4 attributes
364 varying vec4 testVarying;
365 void main (void)
366 {
367     gl_Position = position;
368 
369     testVarying = position.y < 0.0 ?
370                     position.x < 0.0 ? testAttrib[0] : testAttrib[1] :
371                     position.x < 0.0 ? testAttrib[2] : testAttrib[3];
372 })";
373 
374     ANGLE_GL_PROGRAM(program, kVS, kSimpleAttributeFS);
375     glUseProgram(program);
376     GLint attribLoc   = glGetAttribLocation(program, "testAttrib");
377     GLint positionLoc = glGetAttribLocation(program, "position");
378     ASSERT_NE(-1, attribLoc);
379     ASSERT_NE(-1, positionLoc);
380 
381     // Set the current value of two of the test attributes, while leaving the other two as default.
382     glVertexAttrib4f(attribLoc + 1, 0.0f, 1.0f, 0.0f, 1.0f);
383     glVertexAttrib4f(attribLoc + 2, 0.0f, 0.0f, 1.0f, 1.0f);
384 
385     // Set up the position attribute.
386     setupQuadVertexBuffer(0.5f, 1.0f);
387     glEnableVertexAttribArray(positionLoc);
388     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
389 
390     // Draw and verify the four section in the output:
391     //
392     //  +---------------+
393     //  | Black | Green |
394     //  +-------+-------+
395     //  | Blue  | Black |
396     //  +---------------+
397     //
398     glDrawArrays(GL_TRIANGLES, 0, 6);
399 
400     const int w                            = getWindowWidth();
401     const int h                            = getWindowHeight();
402     constexpr unsigned int kPixelTolerance = 5u;
403     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, kPixelTolerance);
404     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::green, kPixelTolerance);
405     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::blue, kPixelTolerance);
406     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::black, kPixelTolerance);
407 }
408 
409 // Tests that drawing with transform feedback paused, then lines without transform feedback works
410 // without Vulkan validation errors.
TEST_P(StateChangeTestES3,DrawPausedXfbThenNonXfbLines)411 TEST_P(StateChangeTestES3, DrawPausedXfbThenNonXfbLines)
412 {
413     // glTransformFeedbackVaryings for program2 returns GL_INVALID_OPERATION on both Linux and
414     // windows.  http://anglebug.com/4265
415     ANGLE_SKIP_TEST_IF(IsIntel() && IsOpenGL());
416     // http://anglebug.com/5388
417     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
418 
419     std::vector<std::string> tfVaryings = {"gl_Position"};
420     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program1, essl1_shaders::vs::Simple(),
421                                         essl1_shaders::fs::Blue(), tfVaryings, GL_SEPARATE_ATTRIBS);
422 
423     GLBuffer xfbBuffer;
424     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
425     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 6 * sizeof(float[4]), nullptr, GL_STATIC_DRAW);
426 
427     GLTransformFeedback xfb;
428     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
429     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
430 
431     glUseProgram(program1);
432     glBeginTransformFeedback(GL_TRIANGLES);
433     glPauseTransformFeedback();
434     glDrawArrays(GL_TRIANGLES, 0, 6);
435 
436     ANGLE_GL_PROGRAM(program2, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
437     glUseProgram(program2);
438     glDrawArrays(GL_LINES, 0, 6);
439     glEndTransformFeedback();
440 
441     ASSERT_GL_NO_ERROR();
442 }
443 
444 // Tests that vertex attribute value is preserved across context switches.
TEST_P(StateChangeTest,MultiContextVertexAttribute)445 TEST_P(StateChangeTest, MultiContextVertexAttribute)
446 {
447     EGLWindow *window   = getEGLWindow();
448     EGLDisplay display  = window->getDisplay();
449     EGLConfig config    = window->getConfig();
450     EGLSurface surface  = window->getSurface();
451     EGLContext context1 = window->getContext();
452 
453     // Set up program in primary context
454     ANGLE_GL_PROGRAM(program1, kSimpleAttributeVS, kSimpleAttributeFS);
455     glUseProgram(program1);
456     GLint attribLoc   = glGetAttribLocation(program1, "testAttrib");
457     GLint positionLoc = glGetAttribLocation(program1, "position");
458     ASSERT_NE(-1, attribLoc);
459     ASSERT_NE(-1, positionLoc);
460 
461     // Set up the position attribute in primary context
462     setupQuadVertexBuffer(0.5f, 1.0f);
463     glEnableVertexAttribArray(positionLoc);
464     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
465 
466     // Set primary context attribute to green and draw quad
467     glVertexAttrib4f(attribLoc, 0.0f, 1.0f, 0.0f, 1.0f);
468     glDrawArrays(GL_TRIANGLES, 0, 6);
469     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
470 
471     // Set up and switch to secondary context
472     EGLint contextAttributes[] = {
473         EGL_CONTEXT_MAJOR_VERSION_KHR,
474         GetParam().majorVersion,
475         EGL_CONTEXT_MINOR_VERSION_KHR,
476         GetParam().minorVersion,
477         EGL_NONE,
478     };
479     EGLContext context2 = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes);
480     ASSERT_NE(context2, EGL_NO_CONTEXT);
481     eglMakeCurrent(display, surface, surface, context2);
482 
483     // Set up program in secondary context
484     ANGLE_GL_PROGRAM(program2, kSimpleAttributeVS, kSimpleAttributeFS);
485     glUseProgram(program2);
486     ASSERT_EQ(attribLoc, glGetAttribLocation(program2, "testAttrib"));
487     ASSERT_EQ(positionLoc, glGetAttribLocation(program2, "position"));
488 
489     // Set up the position attribute in secondary context
490     setupQuadVertexBuffer(0.5f, 1.0f);
491     glEnableVertexAttribArray(positionLoc);
492     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
493 
494     // attribLoc current value should be default - (0,0,0,1)
495     glDrawArrays(GL_TRIANGLES, 0, 6);
496     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
497 
498     // Restore primary context
499     eglMakeCurrent(display, surface, surface, context1);
500     // ReadPixels to ensure context is switched
501     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
502 
503     // Switch to secondary context second time
504     eglMakeCurrent(display, surface, surface, context2);
505     // Check that it still draws black
506     glDrawArrays(GL_TRIANGLES, 0, 6);
507     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
508 
509     // Restore primary context second time
510     eglMakeCurrent(display, surface, surface, context1);
511     // Check if it still draws green
512     glDrawArrays(GL_TRIANGLES, 0, 6);
513     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
514 
515     // Clean up
516     eglDestroyContext(display, context2);
517 }
518 
519 // Ensure that CopyTexSubImage3D syncs framebuffer changes.
TEST_P(StateChangeTestES3,CopyTexSubImage3DSync)520 TEST_P(StateChangeTestES3, CopyTexSubImage3DSync)
521 {
522     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
523 
524     // Init first texture to red
525     glBindTexture(GL_TEXTURE_3D, mTextures[0]);
526     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
527     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
528     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
529     glClear(GL_COLOR_BUFFER_BIT);
530     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
531 
532     // Init second texture to green
533     glBindTexture(GL_TEXTURE_3D, mTextures[1]);
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[1], 0, 0);
536     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
537     glClear(GL_COLOR_BUFFER_BIT);
538     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
539 
540     // Copy in the red texture to the green one.
541     // CopyTexImage should sync the framebuffer attachment change.
542     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[0], 0, 0);
543     glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 16, 16);
544     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextures[1], 0, 0);
545     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
546 
547     ASSERT_GL_NO_ERROR();
548 }
549 
550 // Ensure that BlitFramebuffer syncs framebuffer changes.
TEST_P(StateChangeTestES3,BlitFramebufferSync)551 TEST_P(StateChangeTestES3, BlitFramebufferSync)
552 {
553     // http://anglebug.com/4092
554     ANGLE_SKIP_TEST_IF(IsVulkan());
555     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
556 
557     // Init first texture to red
558     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
559     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
560     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
561     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
562     glClear(GL_COLOR_BUFFER_BIT);
563     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
564 
565     // Init second texture to green
566     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
567     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
568     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0);
569     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
570     glClear(GL_COLOR_BUFFER_BIT);
571     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
572 
573     // Change to the red textures and blit.
574     // BlitFramebuffer should sync the framebuffer attachment change.
575     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
576     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0],
577                            0);
578     glBlitFramebuffer(0, 0, 16, 16, 0, 0, 16, 16, GL_COLOR_BUFFER_BIT, GL_NEAREST);
579     glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
580     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
581 
582     ASSERT_GL_NO_ERROR();
583 }
584 
585 // Ensure that ReadBuffer and DrawBuffers sync framebuffer changes.
TEST_P(StateChangeTestES3,ReadBufferAndDrawBuffersSync)586 TEST_P(StateChangeTestES3, ReadBufferAndDrawBuffersSync)
587 {
588     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
589 
590     // Initialize two FBO attachments
591     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
592     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
593     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
594     glBindTexture(GL_TEXTURE_2D, mTextures[1]);
595     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
596     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[1], 0);
597 
598     // Clear first attachment to red
599     GLenum bufs1[] = {GL_COLOR_ATTACHMENT0, GL_NONE};
600     glDrawBuffers(2, bufs1);
601     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
602     glClear(GL_COLOR_BUFFER_BIT);
603 
604     // Clear second texture to green
605     GLenum bufs2[] = {GL_NONE, GL_COLOR_ATTACHMENT1};
606     glDrawBuffers(2, bufs2);
607     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
608     glClear(GL_COLOR_BUFFER_BIT);
609 
610     // Verify first attachment is red and second is green
611     glReadBuffer(GL_COLOR_ATTACHMENT1);
612     EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
613 
614     glReadBuffer(GL_COLOR_ATTACHMENT0);
615     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
616 
617     ASSERT_GL_NO_ERROR();
618 }
619 
620 // Tests calling invalidate on incomplete framebuffers after switching attachments.
621 // Adapted partially from WebGL 2 test "renderbuffers/invalidate-framebuffer"
TEST_P(StateChangeTestES3,IncompleteRenderbufferAttachmentInvalidateSync)622 TEST_P(StateChangeTestES3, IncompleteRenderbufferAttachmentInvalidateSync)
623 {
624     // http://anglebug.com/4092
625     ANGLE_SKIP_TEST_IF(IsVulkan());
626     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
627     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
628     GLint samples = 0;
629     glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, 1, &samples);
630     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
631     ASSERT_GL_NO_ERROR();
632 
633     // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
634     // attached renderbuffer
635     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
636                      glCheckFramebufferStatus(GL_FRAMEBUFFER));
637     GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
638     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
639     ASSERT_GL_NO_ERROR();
640 
641     glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples), GL_RGBA8,
642                                      getWindowWidth(), getWindowHeight());
643     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
644     glClear(GL_COLOR_BUFFER_BIT);
645     ASSERT_GL_NO_ERROR();
646 
647     GLRenderbuffer renderbuf;
648 
649     glBindRenderbuffer(GL_RENDERBUFFER, renderbuf.get());
650     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
651                               renderbuf.get());
652     ASSERT_GL_NO_ERROR();
653 
654     // invalidate the framebuffer when the attachment is incomplete: no storage allocated to the
655     // attached renderbuffer
656     // Note: the bug will only repro *without* a call to checkStatus before the invalidate.
657     GLenum attachments2[] = {GL_DEPTH_ATTACHMENT};
658     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments2);
659 
660     glRenderbufferStorageMultisample(GL_RENDERBUFFER, static_cast<GLsizei>(samples),
661                                      GL_DEPTH_COMPONENT16, getWindowWidth(), getWindowHeight());
662     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
663     glClear(GL_DEPTH_BUFFER_BIT);
664     ASSERT_GL_NO_ERROR();
665 }
666 
667 class StateChangeRenderTest : public StateChangeTest
668 {
669   protected:
StateChangeRenderTest()670     StateChangeRenderTest() : mProgram(0), mRenderbuffer(0) {}
671 
testSetUp()672     void testSetUp() override
673     {
674         StateChangeTest::testSetUp();
675 
676         constexpr char kVS[] =
677             "attribute vec2 position;\n"
678             "void main() {\n"
679             "    gl_Position = vec4(position, 0, 1);\n"
680             "}";
681         constexpr char kFS[] =
682             "uniform highp vec4 uniformColor;\n"
683             "void main() {\n"
684             "    gl_FragColor = uniformColor;\n"
685             "}";
686 
687         mProgram = CompileProgram(kVS, kFS);
688         ASSERT_NE(0u, mProgram);
689 
690         glGenRenderbuffers(1, &mRenderbuffer);
691     }
692 
testTearDown()693     void testTearDown() override
694     {
695         glDeleteProgram(mProgram);
696         glDeleteRenderbuffers(1, &mRenderbuffer);
697 
698         StateChangeTest::testTearDown();
699     }
700 
setUniformColor(const GLColor & color)701     void setUniformColor(const GLColor &color)
702     {
703         glUseProgram(mProgram);
704         const Vector4 &normalizedColor = color.toNormalizedVector();
705         GLint uniformLocation          = glGetUniformLocation(mProgram, "uniformColor");
706         ASSERT_NE(-1, uniformLocation);
707         glUniform4fv(uniformLocation, 1, normalizedColor.data());
708     }
709 
710     GLuint mProgram;
711     GLuint mRenderbuffer;
712 };
713 
714 // Test that re-creating a currently attached texture works as expected.
TEST_P(StateChangeRenderTest,RecreateTexture)715 TEST_P(StateChangeRenderTest, RecreateTexture)
716 {
717     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
718 
719     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
720     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
721     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
722 
723     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
724     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
725 
726     // Draw with red to the FBO.
727     GLColor red(255, 0, 0, 255);
728     setUniformColor(red);
729     drawQuad(mProgram, "position", 0.5f);
730     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
731 
732     // Recreate the texture with green.
733     GLColor green(0, 255, 0, 255);
734     std::vector<GLColor> greenPixels(32 * 32, green);
735     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE,
736                  greenPixels.data());
737     EXPECT_PIXEL_COLOR_EQ(0, 0, green);
738 
739     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
740     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
741 
742     // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
743     GLColor blue(0, 0, 255, 255);
744     setUniformColor(blue);
745     drawQuad(mProgram, "position", 0.5f);
746     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
747 
748     EXPECT_GL_NO_ERROR();
749 }
750 
751 // Test that re-creating a currently attached renderbuffer works as expected.
TEST_P(StateChangeRenderTest,RecreateRenderbuffer)752 TEST_P(StateChangeRenderTest, RecreateRenderbuffer)
753 {
754     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
755 
756     glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
757     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
758     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
759 
760     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
761     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
762 
763     // Draw with red to the FBO.
764     setUniformColor(GLColor::red);
765     drawQuad(mProgram, "position", 0.5f);
766     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
767 
768     // Recreate the renderbuffer and clear to green.
769     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
770     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
771     glClear(GL_COLOR_BUFFER_BIT);
772     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
773 
774     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
775     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
776 
777     // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
778     setUniformColor(GLColor::blue);
779     drawQuad(mProgram, "position", 0.5f);
780     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
781 
782     EXPECT_GL_NO_ERROR();
783 }
784 
785 // Test that recreating a texture with GenerateMipmaps signals the FBO is dirty.
TEST_P(StateChangeRenderTest,GenerateMipmap)786 TEST_P(StateChangeRenderTest, GenerateMipmap)
787 {
788     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
789 
790     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
791     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
792     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
793     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
794     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
795 
796     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
797     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
798 
799     // Draw once to set the RenderTarget in D3D11
800     GLColor red(255, 0, 0, 255);
801     setUniformColor(red);
802     drawQuad(mProgram, "position", 0.5f);
803     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
804 
805     // This will trigger the texture to be re-created on FL9_3.
806     glGenerateMipmap(GL_TEXTURE_2D);
807 
808     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
809     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
810 
811     // Now ensure we don't have a stale render target.
812     GLColor blue(0, 0, 255, 255);
813     setUniformColor(blue);
814     drawQuad(mProgram, "position", 0.5f);
815     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
816 
817     EXPECT_GL_NO_ERROR();
818 }
819 
820 // Tests that gl_DepthRange syncs correctly after a change.
TEST_P(StateChangeRenderTest,DepthRangeUpdates)821 TEST_P(StateChangeRenderTest, DepthRangeUpdates)
822 {
823     constexpr char kFragCoordShader[] = R"(void main()
824 {
825     if (gl_DepthRange.near == 0.2)
826     {
827         gl_FragColor = vec4(1, 0, 0, 1);
828     }
829     else if (gl_DepthRange.near == 0.5)
830     {
831         gl_FragColor = vec4(0, 1, 0, 1);
832     }
833     else
834     {
835         gl_FragColor = vec4(0, 0, 1, 1);
836     }
837 })";
838 
839     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFragCoordShader);
840     glUseProgram(program);
841 
842     const auto &quadVertices = GetQuadVertices();
843 
844     ASSERT_EQ(0, glGetAttribLocation(program, essl1_shaders::PositionAttrib()));
845 
846     GLBuffer vertexBuffer;
847     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
848     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
849                  quadVertices.data(), GL_STATIC_DRAW);
850     glVertexAttribPointer(0u, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
851     glEnableVertexAttribArray(0u);
852 
853     // First, clear.
854     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
855     glClear(GL_COLOR_BUFFER_BIT);
856 
857     // Draw to left half viewport with a first depth range.
858     glDepthRangef(0.2f, 1.0f);
859     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
860     glDrawArrays(GL_TRIANGLES, 0, 6);
861     ASSERT_GL_NO_ERROR();
862 
863     // Draw to right half viewport with a second depth range.
864     glDepthRangef(0.5f, 1.0f);
865     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
866     glDrawArrays(GL_TRIANGLES, 0, 6);
867     ASSERT_GL_NO_ERROR();
868 
869     // Verify left half of the framebuffer is red and right half is green.
870     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth() / 2, getWindowHeight(), GLColor::red);
871     EXPECT_PIXEL_RECT_EQ(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight(),
872                          GLColor::green);
873 }
874 
875 class StateChangeRenderTestES3 : public StateChangeRenderTest
876 {};
877 
TEST_P(StateChangeRenderTestES3,InvalidateNonCurrentFramebuffer)878 TEST_P(StateChangeRenderTestES3, InvalidateNonCurrentFramebuffer)
879 {
880     glBindTexture(GL_TEXTURE_2D, mTextures[0]);
881     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
882     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
883     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
884     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0);
885     glBindTexture(GL_TEXTURE_2D, 0);
886     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
887     ASSERT_GL_NO_ERROR();
888 
889     // Draw with red to the FBO.
890     GLColor red(255, 0, 0, 255);
891     setUniformColor(red);
892     drawQuad(mProgram, "position", 0.5f);
893     EXPECT_PIXEL_COLOR_EQ(0, 0, red);
894 
895     // Go back to default framebuffer, draw green
896     glBindFramebuffer(GL_FRAMEBUFFER, 0);
897     GLColor green(0, 255, 0, 255);
898     setUniformColor(green);
899     drawQuad(mProgram, "position", 0.5f);
900     EXPECT_PIXEL_COLOR_EQ(0, 0, green);
901 
902     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
903 
904     // Invalidate color buffer of FBO
905     GLenum attachments1[] = {GL_COLOR_ATTACHMENT0};
906     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments1);
907     ASSERT_GL_NO_ERROR();
908 
909     // Verify drawing blue gives blue.
910     GLColor blue(0, 0, 255, 255);
911     setUniformColor(blue);
912     drawQuad(mProgram, "position", 0.5f);
913     EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
914 }
915 
916 // Tests that D3D11 dirty bit updates don't forget about BufferSubData attrib updates.
TEST_P(StateChangeTest,VertexBufferUpdatedAfterDraw)917 TEST_P(StateChangeTest, VertexBufferUpdatedAfterDraw)
918 {
919     constexpr char kVS[] =
920         "attribute vec2 position;\n"
921         "attribute vec4 color;\n"
922         "varying vec4 outcolor;\n"
923         "void main()\n"
924         "{\n"
925         "    gl_Position = vec4(position, 0, 1);\n"
926         "    outcolor = color;\n"
927         "}";
928     constexpr char kFS[] =
929         "varying mediump vec4 outcolor;\n"
930         "void main()\n"
931         "{\n"
932         "    gl_FragColor = outcolor;\n"
933         "}";
934 
935     ANGLE_GL_PROGRAM(program, kVS, kFS);
936     glUseProgram(program);
937 
938     GLint colorLoc = glGetAttribLocation(program, "color");
939     ASSERT_NE(-1, colorLoc);
940     GLint positionLoc = glGetAttribLocation(program, "position");
941     ASSERT_NE(-1, positionLoc);
942 
943     setupQuadVertexBuffer(0.5f, 1.0f);
944     glEnableVertexAttribArray(positionLoc);
945     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
946 
947     GLBuffer colorBuf;
948     glBindBuffer(GL_ARRAY_BUFFER, colorBuf);
949     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
950     glEnableVertexAttribArray(colorLoc);
951 
952     // Fill with green.
953     std::vector<GLColor> colorData(6, GLColor::green);
954     glBufferData(GL_ARRAY_BUFFER, colorData.size() * sizeof(GLColor), colorData.data(),
955                  GL_STATIC_DRAW);
956 
957     // Draw, expect green.
958     glDrawArrays(GL_TRIANGLES, 0, 6);
959     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
960     ASSERT_GL_NO_ERROR();
961 
962     // Update buffer with red.
963     std::fill(colorData.begin(), colorData.end(), GLColor::red);
964     glBufferSubData(GL_ARRAY_BUFFER, 0, colorData.size() * sizeof(GLColor), colorData.data());
965 
966     // Draw, expect red.
967     glDrawArrays(GL_TRIANGLES, 0, 6);
968     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
969     ASSERT_GL_NO_ERROR();
970 }
971 
972 // Tests that drawing after flush without any state change works.
TEST_P(StateChangeTestES3,DrawAfterFlushWithNoStateChange)973 TEST_P(StateChangeTestES3, DrawAfterFlushWithNoStateChange)
974 {
975     // Draw (0.125, 0.25, 0.5, 0.5) once, using additive blend
976     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
977     glUseProgram(drawColor);
978 
979     GLint colorUniformLocation =
980         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
981     ASSERT_NE(colorUniformLocation, -1);
982 
983     GLint positionLocation = glGetAttribLocation(drawColor, essl1_shaders::PositionAttrib());
984     ASSERT_NE(-1, positionLocation);
985 
986     // Setup VAO
987     const auto &quadVertices = GetQuadVertices();
988 
989     GLBuffer vertexBuffer;
990     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
991     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
992 
993     GLVertexArray vertexArray;
994     glBindVertexArray(vertexArray);
995     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
996     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
997     glEnableVertexAttribArray(positionLocation);
998     ASSERT_GL_NO_ERROR();
999 
1000     // Clear and draw
1001     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1002     glClear(GL_COLOR_BUFFER_BIT);
1003 
1004     glEnable(GL_BLEND);
1005     glBlendFunc(GL_ONE, GL_ONE);
1006 
1007     glUniform4f(colorUniformLocation, 0.125f, 0.25f, 0.5f, 0.5f);
1008     glDrawArrays(GL_TRIANGLES, 0, 6);
1009     ASSERT_GL_NO_ERROR();
1010 
1011     // Make sure the work is submitted.
1012     glFinish();
1013 
1014     // Draw again with no state change
1015     glDrawArrays(GL_TRIANGLES, 0, 6);
1016     ASSERT_GL_NO_ERROR();
1017 
1018     // Make sure the pixels have the correct colors.
1019     const int h = getWindowHeight() - 1;
1020     const int w = getWindowWidth() - 1;
1021     const GLColor kExpected(63, 127, 255, 255);
1022 
1023     EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1024     EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, kExpected, 1);
1025     EXPECT_PIXEL_COLOR_NEAR(0, h - 1, kExpected, 1);
1026     EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, kExpected, 1);
1027 }
1028 
1029 // Test that switching VAOs keeps the disabled "current value" attributes up-to-date.
TEST_P(StateChangeTestES3,VertexArrayObjectAndDisabledAttributes)1030 TEST_P(StateChangeTestES3, VertexArrayObjectAndDisabledAttributes)
1031 {
1032     constexpr char kSingleVS[] = "attribute vec4 position; void main() { gl_Position = position; }";
1033     constexpr char kSingleFS[] = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
1034     ANGLE_GL_PROGRAM(singleProgram, kSingleVS, kSingleFS);
1035 
1036     constexpr char kDualVS[] =
1037         "#version 300 es\n"
1038         "in vec4 position;\n"
1039         "in vec4 color;\n"
1040         "out vec4 varyColor;\n"
1041         "void main()\n"
1042         "{\n"
1043         "    gl_Position = position;\n"
1044         "    varyColor = color;\n"
1045         "}";
1046     constexpr char kDualFS[] =
1047         "#version 300 es\n"
1048         "precision mediump float;\n"
1049         "in vec4 varyColor;\n"
1050         "out vec4 colorOut;\n"
1051         "void main()\n"
1052         "{\n"
1053         "    colorOut = varyColor;\n"
1054         "}";
1055 
1056     ANGLE_GL_PROGRAM(dualProgram, kDualVS, kDualFS);
1057 
1058     // Force consistent attribute locations
1059     constexpr GLint positionLocation = 0;
1060     constexpr GLint colorLocation    = 1;
1061 
1062     glBindAttribLocation(singleProgram, positionLocation, "position");
1063     glBindAttribLocation(dualProgram, positionLocation, "position");
1064     glBindAttribLocation(dualProgram, colorLocation, "color");
1065 
1066     {
1067         glLinkProgram(singleProgram);
1068         GLint linkStatus;
1069         glGetProgramiv(singleProgram, GL_LINK_STATUS, &linkStatus);
1070         ASSERT_NE(linkStatus, 0);
1071     }
1072 
1073     {
1074         glLinkProgram(dualProgram);
1075         GLint linkStatus;
1076         glGetProgramiv(dualProgram, GL_LINK_STATUS, &linkStatus);
1077         ASSERT_NE(linkStatus, 0);
1078     }
1079 
1080     glUseProgram(singleProgram);
1081 
1082     // Initialize position vertex buffer.
1083     const auto &quadVertices = GetQuadVertices();
1084 
1085     GLBuffer vertexBuffer;
1086     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1087     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 6, quadVertices.data(), GL_STATIC_DRAW);
1088 
1089     // Initialize a VAO. Draw with single program.
1090     GLVertexArray vertexArray;
1091     glBindVertexArray(vertexArray);
1092     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1093     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1094     glEnableVertexAttribArray(positionLocation);
1095 
1096     // Should draw red.
1097     glDrawArrays(GL_TRIANGLES, 0, 6);
1098     ASSERT_GL_NO_ERROR();
1099     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1100 
1101     // Draw with a green buffer attribute, without the VAO.
1102     glBindVertexArray(0);
1103     glUseProgram(dualProgram);
1104     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1105     glEnableVertexAttribArray(positionLocation);
1106 
1107     std::vector<GLColor> greenColors(6, GLColor::green);
1108     GLBuffer greenBuffer;
1109     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
1110     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * 6, greenColors.data(), GL_STATIC_DRAW);
1111 
1112     glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4, nullptr);
1113     glEnableVertexAttribArray(colorLocation);
1114 
1115     glDrawArrays(GL_TRIANGLES, 0, 6);
1116     ASSERT_GL_NO_ERROR();
1117     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1118 
1119     // Re-bind VAO and try to draw with different program, without changing state.
1120     // Should draw black since current value is not initialized.
1121     glBindVertexArray(vertexArray);
1122     glDrawArrays(GL_TRIANGLES, 0, 6);
1123     ASSERT_GL_NO_ERROR();
1124     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
1125 }
1126 
1127 const char kSamplerMetadataVertexShader0[] = R"(#version 300 es
1128 precision mediump float;
1129 out vec4 color;
1130 uniform sampler2D texture;
1131 void main()
1132 {
1133     vec2 size = vec2(textureSize(texture, 0));
1134     color = size.x != 0.0 ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 0.0);
1135     vec2 pos = vec2(0.0);
1136     switch (gl_VertexID) {
1137         case 0: pos = vec2(-1.0, -1.0); break;
1138         case 1: pos = vec2(3.0, -1.0); break;
1139         case 2: pos = vec2(-1.0, 3.0); break;
1140     };
1141     gl_Position = vec4(pos, 0.0, 1.0);
1142 })";
1143 
1144 const char kSamplerMetadataVertexShader1[] = R"(#version 300 es
1145 precision mediump float;
1146 out vec4 color;
1147 uniform sampler2D texture1;
1148 uniform sampler2D texture2;
1149 void main()
1150 {
1151     vec2 size1 = vec2(textureSize(texture1, 0));
1152     vec2 size2 = vec2(textureSize(texture2, 0));
1153     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);
1154     vec2 pos = vec2(0.0);
1155     switch (gl_VertexID) {
1156         case 0: pos = vec2(-1.0, -1.0); break;
1157         case 1: pos = vec2(3.0, -1.0); break;
1158         case 2: pos = vec2(-1.0, 3.0); break;
1159     };
1160     gl_Position = vec4(pos, 0.0, 1.0);
1161 })";
1162 
1163 const char kSamplerMetadataFragmentShader[] = R"(#version 300 es
1164 precision mediump float;
1165 in vec4 color;
1166 out vec4 result;
1167 void main()
1168 {
1169     result = color;
1170 })";
1171 
1172 // Tests that changing an active program invalidates the sampler metadata properly.
TEST_P(StateChangeTestES3,SamplerMetadataUpdateOnSetProgram)1173 TEST_P(StateChangeTestES3, SamplerMetadataUpdateOnSetProgram)
1174 {
1175     // http://anglebug.com/4092
1176     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1177     // TODO(anglebug.com/5491) Appears as though there's something wrong with textureSize on iOS
1178     // unrelated to switching programs.
1179     ANGLE_SKIP_TEST_IF(IsIOS() && 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     // http://anglebug.com/4092
1221     ANGLE_SKIP_TEST_IF(IsVulkan());
1222     // Create the most simple program possible - simple a passthrough for a float attribute.
1223     constexpr char kVertexShader[] = R"(#version 300 es
1224 in float valueIn;
1225 out float valueOut;
1226 void main()
1227 {
1228     gl_Position = vec4(0, 0, 0, 0);
1229     valueOut = valueIn;
1230 })";
1231 
1232     constexpr char kFragmentShader[] = R"(#version 300 es
1233 out mediump float unused;
1234 void main()
1235 {
1236     unused = 1.0;
1237 })";
1238 
1239     std::vector<std::string> tfVaryings = {"valueOut"};
1240     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, kVertexShader, kFragmentShader, tfVaryings,
1241                                         GL_SEPARATE_ATTRIBS);
1242     glUseProgram(program);
1243 
1244     GLint attribLoc = glGetAttribLocation(program, "valueIn");
1245     ASSERT_NE(-1, attribLoc);
1246 
1247     // Disable rasterization - we're not interested in the framebuffer.
1248     glEnable(GL_RASTERIZER_DISCARD);
1249 
1250     // Initialize a float vertex buffer with 1.0.
1251     std::vector<GLfloat> data1(16, 1.0);
1252     GLsizei size1 = static_cast<GLsizei>(sizeof(GLfloat) * data1.size());
1253 
1254     GLBuffer vertexBuffer;
1255     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1256     glBufferData(GL_ARRAY_BUFFER, size1, data1.data(), GL_STATIC_DRAW);
1257     glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1258     glEnableVertexAttribArray(attribLoc);
1259 
1260     ASSERT_GL_NO_ERROR();
1261 
1262     // Initialize a same-sized XFB buffer.
1263     GLBuffer xfbBuffer;
1264     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfbBuffer);
1265     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size1, nullptr, GL_STATIC_DRAW);
1266 
1267     // Draw with XFB enabled.
1268     GLTransformFeedback xfb;
1269     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb);
1270     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfbBuffer);
1271 
1272     glBeginTransformFeedback(GL_POINTS);
1273     glDrawArrays(GL_POINTS, 0, 16);
1274     glEndTransformFeedback();
1275 
1276     ASSERT_GL_NO_ERROR();
1277 
1278     // Verify the XFB stage caught the 1.0 attribute values.
1279     void *mapped1     = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size1, GL_MAP_READ_BIT);
1280     GLfloat *asFloat1 = reinterpret_cast<GLfloat *>(mapped1);
1281     std::vector<GLfloat> actualData1(asFloat1, asFloat1 + data1.size());
1282     EXPECT_EQ(data1, actualData1);
1283     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1284 
1285     // Now, reinitialize the XFB buffer to a larger size, and draw with 2.0.
1286     std::vector<GLfloat> data2(128, 2.0);
1287     const GLsizei size2 = static_cast<GLsizei>(sizeof(GLfloat) * data2.size());
1288     glBufferData(GL_ARRAY_BUFFER, size2, data2.data(), GL_STATIC_DRAW);
1289     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size2, nullptr, GL_STATIC_DRAW);
1290 
1291     glBeginTransformFeedback(GL_POINTS);
1292     glDrawArrays(GL_POINTS, 0, 128);
1293     glEndTransformFeedback();
1294 
1295     ASSERT_GL_NO_ERROR();
1296 
1297     // Verify the XFB stage caught the 2.0 attribute values.
1298     void *mapped2     = glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size2, GL_MAP_READ_BIT);
1299     GLfloat *asFloat2 = reinterpret_cast<GLfloat *>(mapped2);
1300     std::vector<GLfloat> actualData2(asFloat2, asFloat2 + data2.size());
1301     EXPECT_EQ(data2, actualData2);
1302     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1303 }
1304 
1305 // Simple state change tests for line loop drawing. There is some very specific handling of line
1306 // line loops in Vulkan and we need to test switching between drawElements and drawArrays calls to
1307 // validate every edge cases.
1308 class LineLoopStateChangeTest : public StateChangeTest
1309 {
1310   protected:
LineLoopStateChangeTest()1311     LineLoopStateChangeTest()
1312     {
1313         setWindowWidth(32);
1314         setWindowHeight(32);
1315         setConfigRedBits(8);
1316         setConfigGreenBits(8);
1317         setConfigBlueBits(8);
1318         setConfigAlphaBits(8);
1319     }
1320 
validateSquareAndHourglass() const1321     void validateSquareAndHourglass() const
1322     {
1323         ASSERT_GL_NO_ERROR();
1324 
1325         int quarterWidth  = getWindowWidth() / 4;
1326         int quarterHeight = getWindowHeight() / 4;
1327 
1328         // Bottom left
1329         EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::blue);
1330 
1331         // Top left
1332         EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::blue);
1333 
1334         // Top right
1335         // The last pixel isn't filled on a line loop so we check the pixel right before.
1336         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::blue);
1337 
1338         // dead center to validate the hourglass.
1339         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight * 2, GLColor::blue);
1340 
1341         // Verify line is closed between the 2 last vertices
1342         EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::blue);
1343     }
1344 };
1345 
1346 // Draw an hourglass with a drawElements call followed by a square with drawArrays.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawArrays)1347 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawArrays)
1348 {
1349     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1350     glUseProgram(program);
1351 
1352     // We expect to draw a square with these 4 vertices with a drawArray call.
1353     std::vector<Vector3> vertices;
1354     CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1355                                   getWindowHeight(), &vertices);
1356 
1357     // If we use these indices to draw however, we should be drawing an hourglass.
1358     auto indices = std::vector<GLushort>{0, 2, 1, 3};
1359 
1360     GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1361     ASSERT_NE(-1, mPositionLocation);
1362 
1363     GLBuffer vertexBuffer;
1364     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1365     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1366                  GL_STATIC_DRAW);
1367 
1368     GLBuffer indexBuffer;
1369     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1370     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1371                  GL_STATIC_DRAW);
1372 
1373     glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1374     glEnableVertexAttribArray(mPositionLocation);
1375     glClear(GL_COLOR_BUFFER_BIT);
1376     glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
1377     glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
1378     glDisableVertexAttribArray(mPositionLocation);
1379 
1380     validateSquareAndHourglass();
1381 }
1382 
1383 // Draw line loop using a drawArrays followed by an hourglass with drawElements.
TEST_P(LineLoopStateChangeTest,DrawArraysThenDrawElements)1384 TEST_P(LineLoopStateChangeTest, DrawArraysThenDrawElements)
1385 {
1386     // http://anglebug.com/2856: Seems to fail on older drivers and pass on newer.
1387     // Tested failing on 18.3.3 and passing on 18.9.2.
1388     ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan() && IsWindows());
1389 
1390     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1391     glUseProgram(program);
1392 
1393     // We expect to draw a square with these 4 vertices with a drawArray call.
1394     std::vector<Vector3> vertices;
1395     CreatePixelCenterWindowCoords({{8, 8}, {8, 24}, {24, 24}, {24, 8}}, getWindowWidth(),
1396                                   getWindowHeight(), &vertices);
1397 
1398     // If we use these indices to draw however, we should be drawing an hourglass.
1399     auto indices = std::vector<GLushort>{0, 2, 1, 3};
1400 
1401     GLint mPositionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1402     ASSERT_NE(-1, mPositionLocation);
1403 
1404     GLBuffer vertexBuffer;
1405     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1406     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1407                  GL_STATIC_DRAW);
1408 
1409     GLBuffer indexBuffer;
1410     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1411     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1412                  GL_STATIC_DRAW);
1413 
1414     glVertexAttribPointer(mPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1415     glEnableVertexAttribArray(mPositionLocation);
1416     glClear(GL_COLOR_BUFFER_BIT);
1417     glDrawArrays(GL_LINE_LOOP, 0, 4);                             // square
1418     glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, nullptr);  // hourglass
1419     glDisableVertexAttribArray(mPositionLocation);
1420 
1421     validateSquareAndHourglass();
1422 }
1423 
1424 // Draw a triangle with a drawElements call and a non-zero offset and draw the same
1425 // triangle with the same offset again followed by a line loop with drawElements.
TEST_P(LineLoopStateChangeTest,DrawElementsThenDrawElements)1426 TEST_P(LineLoopStateChangeTest, DrawElementsThenDrawElements)
1427 {
1428     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1429 
1430     glUseProgram(program);
1431 
1432     // Background Red color
1433     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1434     glClear(GL_COLOR_BUFFER_BIT);
1435 
1436     // We expect to draw a triangle with the last three points on the bottom right,
1437     // draw with LineLoop, and then draw a triangle with the same non-zero offset.
1438     auto vertices = std::vector<Vector3>{
1439         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1440 
1441     auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1442 
1443     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1444     ASSERT_NE(-1, positionLocation);
1445 
1446     GLBuffer indexBuffer;
1447     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1448     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1449                  GL_STATIC_DRAW);
1450 
1451     GLBuffer vertexBuffer;
1452     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1453     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1454                  GL_STATIC_DRAW);
1455 
1456     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1457     glEnableVertexAttribArray(positionLocation);
1458 
1459     // Draw a triangle with a non-zero offset on the bottom right.
1460     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1461 
1462     // Draw with LineLoop.
1463     glDrawElements(GL_LINE_LOOP, 3, GL_UNSIGNED_SHORT, nullptr);
1464 
1465     // Draw the triangle again with the same offset.
1466     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1467 
1468     glDisableVertexAttribArray(positionLocation);
1469 
1470     ASSERT_GL_NO_ERROR();
1471 
1472     int quarterWidth  = getWindowWidth() / 4;
1473     int quarterHeight = getWindowHeight() / 4;
1474 
1475     // Validate the top left point's color.
1476     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::blue);
1477 
1478     // Validate the triangle is drawn on the bottom right.
1479     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1480 
1481     // Validate the triangle is NOT on the top left part.
1482     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1483     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1484 }
1485 
1486 // Simple state change tests, primarily focused on basic object lifetime and dependency management
1487 // with back-ends that don't support that automatically (i.e. Vulkan).
1488 class SimpleStateChangeTest : public ANGLETest
1489 {
1490   protected:
1491     static constexpr int kWindowSize = 64;
1492 
SimpleStateChangeTest()1493     SimpleStateChangeTest()
1494     {
1495         setWindowWidth(kWindowSize);
1496         setWindowHeight(kWindowSize);
1497         setConfigRedBits(8);
1498         setConfigGreenBits(8);
1499         setConfigBlueBits(8);
1500         setConfigAlphaBits(8);
1501     }
1502 
1503     void simpleDrawWithBuffer(GLBuffer *buffer);
1504     void simpleDrawWithColor(const GLColor &color);
1505 
1506     using UpdateFunc = std::function<void(GLenum, GLTexture *, GLint, GLint, const GLColor &)>;
1507     void updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc);
1508     void bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture);
1509     void drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty);
1510 };
1511 
1512 class SimpleStateChangeTestES3 : public SimpleStateChangeTest
1513 {
1514   protected:
blendAndVerifyColor(const GLColor32F blendColor,const GLColor expectedColor)1515     void blendAndVerifyColor(const GLColor32F blendColor, const GLColor expectedColor)
1516     {
1517         glEnable(GL_BLEND);
1518         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1519         EXPECT_GL_NO_ERROR();
1520 
1521         ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1522         glUseProgram(program);
1523 
1524         GLint colorUniformLocation =
1525             glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1526         ASSERT_NE(colorUniformLocation, -1);
1527 
1528         glUniform4f(colorUniformLocation, blendColor.R, blendColor.G, blendColor.B, blendColor.A);
1529         EXPECT_GL_NO_ERROR();
1530 
1531         drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1532         EXPECT_GL_NO_ERROR();
1533         EXPECT_PIXEL_COLOR_NEAR(0, 0, expectedColor, 1);
1534     }
1535 };
1536 
1537 class SimpleStateChangeTestES31 : public SimpleStateChangeTestES3
1538 {};
1539 
1540 class SimpleStateChangeTestComputeES31 : public SimpleStateChangeTest
1541 {
1542   protected:
testSetUp()1543     void testSetUp() override
1544     {
1545         glGenFramebuffers(1, &mFramebuffer);
1546         glGenTextures(1, &mTexture);
1547 
1548         glBindTexture(GL_TEXTURE_2D, mTexture);
1549         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
1550         EXPECT_GL_NO_ERROR();
1551 
1552         constexpr char kCS[] = R"(#version 310 es
1553 layout(local_size_x=2, local_size_y=2) in;
1554 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
1555 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
1556 void main()
1557 {
1558     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1559                imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
1560 })";
1561 
1562         mProgram = CompileComputeProgram(kCS);
1563         ASSERT_NE(mProgram, 0u);
1564 
1565         glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1566 
1567         glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
1568         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture,
1569                                0);
1570 
1571         ASSERT_GL_NO_ERROR();
1572     }
1573 
testTearDown()1574     void testTearDown() override
1575     {
1576         if (mFramebuffer != 0)
1577         {
1578             glDeleteFramebuffers(1, &mFramebuffer);
1579             mFramebuffer = 0;
1580         }
1581 
1582         if (mTexture != 0)
1583         {
1584             glDeleteTextures(1, &mTexture);
1585             mTexture = 0;
1586         }
1587         glDeleteProgram(mProgram);
1588     }
1589 
1590     GLuint mProgram;
1591     GLuint mFramebuffer = 0;
1592     GLuint mTexture     = 0;
1593 };
1594 
1595 class ImageES31PPO
1596 {
1597   protected:
ImageES31PPO()1598     ImageES31PPO() : mComputeProg(0), mPipeline(0) {}
1599 
bindProgramPipeline(const GLchar * computeString)1600     void bindProgramPipeline(const GLchar *computeString)
1601     {
1602         mComputeProg = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &computeString);
1603         ASSERT_NE(mComputeProg, 0u);
1604 
1605         // Generate a program pipeline and attach the programs to their respective stages
1606         glGenProgramPipelines(1, &mPipeline);
1607         EXPECT_GL_NO_ERROR();
1608         glUseProgramStages(mPipeline, GL_COMPUTE_SHADER_BIT, mComputeProg);
1609         EXPECT_GL_NO_ERROR();
1610         glBindProgramPipeline(mPipeline);
1611         EXPECT_GL_NO_ERROR();
1612         glActiveShaderProgram(mPipeline, mComputeProg);
1613         EXPECT_GL_NO_ERROR();
1614     }
1615 
1616     GLuint mComputeProg;
1617     GLuint mPipeline;
1618 };
1619 
1620 class SimpleStateChangeTestComputeES31PPO : public ImageES31PPO, public SimpleStateChangeTest
1621 {
1622   protected:
SimpleStateChangeTestComputeES31PPO()1623     SimpleStateChangeTestComputeES31PPO() : ImageES31PPO(), SimpleStateChangeTest() {}
1624 
testTearDown()1625     void testTearDown() override
1626     {
1627         if (mFramebuffer != 0)
1628         {
1629             glDeleteFramebuffers(1, &mFramebuffer);
1630             mFramebuffer = 0;
1631         }
1632 
1633         if (mTexture != 0)
1634         {
1635             glDeleteTextures(1, &mTexture);
1636             mTexture = 0;
1637         }
1638         glDeleteProgramPipelines(1, &mPipeline);
1639     }
1640 
1641     GLuint mFramebuffer = 0;
1642     GLuint mTexture     = 0;
1643 };
1644 
1645 constexpr char kSimpleVertexShader[] = R"(attribute vec2 position;
1646 attribute vec4 color;
1647 varying vec4 vColor;
1648 void main()
1649 {
1650     gl_Position = vec4(position, 0, 1);
1651     vColor = color;
1652 }
1653 )";
1654 
1655 constexpr char kSimpleFragmentShader[] = R"(precision mediump float;
1656 varying vec4 vColor;
1657 void main()
1658 {
1659     gl_FragColor = vColor;
1660 }
1661 )";
1662 
simpleDrawWithBuffer(GLBuffer * buffer)1663 void SimpleStateChangeTest::simpleDrawWithBuffer(GLBuffer *buffer)
1664 {
1665     ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
1666     glUseProgram(program);
1667 
1668     GLint colorLoc = glGetAttribLocation(program, "color");
1669     ASSERT_NE(-1, colorLoc);
1670 
1671     glBindBuffer(GL_ARRAY_BUFFER, *buffer);
1672     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1673     glEnableVertexAttribArray(colorLoc);
1674 
1675     drawQuad(program, "position", 0.5f, 1.0f, true);
1676     ASSERT_GL_NO_ERROR();
1677 }
1678 
simpleDrawWithColor(const GLColor & color)1679 void SimpleStateChangeTest::simpleDrawWithColor(const GLColor &color)
1680 {
1681     std::vector<GLColor> colors(6, color);
1682     GLBuffer colorBuffer;
1683     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
1684     glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(GLColor), colors.data(), GL_STATIC_DRAW);
1685     simpleDrawWithBuffer(&colorBuffer);
1686 }
1687 
1688 // Test that we can do a drawElements call successfully after making a drawArrays call in the same
1689 // frame.
TEST_P(SimpleStateChangeTest,DrawArraysThenDrawElements)1690 TEST_P(SimpleStateChangeTest, DrawArraysThenDrawElements)
1691 {
1692     // http://anglebug.com/4121
1693     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
1694     // http://anglebug.com/4177
1695     ANGLE_SKIP_TEST_IF(IsOSX() && IsMetal());
1696     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1697     glUseProgram(program);
1698 
1699     // We expect to draw a triangle with the first 3 points to the left, then another triangle with
1700     // the last 3 vertices using a drawElements call.
1701     auto vertices = std::vector<Vector3>{{-1.0f, -1.0f, 0.0f},
1702                                          {-1.0f, 1.0f, 0.0f},
1703                                          {0.0f, 0.0f, 0.0f},
1704                                          {1.0f, 1.0f, 0.0f},
1705                                          {1.0f, -1.0f, 0.0f}};
1706 
1707     // If we use these indices to draw we'll be using the last 2 vertex only to draw.
1708     auto indices = std::vector<GLushort>{2, 3, 4};
1709 
1710     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1711     ASSERT_NE(-1, positionLocation);
1712 
1713     GLBuffer vertexBuffer;
1714     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1715     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1716                  GL_STATIC_DRAW);
1717 
1718     GLBuffer indexBuffer;
1719     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1720     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1721                  GL_STATIC_DRAW);
1722 
1723     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1724     glEnableVertexAttribArray(positionLocation);
1725 
1726     for (int i = 0; i < 10; i++)
1727     {
1728         glClear(GL_COLOR_BUFFER_BIT);
1729         glDrawArrays(GL_TRIANGLES, 0, 3);                             // triangle to the left
1730         glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, nullptr);  // triangle to the right
1731         glFinish();
1732     }
1733     glDisableVertexAttribArray(positionLocation);
1734 
1735     ASSERT_GL_NO_ERROR();
1736 
1737     int quarterWidth = getWindowWidth() / 4;
1738     int halfHeight   = getWindowHeight() / 2;
1739 
1740     // Validate triangle to the left
1741     EXPECT_PIXEL_COLOR_EQ(quarterWidth, halfHeight, GLColor::blue);
1742 
1743     // Validate triangle to the right
1744     EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), halfHeight, GLColor::blue);
1745 }
1746 
1747 // Draw a triangle with drawElements and a non-zero offset and draw the same
1748 // triangle with the same offset followed by binding the same element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElements)1749 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElements)
1750 {
1751     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1752 
1753     glUseProgram(program);
1754 
1755     // Background Red color
1756     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1757     glClear(GL_COLOR_BUFFER_BIT);
1758 
1759     // We expect to draw the triangle with the last three points on the bottom right, and
1760     // rebind the same element buffer and draw with the same indices.
1761     auto vertices = std::vector<Vector3>{
1762         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1763 
1764     auto indices = std::vector<GLushort>{0, 1, 2, 1, 2, 3};
1765 
1766     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1767     ASSERT_NE(-1, positionLocation);
1768 
1769     GLBuffer indexBuffer;
1770     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1771     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), &indices[0],
1772                  GL_STATIC_DRAW);
1773 
1774     GLBuffer vertexBuffer;
1775     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1776     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1777                  GL_STATIC_DRAW);
1778 
1779     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1780     glEnableVertexAttribArray(positionLocation);
1781 
1782     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1783 
1784     // Rebind the same element buffer.
1785     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1786 
1787     // Draw the triangle again with the same offset.
1788     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(3 * sizeof(GLushort)));
1789 
1790     glDisableVertexAttribArray(positionLocation);
1791 
1792     ASSERT_GL_NO_ERROR();
1793 
1794     int quarterWidth  = getWindowWidth() / 4;
1795     int quarterHeight = getWindowHeight() / 4;
1796 
1797     // Validate the triangle is drawn on the bottom right.
1798     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1799 
1800     // Validate the triangle is NOT on the top left part.
1801     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::red);
1802     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::red);
1803 }
1804 
1805 // Draw a triangle with drawElements then change the index buffer and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndexBuffer)1806 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndexBuffer)
1807 {
1808     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1809 
1810     glUseProgram(program);
1811 
1812     // Background Red color
1813     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1814     glClear(GL_COLOR_BUFFER_BIT);
1815 
1816     // We expect to draw the triangle with the last three points on the bottom right, and
1817     // rebind the same element buffer and draw with the same indices.
1818     auto vertices = std::vector<Vector3>{
1819         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1820 
1821     auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
1822 
1823     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1824     ASSERT_NE(-1, positionLocation);
1825 
1826     GLint colorUniformLocation =
1827         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1828     ASSERT_NE(colorUniformLocation, -1);
1829 
1830     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1831 
1832     GLBuffer indexBuffer8;
1833     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1834     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1835                  GL_STATIC_DRAW);
1836 
1837     GLBuffer vertexBuffer;
1838     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1839     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1840                  GL_STATIC_DRAW);
1841 
1842     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1843     glEnableVertexAttribArray(positionLocation);
1844 
1845     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1846 
1847     auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
1848 
1849     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
1850                  GL_STATIC_DRAW);
1851 
1852     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1853 
1854     // Draw the triangle again with the same offset.
1855     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1856 
1857     glDisableVertexAttribArray(positionLocation);
1858 
1859     ASSERT_GL_NO_ERROR();
1860 
1861     int quarterWidth  = getWindowWidth() / 4;
1862     int quarterHeight = getWindowHeight() / 4;
1863 
1864     // Validate the triangle is drawn on the bottom left.
1865     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1866     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1867 
1868     // Validate the triangle is NOT on the top right part.
1869     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1870 }
1871 
1872 // Draw a triangle with drawElements then change the indices and draw again.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsNewIndices)1873 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsNewIndices)
1874 {
1875     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1876 
1877     glUseProgram(program);
1878 
1879     // Background Red color
1880     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1881     glClear(GL_COLOR_BUFFER_BIT);
1882 
1883     // We expect to draw the triangle with the last three points on the bottom right, and
1884     // rebind the same element buffer and draw with the same indices.
1885     std::vector<Vector3> vertices = {
1886         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1887 
1888     std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1889 
1890     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1891     ASSERT_NE(-1, positionLocation);
1892 
1893     GLint colorUniformLocation =
1894         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1895     ASSERT_NE(colorUniformLocation, -1);
1896 
1897     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1898 
1899     GLBuffer indexBuffer8;
1900     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1901     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1902                  GL_DYNAMIC_DRAW);
1903 
1904     GLBuffer vertexBuffer;
1905     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1906     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1907                  GL_STATIC_DRAW);
1908 
1909     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1910     glEnableVertexAttribArray(positionLocation);
1911 
1912     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1913 
1914     std::vector<GLubyte> newIndices8 = {2, 3, 0};
1915 
1916     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1917                     &newIndices8[0]);
1918 
1919     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1920 
1921     // Draw the triangle again with the same offset.
1922     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1923 
1924     glDisableVertexAttribArray(positionLocation);
1925 
1926     ASSERT_GL_NO_ERROR();
1927 
1928     int quarterWidth  = getWindowWidth() / 4;
1929     int quarterHeight = getWindowHeight() / 4;
1930 
1931     // Validate the triangle is drawn on the bottom left.
1932     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
1933     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
1934 
1935     // Validate the triangle is NOT on the top right part.
1936     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
1937 }
1938 
1939 // Draw a triangle with drawElements then change the indices and draw again.  Similar to
1940 // DrawElementsThenDrawElementsNewIndices, but changes the whole index buffer (not just half).  This
1941 // triggers a different path in the Vulkan backend based on the fact that the majority of the buffer
1942 // is being updated.
TEST_P(SimpleStateChangeTest,DrawElementsThenDrawElementsWholeNewIndices)1943 TEST_P(SimpleStateChangeTest, DrawElementsThenDrawElementsWholeNewIndices)
1944 {
1945     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1946 
1947     glUseProgram(program);
1948 
1949     // Background Red color
1950     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1951     glClear(GL_COLOR_BUFFER_BIT);
1952 
1953     // We expect to draw the triangle with the last three points on the bottom right, and
1954     // rebind the same element buffer and draw with the same indices.
1955     std::vector<Vector3> vertices = {
1956         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
1957 
1958     std::vector<GLubyte> indices8 = {0, 1, 2, 2, 3, 0};
1959 
1960     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
1961     ASSERT_NE(-1, positionLocation);
1962 
1963     GLint colorUniformLocation =
1964         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
1965     ASSERT_NE(colorUniformLocation, -1);
1966 
1967     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
1968 
1969     GLBuffer indexBuffer8;
1970     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
1971     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
1972                  GL_DYNAMIC_DRAW);
1973 
1974     GLBuffer vertexBuffer;
1975     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
1976     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
1977                  GL_STATIC_DRAW);
1978 
1979     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1980     glEnableVertexAttribArray(positionLocation);
1981 
1982     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1983 
1984     std::vector<GLubyte> newIndices8 = {2, 3, 0, 0, 0, 0};
1985 
1986     glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, newIndices8.size() * sizeof(GLubyte),
1987                     &newIndices8[0]);
1988 
1989     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
1990 
1991     // Draw the triangle again with the same offset.
1992     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
1993 
1994     glDisableVertexAttribArray(positionLocation);
1995 
1996     ASSERT_GL_NO_ERROR();
1997 
1998     int quarterWidth  = getWindowWidth() / 4;
1999     int quarterHeight = getWindowHeight() / 4;
2000 
2001     // Validate the triangle is drawn on the bottom left.
2002     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::blue);
2003     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2004 
2005     // Validate the triangle is NOT on the top right part.
2006     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::white);
2007 }
2008 
2009 // Draw a triangle with drawElements and a non-zero offset and draw the same
2010 // triangle with the same offset followed by binding a USHORT element buffer.
TEST_P(SimpleStateChangeTest,DrawElementsUBYTEX2ThenDrawElementsUSHORT)2011 TEST_P(SimpleStateChangeTest, DrawElementsUBYTEX2ThenDrawElementsUSHORT)
2012 {
2013     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
2014 
2015     glUseProgram(program);
2016 
2017     // Background Red color
2018     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2019     glClear(GL_COLOR_BUFFER_BIT);
2020 
2021     // We expect to draw the triangle with the last three points on the bottom right, and
2022     // rebind the same element buffer and draw with the same indices.
2023     auto vertices = std::vector<Vector3>{
2024         {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}};
2025 
2026     auto indices8 = std::vector<GLubyte>{0, 1, 2, 1, 2, 3};
2027 
2028     GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
2029     ASSERT_NE(-1, positionLocation);
2030 
2031     GLint colorUniformLocation =
2032         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
2033     ASSERT_NE(colorUniformLocation, -1);
2034 
2035     glUniform4f(colorUniformLocation, 1.0f, 1.0f, 1.0f, 1.0f);
2036 
2037     GLBuffer indexBuffer8;
2038     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer8);
2039     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices8.size() * sizeof(GLubyte), &indices8[0],
2040                  GL_STATIC_DRAW);
2041 
2042     GLBuffer vertexBuffer;
2043     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
2044     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2045                  GL_STATIC_DRAW);
2046 
2047     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2048     glEnableVertexAttribArray(positionLocation);
2049 
2050     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2051 
2052     auto indices2nd8 = std::vector<GLubyte>{2, 3, 0, 0, 1, 2};
2053     GLBuffer indexBuffer2nd8;
2054     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer2nd8);
2055     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices2nd8.size() * sizeof(GLubyte), &indices2nd8[0],
2056                  GL_STATIC_DRAW);
2057     glUniform4f(colorUniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
2058 
2059     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, (void *)(0 * sizeof(GLubyte)));
2060 
2061     // Bind the 16bit element buffer.
2062     auto indices16 = std::vector<GLushort>{0, 1, 3, 1, 2, 3};
2063     GLBuffer indexBuffer16;
2064     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2065     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices16.size() * sizeof(GLushort), &indices16[0],
2066                  GL_STATIC_DRAW);
2067 
2068     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer16);
2069 
2070     glUniform4f(colorUniformLocation, 0.0f, 0.0f, 1.0f, 1.0f);
2071 
2072     // Draw the triangle again with the same offset.
2073     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, (void *)(0 * sizeof(GLushort)));
2074 
2075     glDisableVertexAttribArray(positionLocation);
2076 
2077     ASSERT_GL_NO_ERROR();
2078 
2079     int quarterWidth  = getWindowWidth() / 4;
2080     int quarterHeight = getWindowHeight() / 4;
2081 
2082     // Validate green triangle is drawn on the bottom.
2083     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight, GLColor::green);
2084 
2085     // Validate white triangle is drawn on the right.
2086     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 3, quarterHeight * 2, GLColor::white);
2087 
2088     // Validate blue triangle is on the top left part.
2089     EXPECT_PIXEL_COLOR_EQ(quarterWidth * 2, quarterHeight * 3, GLColor::blue);
2090     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight * 2, GLColor::blue);
2091 }
2092 
2093 // Draw a points use multiple unaligned vertex buffer with same data,
2094 // verify all the rendering results are the same.
TEST_P(SimpleStateChangeTest,DrawRepeatUnalignedVboChange)2095 TEST_P(SimpleStateChangeTest, DrawRepeatUnalignedVboChange)
2096 {
2097     // http://anglebug.com/4470
2098     ANGLE_SKIP_TEST_IF(isSwiftshader() && (IsWindows() || IsLinux()));
2099     // http://anglebug.com/6171
2100     ANGLE_SKIP_TEST_IF(IsOSX() && IsARM64() && IsMetal());
2101 
2102     const int kRepeat = 2;
2103 
2104     // set up VBO, colorVBO is unaligned
2105     GLBuffer positionBuffer;
2106     constexpr size_t posOffset = 0;
2107     const GLfloat posData[]    = {0.5f, 0.5f};
2108     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2109     glBufferData(GL_ARRAY_BUFFER, sizeof(posData), posData, GL_STATIC_DRAW);
2110 
2111     GLBuffer colorBuffers[kRepeat];
2112     constexpr size_t colorOffset                = 1;
2113     const GLfloat colorData[]                   = {0.515f, 0.515f, 0.515f, 1.0f};
2114     constexpr size_t colorBufferSize            = colorOffset + sizeof(colorData);
2115     uint8_t colorDataUnaligned[colorBufferSize] = {0};
2116     memcpy(reinterpret_cast<void *>(colorDataUnaligned + colorOffset), colorData,
2117            sizeof(colorData));
2118     for (uint32_t i = 0; i < kRepeat; i++)
2119     {
2120         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2121         glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorDataUnaligned, GL_STATIC_DRAW);
2122     }
2123 
2124     // set up frame buffer
2125     GLFramebuffer framebuffer;
2126     GLTexture framebufferTexture;
2127     bindTextureToFbo(framebuffer, framebufferTexture);
2128 
2129     // set up program
2130     ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
2131     glUseProgram(program);
2132     GLuint colorAttrLocation = glGetAttribLocation(program, "color");
2133     glEnableVertexAttribArray(colorAttrLocation);
2134     GLuint posAttrLocation = glGetAttribLocation(program, "position");
2135     glEnableVertexAttribArray(posAttrLocation);
2136     EXPECT_GL_NO_ERROR();
2137 
2138     // draw and get drawing results
2139     constexpr size_t kRenderSize = kWindowSize * kWindowSize;
2140     std::array<GLColor, kRenderSize> pixelBufs[kRepeat];
2141 
2142     for (uint32_t i = 0; i < kRepeat; i++)
2143     {
2144         glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2145         glClear(GL_COLOR_BUFFER_BIT);
2146 
2147         glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2148         glVertexAttribPointer(posAttrLocation, 2, GL_FLOAT, GL_FALSE, 0,
2149                               reinterpret_cast<const void *>(posOffset));
2150         glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2151         glVertexAttribPointer(colorAttrLocation, 4, GL_FLOAT, GL_FALSE, 0,
2152                               reinterpret_cast<const void *>(colorOffset));
2153 
2154         glDrawArrays(GL_POINTS, 0, 1);
2155 
2156         // read drawing results
2157         glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE,
2158                      pixelBufs[i].data());
2159         EXPECT_GL_NO_ERROR();
2160     }
2161 
2162     // verify something is drawn
2163     static_assert(kRepeat >= 2, "More than one repetition required");
2164     std::array<GLColor, kRenderSize> pixelAllBlack{0};
2165     EXPECT_NE(pixelBufs[0], pixelAllBlack);
2166     // verify drawing results are all identical
2167     for (uint32_t i = 1; i < kRepeat; i++)
2168     {
2169         EXPECT_EQ(pixelBufs[i - 1], pixelBufs[i]);
2170     }
2171 }
2172 
2173 // Handles deleting a Buffer when it's being used.
TEST_P(SimpleStateChangeTest,DeleteBufferInUse)2174 TEST_P(SimpleStateChangeTest, DeleteBufferInUse)
2175 {
2176     std::vector<GLColor> colorData(6, GLColor::red);
2177 
2178     GLBuffer buffer;
2179     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2180     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * colorData.size(), colorData.data(),
2181                  GL_STATIC_DRAW);
2182 
2183     simpleDrawWithBuffer(&buffer);
2184 
2185     buffer.reset();
2186     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2187 }
2188 
2189 // Tests that resizing a Buffer during a draw works as expected.
TEST_P(SimpleStateChangeTest,RedefineBufferInUse)2190 TEST_P(SimpleStateChangeTest, RedefineBufferInUse)
2191 {
2192     std::vector<GLColor> redColorData(6, GLColor::red);
2193 
2194     GLBuffer buffer;
2195     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2196     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2197                  GL_STATIC_DRAW);
2198 
2199     // Trigger a pull from the buffer.
2200     simpleDrawWithBuffer(&buffer);
2201 
2202     // Redefine the buffer that's in-flight.
2203     std::vector<GLColor> greenColorData(1024, GLColor::green);
2204     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * greenColorData.size(), greenColorData.data(),
2205                  GL_STATIC_DRAW);
2206 
2207     // Trigger the flush and verify the first draw worked.
2208     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2209 
2210     // Draw again and verify the new data is correct.
2211     simpleDrawWithBuffer(&buffer);
2212     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2213 }
2214 
2215 // Tests updating a buffer's contents while in use, without redefining it.
TEST_P(SimpleStateChangeTest,UpdateBufferInUse)2216 TEST_P(SimpleStateChangeTest, UpdateBufferInUse)
2217 {
2218     std::vector<GLColor> redColorData(6, GLColor::red);
2219 
2220     GLBuffer buffer;
2221     glBindBuffer(GL_ARRAY_BUFFER, buffer);
2222     glBufferData(GL_ARRAY_BUFFER, sizeof(GLColor) * redColorData.size(), redColorData.data(),
2223                  GL_STATIC_DRAW);
2224 
2225     // Trigger a pull from the buffer.
2226     simpleDrawWithBuffer(&buffer);
2227 
2228     // Update the buffer that's in-flight.
2229     std::vector<GLColor> greenColorData(6, GLColor::green);
2230     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * greenColorData.size(),
2231                     greenColorData.data());
2232 
2233     // Trigger the flush and verify the first draw worked.
2234     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2235 
2236     // Draw again and verify the new data is correct.
2237     simpleDrawWithBuffer(&buffer);
2238     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2239 }
2240 
2241 // Tests that deleting an in-flight Texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTest,DeleteTextureInUse)2242 TEST_P(SimpleStateChangeTest, DeleteTextureInUse)
2243 {
2244     std::array<GLColor, 4> colors = {
2245         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2246 
2247     GLTexture tex;
2248     glBindTexture(GL_TEXTURE_2D, tex);
2249     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2250     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2251     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2252 
2253     draw2DTexturedQuad(0.5f, 1.0f, true);
2254     tex.reset();
2255     EXPECT_GL_NO_ERROR();
2256 
2257     int w = getWindowWidth() - 2;
2258     int h = getWindowHeight() - 2;
2259 
2260     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2261     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2262     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2263     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2264 }
2265 
2266 // Tests that modifying a texture parameter in-flight does not cause problems.
TEST_P(SimpleStateChangeTest,ChangeTextureFilterModeBetweenTwoDraws)2267 TEST_P(SimpleStateChangeTest, ChangeTextureFilterModeBetweenTwoDraws)
2268 {
2269     std::array<GLColor, 4> colors = {
2270         {GLColor::black, GLColor::white, GLColor::black, GLColor::white}};
2271 
2272     GLTexture tex;
2273     glBindTexture(GL_TEXTURE_2D, tex);
2274     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2275 
2276     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
2277     glClear(GL_COLOR_BUFFER_BIT);
2278 
2279     // Draw to the left side of the window only with NEAREST.
2280     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
2281     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2282     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2283     draw2DTexturedQuad(0.5f, 1.0f, true);
2284 
2285     // Draw to the right side of the window only with LINEAR.
2286     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
2287     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2288     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2289     draw2DTexturedQuad(0.5f, 1.0f, true);
2290     EXPECT_GL_NO_ERROR();
2291 
2292     glViewport(0, 0, getWindowWidth(), getWindowHeight());
2293 
2294     // The first half (left) should be only black followed by plain white.
2295     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
2296     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::black);
2297     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 3, 0, GLColor::white);
2298     EXPECT_PIXEL_COLOR_EQ((getWindowWidth() / 2) - 4, 0, GLColor::white);
2299 
2300     // The second half (right) should be a gradient so we shouldn't find plain black/white in the
2301     // middle.
2302     EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::black);
2303     EXPECT_NE(angle::ReadColor((getWindowWidth() / 4) * 3, 0), GLColor::white);
2304 }
2305 
2306 // Tests that bind the same texture all the time between different draw calls.
TEST_P(SimpleStateChangeTest,RebindTextureDrawAgain)2307 TEST_P(SimpleStateChangeTest, RebindTextureDrawAgain)
2308 {
2309     GLuint program = get2DTexturedQuadProgram();
2310     glUseProgram(program);
2311 
2312     std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2313 
2314     // Setup the texture
2315     GLTexture tex;
2316     glBindTexture(GL_TEXTURE_2D, tex);
2317     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2318     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2319     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2320 
2321     // Setup the vertex array to draw a quad.
2322     GLint positionLocation = glGetAttribLocation(program, "position");
2323     setupQuadVertexBuffer(1.0f, 1.0f);
2324     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2325     glEnableVertexAttribArray(positionLocation);
2326 
2327     // Draw quad
2328     glDrawArrays(GL_TRIANGLES, 0, 6);
2329     ASSERT_GL_NO_ERROR();
2330 
2331     // Bind again
2332     glBindTexture(GL_TEXTURE_2D, tex);
2333     ASSERT_GL_NO_ERROR();
2334 
2335     // Draw again, should still work.
2336     glDrawArrays(GL_TRIANGLES, 0, 6);
2337     ASSERT_GL_NO_ERROR();
2338 
2339     // Validate whole surface is filled with cyan.
2340     int h = getWindowHeight() - 1;
2341     int w = getWindowWidth() - 1;
2342 
2343     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2344 }
2345 
2346 // Tests that we can draw with a texture, modify the texture with a texSubImage, and then draw again
2347 // correctly.
TEST_P(SimpleStateChangeTest,DrawWithTextureTexSubImageThenDrawAgain)2348 TEST_P(SimpleStateChangeTest, DrawWithTextureTexSubImageThenDrawAgain)
2349 {
2350     GLuint program = get2DTexturedQuadProgram();
2351     ASSERT_NE(0u, program);
2352     glUseProgram(program);
2353 
2354     std::array<GLColor, 4> colors    = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
2355     std::array<GLColor, 4> subColors = {
2356         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
2357 
2358     // Setup the texture
2359     GLTexture tex;
2360     glBindTexture(GL_TEXTURE_2D, tex);
2361     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2362     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2363     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2364 
2365     // Setup the vertex array to draw a quad.
2366     GLint positionLocation = glGetAttribLocation(program, "position");
2367     setupQuadVertexBuffer(1.0f, 1.0f);
2368     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2369     glEnableVertexAttribArray(positionLocation);
2370 
2371     // Draw quad
2372     glDrawArrays(GL_TRIANGLES, 0, 6);
2373     ASSERT_GL_NO_ERROR();
2374 
2375     // Update bottom-half of texture with green.
2376     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
2377     ASSERT_GL_NO_ERROR();
2378 
2379     // Draw again, should still work.
2380     glDrawArrays(GL_TRIANGLES, 0, 6);
2381     ASSERT_GL_NO_ERROR();
2382 
2383     // Validate first half of the screen is red and the bottom is green.
2384     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2385     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 4 * 3, GLColor::red);
2386 }
2387 
2388 // Test that we can alternate between textures between different draws.
TEST_P(SimpleStateChangeTest,DrawTextureAThenTextureBThenTextureA)2389 TEST_P(SimpleStateChangeTest, DrawTextureAThenTextureBThenTextureA)
2390 {
2391     GLuint program = get2DTexturedQuadProgram();
2392     glUseProgram(program);
2393 
2394     std::array<GLColor, 4> colorsTex1 = {
2395         {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
2396 
2397     std::array<GLColor, 4> colorsTex2 = {
2398         {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
2399 
2400     // Setup the texture
2401     GLTexture tex1;
2402     glBindTexture(GL_TEXTURE_2D, tex1);
2403     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex1.data());
2404     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2405     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2406 
2407     GLTexture tex2;
2408     glBindTexture(GL_TEXTURE_2D, tex2);
2409     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colorsTex2.data());
2410     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2411     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2412 
2413     // Setup the vertex array to draw a quad.
2414     GLint positionLocation = glGetAttribLocation(program, "position");
2415     setupQuadVertexBuffer(1.0f, 1.0f);
2416     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
2417     glEnableVertexAttribArray(positionLocation);
2418 
2419     // Draw quad
2420     glBindTexture(GL_TEXTURE_2D, tex1);
2421     glDrawArrays(GL_TRIANGLES, 0, 6);
2422     ASSERT_GL_NO_ERROR();
2423 
2424     // Bind again, draw again
2425     glBindTexture(GL_TEXTURE_2D, tex2);
2426     glDrawArrays(GL_TRIANGLES, 0, 6);
2427     ASSERT_GL_NO_ERROR();
2428 
2429     // Bind again, draw again
2430     glBindTexture(GL_TEXTURE_2D, tex1);
2431     glDrawArrays(GL_TRIANGLES, 0, 6);
2432 
2433     // Validate whole surface is filled with cyan.
2434     int h = getWindowHeight() - 1;
2435     int w = getWindowWidth() - 1;
2436 
2437     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::cyan);
2438 }
2439 
2440 // Tests that redefining an in-flight Texture does not affect the in-flight resource.
TEST_P(SimpleStateChangeTest,RedefineTextureInUse)2441 TEST_P(SimpleStateChangeTest, RedefineTextureInUse)
2442 {
2443     std::array<GLColor, 4> colors = {
2444         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2445 
2446     GLTexture tex;
2447     glBindTexture(GL_TEXTURE_2D, tex);
2448     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
2449     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2450     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2451 
2452     // Draw with the first texture.
2453     draw2DTexturedQuad(0.5f, 1.0f, true);
2454 
2455     // Redefine the in-flight texture.
2456     constexpr int kBigSize = 32;
2457     std::vector<GLColor> bigColors;
2458     for (int y = 0; y < kBigSize; ++y)
2459     {
2460         for (int x = 0; x < kBigSize; ++x)
2461         {
2462             bool xComp = x < kBigSize / 2;
2463             bool yComp = y < kBigSize / 2;
2464             if (yComp)
2465             {
2466                 bigColors.push_back(xComp ? GLColor::cyan : GLColor::magenta);
2467             }
2468             else
2469             {
2470                 bigColors.push_back(xComp ? GLColor::yellow : GLColor::white);
2471             }
2472         }
2473     }
2474 
2475     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bigColors.data());
2476     EXPECT_GL_NO_ERROR();
2477 
2478     // Verify the first draw had the correct data via ReadPixels.
2479     int w = getWindowWidth() - 2;
2480     int h = getWindowHeight() - 2;
2481 
2482     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2483     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
2484     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
2485     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
2486 
2487     // Draw and verify with the redefined data.
2488     draw2DTexturedQuad(0.5f, 1.0f, true);
2489     EXPECT_GL_NO_ERROR();
2490 
2491     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2492     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::magenta);
2493     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::yellow);
2494     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::white);
2495 }
2496 
2497 // Test updating a Texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTest,UpdateTextureInUse)2498 TEST_P(SimpleStateChangeTest, UpdateTextureInUse)
2499 {
2500     std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2501 
2502     // Set up 2D quad resources.
2503     GLuint program = get2DTexturedQuadProgram();
2504     glUseProgram(program);
2505     ASSERT_EQ(0, glGetAttribLocation(program, "position"));
2506 
2507     const auto &quadVerts = GetQuadVertices();
2508 
2509     GLBuffer vbo;
2510     glBindBuffer(GL_ARRAY_BUFFER, vbo);
2511     glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
2512                  GL_STATIC_DRAW);
2513     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2514     glEnableVertexAttribArray(0);
2515 
2516     GLTexture tex;
2517     glBindTexture(GL_TEXTURE_2D, tex);
2518     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
2519     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2520     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2521 
2522     // Draw RGBY to the Framebuffer. The texture is now in-use by GL.
2523     const int w  = getWindowWidth() - 2;
2524     const int h  = getWindowHeight() - 2;
2525     const int w2 = w >> 1;
2526 
2527     glViewport(0, 0, w2, h);
2528     glDrawArrays(GL_TRIANGLES, 0, 6);
2529 
2530     // Update the texture to be YBGR, while the Texture is in-use. Should not affect the draw.
2531     std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
2532     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
2533     ASSERT_GL_NO_ERROR();
2534 
2535     // Draw again to the Framebuffer. The second draw call should use the updated YBGR data.
2536     glViewport(w2, 0, w2, h);
2537     glDrawArrays(GL_TRIANGLES, 0, 6);
2538 
2539     // Check the Framebuffer. Both draws should have completed.
2540     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2541     EXPECT_PIXEL_COLOR_EQ(w2 - 1, 0, GLColor::green);
2542     EXPECT_PIXEL_COLOR_EQ(0, h - 1, GLColor::blue);
2543     EXPECT_PIXEL_COLOR_EQ(w2 - 1, h - 1, GLColor::yellow);
2544 
2545     EXPECT_PIXEL_COLOR_EQ(w2 + 1, 0, GLColor::yellow);
2546     EXPECT_PIXEL_COLOR_EQ(w - 1, 0, GLColor::blue);
2547     EXPECT_PIXEL_COLOR_EQ(w2 + 1, h - 1, GLColor::green);
2548     EXPECT_PIXEL_COLOR_EQ(w - 1, h - 1, GLColor::red);
2549     ASSERT_GL_NO_ERROR();
2550 }
2551 
updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)2552 void SimpleStateChangeTest::updateTextureBoundToFramebufferHelper(UpdateFunc updateFunc)
2553 {
2554     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2555 
2556     std::vector<GLColor> red(4, GLColor::red);
2557     std::vector<GLColor> green(4, GLColor::green);
2558 
2559     GLTexture renderTarget;
2560     glBindTexture(GL_TEXTURE_2D, renderTarget);
2561     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2562 
2563     GLFramebuffer fbo;
2564     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
2565     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2566                            0);
2567     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2568     glViewport(0, 0, 2, 2);
2569     ASSERT_GL_NO_ERROR();
2570 
2571     GLTexture tex;
2572     glBindTexture(GL_TEXTURE_2D, tex);
2573     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
2574     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2575     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2576 
2577     // Draw once to flush dirty state bits.
2578     draw2DTexturedQuad(0.5f, 1.0f, true);
2579 
2580     ASSERT_GL_NO_ERROR();
2581 
2582     // Update the (0, 1) pixel to be blue
2583     updateFunc(GL_TEXTURE_2D, &renderTarget, 0, 1, GLColor::blue);
2584 
2585     // Draw green to the right half of the Framebuffer.
2586     glBindTexture(GL_TEXTURE_2D, tex);
2587     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, green.data());
2588     glViewport(1, 0, 1, 2);
2589     draw2DTexturedQuad(0.5f, 1.0f, true);
2590 
2591     // Update the (1, 1) pixel to be yellow
2592     updateFunc(GL_TEXTURE_2D, &renderTarget, 1, 1, GLColor::yellow);
2593 
2594     ASSERT_GL_NO_ERROR();
2595 
2596     // Verify we have a quad with the right colors in the FBO.
2597     std::vector<GLColor> expected = {
2598         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
2599     std::vector<GLColor> actual(4);
2600     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
2601     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, actual.data());
2602     EXPECT_EQ(expected, actual);
2603 }
2604 
2605 // Tests that TexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,TexSubImageOnTextureBoundToFrambuffer)2606 TEST_P(SimpleStateChangeTest, TexSubImageOnTextureBoundToFrambuffer)
2607 {
2608     // http://anglebug.com/4092
2609     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2610     auto updateFunc = [](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2611                          const GLColor &color) {
2612         glBindTexture(textureBinding, *tex);
2613         glTexSubImage2D(textureBinding, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2614     };
2615 
2616     updateTextureBoundToFramebufferHelper(updateFunc);
2617 }
2618 
2619 // Tests that CopyTexSubImage updates are flushed before rendering.
TEST_P(SimpleStateChangeTest,CopyTexSubImageOnTextureBoundToFrambuffer)2620 TEST_P(SimpleStateChangeTest, CopyTexSubImageOnTextureBoundToFrambuffer)
2621 {
2622     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
2623 
2624     GLTexture copySource;
2625     glBindTexture(GL_TEXTURE_2D, copySource);
2626     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2627 
2628     GLFramebuffer copyFBO;
2629     glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFBO);
2630     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySource, 0);
2631 
2632     ASSERT_GL_NO_ERROR();
2633     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2634 
2635     auto updateFunc = [&copySource](GLenum textureBinding, GLTexture *tex, GLint x, GLint y,
2636                                     const GLColor &color) {
2637         glBindTexture(GL_TEXTURE_2D, copySource);
2638         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color.data());
2639 
2640         glBindTexture(textureBinding, *tex);
2641         glCopyTexSubImage2D(textureBinding, 0, x, y, 0, 0, 1, 1);
2642     };
2643 
2644     updateTextureBoundToFramebufferHelper(updateFunc);
2645 }
2646 
2647 // Tests that the read framebuffer doesn't affect what the draw call thinks the attachments are
2648 // (which is what the draw framebuffer dictates) when a command is issued with the GL_FRAMEBUFFER
2649 // target.
TEST_P(SimpleStateChangeTestES3,ReadFramebufferDrawFramebufferDifferentAttachments)2650 TEST_P(SimpleStateChangeTestES3, ReadFramebufferDrawFramebufferDifferentAttachments)
2651 {
2652     // http://anglebug.com/4092
2653     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2654 
2655     GLRenderbuffer drawColorBuffer;
2656     glBindRenderbuffer(GL_RENDERBUFFER, drawColorBuffer);
2657     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2658 
2659     GLRenderbuffer drawDepthBuffer;
2660     glBindRenderbuffer(GL_RENDERBUFFER, drawDepthBuffer);
2661     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1, 1);
2662 
2663     GLRenderbuffer readColorBuffer;
2664     glBindRenderbuffer(GL_RENDERBUFFER, readColorBuffer);
2665     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
2666 
2667     GLFramebuffer drawFBO;
2668     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2669     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2670                               drawColorBuffer);
2671     glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
2672                               drawDepthBuffer);
2673     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2674 
2675     GLFramebuffer readFBO;
2676     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2677     glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2678                               readColorBuffer);
2679     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2680 
2681     EXPECT_GL_NO_ERROR();
2682 
2683     glClearDepthf(1.0f);
2684     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2685 
2686     // A handful of non-draw calls can sync framebuffer state, such as discard, invalidate,
2687     // invalidateSub and multisamplefv.  The trick here is to give GL_FRAMEBUFFER as target, which
2688     // includes both the read and draw framebuffers.  The test is to make sure syncing the read
2689     // framebuffer doesn't affect the draw call.
2690     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2691     glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, &invalidateAttachment);
2692     EXPECT_GL_NO_ERROR();
2693 
2694     glEnable(GL_DEPTH_TEST);
2695     glDepthFunc(GL_EQUAL);
2696 
2697     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Blue());
2698 
2699     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f);
2700     EXPECT_GL_NO_ERROR();
2701 
2702     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2703     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2704 }
2705 
2706 // Tests that invalidate then copy then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenCopyThenBlend)2707 TEST_P(SimpleStateChangeTestES3, InvalidateThenCopyThenBlend)
2708 {
2709     // Create a framebuffer as the source of copy
2710     const GLColor kSrcData = GLColor::cyan;
2711     GLTexture copySrc;
2712     glBindTexture(GL_TEXTURE_2D, copySrc);
2713     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2714 
2715     GLFramebuffer readFBO;
2716     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2717     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copySrc, 0);
2718     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2719 
2720     // Create the framebuffer that will be invalidated
2721     GLTexture renderTarget;
2722     glBindTexture(GL_TEXTURE_2D, renderTarget);
2723     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2724 
2725     GLFramebuffer drawFBO;
2726     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2727     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2728                            0);
2729     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2730 
2731     EXPECT_GL_NO_ERROR();
2732 
2733     // Clear the framebuffer and invalidate it.
2734     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2735     glClear(GL_COLOR_BUFFER_BIT);
2736 
2737     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2738     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2739     EXPECT_GL_NO_ERROR();
2740 
2741     // Copy into the framebuffer's texture.  The framebuffer should now be cyan.
2742     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
2743     EXPECT_GL_NO_ERROR();
2744 
2745     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2746     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2747     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2748 }
2749 
2750 // Tests that invalidate then blit then blend works.
TEST_P(SimpleStateChangeTestES3,InvalidateThenBlitThenBlend)2751 TEST_P(SimpleStateChangeTestES3, InvalidateThenBlitThenBlend)
2752 {
2753     // Create a framebuffer as the source of blit
2754     const GLColor kSrcData = GLColor::cyan;
2755     GLTexture blitSrc;
2756     glBindTexture(GL_TEXTURE_2D, blitSrc);
2757     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kSrcData);
2758 
2759     GLFramebuffer readFBO;
2760     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
2761     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
2762     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
2763 
2764     // Create the framebuffer that will be invalidated
2765     GLTexture renderTarget;
2766     glBindTexture(GL_TEXTURE_2D, renderTarget);
2767     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2768 
2769     GLFramebuffer drawFBO;
2770     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2771     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2772                            0);
2773     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2774 
2775     EXPECT_GL_NO_ERROR();
2776 
2777     // Clear the framebuffer and invalidate it.
2778     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2779     glClear(GL_COLOR_BUFFER_BIT);
2780 
2781     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2782     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2783     EXPECT_GL_NO_ERROR();
2784 
2785     // Blit into the framebuffer.  The framebuffer should now be cyan.
2786     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2787     EXPECT_GL_NO_ERROR();
2788 
2789     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2790     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2791     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2792 }
2793 
2794 // Tests that invalidate then generate mipmaps works
TEST_P(SimpleStateChangeTestES3,InvalidateThenGenerateMipmapsThenBlend)2795 TEST_P(SimpleStateChangeTestES3, InvalidateThenGenerateMipmapsThenBlend)
2796 {
2797     // Create a texture on which generate mipmaps would be called
2798     const GLColor kMip0Data[4] = {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan};
2799     const GLColor kMip1Data    = GLColor::blue;
2800     GLTexture texture;
2801     glBindTexture(GL_TEXTURE_2D, texture);
2802     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMip0Data);
2803     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kMip1Data);
2804 
2805     // Create the framebuffer that will be invalidated
2806     GLFramebuffer drawFBO;
2807     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2808     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 1);
2809     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2810 
2811     EXPECT_GL_NO_ERROR();
2812 
2813     // Clear the framebuffer and invalidate it.
2814     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2815     glClear(GL_COLOR_BUFFER_BIT);
2816 
2817     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2818     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2819     EXPECT_GL_NO_ERROR();
2820 
2821     // Generate mipmaps
2822     glGenerateMipmap(GL_TEXTURE_2D);
2823 
2824     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2825     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2826     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2827 }
2828 
2829 // Tests that invalidate then upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenUploadThenBlend)2830 TEST_P(SimpleStateChangeTestES3, InvalidateThenUploadThenBlend)
2831 {
2832     // http://anglebug.com/4870
2833     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2834 
2835     // Create the framebuffer that will be invalidated
2836     GLTexture renderTarget;
2837     glBindTexture(GL_TEXTURE_2D, renderTarget);
2838     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2839 
2840     GLFramebuffer drawFBO;
2841     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2842     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2843                            0);
2844     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2845 
2846     EXPECT_GL_NO_ERROR();
2847 
2848     // Clear the framebuffer and invalidate it.
2849     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2850     glClear(GL_COLOR_BUFFER_BIT);
2851 
2852     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2853     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2854     EXPECT_GL_NO_ERROR();
2855 
2856     // Upload data to it
2857     const GLColor kUploadColor = GLColor::cyan;
2858     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2859 
2860     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2861     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2862     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2863 }
2864 
2865 // Tests that invalidate then sub upload works
TEST_P(SimpleStateChangeTestES3,InvalidateThenSubUploadThenBlend)2866 TEST_P(SimpleStateChangeTestES3, InvalidateThenSubUploadThenBlend)
2867 {
2868     // http://anglebug.com/4870
2869     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2870 
2871     // Create the framebuffer that will be invalidated
2872     GLTexture renderTarget;
2873     glBindTexture(GL_TEXTURE_2D, renderTarget);
2874     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2875 
2876     GLFramebuffer drawFBO;
2877     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2878     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2879                            0);
2880     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2881 
2882     EXPECT_GL_NO_ERROR();
2883 
2884     // Clear the framebuffer and invalidate it.
2885     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2886     glClear(GL_COLOR_BUFFER_BIT);
2887 
2888     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2889     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2890     EXPECT_GL_NO_ERROR();
2891 
2892     // Upload data to it
2893     const GLColor kUploadColor = GLColor::cyan;
2894     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &kUploadColor);
2895 
2896     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2897     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2898     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2899 }
2900 
2901 // Tests that invalidate then compute write works
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlend)2902 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlend)
2903 {
2904     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2905     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2906     // http://anglebug.com/5387
2907     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
2908 
2909     constexpr char kCS[] = R"(#version 310 es
2910 layout(local_size_x=1, local_size_y=1) in;
2911 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2912 void main()
2913 {
2914     imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2915 })";
2916 
2917     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2918     glUseProgram(program);
2919     EXPECT_GL_NO_ERROR();
2920 
2921     // Create the framebuffer texture
2922     GLTexture renderTarget;
2923     glBindTexture(GL_TEXTURE_2D, renderTarget);
2924     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2925     glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2926 
2927     // Write to the texture with compute once.  In the Vulkan backend, this will make sure the image
2928     // is already created with STORAGE usage and avoids recreate later.
2929     glDispatchCompute(1, 1, 1);
2930     EXPECT_GL_NO_ERROR();
2931 
2932     // Create the framebuffer that will be invalidated
2933     GLFramebuffer drawFBO;
2934     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2935     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
2936                            0);
2937     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
2938 
2939     EXPECT_GL_NO_ERROR();
2940 
2941     // Clear the framebuffer and invalidate it.
2942     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
2943     glClear(GL_COLOR_BUFFER_BIT);
2944 
2945     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
2946     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
2947     EXPECT_GL_NO_ERROR();
2948 
2949     // Write to it with a compute shader
2950     glDispatchCompute(1, 1, 1);
2951     EXPECT_GL_NO_ERROR();
2952 
2953     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2954 
2955     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
2956     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
2957     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
2958 }
2959 
2960 // Tests that invalidate then compute write works inside PPO
TEST_P(SimpleStateChangeTestES31,InvalidateThenStorageWriteThenBlendPpo)2961 TEST_P(SimpleStateChangeTestES31, InvalidateThenStorageWriteThenBlendPpo)
2962 {
2963     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
2964     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
2965     // PPOs are only supported in the Vulkan backend
2966     ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2967 
2968     constexpr char kCS[] = R"(#version 310 es
2969 layout(local_size_x=1, local_size_y=1) in;
2970 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
2971 void main()
2972 {
2973     imageStore(dstImage, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
2974 })";
2975 
2976     GLProgramPipeline pipeline;
2977     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2978     glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
2979     glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, program);
2980     EXPECT_GL_NO_ERROR();
2981     glBindProgramPipeline(pipeline);
2982     EXPECT_GL_NO_ERROR();
2983     glUseProgram(0);
2984 
2985     // Create the framebuffer texture
2986     GLTexture renderTarget;
2987     glBindTexture(GL_TEXTURE_2D, renderTarget);
2988     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2989     glBindImageTexture(1, renderTarget, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
2990 
2991     // Write to the texture with compute once.  In the Vulkan backend, this will make sure the image
2992     // is already created with STORAGE usage and avoids recreate later.
2993     glDispatchCompute(1, 1, 1);
2994     EXPECT_GL_NO_ERROR();
2995 
2996     // Create the framebuffer that will be invalidated
2997     GLFramebuffer drawFBO;
2998     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
2999     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3000                            0);
3001     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3002 
3003     EXPECT_GL_NO_ERROR();
3004 
3005     // Clear the framebuffer and invalidate it.
3006     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3007     glClear(GL_COLOR_BUFFER_BIT);
3008 
3009     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3010     glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment);
3011     EXPECT_GL_NO_ERROR();
3012 
3013     // Write to it with a compute shader
3014     glDispatchCompute(1, 1, 1);
3015     EXPECT_GL_NO_ERROR();
3016 
3017     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3018 
3019     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3020     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3021     blendAndVerifyColor(GLColor32F(1.0f, 0.0f, 0.0f, 0.5f), GLColor(127, 127, 127, 191));
3022 }
3023 
3024 // Tests that sub-invalidate then draw works.
TEST_P(SimpleStateChangeTestES3,SubInvalidateThenDraw)3025 TEST_P(SimpleStateChangeTestES3, SubInvalidateThenDraw)
3026 {
3027     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3028     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3029 
3030     // Create the framebuffer that will be invalidated
3031     GLTexture renderTarget;
3032     glBindTexture(GL_TEXTURE_2D, renderTarget);
3033     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3034 
3035     GLFramebuffer drawFBO;
3036     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
3037     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTarget,
3038                            0);
3039     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
3040 
3041     EXPECT_GL_NO_ERROR();
3042 
3043     // Clear the framebuffer.
3044     glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
3045     glClear(GL_COLOR_BUFFER_BIT);
3046 
3047     // Draw into a quarter of the framebuffer, then invalidate that same region.
3048     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3049     glEnable(GL_SCISSOR_TEST);
3050     glScissor(1, 1, 1, 1);
3051     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3052 
3053     // Only invalidate a quarter of the framebuffer.
3054     GLenum invalidateAttachment = GL_COLOR_ATTACHMENT0;
3055     glInvalidateSubFramebuffer(GL_DRAW_FRAMEBUFFER, 1, &invalidateAttachment, 1, 1, 1, 1);
3056     EXPECT_GL_NO_ERROR();
3057 
3058     glDisable(GL_SCISSOR_TEST);
3059 
3060     // Blend into the framebuffer, then verify that the framebuffer should have had cyan.
3061     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3062     blendAndVerifyColor(GLColor32F(0.0f, 0.0f, 1.0f, 0.5f), GLColor(127, 127, 127, 191));
3063 }
3064 
3065 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,DeleteFramebufferInUse)3066 TEST_P(SimpleStateChangeTest, DeleteFramebufferInUse)
3067 {
3068     constexpr int kSize = 16;
3069 
3070     // Create a simple framebuffer.
3071     GLTexture texture;
3072     glBindTexture(GL_TEXTURE_2D, texture);
3073     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3074 
3075     GLFramebuffer framebuffer;
3076     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3077     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3078     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3079 
3080     glViewport(0, 0, kSize, kSize);
3081 
3082     // Draw a solid red color to the framebuffer.
3083     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3084     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
3085 
3086     // Delete the framebuffer while the call is in flight.
3087     framebuffer.reset();
3088 
3089     // Make a new framebuffer so we can read back the texture.
3090     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3091     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3092     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3093 
3094     // Flush via ReadPixels and check red was drawn.
3095     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3096     ASSERT_GL_NO_ERROR();
3097 }
3098 
3099 // This test was made to reproduce a specific issue with our Vulkan backend where were releasing
3100 // buffers too early. The test has 2 textures, we first create a texture and update it with
3101 // multiple updates, but we don't use it right away, we instead draw using another texture
3102 // then we bind the first texture and draw with it.
TEST_P(SimpleStateChangeTest,DynamicAllocationOfMemoryForTextures)3103 TEST_P(SimpleStateChangeTest, DynamicAllocationOfMemoryForTextures)
3104 {
3105     constexpr int kSize = 64;
3106 
3107     GLuint program = get2DTexturedQuadProgram();
3108     glUseProgram(program);
3109 
3110     std::vector<GLColor> greenPixels(kSize * kSize, GLColor::green);
3111     std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
3112     GLTexture texture1;
3113     glBindTexture(GL_TEXTURE_2D, texture1);
3114     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3115 
3116     for (int i = 0; i < 100; i++)
3117     {
3118         // We do this a lot of time to make sure we use multiple buffers in the vulkan backend.
3119         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
3120                         greenPixels.data());
3121     }
3122     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3123     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3124 
3125     ASSERT_GL_NO_ERROR();
3126 
3127     GLTexture texture2;
3128     glBindTexture(GL_TEXTURE_2D, texture2);
3129     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redPixels.data());
3130     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3131     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3132 
3133     // Setup the vertex array to draw a quad.
3134     GLint positionLocation = glGetAttribLocation(program, "position");
3135     setupQuadVertexBuffer(1.0f, 1.0f);
3136     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3137     glEnableVertexAttribArray(positionLocation);
3138 
3139     // Draw quad with texture 2 while texture 1 has "staged" changes that have not been flushed yet.
3140     glBindTexture(GL_TEXTURE_2D, texture2);
3141     glDrawArrays(GL_TRIANGLES, 0, 6);
3142     ASSERT_GL_NO_ERROR();
3143     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3144 
3145     // If we now try to draw with texture1, we should trigger the issue.
3146     glBindTexture(GL_TEXTURE_2D, texture1);
3147     glDrawArrays(GL_TRIANGLES, 0, 6);
3148     ASSERT_GL_NO_ERROR();
3149 
3150     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3151 }
3152 
3153 // Tests deleting a Framebuffer that is in use.
TEST_P(SimpleStateChangeTest,RedefineFramebufferInUse)3154 TEST_P(SimpleStateChangeTest, RedefineFramebufferInUse)
3155 {
3156     constexpr int kSize = 16;
3157 
3158     // Create a simple framebuffer.
3159     GLTexture texture;
3160     glBindTexture(GL_TEXTURE_2D, texture);
3161     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3162 
3163     GLFramebuffer framebuffer;
3164     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3165     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3166     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3167 
3168     glViewport(0, 0, kSize, kSize);
3169 
3170     // Draw red to the framebuffer.
3171     simpleDrawWithColor(GLColor::red);
3172 
3173     // Change the framebuffer while the call is in flight to a new texture.
3174     GLTexture otherTexture;
3175     glBindTexture(GL_TEXTURE_2D, otherTexture);
3176     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3177 
3178     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, otherTexture, 0);
3179     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3180 
3181     // Draw green to the framebuffer. Verify the color.
3182     simpleDrawWithColor(GLColor::green);
3183     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3184 
3185     // Make a new framebuffer so we can read back the first texture and verify red.
3186     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3187     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3188     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3189 
3190     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3191     ASSERT_GL_NO_ERROR();
3192 }
3193 
3194 // Tests that redefining a Framebuffer Texture Attachment works as expected.
TEST_P(SimpleStateChangeTest,RedefineFramebufferTexture)3195 TEST_P(SimpleStateChangeTest, RedefineFramebufferTexture)
3196 {
3197     GLFramebuffer framebuffer;
3198     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3199 
3200     // Bind a simple 8x8 texture to the framebuffer, draw red.
3201     GLTexture texture;
3202     glBindTexture(GL_TEXTURE_2D, texture);
3203     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3204     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
3205 
3206     glViewport(0, 0, 8, 8);
3207     simpleDrawWithColor(GLColor::red);
3208     ASSERT_GL_NO_ERROR();
3209     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red) << "first draw should be red";
3210 
3211     // Redefine the texture to 32x32, draw green. Verify we get what we expect.
3212     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3213     glViewport(0, 0, 32, 32);
3214     simpleDrawWithColor(GLColor::green);
3215     ASSERT_GL_NO_ERROR();
3216     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "second draw should be green";
3217 }
3218 
3219 // Trips a bug in the Vulkan back-end where a Texture wouldn't transition correctly.
TEST_P(SimpleStateChangeTest,DrawAndClearTextureRepeatedly)3220 TEST_P(SimpleStateChangeTest, DrawAndClearTextureRepeatedly)
3221 {
3222     // Fails on 431.02 driver. http://anglebug.com/3748
3223     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsVulkan());
3224 
3225     // Fails on AMD OpenGL Windows. This configuration isn't maintained.
3226     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
3227 
3228     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
3229 
3230     GLTexture tex;
3231     glBindTexture(GL_TEXTURE_2D, tex);
3232     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
3233     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3234     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3235     ASSERT_GL_NO_ERROR();
3236 
3237     GLFramebuffer fbo;
3238     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3239     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
3240     ASSERT_GL_NO_ERROR();
3241     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3242 
3243     glUseProgram(program);
3244 
3245     GLint uniLoc = glGetUniformLocation(program, essl1_shaders::Texture2DUniform());
3246     ASSERT_NE(-1, uniLoc);
3247     glUniform1i(uniLoc, 0);
3248 
3249     const int numRowsCols = 2;
3250     const int cellSize    = getWindowWidth() / 2;
3251 
3252     for (int cellY = 0; cellY < numRowsCols; cellY++)
3253     {
3254         for (int cellX = 0; cellX < numRowsCols; cellX++)
3255         {
3256             int seed            = cellX + cellY * numRowsCols;
3257             const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3258 
3259             // Set the texture to a constant color using glClear and a user FBO.
3260             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3261             glClearColor(color[0], color[1], color[2], color[3]);
3262             glClear(GL_COLOR_BUFFER_BIT);
3263 
3264             // Draw a small colored quad to the default FBO using the viewport.
3265             glBindFramebuffer(GL_FRAMEBUFFER, 0);
3266             glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
3267             drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
3268         }
3269     }
3270 
3271     // Verify the colored quads were drawn correctly despite no flushing.
3272     std::vector<GLColor> pixelData(getWindowWidth() * getWindowHeight());
3273     glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
3274                  pixelData.data());
3275 
3276     ASSERT_GL_NO_ERROR();
3277 
3278     for (int cellY = 0; cellY < numRowsCols; cellY++)
3279     {
3280         for (int cellX = 0; cellX < numRowsCols; cellX++)
3281         {
3282             int seed            = cellX + cellY * numRowsCols;
3283             const Vector4 color = RandomVec4(seed, 0.0f, 1.0f);
3284 
3285             GLColor expectedColor(color);
3286 
3287             int testN =
3288                 cellX * cellSize + cellY * getWindowWidth() * cellSize + getWindowWidth() + 1;
3289             GLColor actualColor = pixelData[testN];
3290             EXPECT_COLOR_NEAR(expectedColor, actualColor, 1);
3291         }
3292     }
3293 }
3294 
3295 // Test that clear followed by rebind of framebuffer attachment works (with noop clear in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopClearThenRebindAttachment)3296 TEST_P(SimpleStateChangeTestES3, ClearThenNoopClearThenRebindAttachment)
3297 {
3298     // Create a texture with red
3299     const GLColor kInitColor1 = GLColor::red;
3300     GLTexture texture1;
3301     glBindTexture(GL_TEXTURE_2D, texture1);
3302     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3303 
3304     // Create a framebuffer to be cleared
3305     GLTexture texture2;
3306     glBindTexture(GL_TEXTURE_2D, texture2);
3307     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3308 
3309     GLFramebuffer drawFBO;
3310     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3311     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3312     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3313 
3314     EXPECT_GL_NO_ERROR();
3315 
3316     // Clear the framebuffer to green
3317     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3318     glClear(GL_COLOR_BUFFER_BIT);
3319 
3320     // Clear again, but in a way that would be a no-op.  In the Vulkan backend, this will result in
3321     // a framebuffer sync state, which extracts deferred clears.  However, as the clear is actually
3322     // a noop, the deferred clears will remain unflushed.
3323     glClear(0);
3324 
3325     // Change framebuffer's attachment to the other texture.
3326     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3327     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3328 
3329     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3330     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3331     glUseProgram(program);
3332 
3333     glEnable(GL_BLEND);
3334     glBlendFunc(GL_ZERO, GL_ONE);
3335     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3336     EXPECT_GL_NO_ERROR();
3337 
3338     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3339     // to the new attachment, green will be read back.
3340     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3341 
3342     // Attach back to texture2.  It should be cleared to green.
3343     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3344     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3345 }
3346 
3347 // Test that clear followed by rebind of framebuffer attachment works (with 0-sized scissor clear in
3348 // between).
TEST_P(SimpleStateChangeTestES3,ClearThenZeroSizeScissoredClearThenRebindAttachment)3349 TEST_P(SimpleStateChangeTestES3, ClearThenZeroSizeScissoredClearThenRebindAttachment)
3350 {
3351     // Create a texture with red
3352     const GLColor kInitColor1 = GLColor::red;
3353     GLTexture texture1;
3354     glBindTexture(GL_TEXTURE_2D, texture1);
3355     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3356 
3357     // Create a framebuffer to be cleared
3358     GLTexture texture2;
3359     glBindTexture(GL_TEXTURE_2D, texture2);
3360     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3361 
3362     GLFramebuffer drawFBO;
3363     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3364     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3365     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3366 
3367     EXPECT_GL_NO_ERROR();
3368 
3369     // Clear the framebuffer to green
3370     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3371     glClear(GL_COLOR_BUFFER_BIT);
3372 
3373     // Clear again, but in a way that would be a no-op.  In the Vulkan backend, this will result in
3374     // a framebuffer sync state, which extracts deferred clears.  However, as the clear is actually
3375     // a noop, the deferred clears will remain unflushed.
3376     glEnable(GL_SCISSOR_TEST);
3377     glScissor(0, 0, 0, 0);
3378     glClear(GL_COLOR_BUFFER_BIT);
3379     glDisable(GL_SCISSOR_TEST);
3380 
3381     // Change framebuffer's attachment to the other texture.
3382     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3383     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3384 
3385     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3386     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3387     glUseProgram(program);
3388 
3389     glEnable(GL_BLEND);
3390     glBlendFunc(GL_ZERO, GL_ONE);
3391     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3392     EXPECT_GL_NO_ERROR();
3393 
3394     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3395     // to the new attachment, green will be read back.
3396     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3397 
3398     // Attach back to texture2.  It should be cleared to green.
3399     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3400     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3401 }
3402 
3403 // Test that clear followed by rebind of framebuffer attachment works (with noop blit in between).
TEST_P(SimpleStateChangeTestES3,ClearThenNoopBlitThenRebindAttachment)3404 TEST_P(SimpleStateChangeTestES3, ClearThenNoopBlitThenRebindAttachment)
3405 {
3406     // Create a texture with red
3407     const GLColor kInitColor1 = GLColor::red;
3408     GLTexture texture1;
3409     glBindTexture(GL_TEXTURE_2D, texture1);
3410     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor1);
3411 
3412     // Create a framebuffer to be cleared
3413     GLTexture texture2;
3414     glBindTexture(GL_TEXTURE_2D, texture2);
3415     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3416 
3417     GLFramebuffer drawFBO;
3418     glBindFramebuffer(GL_FRAMEBUFFER, drawFBO);
3419     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3420     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3421 
3422     EXPECT_GL_NO_ERROR();
3423 
3424     // Clear the framebuffer to green
3425     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
3426     glClear(GL_COLOR_BUFFER_BIT);
3427 
3428     // Issue noop blit.  In the Vulkan backend, this will result in a framebuffer sync state, which
3429     // extracts deferred clears.  However, as the blit is actually a noop, the deferred clears will
3430     // remain unflushed.
3431     GLTexture blitSrc;
3432     glBindTexture(GL_TEXTURE_2D, blitSrc);
3433     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3434 
3435     GLFramebuffer readFBO;
3436     glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
3437     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, blitSrc, 0);
3438     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
3439 
3440     glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
3441     EXPECT_GL_NO_ERROR();
3442 
3443     // Change framebuffer's attachment to the other texture.
3444     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3445     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3446 
3447     // A bogus draw to make sure the render pass is cleared in the Vulkan backend.
3448     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3449     glUseProgram(program);
3450 
3451     glEnable(GL_BLEND);
3452     glBlendFunc(GL_ZERO, GL_ONE);
3453     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
3454     EXPECT_GL_NO_ERROR();
3455 
3456     // Expect red, which is the original contents of texture1.  If the clear is mistakenly applied
3457     // to the new attachment, green will be read back.
3458     glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFBO);
3459     EXPECT_PIXEL_COLOR_EQ(0, 0, kInitColor1);
3460 
3461     // Attach back to texture2.  It should be cleared to green.
3462     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3463     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3464 }
3465 
3466 // Validates disabling cull face really disables it.
TEST_P(SimpleStateChangeTest,EnableAndDisableCullFace)3467 TEST_P(SimpleStateChangeTest, EnableAndDisableCullFace)
3468 {
3469     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3470     glUseProgram(program);
3471 
3472     glClear(GL_COLOR_BUFFER_BIT);
3473     glEnable(GL_CULL_FACE);
3474 
3475     glCullFace(GL_FRONT);
3476 
3477     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3478 
3479     ASSERT_GL_NO_ERROR();
3480 
3481     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3482 
3483     // Disable cull face and redraw, then make sure we have the quad drawn.
3484     glDisable(GL_CULL_FACE);
3485 
3486     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3487 
3488     ASSERT_GL_NO_ERROR();
3489 
3490     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3491 }
3492 
TEST_P(SimpleStateChangeTest,ScissorTest)3493 TEST_P(SimpleStateChangeTest, ScissorTest)
3494 {
3495     // This test validates this order of state changes:
3496     // 1- Set scissor but don't enable it, validate its not used.
3497     // 2- Enable it and validate its working.
3498     // 3- Disable the scissor validate its not used anymore.
3499 
3500     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3501 
3502     glClear(GL_COLOR_BUFFER_BIT);
3503 
3504     // Set the scissor region, but don't enable it yet.
3505     glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
3506               getWindowHeight() / 2);
3507 
3508     // Fill the whole screen with a quad.
3509     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3510 
3511     ASSERT_GL_NO_ERROR();
3512 
3513     // Test outside, scissor isnt enabled so its red.
3514     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3515 
3516     // Test inside, red of the fragment shader.
3517     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3518 
3519     // Clear everything and start over with the test enabled.
3520     glClear(GL_COLOR_BUFFER_BIT);
3521     glEnable(GL_SCISSOR_TEST);
3522 
3523     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3524 
3525     ASSERT_GL_NO_ERROR();
3526 
3527     // Test outside the scissor test, pitch black.
3528     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
3529 
3530     // Test inside, red of the fragment shader.
3531     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3532 
3533     // Now disable the scissor test, do it again, and verify the region isn't used
3534     // for the scissor test.
3535     glDisable(GL_SCISSOR_TEST);
3536 
3537     // Clear everything and start over with the test enabled.
3538     glClear(GL_COLOR_BUFFER_BIT);
3539 
3540     drawQuad(program.get(), essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
3541 
3542     ASSERT_GL_NO_ERROR();
3543 
3544     // Test outside, scissor isnt enabled so its red.
3545     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3546 
3547     // Test inside, red of the fragment shader.
3548     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
3549 }
3550 
3551 // This test validates we are able to change the valid of a uniform dynamically.
TEST_P(SimpleStateChangeTest,UniformUpdateTest)3552 TEST_P(SimpleStateChangeTest, UniformUpdateTest)
3553 {
3554     constexpr char kPositionUniformVertexShader[] = R"(
3555 precision mediump float;
3556 attribute vec2 position;
3557 uniform vec2 uniPosModifier;
3558 void main()
3559 {
3560     gl_Position = vec4(position + uniPosModifier, 0, 1);
3561 })";
3562 
3563     ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, essl1_shaders::fs::UniformColor());
3564     glUseProgram(program);
3565 
3566     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
3567     glClear(GL_COLOR_BUFFER_BIT);
3568 
3569     GLint posUniformLocation = glGetUniformLocation(program, "uniPosModifier");
3570     ASSERT_NE(posUniformLocation, -1);
3571     GLint colorUniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3572     ASSERT_NE(colorUniformLocation, -1);
3573 
3574     // draw a red quad to the left side.
3575     glUniform2f(posUniformLocation, -0.5, 0.0);
3576     glUniform4f(colorUniformLocation, 1.0, 0.0, 0.0, 1.0);
3577     drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3578 
3579     // draw a green quad to the right side.
3580     glUniform2f(posUniformLocation, 0.5, 0.0);
3581     glUniform4f(colorUniformLocation, 0.0, 1.0, 0.0, 1.0);
3582     drawQuad(program.get(), "position", 0.0f, 0.5f, true);
3583 
3584     ASSERT_GL_NO_ERROR();
3585 
3586     // Test the center of the left quad. Should be red.
3587     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 2, GLColor::red);
3588 
3589     // Test the center of the right quad. Should be green.
3590     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4 * 3, getWindowHeight() / 2, GLColor::green);
3591 }
3592 
3593 // Tests that changing the storage of a Renderbuffer currently in use by GL works as expected.
TEST_P(SimpleStateChangeTest,RedefineRenderbufferInUse)3594 TEST_P(SimpleStateChangeTest, RedefineRenderbufferInUse)
3595 {
3596     GLRenderbuffer renderbuffer;
3597     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
3598     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
3599 
3600     GLFramebuffer framebuffer;
3601     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3602     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
3603 
3604     ASSERT_GL_NO_ERROR();
3605     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3606 
3607     ANGLE_GL_PROGRAM(program, kSimpleVertexShader, kSimpleFragmentShader);
3608     GLint colorLoc = glGetAttribLocation(program, "color");
3609     ASSERT_NE(-1, colorLoc);
3610 
3611     // Set up and draw red to the left half the screen.
3612     std::vector<GLColor> redData(6, GLColor::red);
3613     GLBuffer vertexBufferRed;
3614     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferRed);
3615     glBufferData(GL_ARRAY_BUFFER, redData.size() * sizeof(GLColor), redData.data(), GL_STATIC_DRAW);
3616     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3617     glEnableVertexAttribArray(colorLoc);
3618 
3619     glViewport(0, 0, 16, 16);
3620     drawQuad(program, "position", 0.5f, 1.0f, true);
3621 
3622     // Immediately redefine the Renderbuffer.
3623     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 64, 64);
3624 
3625     // Set up and draw green to the right half of the screen.
3626     std::vector<GLColor> greenData(6, GLColor::green);
3627     GLBuffer vertexBufferGreen;
3628     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferGreen);
3629     glBufferData(GL_ARRAY_BUFFER, greenData.size() * sizeof(GLColor), greenData.data(),
3630                  GL_STATIC_DRAW);
3631     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
3632     glEnableVertexAttribArray(colorLoc);
3633 
3634     glViewport(0, 0, 64, 64);
3635     drawQuad(program, "position", 0.5f, 1.0f, true);
3636 
3637     ASSERT_GL_NO_ERROR();
3638     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3639 }
3640 
3641 // Validate that we can draw -> change frame buffer size -> draw and we'll be rendering
3642 // at the full size of the new framebuffer.
TEST_P(SimpleStateChangeTest,ChangeFramebufferSizeBetweenTwoDraws)3643 TEST_P(SimpleStateChangeTest, ChangeFramebufferSizeBetweenTwoDraws)
3644 {
3645     constexpr size_t kSmallTextureSize = 2;
3646     constexpr size_t kBigTextureSize   = 4;
3647 
3648     // Create 2 textures, one of 2x2 and the other 4x4
3649     GLTexture texture1;
3650     glBindTexture(GL_TEXTURE_2D, texture1);
3651     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallTextureSize, kSmallTextureSize, 0, GL_RGBA,
3652                  GL_UNSIGNED_BYTE, nullptr);
3653     ASSERT_GL_NO_ERROR();
3654 
3655     GLTexture texture2;
3656     glBindTexture(GL_TEXTURE_2D, texture2);
3657     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kBigTextureSize, kBigTextureSize, 0, GL_RGBA,
3658                  GL_UNSIGNED_BYTE, nullptr);
3659     ASSERT_GL_NO_ERROR();
3660 
3661     // A framebuffer for each texture to draw on.
3662     GLFramebuffer framebuffer1;
3663     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3664     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0);
3665     ASSERT_GL_NO_ERROR();
3666     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3667 
3668     GLFramebuffer framebuffer2;
3669     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3670     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture2, 0);
3671     ASSERT_GL_NO_ERROR();
3672     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
3673 
3674     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3675     glUseProgram(program);
3676     GLint uniformLocation = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3677     ASSERT_NE(uniformLocation, -1);
3678 
3679     // Bind to the first framebuffer for drawing.
3680     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
3681 
3682     // Set a scissor, that will trigger setting the internal scissor state in Vulkan to
3683     // (0,0,framebuffer.width, framebuffer.height) size since the scissor isn't enabled.
3684     glScissor(0, 0, 16, 16);
3685     ASSERT_GL_NO_ERROR();
3686 
3687     // Set color to red.
3688     glUniform4f(uniformLocation, 1.0f, 0.0f, 0.0f, 1.0f);
3689     glViewport(0, 0, kSmallTextureSize, kSmallTextureSize);
3690 
3691     // Draw a full sized red quad
3692     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3693     ASSERT_GL_NO_ERROR();
3694 
3695     // Bind to the second (bigger) framebuffer
3696     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
3697     glViewport(0, 0, kBigTextureSize, kBigTextureSize);
3698 
3699     ASSERT_GL_NO_ERROR();
3700 
3701     // Set color to green.
3702     glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 1.0f);
3703 
3704     // Draw again and we should fill everything with green and expect everything to be green.
3705     drawQuad(program, essl1_shaders::PositionAttrib(), 1.0f, 1.0f, true);
3706     ASSERT_GL_NO_ERROR();
3707 
3708     EXPECT_PIXEL_RECT_EQ(0, 0, kBigTextureSize, kBigTextureSize, GLColor::green);
3709 }
3710 
3711 // Tries to relink a program in use and use it again to draw something else.
TEST_P(SimpleStateChangeTest,RelinkProgram)3712 TEST_P(SimpleStateChangeTest, RelinkProgram)
3713 {
3714     // http://anglebug.com/4121
3715     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGLES());
3716     const GLuint program = glCreateProgram();
3717 
3718     GLuint vs     = CompileShader(GL_VERTEX_SHADER, essl1_shaders::vs::Simple());
3719     GLuint blueFs = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Blue());
3720     GLuint redFs  = CompileShader(GL_FRAGMENT_SHADER, essl1_shaders::fs::Red());
3721 
3722     glAttachShader(program, vs);
3723     glAttachShader(program, blueFs);
3724 
3725     glLinkProgram(program);
3726     CheckLinkStatusAndReturnProgram(program, true);
3727 
3728     glClear(GL_COLOR_BUFFER_BIT);
3729     std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f},
3730                                      {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {-1.0, 1.0f, 0.0f}};
3731     GLBuffer vertexBuffer;
3732     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3733     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3734                  GL_STATIC_DRAW);
3735     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3736     ASSERT_NE(-1, positionLocation);
3737     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3738     glEnableVertexAttribArray(positionLocation);
3739 
3740     // Draw a blue triangle to the right
3741     glUseProgram(program);
3742     glDrawArrays(GL_TRIANGLES, 0, 3);
3743 
3744     // Relink to draw red to the left
3745     glDetachShader(program, blueFs);
3746     glAttachShader(program, redFs);
3747 
3748     glLinkProgram(program);
3749     CheckLinkStatusAndReturnProgram(program, true);
3750 
3751     glDrawArrays(GL_TRIANGLES, 3, 3);
3752 
3753     ASSERT_GL_NO_ERROR();
3754 
3755     glDisableVertexAttribArray(positionLocation);
3756 
3757     // Verify we drew red and green in the right places.
3758     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::blue);
3759     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red);
3760 
3761     glDeleteShader(vs);
3762     glDeleteShader(blueFs);
3763     glDeleteShader(redFs);
3764     glDeleteProgram(program);
3765 }
3766 
3767 // Creates a program that uses uniforms and then immediately release it and then use it. Should be
3768 // valid.
TEST_P(SimpleStateChangeTest,ReleaseShaderInUseThatReadsFromUniforms)3769 TEST_P(SimpleStateChangeTest, ReleaseShaderInUseThatReadsFromUniforms)
3770 {
3771     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
3772     glUseProgram(program);
3773 
3774     const GLint uniformLoc = glGetUniformLocation(program, essl1_shaders::ColorUniform());
3775     EXPECT_NE(-1, uniformLoc);
3776 
3777     // Set color to red.
3778     glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3779 
3780     glClear(GL_COLOR_BUFFER_BIT);
3781     std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
3782     GLBuffer vertexBuffer;
3783     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
3784     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
3785                  GL_STATIC_DRAW);
3786     const GLint positionLocation = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
3787     ASSERT_NE(-1, positionLocation);
3788     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
3789     glEnableVertexAttribArray(positionLocation);
3790 
3791     // Release program while its in use.
3792     glDeleteProgram(program);
3793 
3794     // Draw a red triangle
3795     glDrawArrays(GL_TRIANGLES, 0, 3);
3796 
3797     // Set color to green
3798     glUniform4f(uniformLoc, 1.0f, 0.0f, 0.0f, 1.0f);
3799 
3800     // Draw a green triangle
3801     glDrawArrays(GL_TRIANGLES, 0, 3);
3802 
3803     ASSERT_GL_NO_ERROR();
3804 
3805     glDisableVertexAttribArray(positionLocation);
3806 
3807     glUseProgram(0);
3808 
3809     // Verify we drew red in the end since thats the last draw.
3810     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
3811 }
3812 
3813 // Tests that sampler sync isn't masked by program textures.
TEST_P(SimpleStateChangeTestES3,SamplerSyncNotTiedToProgram)3814 TEST_P(SimpleStateChangeTestES3, SamplerSyncNotTiedToProgram)
3815 {
3816     // Create a sampler with NEAREST filtering.
3817     GLSampler sampler;
3818     glBindSampler(0, sampler);
3819     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3820     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3821     glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3822     glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3823     glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3824     ASSERT_GL_NO_ERROR();
3825 
3826     // Draw with a program that uses no textures.
3827     ANGLE_GL_PROGRAM(program1, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
3828     drawQuad(program1, essl1_shaders::PositionAttrib(), 0.5f);
3829     ASSERT_GL_NO_ERROR();
3830     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3831 
3832     // Create a simple texture with four colors and linear filtering.
3833     constexpr GLsizei kSize       = 2;
3834     std::array<GLColor, 4> pixels = {
3835         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
3836     GLTexture redTex;
3837     glBindTexture(GL_TEXTURE_2D, redTex);
3838     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3839                  pixels.data());
3840     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3841     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3842     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3843     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3844     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3845 
3846     // Create a program that uses the texture.
3847     constexpr char kVS[] = R"(attribute vec4 position;
3848 varying vec2 texCoord;
3849 void main()
3850 {
3851     gl_Position = position;
3852     texCoord = position.xy * 0.5 + vec2(0.5);
3853 })";
3854 
3855     constexpr char kFS[] = R"(precision mediump float;
3856 varying vec2 texCoord;
3857 uniform sampler2D tex;
3858 void main()
3859 {
3860     gl_FragColor = texture2D(tex, texCoord);
3861 })";
3862 
3863     // Draw. The sampler should override the clamp wrap mode with nearest.
3864     ANGLE_GL_PROGRAM(program2, kVS, kFS);
3865     ASSERT_EQ(0, glGetUniformLocation(program2, "tex"));
3866     drawQuad(program2, "position", 0.5f);
3867     ASSERT_GL_NO_ERROR();
3868 
3869     constexpr int kHalfSize = kWindowSize / 2;
3870 
3871     EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
3872     EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
3873     EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
3874     EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
3875 }
3876 
3877 // Tests different samplers can be used with same texture obj on different tex units.
TEST_P(SimpleStateChangeTestES3,MultipleSamplersWithSingleTextureObject)3878 TEST_P(SimpleStateChangeTestES3, MultipleSamplersWithSingleTextureObject)
3879 {
3880     // Test overview - Create two separate sampler objects, initially with the same
3881     // sampling args (NEAREST). Bind the same texture object to separate texture units.
3882     // FS samples from two samplers and blends result.
3883     // Bind separate sampler objects to the same texture units as the texture object.
3884     // Render & verify initial results
3885     // Next modify sampler0 to have LINEAR filtering instead of NEAREST
3886     // Render and save results
3887     // Now restore sampler0 to NEAREST filtering and make sampler1 LINEAR
3888     // Render and verify results are the same as previous
3889 
3890     // Create 2 samplers with NEAREST filtering.
3891     constexpr GLsizei kNumSamplers = 2;
3892     // We create/bind an extra sampler w/o bound tex object for testing purposes
3893     GLSampler samplers[kNumSamplers + 1];
3894     // Set samplers to initially have same state w/ NEAREST filter mode
3895     for (uint32_t i = 0; i < kNumSamplers + 1; ++i)
3896     {
3897         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3898         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3899         glSamplerParameteri(samplers[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3900         glSamplerParameteri(samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3901         glSamplerParameteri(samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3902         glSamplerParameterf(samplers[i], GL_TEXTURE_MAX_LOD, 1000);
3903         glSamplerParameterf(samplers[i], GL_TEXTURE_MIN_LOD, -1000);
3904         glBindSampler(i, samplers[i]);
3905         ASSERT_GL_NO_ERROR();
3906     }
3907 
3908     // Create a simple texture with four colors
3909     constexpr GLsizei kSize       = 2;
3910     std::array<GLColor, 4> pixels = {
3911         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
3912     GLTexture rgbyTex;
3913     // Bind same texture object to tex units 0 & 1
3914     glActiveTexture(GL_TEXTURE0);
3915     glBindTexture(GL_TEXTURE_2D, rgbyTex);
3916     glActiveTexture(GL_TEXTURE1);
3917     glBindTexture(GL_TEXTURE_2D, rgbyTex);
3918     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
3919                  pixels.data());
3920 
3921     // Create a program that uses the texture with 2 separate samplers.
3922     constexpr char kFS[] = R"(precision mediump float;
3923 varying vec2 v_texCoord;
3924 uniform sampler2D samp1;
3925 uniform sampler2D samp2;
3926 void main()
3927 {
3928     gl_FragColor = mix(texture2D(samp1, v_texCoord), texture2D(samp2, v_texCoord), 0.5);
3929 })";
3930 
3931     // Create program and bind samplers to tex units 0 & 1
3932     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
3933     GLint s1loc = glGetUniformLocation(program, "samp1");
3934     GLint s2loc = glGetUniformLocation(program, "samp2");
3935     glUseProgram(program);
3936     glUniform1i(s1loc, 0);
3937     glUniform1i(s2loc, 1);
3938     // Draw. This first draw is a confidence check and not really necessary for the test
3939     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3940     ASSERT_GL_NO_ERROR();
3941 
3942     constexpr int kHalfSize = kWindowSize / 2;
3943 
3944     // When rendering w/ NEAREST, colors are all maxed out so should still be solid
3945     EXPECT_PIXEL_RECT_EQ(0, 0, kHalfSize, kHalfSize, GLColor::red);
3946     EXPECT_PIXEL_RECT_EQ(kHalfSize, 0, kHalfSize, kHalfSize, GLColor::green);
3947     EXPECT_PIXEL_RECT_EQ(0, kHalfSize, kHalfSize, kHalfSize, GLColor::blue);
3948     EXPECT_PIXEL_RECT_EQ(kHalfSize, kHalfSize, kHalfSize, kHalfSize, GLColor::yellow);
3949 
3950     // Make first sampler use linear filtering
3951     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3952     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3953 
3954     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3955     ASSERT_GL_NO_ERROR();
3956     // Capture rendered pixel color with s0 linear
3957     std::vector<GLColor> s0LinearColors(kWindowSize * kWindowSize);
3958     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s0LinearColors.data());
3959 
3960     // Now restore first sampler & update second sampler
3961     glSamplerParameteri(samplers[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3962     glSamplerParameteri(samplers[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3963     glSamplerParameteri(samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3964     glSamplerParameteri(samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3965 
3966     drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.5f);
3967     ASSERT_GL_NO_ERROR();
3968     // Capture rendered pixel color w/ s1 linear
3969     std::vector<GLColor> s1LinearColors(kWindowSize * kWindowSize);
3970     glReadPixels(0, 0, kWindowSize, kWindowSize, GL_RGBA, GL_UNSIGNED_BYTE, s1LinearColors.data());
3971     // Results should be the same regardless of if s0 or s1 is linear
3972     EXPECT_EQ(s0LinearColors, s1LinearColors);
3973 }
3974 
3975 // Tests that rendering works as expected with multiple VAOs.
TEST_P(SimpleStateChangeTestES31,MultipleVertexArrayObjectRendering)3976 TEST_P(SimpleStateChangeTestES31, MultipleVertexArrayObjectRendering)
3977 {
3978     constexpr char kVertexShader[] = R"(attribute vec4 a_position;
3979 attribute vec4 a_color;
3980 varying vec4 v_color;
3981 void main()
3982 {
3983     gl_Position = a_position;
3984     v_color = a_color;
3985 })";
3986 
3987     constexpr char kFragmentShader[] = R"(precision mediump float;
3988 varying vec4 v_color;
3989 void main()
3990 {
3991     gl_FragColor = v_color;
3992 })";
3993 
3994     ANGLE_GL_PROGRAM(mProgram, kVertexShader, kFragmentShader);
3995     GLint positionLoc = glGetAttribLocation(mProgram, "a_position");
3996     ASSERT_NE(-1, positionLoc);
3997     GLint colorLoc = glGetAttribLocation(mProgram, "a_color");
3998     ASSERT_NE(-1, colorLoc);
3999 
4000     GLVertexArray VAOS[2];
4001     GLBuffer positionBuffer;
4002     GLBuffer colorBuffer;
4003     const auto quadVertices = GetQuadVertices();
4004 
4005     glBindVertexArray(VAOS[0]);
4006     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4007     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4008                  GL_STATIC_DRAW);
4009     glEnableVertexAttribArray(positionLoc);
4010     glVertexAttribPointer(positionLoc, 3, GL_BYTE, GL_FALSE, 0, 0);
4011 
4012     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4013     std::vector<GLColor32F> blueColor(6, kFloatBlue);
4014     glBufferData(GL_ARRAY_BUFFER, blueColor.size() * sizeof(GLColor32F), blueColor.data(),
4015                  GL_STATIC_DRAW);
4016     glEnableVertexAttribArray(colorLoc);
4017     glVertexAttribPointer(colorLoc, 4, GL_BYTE, GL_FALSE, 0, 0);
4018 
4019     glBindVertexArray(0);
4020     glBindBuffer(GL_ARRAY_BUFFER, 0);
4021 
4022     glBindVertexArray(VAOS[1]);
4023     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4024     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
4025                  GL_STATIC_DRAW);
4026     glEnableVertexAttribArray(positionLoc);
4027     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
4028 
4029     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4030     std::vector<GLColor32F> greenColor(6, kFloatGreen);
4031     glBufferData(GL_ARRAY_BUFFER, greenColor.size() * sizeof(GLColor32F), greenColor.data(),
4032                  GL_STATIC_DRAW);
4033     glEnableVertexAttribArray(colorLoc);
4034     glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, 0);
4035 
4036     glBindVertexArray(0);
4037     glBindBuffer(GL_ARRAY_BUFFER, 0);
4038 
4039     glUseProgram(mProgram);
4040     ASSERT_GL_NO_ERROR();
4041 
4042     glBindVertexArray(VAOS[1]);
4043     glClear(GL_COLOR_BUFFER_BIT);
4044     glDrawArrays(GL_TRIANGLES, 0, 6);
4045 
4046     // This drawing should not affect the next drawing.
4047     glBindVertexArray(VAOS[0]);
4048     glClear(GL_COLOR_BUFFER_BIT);
4049     glDrawArrays(GL_TRIANGLES, 0, 6);
4050 
4051     glBindVertexArray(VAOS[1]);
4052     glClear(GL_COLOR_BUFFER_BIT);
4053     glDrawArrays(GL_TRIANGLES, 0, 6);
4054 
4055     EXPECT_GL_NO_ERROR();
4056     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::green);
4057     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
4058     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4059     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::green);
4060 
4061     ASSERT_GL_NO_ERROR();
4062 }
4063 
4064 // Tests that consecutive identical draw calls that write to an image in the fragment shader work
4065 // correctly.  This requires a memory barrier in between the draw calls which should not be
4066 // reordered w.r.t the calls.
TEST_P(SimpleStateChangeTestES31,DrawWithImageTextureThenDrawAgain)4067 TEST_P(SimpleStateChangeTestES31, DrawWithImageTextureThenDrawAgain)
4068 {
4069     // http://anglebug.com/5593
4070     ANGLE_SKIP_TEST_IF(IsD3D11());
4071 
4072     GLint maxFragmentImageUniforms;
4073     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4074 
4075     ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4076 
4077     // The test uses a GL_R32F framebuffer.
4078     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
4079 
4080     constexpr GLsizei kSize = 1;
4081 
4082     GLTexture color;
4083     glBindTexture(GL_TEXTURE_2D, color);
4084     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4085     EXPECT_GL_NO_ERROR();
4086 
4087     GLFramebuffer fbo;
4088     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4089     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4090     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4091     EXPECT_GL_NO_ERROR();
4092 
4093     const float kInitialValue = 0.125f;
4094 
4095     GLTexture texture;
4096     glBindTexture(GL_TEXTURE_2D, texture);
4097     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4098     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &kInitialValue);
4099     EXPECT_GL_NO_ERROR();
4100 
4101     GLFramebuffer readbackFbo;
4102     glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4103     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4104     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
4105     EXPECT_GL_NO_ERROR();
4106 
4107     // Create a program that outputs to the image in the fragment shader.
4108     constexpr char kFS[] = R"(#version 310 es
4109 precision mediump float;
4110 layout(r32f, binding = 0) uniform highp image2D dst;
4111 out vec4 colorOut;
4112 void main()
4113 {
4114     vec4 result = imageLoad(dst, ivec2(gl_FragCoord.xy));
4115     colorOut = result;
4116 
4117     result.x += 0.193;
4118     imageStore(dst, ivec2(gl_FragCoord.xy), result);
4119 })";
4120 
4121     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
4122     glUseProgram(program);
4123 
4124     GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
4125     ASSERT_NE(-1, positionLoc);
4126 
4127     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4128     EXPECT_GL_NO_ERROR();
4129 
4130     // Setup the draw so that there's no state change between the draw calls.
4131     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4132     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4133 
4134     GLBuffer posBuffer;
4135     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4136     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4137     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4138     glEnableVertexAttribArray(positionLoc);
4139     EXPECT_GL_NO_ERROR();
4140 
4141     glDrawArrays(GL_TRIANGLES, 0, 6);
4142     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4143     glDrawArrays(GL_TRIANGLES, 0, 6);
4144     EXPECT_GL_NO_ERROR();
4145 
4146     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4147     EXPECT_GL_NO_ERROR();
4148 
4149     // Verify the output of the two draw calls through the image is correct
4150     EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(kInitialValue + 0.193f * 2, 0.0f, 0.0f, 1.0f),
4151                                0.001f);
4152 
4153     // Verify the output of rendering as well
4154     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4155     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(81, 0, 0, 255), 1);
4156 }
4157 
4158 // Tests that sampling from a texture in one draw call followed by writing to its image in another
4159 // draw call works correctly.  This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithTextureThenDrawWithImage)4160 TEST_P(SimpleStateChangeTestES31, DrawWithTextureThenDrawWithImage)
4161 {
4162     // http://anglebug.com/5593
4163     ANGLE_SKIP_TEST_IF(IsD3D11());
4164     // http://anglebug.com/5686
4165     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsDesktopOpenGL());
4166 
4167     GLint maxFragmentImageUniforms;
4168     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
4169 
4170     ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms < 1);
4171 
4172     constexpr GLsizei kSize = 1;
4173 
4174     GLTexture color;
4175     glBindTexture(GL_TEXTURE_2D, color);
4176     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4177     EXPECT_GL_NO_ERROR();
4178 
4179     GLFramebuffer fbo;
4180     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4181     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4182     EXPECT_GL_NO_ERROR();
4183 
4184     const GLColor kInitialColor = GLColor::red;
4185 
4186     GLTexture texture;
4187     glBindTexture(GL_TEXTURE_2D, texture);
4188     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4189     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4190                     &kInitialColor);
4191     EXPECT_GL_NO_ERROR();
4192 
4193     GLFramebuffer readbackFbo;
4194     glBindFramebuffer(GL_READ_FRAMEBUFFER, readbackFbo);
4195     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
4196     EXPECT_GL_NO_ERROR();
4197 
4198     // Create a program that samples from the texture in the fragment shader.
4199     constexpr char kFSSample[] = R"(#version 310 es
4200 precision mediump float;
4201 uniform sampler2D tex;
4202 out vec4 colorOut;
4203 void main()
4204 {
4205     colorOut = texture(tex, vec2(0));
4206 })";
4207     ANGLE_GL_PROGRAM(sampleProgram, essl31_shaders::vs::Simple(), kFSSample);
4208 
4209     // Create a program that outputs to the image in the fragment shader.
4210     constexpr char kFSWrite[] = R"(#version 310 es
4211 precision mediump float;
4212 layout(rgba8, binding = 0) uniform highp writeonly image2D dst;
4213 out vec4 colorOut;
4214 void main()
4215 {
4216     colorOut = vec4(0, 0, 1.0, 0);
4217     imageStore(dst, ivec2(gl_FragCoord.xy), vec4(0.0, 1.0, 0.0, 1.0));
4218 })";
4219 
4220     ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4221 
4222     glUseProgram(sampleProgram);
4223     GLint positionLocSample = glGetAttribLocation(sampleProgram, essl31_shaders::PositionAttrib());
4224     ASSERT_NE(-1, positionLocSample);
4225 
4226     glUseProgram(writeProgram);
4227     GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4228     ASSERT_NE(-1, positionLocWrite);
4229 
4230     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
4231 
4232     // Setup the draw so that there's no state change between the draw calls.
4233     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4234     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4235 
4236     GLBuffer posBuffer;
4237     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4238     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4239     glVertexAttribPointer(positionLocSample, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4240     glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4241     glEnableVertexAttribArray(positionLocSample);
4242     glEnableVertexAttribArray(positionLocWrite);
4243 
4244     glUseProgram(sampleProgram);
4245     glDrawArrays(GL_TRIANGLES, 0, 6);
4246 
4247     glEnable(GL_BLEND);
4248     glBlendFunc(GL_ONE, GL_ONE);
4249     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4250 
4251     glUseProgram(writeProgram);
4252     glDrawArrays(GL_TRIANGLES, 0, 6);
4253 
4254     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4255     EXPECT_GL_NO_ERROR();
4256 
4257     // Verify the output of the two draw calls through the image is correct
4258     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4259 
4260     // Verify the output of rendering as well
4261     glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
4262     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
4263 }
4264 
4265 // Tests that reading from a ubo in one draw call followed by writing to it as SSBO in another draw
4266 // call works correctly.  This requires a barrier in between the draw calls.
TEST_P(SimpleStateChangeTestES31,DrawWithUBOThenDrawWithSSBO)4267 TEST_P(SimpleStateChangeTestES31, DrawWithUBOThenDrawWithSSBO)
4268 {
4269     // http://anglebug.com/5593
4270     ANGLE_SKIP_TEST_IF(IsD3D11());
4271 
4272     GLint maxFragmentShaderStorageBlocks;
4273     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
4274 
4275     ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
4276 
4277     constexpr GLsizei kSize = 1;
4278 
4279     GLTexture color;
4280     glBindTexture(GL_TEXTURE_2D, color);
4281     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4282     EXPECT_GL_NO_ERROR();
4283 
4284     GLFramebuffer fbo;
4285     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4286     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4287     EXPECT_GL_NO_ERROR();
4288 
4289     constexpr std::array<float, 4> kBufferInitValue = {0.125f, 0.25f, 0.5f, 1.0f};
4290     GLBuffer buffer;
4291     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
4292     glBufferData(GL_UNIFORM_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4293                  GL_STATIC_DRAW);
4294     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4295 
4296     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4297     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4298 
4299     // Create a program that reads from the ubo in the fragment shader.
4300     constexpr char kFSRead[] = R"(#version 310 es
4301 precision mediump float;
4302 uniform block { vec4 vec; } b;
4303 out vec4 colorOut;
4304 void main()
4305 {
4306     colorOut = b.vec;
4307 })";
4308     ANGLE_GL_PROGRAM(readProgram, essl31_shaders::vs::Simple(), kFSRead);
4309 
4310     // Create a program that outputs to the image in the fragment shader.
4311     constexpr char kFSWrite[] = R"(#version 310 es
4312 precision mediump float;
4313 layout(binding = 0, std430) buffer Output {
4314     vec4 vec;
4315 } b;
4316 out vec4 colorOut;
4317 void main()
4318 {
4319     b.vec = vec4(0.7, 0.6, 0.4, 0.3);
4320     colorOut = vec4(0.125, 0.125, 0.125, 0);
4321 })";
4322 
4323     ANGLE_GL_PROGRAM(writeProgram, essl31_shaders::vs::Simple(), kFSWrite);
4324 
4325     glUseProgram(readProgram);
4326     GLint positionLocRead = glGetAttribLocation(readProgram, essl31_shaders::PositionAttrib());
4327     ASSERT_NE(-1, positionLocRead);
4328 
4329     glUseProgram(writeProgram);
4330     GLint positionLocWrite = glGetAttribLocation(writeProgram, essl31_shaders::PositionAttrib());
4331     ASSERT_NE(-1, positionLocWrite);
4332 
4333     // Setup the draw so that there's no state change between the draw calls.
4334     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4335     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4336 
4337     GLBuffer posBuffer;
4338     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4339     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4340     glVertexAttribPointer(positionLocRead, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4341     glVertexAttribPointer(positionLocWrite, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4342     glEnableVertexAttribArray(positionLocRead);
4343     glEnableVertexAttribArray(positionLocWrite);
4344 
4345     glUseProgram(readProgram);
4346     glDrawArrays(GL_TRIANGLES, 0, 6);
4347 
4348     glEnable(GL_BLEND);
4349     glBlendFunc(GL_ONE, GL_ONE);
4350     glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
4351 
4352     glUseProgram(writeProgram);
4353     glDrawArrays(GL_TRIANGLES, 0, 6);
4354 
4355     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4356     EXPECT_GL_NO_ERROR();
4357 
4358     // Verify the output of rendering
4359     EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(63, 95, 159, 255), 1);
4360 
4361     // Verify the output from the second draw call
4362     const float *ptr = reinterpret_cast<const float *>(
4363         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4364 
4365     EXPECT_NEAR(ptr[0], 0.7f, 0.001);
4366     EXPECT_NEAR(ptr[1], 0.6f, 0.001);
4367     EXPECT_NEAR(ptr[2], 0.4f, 0.001);
4368     EXPECT_NEAR(ptr[3], 0.3f, 0.001);
4369 
4370     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4371 }
4372 
4373 // Tests that rendering to a texture in one draw call followed by sampling from it in a dispatch
4374 // call works correctly.  This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,DrawThenSampleWithCompute)4375 TEST_P(SimpleStateChangeTestES31, DrawThenSampleWithCompute)
4376 {
4377     // TODO(anglebug.com/5649): Test is failing since it was introduced on Linux AMD GLES
4378     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsAMD() && IsLinux());
4379 
4380     constexpr GLsizei kSize = 1;
4381     const GLColor kInitColor(111, 222, 33, 44);
4382 
4383     GLTexture color;
4384     glBindTexture(GL_TEXTURE_2D, color);
4385     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4386     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4387     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4388     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &kInitColor);
4389     EXPECT_GL_NO_ERROR();
4390 
4391     GLFramebuffer fbo;
4392     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4393     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4394     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4395     EXPECT_GL_NO_ERROR();
4396 
4397     constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4398     GLBuffer buffer;
4399     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4400     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4401                  GL_STATIC_DRAW);
4402     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4403     EXPECT_GL_NO_ERROR();
4404 
4405     ANGLE_GL_PROGRAM(drawProgram, essl31_shaders::vs::Simple(), essl31_shaders::fs::Red());
4406 
4407     constexpr char kCS[] = R"(#version 310 es
4408 layout(local_size_x=1, local_size_y=1) in;
4409 uniform sampler2D tex;
4410 layout(binding = 0, std430) buffer Output {
4411     vec4 vec;
4412 } b;
4413 void main()
4414 {
4415     b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4416 })";
4417 
4418     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4419     glUseProgram(readProgram);
4420 
4421     glActiveTexture(GL_TEXTURE0);
4422     glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4423 
4424     drawQuad(drawProgram, essl31_shaders::PositionAttrib(), 0.5f);
4425     EXPECT_GL_NO_ERROR();
4426 
4427     glUseProgram(readProgram);
4428     glDispatchCompute(1, 1, 1);
4429 
4430     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4431     EXPECT_GL_NO_ERROR();
4432 
4433     // Verify the output of rendering
4434     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4435 
4436     // Verify the output from the compute shader
4437     const float *ptr = reinterpret_cast<const float *>(
4438         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4439 
4440     EXPECT_EQ(ptr[0], 1.0f);
4441     EXPECT_EQ(ptr[1], 0.0f);
4442     EXPECT_EQ(ptr[2], 0.0f);
4443     EXPECT_EQ(ptr[3], 1.0f);
4444 
4445     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4446 }
4447 
4448 // Tests that clearing a texture followed by sampling from it in a dispatch call works correctly.
4449 // In the Vulkan backend, the clear is deferred and should be flushed correctly.
TEST_P(SimpleStateChangeTestES31,ClearThenSampleWithCompute)4450 TEST_P(SimpleStateChangeTestES31, ClearThenSampleWithCompute)
4451 {
4452     // http://anglebug.com/5687
4453     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
4454 
4455     constexpr GLsizei kSize = 1;
4456 
4457     GLTexture color;
4458     glBindTexture(GL_TEXTURE_2D, color);
4459     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4460     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4461     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4462     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
4463     EXPECT_GL_NO_ERROR();
4464 
4465     GLFramebuffer fbo;
4466     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4467     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
4468     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4469     EXPECT_GL_NO_ERROR();
4470 
4471     // Make sure the update to the texture is effective.
4472     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4473 
4474     // Clear the texture through the framebuffer
4475     glClearColor(0, 1.0f, 0, 1.0f);
4476     glClear(GL_COLOR_BUFFER_BIT);
4477 
4478     constexpr std::array<float, 4> kBufferInitValue = {0.123f, 0.456f, 0.789f, 0.852f};
4479     GLBuffer buffer;
4480     glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
4481     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
4482                  GL_STATIC_DRAW);
4483     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
4484     EXPECT_GL_NO_ERROR();
4485 
4486     constexpr char kCS[] = R"(#version 310 es
4487 layout(local_size_x=1, local_size_y=1) in;
4488 uniform sampler2D tex;
4489 layout(binding = 0, std430) buffer Output {
4490     vec4 vec;
4491 } b;
4492 void main()
4493 {
4494     b.vec = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
4495 })";
4496 
4497     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4498     glUseProgram(readProgram);
4499 
4500     glActiveTexture(GL_TEXTURE0);
4501     glUniform1i(glGetUniformLocation(readProgram, "tex"), 0);
4502 
4503     glUseProgram(readProgram);
4504     glDispatchCompute(1, 1, 1);
4505 
4506     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4507     EXPECT_GL_NO_ERROR();
4508 
4509     // Verify the clear
4510     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4511 
4512     // Verify the output from the compute shader
4513     const float *ptr = reinterpret_cast<const float *>(
4514         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferInitValue), GL_MAP_READ_BIT));
4515 
4516     EXPECT_EQ(ptr[0], 0.0f);
4517     EXPECT_EQ(ptr[1], 1.0f);
4518     EXPECT_EQ(ptr[2], 0.0f);
4519     EXPECT_EQ(ptr[3], 1.0f);
4520 
4521     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4522 }
4523 
4524 // Tests that writing to a buffer with transform feedback in one draw call followed by reading from
4525 // it in a dispatch call works correctly.  This requires an implicit barrier in between the calls.
TEST_P(SimpleStateChangeTestES31,TransformFeedbackThenReadWithCompute)4526 TEST_P(SimpleStateChangeTestES31, TransformFeedbackThenReadWithCompute)
4527 {
4528     // http://anglebug.com/5687
4529     ANGLE_SKIP_TEST_IF(IsAMD() && IsVulkan());
4530 
4531     constexpr GLsizei kBufferSize = sizeof(float) * 4 * 6;
4532     GLBuffer buffer;
4533     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
4534     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
4535     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
4536 
4537     std::vector<std::string> tfVaryings = {"gl_Position"};
4538     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
4539                                         essl3_shaders::fs::Green(), tfVaryings,
4540                                         GL_INTERLEAVED_ATTRIBS);
4541     glUseProgram(program);
4542 
4543     glBeginTransformFeedback(GL_TRIANGLES);
4544     drawQuad(program, essl3_shaders::PositionAttrib(), 0.0f);
4545     glEndTransformFeedback();
4546 
4547     constexpr char kCS[] = R"(#version 310 es
4548 layout(local_size_x=1, local_size_y=1) in;
4549 layout(binding = 0) uniform Input
4550 {
4551     vec4 data[3];
4552 };
4553 layout(binding = 0, std430) buffer Output {
4554     bool pass;
4555 };
4556 void main()
4557 {
4558     pass = data[0] == vec4(-1, 1, 0, 1) &&
4559            data[1] == vec4(-1, -1, 0, 1) &&
4560            data[2] == vec4(1, -1, 0, 1);
4561 })";
4562 
4563     ANGLE_GL_COMPUTE_PROGRAM(readProgram, kCS);
4564     glUseProgram(readProgram);
4565 
4566     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
4567 
4568     constexpr GLsizei kResultSize = sizeof(uint32_t);
4569     GLBuffer resultBuffer;
4570     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
4571     glBufferData(GL_SHADER_STORAGE_BUFFER, kResultSize, nullptr, GL_STATIC_DRAW);
4572     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
4573 
4574     glDispatchCompute(1, 1, 1);
4575 
4576     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4577     EXPECT_GL_NO_ERROR();
4578 
4579     // Verify the output of rendering
4580     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4581 
4582     // Verify the output from the compute shader
4583     const uint32_t *ptr = reinterpret_cast<const uint32_t *>(
4584         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kResultSize, GL_MAP_READ_BIT));
4585 
4586     EXPECT_EQ(ptr[0], 1u);
4587 
4588     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4589 }
4590 
4591 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31,DeleteImageTextureInUse)4592 TEST_P(SimpleStateChangeTestComputeES31, DeleteImageTextureInUse)
4593 {
4594     std::array<GLColor, 4> colors = {
4595         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4596     GLTexture texRead;
4597     glBindTexture(GL_TEXTURE_2D, texRead);
4598     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4599     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4600     EXPECT_GL_NO_ERROR();
4601 
4602     glUseProgram(mProgram);
4603 
4604     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4605     glDispatchCompute(1, 1, 1);
4606     texRead.reset();
4607 
4608     std::array<GLColor, 4> results;
4609     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4610     EXPECT_GL_NO_ERROR();
4611 
4612     for (int i = 0; i < 4; i++)
4613     {
4614         EXPECT_EQ(colors[i], results[i]);
4615     }
4616 }
4617 
4618 // Tests that bind the same image texture all the time between different dispatch calls.
TEST_P(SimpleStateChangeTestComputeES31,RebindImageTextureDispatchAgain)4619 TEST_P(SimpleStateChangeTestComputeES31, RebindImageTextureDispatchAgain)
4620 {
4621     std::array<GLColor, 4> colors = {{GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4622     GLTexture texRead;
4623     glBindTexture(GL_TEXTURE_2D, texRead);
4624     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4625     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4626 
4627     glUseProgram(mProgram);
4628 
4629     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4630     glDispatchCompute(1, 1, 1);
4631 
4632     // Bind again
4633     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4634     glDispatchCompute(1, 1, 1);
4635     EXPECT_GL_NO_ERROR();
4636 
4637     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4638 }
4639 
4640 // Tests that we can dispatch with an image texture, modify the image texture with a texSubImage,
4641 // and then dispatch again correctly.
TEST_P(SimpleStateChangeTestComputeES31,DispatchWithImageTextureTexSubImageThenDispatchAgain)4642 TEST_P(SimpleStateChangeTestComputeES31, DispatchWithImageTextureTexSubImageThenDispatchAgain)
4643 {
4644     std::array<GLColor, 4> colors    = {{GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
4645     std::array<GLColor, 4> subColors = {
4646         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
4647 
4648     GLTexture texRead;
4649     glBindTexture(GL_TEXTURE_2D, texRead);
4650     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4651     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4652 
4653     glUseProgram(mProgram);
4654 
4655     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4656     glDispatchCompute(1, 1, 1);
4657 
4658     // Update bottom-half of image texture with green.
4659     glBindTexture(GL_TEXTURE_2D, texRead);
4660     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 1, GL_RGBA, GL_UNSIGNED_BYTE, subColors.data());
4661     ASSERT_GL_NO_ERROR();
4662 
4663     // Dispatch again, should still work.
4664     glDispatchCompute(1, 1, 1);
4665     ASSERT_GL_NO_ERROR();
4666 
4667     // Validate first half of the image is red and the bottom is green.
4668     std::array<GLColor, 4> results;
4669     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4670     EXPECT_GL_NO_ERROR();
4671 
4672     EXPECT_EQ(GLColor::green, results[0]);
4673     EXPECT_EQ(GLColor::green, results[1]);
4674     EXPECT_EQ(GLColor::red, results[2]);
4675     EXPECT_EQ(GLColor::red, results[3]);
4676 }
4677 
4678 // Test updating an image texture's contents while in use by GL works as expected.
TEST_P(SimpleStateChangeTestComputeES31,UpdateImageTextureInUse)4679 TEST_P(SimpleStateChangeTestComputeES31, UpdateImageTextureInUse)
4680 {
4681     std::array<GLColor, 4> rgby = {{GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4682 
4683     GLTexture texRead;
4684     glBindTexture(GL_TEXTURE_2D, texRead);
4685     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4686     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, rgby.data());
4687 
4688     glUseProgram(mProgram);
4689 
4690     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4691     glDispatchCompute(1, 1, 1);
4692 
4693     // Update the texture to be YBGR, while the Texture is in-use. Should not affect the dispatch.
4694     std::array<GLColor, 4> ybgr = {{GLColor::yellow, GLColor::blue, GLColor::green, GLColor::red}};
4695     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, ybgr.data());
4696     ASSERT_GL_NO_ERROR();
4697 
4698     // Check the Framebuffer. The dispatch call should have completed with the original RGBY data.
4699     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4700     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
4701     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue);
4702     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
4703 
4704     // Dispatch again. The second dispatch call should use the updated YBGR data.
4705     glDispatchCompute(1, 1, 1);
4706 
4707     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4708     EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
4709     EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
4710     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4711     ASSERT_GL_NO_ERROR();
4712 }
4713 
4714 // Test that we can alternate between image textures between different dispatchs.
TEST_P(SimpleStateChangeTestComputeES31,DispatchImageTextureAThenTextureBThenTextureA)4715 TEST_P(SimpleStateChangeTestComputeES31, DispatchImageTextureAThenTextureBThenTextureA)
4716 {
4717     std::array<GLColor, 4> colorsTexA = {
4718         {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan}};
4719 
4720     std::array<GLColor, 4> colorsTexB = {
4721         {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta}};
4722 
4723     GLTexture texA;
4724     glBindTexture(GL_TEXTURE_2D, texA);
4725     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4726     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexA.data());
4727     GLTexture texB;
4728     glBindTexture(GL_TEXTURE_2D, texB);
4729     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4730     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colorsTexB.data());
4731 
4732     glUseProgram(mProgram);
4733 
4734     glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4735     glDispatchCompute(1, 1, 1);
4736 
4737     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4738     glBindImageTexture(0, texB, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4739     glDispatchCompute(1, 1, 1);
4740 
4741     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4742     glBindImageTexture(0, texA, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4743     glDispatchCompute(1, 1, 1);
4744 
4745     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4746     EXPECT_PIXEL_RECT_EQ(0, 0, 2, 2, GLColor::cyan);
4747     ASSERT_GL_NO_ERROR();
4748 }
4749 
4750 // Copied from SimpleStateChangeTestComputeES31::DeleteImageTextureInUse
4751 // Tests that deleting an in-flight image texture does not immediately delete the resource.
TEST_P(SimpleStateChangeTestComputeES31PPO,DeleteImageTextureInUse)4752 TEST_P(SimpleStateChangeTestComputeES31PPO, DeleteImageTextureInUse)
4753 {
4754     ANGLE_SKIP_TEST_IF(!IsVulkan());
4755 
4756     glGenFramebuffers(1, &mFramebuffer);
4757     glGenTextures(1, &mTexture);
4758 
4759     glBindTexture(GL_TEXTURE_2D, mTexture);
4760     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4761     EXPECT_GL_NO_ERROR();
4762 
4763     constexpr char kCS[] = R"(#version 310 es
4764 layout(local_size_x=2, local_size_y=2) in;
4765 layout (rgba8, binding = 0) readonly uniform highp image2D srcImage;
4766 layout (rgba8, binding = 1) writeonly uniform highp image2D dstImage;
4767 void main()
4768 {
4769 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
4770            imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)));
4771 })";
4772 
4773     bindProgramPipeline(kCS);
4774 
4775     glBindImageTexture(1, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4776 
4777     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
4778     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
4779 
4780     ASSERT_GL_NO_ERROR();
4781 
4782     std::array<GLColor, 4> colors = {
4783         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
4784     GLTexture texRead;
4785     glBindTexture(GL_TEXTURE_2D, texRead);
4786     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4787     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
4788     EXPECT_GL_NO_ERROR();
4789 
4790     glBindImageTexture(0, texRead, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
4791     glDispatchCompute(1, 1, 1);
4792     texRead.reset();
4793 
4794     std::array<GLColor, 4> results;
4795     glReadPixels(0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, results.data());
4796     EXPECT_GL_NO_ERROR();
4797 
4798     for (int i = 0; i < 4; i++)
4799     {
4800         EXPECT_EQ(colors[i], results[i]);
4801     }
4802 }
4803 
4804 static constexpr char kColorVS[] = R"(attribute vec2 position;
4805 attribute vec4 color;
4806 varying vec4 vColor;
4807 void main()
4808 {
4809     gl_Position = vec4(position, 0, 1);
4810     vColor = color;
4811 })";
4812 
4813 static constexpr char kColorFS[] = R"(precision mediump float;
4814 varying vec4 vColor;
4815 void main()
4816 {
4817     gl_FragColor = vColor;
4818 })";
4819 
4820 class ValidationStateChangeTest : public ANGLETest
4821 {
4822   protected:
ValidationStateChangeTest()4823     ValidationStateChangeTest()
4824     {
4825         setWindowWidth(64);
4826         setWindowHeight(64);
4827         setConfigRedBits(8);
4828         setConfigGreenBits(8);
4829         setConfigBlueBits(8);
4830         setConfigAlphaBits(8);
4831     }
4832 };
4833 
4834 class WebGL2ValidationStateChangeTest : public ValidationStateChangeTest
4835 {
4836   protected:
WebGL2ValidationStateChangeTest()4837     WebGL2ValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4838 };
4839 
4840 class ValidationStateChangeTestES31 : public ANGLETest
4841 {};
4842 
4843 class WebGLComputeValidationStateChangeTest : public ANGLETest
4844 {
4845   public:
WebGLComputeValidationStateChangeTest()4846     WebGLComputeValidationStateChangeTest() { setWebGLCompatibilityEnabled(true); }
4847 };
4848 
4849 class RobustBufferAccessWebGL2ValidationStateChangeTest : public WebGL2ValidationStateChangeTest
4850 {
4851   protected:
RobustBufferAccessWebGL2ValidationStateChangeTest()4852     RobustBufferAccessWebGL2ValidationStateChangeTest()
4853     {
4854         // SwS/OSX GL do not support robustness. Mali does not support it.
4855         if (!isSwiftshader() && !IsOSX() && !IsIOS() && !IsARM())
4856         {
4857             setRobustAccess(true);
4858         }
4859     }
4860 };
4861 
4862 // Tests that mapping and unmapping an array buffer in various ways causes rendering to fail.
4863 // This isn't guaranteed to produce an error by GL. But we assume ANGLE always errors.
TEST_P(ValidationStateChangeTest,MapBufferAndDraw)4864 TEST_P(ValidationStateChangeTest, MapBufferAndDraw)
4865 {
4866     // Initialize program and set up state.
4867     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
4868 
4869     glUseProgram(program);
4870     GLint positionLoc = glGetAttribLocation(program, "position");
4871     ASSERT_NE(-1, positionLoc);
4872     GLint colorLoc = glGetAttribLocation(program, "color");
4873     ASSERT_NE(-1, colorLoc);
4874 
4875     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4876     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4877 
4878     GLBuffer posBuffer;
4879     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4880     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
4881 
4882     // Start with position enabled.
4883     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4884     glEnableVertexAttribArray(positionLoc);
4885 
4886     std::vector<GLColor> colorVertices(6, GLColor::blue);
4887     const size_t colorBufferSize = sizeof(GLColor) * 6;
4888 
4889     GLBuffer colorBuffer;
4890     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4891     glBufferData(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(), GL_STATIC_DRAW);
4892 
4893     // Start with color disabled.
4894     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
4895     glDisableVertexAttribArray(colorLoc);
4896 
4897     ASSERT_GL_NO_ERROR();
4898 
4899     // Draw without a mapped buffer. Should succeed.
4900     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
4901     glDrawArrays(GL_TRIANGLES, 0, 6);
4902     ASSERT_GL_NO_ERROR();
4903     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4904 
4905     // Map position buffer and draw. Should fail.
4906     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4907     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize, GL_MAP_READ_BIT);
4908     ASSERT_GL_NO_ERROR();
4909 
4910     glDrawArrays(GL_TRIANGLES, 0, 6);
4911     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map position buffer and draw should fail.";
4912     glUnmapBuffer(GL_ARRAY_BUFFER);
4913 
4914     // Map then enable color buffer. Should fail.
4915     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4916     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize, GL_MAP_READ_BIT);
4917     glEnableVertexAttribArray(colorLoc);
4918     ASSERT_GL_NO_ERROR();
4919 
4920     glDrawArrays(GL_TRIANGLES, 0, 6);
4921     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Map then enable color buffer should fail.";
4922 
4923     // Unmap then draw. Should succeed.
4924     glUnmapBuffer(GL_ARRAY_BUFFER);
4925     ASSERT_GL_NO_ERROR();
4926 
4927     glDrawArrays(GL_TRIANGLES, 0, 6);
4928     ASSERT_GL_NO_ERROR();
4929     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4930 }
4931 
4932 // Tests that mapping an immutable and persistent buffer after calling glVertexAttribPointer()
4933 // allows rendering to succeed.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferAndDraw)4934 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferAndDraw)
4935 {
4936     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
4937 
4938     // Initialize program and set up state.
4939     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
4940 
4941     glUseProgram(program);
4942     GLint positionLoc = glGetAttribLocation(program, "position");
4943     ASSERT_NE(-1, positionLoc);
4944     GLint colorLoc = glGetAttribLocation(program, "color");
4945     ASSERT_NE(-1, colorLoc);
4946 
4947     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
4948     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
4949 
4950     GLBuffer posBuffer;
4951     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4952     glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
4953                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4954 
4955     // Start with position enabled.
4956     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4957     glEnableVertexAttribArray(positionLoc);
4958 
4959     std::vector<GLColor> colorVertices(6, GLColor::blue);
4960     const size_t colorBufferSize = sizeof(GLColor) * 6;
4961 
4962     GLBuffer colorBuffer;
4963     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4964     glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
4965                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4966 
4967     // Start with color disabled.
4968     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
4969     glDisableVertexAttribArray(colorLoc);
4970 
4971     ASSERT_GL_NO_ERROR();
4972 
4973     // Draw without a mapped buffer. Should succeed.
4974     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
4975     glDrawArrays(GL_TRIANGLES, 0, 6);
4976     ASSERT_GL_NO_ERROR();
4977     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4978 
4979     // Map position buffer and draw. Should succeed.
4980     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
4981     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
4982                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4983     ASSERT_GL_NO_ERROR();
4984 
4985     glDrawArrays(GL_TRIANGLES, 0, 6);
4986     ASSERT_GL_NO_ERROR();
4987     glUnmapBuffer(GL_ARRAY_BUFFER);
4988 
4989     // Map then enable color buffer. Should succeed.
4990     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
4991     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
4992                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4993     glEnableVertexAttribArray(colorLoc);
4994     ASSERT_GL_NO_ERROR();
4995 
4996     glDrawArrays(GL_TRIANGLES, 0, 6);
4997     ASSERT_GL_NO_ERROR();
4998 
4999     // Unmap then draw. Should succeed.
5000     glUnmapBuffer(GL_ARRAY_BUFFER);
5001     ASSERT_GL_NO_ERROR();
5002 
5003     glDrawArrays(GL_TRIANGLES, 0, 6);
5004     ASSERT_GL_NO_ERROR();
5005     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5006 }
5007 
5008 // Tests that mapping an immutable and persistent buffer before calling glVertexAttribPointer()
5009 // allows rendering to succeed. This case is special in that the VertexArray is not observing the
5010 // buffer yet, so it's various cached buffer states aren't updated when the buffer is mapped.
TEST_P(ValidationStateChangeTest,MapImmutablePersistentBufferThenVAPAndDraw)5011 TEST_P(ValidationStateChangeTest, MapImmutablePersistentBufferThenVAPAndDraw)
5012 {
5013     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
5014 
5015     // Initialize program and set up state.
5016     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5017 
5018     glUseProgram(program);
5019     GLint positionLoc = glGetAttribLocation(program, "position");
5020     ASSERT_NE(-1, positionLoc);
5021     GLint colorLoc = glGetAttribLocation(program, "color");
5022     ASSERT_NE(-1, colorLoc);
5023 
5024     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5025     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5026 
5027     GLBuffer posBuffer;
5028     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5029     glBufferStorageEXT(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(),
5030                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5031 
5032     glMapBufferRange(GL_ARRAY_BUFFER, 0, posBufferSize,
5033                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5034 
5035     // Start with position enabled.
5036     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5037     glEnableVertexAttribArray(positionLoc);
5038 
5039     std::vector<GLColor> colorVertices(6, GLColor::blue);
5040     const size_t colorBufferSize = sizeof(GLColor) * 6;
5041 
5042     GLBuffer colorBuffer;
5043     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
5044     glBufferStorageEXT(GL_ARRAY_BUFFER, colorBufferSize, colorVertices.data(),
5045                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5046 
5047     glMapBufferRange(GL_ARRAY_BUFFER, 0, colorBufferSize,
5048                      GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT);
5049     ASSERT_GL_NO_ERROR();
5050 
5051     // Start with color disabled.
5052     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
5053     glDisableVertexAttribArray(colorLoc);
5054 
5055     ASSERT_GL_NO_ERROR();
5056 
5057     // Draw without a mapped buffer. Should succeed.
5058     glVertexAttrib4f(colorLoc, 0, 1, 0, 1);
5059     glDrawArrays(GL_TRIANGLES, 0, 6);
5060     ASSERT_GL_NO_ERROR();
5061     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5062 
5063     // Unmap then draw. Should succeed.
5064     glUnmapBuffer(GL_ARRAY_BUFFER);
5065     glEnableVertexAttribArray(colorLoc);
5066     ASSERT_GL_NO_ERROR();
5067     glDrawArrays(GL_TRIANGLES, 0, 6);
5068     ASSERT_GL_NO_ERROR();
5069     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5070 }
5071 
5072 // Tests that changing a vertex binding with glVertexAttribDivisor updates the mapped buffer check.
TEST_P(ValidationStateChangeTestES31,MapBufferAndDrawWithDivisor)5073 TEST_P(ValidationStateChangeTestES31, MapBufferAndDrawWithDivisor)
5074 {
5075     // Seems to trigger a GL error in some edge cases. http://anglebug.com/2755
5076     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
5077 
5078     // Initialize program and set up state.
5079     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5080 
5081     glUseProgram(program);
5082     GLint positionLoc = glGetAttribLocation(program, "position");
5083     ASSERT_NE(-1, positionLoc);
5084     GLint colorLoc = glGetAttribLocation(program, "color");
5085     ASSERT_NE(-1, colorLoc);
5086 
5087     // Create a user vertex array.
5088     GLVertexArray vao;
5089     glBindVertexArray(vao);
5090 
5091     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5092     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5093 
5094     GLBuffer posBuffer;
5095     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5096     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5097 
5098     // Start with position enabled.
5099     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5100     glEnableVertexAttribArray(positionLoc);
5101 
5102     std::vector<GLColor> blueVertices(6, GLColor::blue);
5103     const size_t blueBufferSize = sizeof(GLColor) * 6;
5104 
5105     GLBuffer blueBuffer;
5106     glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5107     glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5108 
5109     // Start with color enabled at an unused binding.
5110     constexpr GLint kUnusedBinding = 3;
5111     ASSERT_NE(colorLoc, kUnusedBinding);
5112     ASSERT_NE(positionLoc, kUnusedBinding);
5113     glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5114     glVertexAttribBinding(colorLoc, kUnusedBinding);
5115     glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5116     glEnableVertexAttribArray(colorLoc);
5117 
5118     // Make binding 'colorLoc' use a mapped buffer.
5119     std::vector<GLColor> greenVertices(6, GLColor::green);
5120     const size_t greenBufferSize = sizeof(GLColor) * 6;
5121     GLBuffer greenBuffer;
5122     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5123     glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5124     glMapBufferRange(GL_ARRAY_BUFFER, 0, greenBufferSize, GL_MAP_READ_BIT);
5125     glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5126 
5127     ASSERT_GL_NO_ERROR();
5128 
5129     // Draw without a mapped buffer. Should succeed.
5130     glDrawArrays(GL_TRIANGLES, 0, 6);
5131     ASSERT_GL_NO_ERROR();
5132     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5133 
5134     // Change divisor with VertexAttribDivisor. Should fail.
5135     glVertexAttribDivisor(colorLoc, 0);
5136     ASSERT_GL_NO_ERROR();
5137     glDrawArrays(GL_TRIANGLES, 0, 6);
5138     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with mapped buffer should fail.";
5139 
5140     // Unmap the buffer. Should succeed.
5141     glUnmapBuffer(GL_ARRAY_BUFFER);
5142     glDrawArrays(GL_TRIANGLES, 0, 6);
5143     ASSERT_GL_NO_ERROR();
5144     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5145 }
5146 
5147 // Tests that changing a vertex binding with glVertexAttribDivisor updates the buffer size check.
TEST_P(WebGLComputeValidationStateChangeTest,DrawPastEndOfBufferWithDivisor)5148 TEST_P(WebGLComputeValidationStateChangeTest, DrawPastEndOfBufferWithDivisor)
5149 {
5150     // Initialize program and set up state.
5151     ANGLE_GL_PROGRAM(program, kColorVS, kColorFS);
5152 
5153     glUseProgram(program);
5154     GLint positionLoc = glGetAttribLocation(program, "position");
5155     ASSERT_NE(-1, positionLoc);
5156     GLint colorLoc = glGetAttribLocation(program, "color");
5157     ASSERT_NE(-1, colorLoc);
5158 
5159     // Create a user vertex array.
5160     GLVertexArray vao;
5161     glBindVertexArray(vao);
5162 
5163     const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
5164     const size_t posBufferSize                 = quadVertices.size() * sizeof(Vector3);
5165 
5166     GLBuffer posBuffer;
5167     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
5168     glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
5169 
5170     // Start with position enabled.
5171     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5172     glEnableVertexAttribArray(positionLoc);
5173 
5174     std::vector<GLColor> blueVertices(6, GLColor::blue);
5175     const size_t blueBufferSize = sizeof(GLColor) * 6;
5176 
5177     GLBuffer blueBuffer;
5178     glBindBuffer(GL_ARRAY_BUFFER, blueBuffer);
5179     glBufferData(GL_ARRAY_BUFFER, blueBufferSize, blueVertices.data(), GL_STATIC_DRAW);
5180 
5181     // Start with color enabled at an unused binding.
5182     constexpr GLint kUnusedBinding = 3;
5183     ASSERT_NE(colorLoc, kUnusedBinding);
5184     ASSERT_NE(positionLoc, kUnusedBinding);
5185     glVertexAttribFormat(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0);
5186     glVertexAttribBinding(colorLoc, kUnusedBinding);
5187     glBindVertexBuffer(kUnusedBinding, blueBuffer, 0, sizeof(GLColor));
5188     glEnableVertexAttribArray(colorLoc);
5189 
5190     // Make binding 'colorLoc' use a small buffer.
5191     std::vector<GLColor> greenVertices(6, GLColor::green);
5192     const size_t greenBufferSize = sizeof(GLColor) * 3;
5193     GLBuffer greenBuffer;
5194     glBindBuffer(GL_ARRAY_BUFFER, greenBuffer);
5195     glBufferData(GL_ARRAY_BUFFER, greenBufferSize, greenVertices.data(), GL_STATIC_DRAW);
5196     glBindVertexBuffer(colorLoc, greenBuffer, 0, sizeof(GLColor));
5197 
5198     ASSERT_GL_NO_ERROR();
5199 
5200     // Draw without a mapped buffer. Should succeed.
5201     glDrawArrays(GL_TRIANGLES, 0, 6);
5202     ASSERT_GL_NO_ERROR();
5203     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
5204 
5205     // Change divisor with VertexAttribDivisor. Should fail.
5206     glVertexAttribDivisor(colorLoc, 0);
5207     ASSERT_GL_NO_ERROR();
5208     glDrawArrays(GL_TRIANGLES, 0, 6);
5209     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "draw with small buffer should fail.";
5210 
5211     // Do a small draw. Should succeed.
5212     glDrawArrays(GL_TRIANGLES, 0, 3);
5213     ASSERT_GL_NO_ERROR();
5214     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5215 }
5216 
5217 // Tests state changes with uniform block validation.
TEST_P(WebGL2ValidationStateChangeTest,UniformBlockNegativeAPI)5218 TEST_P(WebGL2ValidationStateChangeTest, UniformBlockNegativeAPI)
5219 {
5220     constexpr char kVS[] = R"(#version 300 es
5221 in vec2 position;
5222 void main()
5223 {
5224     gl_Position = vec4(position, 0, 1);
5225 })";
5226 
5227     constexpr char kFS[] = R"(#version 300 es
5228 precision mediump float;
5229 uniform uni { vec4 vec; };
5230 out vec4 color;
5231 void main()
5232 {
5233     color = vec;
5234 })";
5235 
5236     ANGLE_GL_PROGRAM(program, kVS, kFS);
5237     glUseProgram(program);
5238 
5239     GLuint blockIndex = glGetUniformBlockIndex(program, "uni");
5240     ASSERT_NE(GL_INVALID_INDEX, blockIndex);
5241 
5242     glUniformBlockBinding(program, blockIndex, 0);
5243 
5244     GLBuffer uniformBuffer;
5245     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5246     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5247     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5248 
5249     const auto &quadVertices = GetQuadVertices();
5250 
5251     GLBuffer positionBuffer;
5252     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5253     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5254                  GL_STATIC_DRAW);
5255 
5256     GLint positionLocation = glGetAttribLocation(program, "position");
5257     ASSERT_NE(-1, positionLocation);
5258 
5259     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5260     glEnableVertexAttribArray(positionLocation);
5261     ASSERT_GL_NO_ERROR();
5262 
5263     // First draw should succeed.
5264     glDrawArrays(GL_TRIANGLES, 0, 6);
5265     ASSERT_GL_NO_ERROR();
5266     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5267 
5268     // Change the uniform block binding. Should fail.
5269     glUniformBlockBinding(program, blockIndex, 1);
5270     ASSERT_GL_NO_ERROR();
5271     glDrawArrays(GL_TRIANGLES, 0, 6);
5272     ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid uniform block binding should fail";
5273 
5274     // Reset to a correct state.
5275     glUniformBlockBinding(program, blockIndex, 0);
5276     glDrawArrays(GL_TRIANGLES, 0, 6);
5277     ASSERT_GL_NO_ERROR();
5278     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5279 
5280     // Change the buffer binding. Should fail.
5281     glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
5282     ASSERT_GL_NO_ERROR();
5283     glDrawArrays(GL_TRIANGLES, 0, 6);
5284     ASSERT_GL_ERROR(GL_INVALID_OPERATION) << "Setting invalid uniform buffer should fail";
5285 
5286     // Reset to a correct state.
5287     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5288     glDrawArrays(GL_TRIANGLES, 0, 6);
5289     ASSERT_GL_NO_ERROR();
5290     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5291 
5292     // Resize the buffer to be too small. Should fail.
5293     glBufferData(GL_UNIFORM_BUFFER, 1, nullptr, GL_STATIC_DRAW);
5294     glDrawArrays(GL_TRIANGLES, 0, 6);
5295     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Invalid buffer size should fail";
5296 }
5297 
5298 // Tests various state change effects on draw framebuffer validation.
TEST_P(WebGL2ValidationStateChangeTest,DrawFramebufferNegativeAPI)5299 TEST_P(WebGL2ValidationStateChangeTest, DrawFramebufferNegativeAPI)
5300 {
5301     // Set up a simple draw from a Texture to a user Framebuffer.
5302     GLuint program = get2DTexturedQuadProgram();
5303     ASSERT_NE(0u, program);
5304     glUseProgram(program);
5305 
5306     GLint posLoc = glGetAttribLocation(program, "position");
5307     ASSERT_NE(-1, posLoc);
5308 
5309     const auto &quadVertices = GetQuadVertices();
5310 
5311     GLBuffer positionBuffer;
5312     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5313     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5314                  GL_STATIC_DRAW);
5315 
5316     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5317     glEnableVertexAttribArray(posLoc);
5318 
5319     constexpr size_t kSize = 2;
5320 
5321     GLTexture colorBufferTexture;
5322     glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5323     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
5324     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5325     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5326 
5327     GLFramebuffer framebuffer;
5328     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5329     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5330                            0);
5331     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5332 
5333     std::vector<GLColor> greenColor(kSize * kSize, GLColor::green);
5334 
5335     GLTexture greenTexture;
5336     glBindTexture(GL_TEXTURE_2D, greenTexture);
5337     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5338                  greenColor.data());
5339     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5340     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5341 
5342     // Second framebuffer with a feedback loop. Initially unbound.
5343     GLFramebuffer loopedFramebuffer;
5344     glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5345     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, greenTexture, 0);
5346     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5347     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
5348 
5349     ASSERT_GL_NO_ERROR();
5350 
5351     glDrawArrays(GL_TRIANGLES, 0, 6);
5352     ASSERT_GL_NO_ERROR();
5353     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5354 
5355     // Create a rendering feedback loop. Should fail.
5356     glBindTexture(GL_TEXTURE_2D, colorBufferTexture);
5357     ASSERT_GL_NO_ERROR();
5358     glDrawArrays(GL_TRIANGLES, 0, 6);
5359     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5360 
5361     // Reset to a valid state.
5362     glBindTexture(GL_TEXTURE_2D, greenTexture);
5363     glDrawArrays(GL_TRIANGLES, 0, 6);
5364     ASSERT_GL_NO_ERROR();
5365     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5366 
5367     // Bind a second framebuffer with a feedback loop.
5368     glBindFramebuffer(GL_FRAMEBUFFER, loopedFramebuffer);
5369     ASSERT_GL_NO_ERROR();
5370     glDrawArrays(GL_TRIANGLES, 0, 6);
5371     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5372 
5373     // Update the framebuffer texture attachment. Should succeed.
5374     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferTexture,
5375                            0);
5376     glDrawArrays(GL_TRIANGLES, 0, 6);
5377     ASSERT_GL_NO_ERROR();
5378     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5379 }
5380 
5381 // Tests various state change effects on draw framebuffer validation with MRT.
TEST_P(WebGL2ValidationStateChangeTest,MultiAttachmentDrawFramebufferNegativeAPI)5382 TEST_P(WebGL2ValidationStateChangeTest, MultiAttachmentDrawFramebufferNegativeAPI)
5383 {
5384     // Crashes on 64-bit Android.  http://anglebug.com/3878
5385     ANGLE_SKIP_TEST_IF(IsVulkan() && IsAndroid());
5386 
5387     // http://anglebug.com/5233
5388     ANGLE_SKIP_TEST_IF(IsMetal());
5389 
5390     // Set up a program that writes to two outputs: one int and one float.
5391     constexpr char kVS[] = R"(#version 300 es
5392 layout(location = 0) in vec2 position;
5393 out vec2 texCoord;
5394 void main()
5395 {
5396     gl_Position = vec4(position, 0, 1);
5397     texCoord = position * 0.5 + vec2(0.5);
5398 })";
5399 
5400     constexpr char kFS[] = R"(#version 300 es
5401 precision mediump float;
5402 in vec2 texCoord;
5403 layout(location = 0) out vec4 outFloat;
5404 layout(location = 1) out uvec4 outInt;
5405 void main()
5406 {
5407     outFloat = vec4(0, 1, 0, 1);
5408     outInt = uvec4(0, 1, 0, 1);
5409 })";
5410 
5411     ANGLE_GL_PROGRAM(program, kVS, kFS);
5412     glUseProgram(program);
5413 
5414     constexpr GLint kPosLoc = 0;
5415 
5416     const auto &quadVertices = GetQuadVertices();
5417 
5418     GLBuffer positionBuffer;
5419     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5420     glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * quadVertices.size(), quadVertices.data(),
5421                  GL_STATIC_DRAW);
5422 
5423     glVertexAttribPointer(kPosLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5424     glEnableVertexAttribArray(kPosLoc);
5425 
5426     constexpr size_t kSize = 2;
5427 
5428     GLFramebuffer floatFramebuffer;
5429     glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5430 
5431     GLTexture floatTextures[2];
5432     for (int i = 0; i < 2; ++i)
5433     {
5434         glBindTexture(GL_TEXTURE_2D, floatTextures[i]);
5435         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5436                      nullptr);
5437         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5438                                floatTextures[i], 0);
5439         ASSERT_GL_NO_ERROR();
5440     }
5441 
5442     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5443 
5444     GLFramebuffer intFramebuffer;
5445     glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5446 
5447     GLTexture intTextures[2];
5448     for (int i = 0; i < 2; ++i)
5449     {
5450         glBindTexture(GL_TEXTURE_2D, intTextures[i]);
5451         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, kSize, kSize, 0, GL_RGBA_INTEGER,
5452                      GL_UNSIGNED_BYTE, nullptr);
5453         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
5454                                intTextures[i], 0);
5455         ASSERT_GL_NO_ERROR();
5456     }
5457 
5458     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5459 
5460     ASSERT_GL_NO_ERROR();
5461 
5462     constexpr GLenum kColor0Enabled[]     = {GL_COLOR_ATTACHMENT0, GL_NONE};
5463     constexpr GLenum kColor1Enabled[]     = {GL_NONE, GL_COLOR_ATTACHMENT1};
5464     constexpr GLenum kColor0And1Enabled[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
5465 
5466     // Draw float. Should work.
5467     glBindFramebuffer(GL_FRAMEBUFFER, floatFramebuffer);
5468     glDrawBuffers(2, kColor0Enabled);
5469 
5470     glDrawArrays(GL_TRIANGLES, 0, 6);
5471     ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5472     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5473 
5474     // Set an invalid component write.
5475     glDrawBuffers(2, kColor0And1Enabled);
5476     ASSERT_GL_NO_ERROR() << "Draw to float texture with invalid mask";
5477     glDrawArrays(GL_TRIANGLES, 0, 6);
5478     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5479     // Set all 4 channels of color mask to false. Validate success.
5480     glColorMask(false, false, false, false);
5481     glDrawArrays(GL_TRIANGLES, 0, 6);
5482     EXPECT_GL_NO_ERROR();
5483     glColorMask(false, true, false, false);
5484     glDrawArrays(GL_TRIANGLES, 0, 6);
5485     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5486     glColorMask(true, true, true, true);
5487     glDrawArrays(GL_TRIANGLES, 0, 6);
5488     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5489 
5490     // Restore state.
5491     glDrawBuffers(2, kColor0Enabled);
5492     glDrawArrays(GL_TRIANGLES, 0, 6);
5493     ASSERT_GL_NO_ERROR() << "Draw to float texture with correct mask";
5494     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5495 
5496     // Bind an invalid framebuffer. Validate failure.
5497     glBindFramebuffer(GL_FRAMEBUFFER, intFramebuffer);
5498     ASSERT_GL_NO_ERROR();
5499     glDrawArrays(GL_TRIANGLES, 0, 6);
5500     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Draw to int texture with default mask";
5501 
5502     // Set draw mask to a valid mask. Validate success.
5503     glDrawBuffers(2, kColor1Enabled);
5504     glDrawArrays(GL_TRIANGLES, 0, 6);
5505     ASSERT_GL_NO_ERROR() << "Draw to int texture with correct mask";
5506 }
5507 
5508 // Tests negative API state change cases with Transform Feedback bindings.
TEST_P(WebGL2ValidationStateChangeTest,TransformFeedbackNegativeAPI)5509 TEST_P(WebGL2ValidationStateChangeTest, TransformFeedbackNegativeAPI)
5510 {
5511     ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5512 
5513     // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
5514     ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
5515 
5516     constexpr char kFS[] = R"(#version 300 es
5517 precision mediump float;
5518 uniform block { vec4 color; };
5519 out vec4 colorOut;
5520 void main()
5521 {
5522     colorOut = color;
5523 })";
5524 
5525     std::vector<std::string> tfVaryings = {"gl_Position"};
5526     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(), kFS, tfVaryings,
5527                                         GL_INTERLEAVED_ATTRIBS);
5528     glUseProgram(program);
5529 
5530     std::vector<Vector4> positionData;
5531     for (const Vector3 &quadVertex : GetQuadVertices())
5532     {
5533         positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5534     }
5535 
5536     GLBuffer arrayBuffer;
5537     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5538     glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5539                  GL_STATIC_DRAW);
5540 
5541     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5542     ASSERT_NE(-1, positionLoc);
5543 
5544     glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5545     glEnableVertexAttribArray(positionLoc);
5546 
5547     EXPECT_GL_NO_ERROR();
5548 
5549     // Set up transform feedback.
5550     GLTransformFeedback transformFeedback;
5551     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5552 
5553     constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5554 
5555     GLBuffer transformFeedbackBuffer;
5556     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5557     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5558     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5559 
5560     // Set up uniform buffer.
5561     GLBuffer uniformBuffer;
5562     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
5563     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen.R, GL_STATIC_DRAW);
5564     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
5565 
5566     ASSERT_GL_NO_ERROR();
5567 
5568     // Do the draw operation. Should succeed.
5569     glBeginTransformFeedback(GL_TRIANGLES);
5570     glDrawArrays(GL_TRIANGLES, 0, 6);
5571     glEndTransformFeedback();
5572 
5573     ASSERT_GL_NO_ERROR();
5574     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5575 
5576     const GLvoid *mapPointer =
5577         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, kTransformFeedbackSize, GL_MAP_READ_BIT);
5578     ASSERT_GL_NO_ERROR();
5579     ASSERT_NE(nullptr, mapPointer);
5580     const Vector4 *typedMapPointer = reinterpret_cast<const Vector4 *>(mapPointer);
5581     std::vector<Vector4> actualData(typedMapPointer, typedMapPointer + 6);
5582     EXPECT_EQ(positionData, actualData);
5583     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5584 
5585     // Draw once to update validation cache.
5586     glBeginTransformFeedback(GL_TRIANGLES);
5587     glDrawArrays(GL_TRIANGLES, 0, 6);
5588 
5589     // Bind transform feedback buffer to another binding point. Should cause a conflict.
5590     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, transformFeedbackBuffer);
5591     ASSERT_GL_NO_ERROR();
5592     glDrawArrays(GL_TRIANGLES, 0, 6);
5593     glEndTransformFeedback();
5594     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous element buffer binding should fail";
5595 
5596     // Reset to valid state.
5597     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
5598     glBeginTransformFeedback(GL_TRIANGLES);
5599     glDrawArrays(GL_TRIANGLES, 0, 6);
5600     glEndTransformFeedback();
5601     ASSERT_GL_NO_ERROR();
5602 
5603     // Simultaneous non-vertex-array binding. Should fail.
5604     glBeginTransformFeedback(GL_TRIANGLES);
5605     glDrawArrays(GL_TRIANGLES, 0, 6);
5606     ASSERT_GL_NO_ERROR();
5607     glBindBuffer(GL_PIXEL_PACK_BUFFER, transformFeedbackBuffer);
5608     ASSERT_GL_NO_ERROR();
5609     glDrawArrays(GL_TRIANGLES, 0, 6);
5610     glEndTransformFeedback();
5611     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Simultaneous pack buffer binding should fail";
5612 }
5613 
5614 // Test sampler format validation caching works.
TEST_P(WebGL2ValidationStateChangeTest,SamplerFormatCache)5615 TEST_P(WebGL2ValidationStateChangeTest, SamplerFormatCache)
5616 {
5617     // Crashes in depth data upload due to lack of support for GL_UNSIGNED_INT data when
5618     // DEPTH_COMPONENT24 is emulated with D32_S8X24.  http://anglebug.com/3880
5619     ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && IsAMD());
5620 
5621     constexpr char kFS[] = R"(#version 300 es
5622 precision mediump float;
5623 uniform sampler2D sampler;
5624 out vec4 colorOut;
5625 void main()
5626 {
5627     colorOut = texture(sampler, vec2(0));
5628 })";
5629 
5630     std::vector<std::string> tfVaryings = {"gl_Position"};
5631     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
5632     glUseProgram(program);
5633 
5634     std::array<GLColor, 4> colors = {
5635         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
5636 
5637     GLTexture tex;
5638     glBindTexture(GL_TEXTURE_2D, tex);
5639     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
5640 
5641     const auto &quadVertices = GetQuadVertices();
5642 
5643     GLBuffer arrayBuffer;
5644     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5645     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5646                  GL_STATIC_DRAW);
5647 
5648     GLint samplerLoc = glGetUniformLocation(program, "sampler");
5649     ASSERT_NE(-1, samplerLoc);
5650     glUniform1i(samplerLoc, 0);
5651 
5652     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5653     ASSERT_NE(-1, positionLoc);
5654     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5655     glEnableVertexAttribArray(positionLoc);
5656 
5657     ASSERT_GL_NO_ERROR();
5658 
5659     glDrawArrays(GL_TRIANGLES, 0, 6);
5660     ASSERT_GL_NO_ERROR();
5661 
5662     // TexImage2D should update the sampler format cache.
5663     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 2, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE,
5664                  colors.data());
5665     glDrawArrays(GL_TRIANGLES, 0, 6);
5666     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Sampling integer texture with a float sampler.";
5667 
5668     glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 2, 2, 0, GL_DEPTH_COMPONENT,
5669                  GL_UNSIGNED_INT, colors.data());
5670     glDrawArrays(GL_TRIANGLES, 0, 6);
5671     ASSERT_GL_NO_ERROR() << "Depth texture with no compare mode.";
5672 
5673     // TexParameteri should update the sampler format cache.
5674     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
5675     glDrawArrays(GL_TRIANGLES, 0, 6);
5676     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Depth texture with compare mode set.";
5677 }
5678 
5679 // Tests that we retain the correct draw mode settings with transform feedback changes.
TEST_P(ValidationStateChangeTest,TransformFeedbackDrawModes)5680 TEST_P(ValidationStateChangeTest, TransformFeedbackDrawModes)
5681 {
5682     ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
5683 
5684     std::vector<std::string> tfVaryings = {"gl_Position"};
5685     ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(program, essl3_shaders::vs::Simple(),
5686                                         essl3_shaders::fs::Red(), tfVaryings,
5687                                         GL_INTERLEAVED_ATTRIBS);
5688     glUseProgram(program);
5689 
5690     std::vector<Vector4> positionData;
5691     for (const Vector3 &quadVertex : GetQuadVertices())
5692     {
5693         positionData.emplace_back(quadVertex.x(), quadVertex.y(), quadVertex.z(), 1.0f);
5694     }
5695 
5696     GLBuffer arrayBuffer;
5697     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5698     glBufferData(GL_ARRAY_BUFFER, positionData.size() * sizeof(Vector4), positionData.data(),
5699                  GL_STATIC_DRAW);
5700 
5701     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5702     ASSERT_NE(-1, positionLoc);
5703 
5704     glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
5705     glEnableVertexAttribArray(positionLoc);
5706 
5707     // Set up transform feedback.
5708     GLTransformFeedback transformFeedback;
5709     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5710 
5711     constexpr size_t kTransformFeedbackSize = 6 * sizeof(Vector4);
5712 
5713     GLBuffer transformFeedbackBuffer;
5714     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, transformFeedbackBuffer);
5715     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, kTransformFeedbackSize * 2, nullptr, GL_STATIC_DRAW);
5716     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, transformFeedbackBuffer);
5717 
5718     GLTransformFeedback pointsXFB;
5719     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5720     GLBuffer pointsXFBBuffer;
5721     glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, pointsXFBBuffer);
5722     glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
5723     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, pointsXFBBuffer);
5724 
5725     // Begin TRIANGLES, switch to paused POINTS, should be valid.
5726     glBeginTransformFeedback(GL_POINTS);
5727     glPauseTransformFeedback();
5728     ASSERT_GL_NO_ERROR() << "Starting point transform feedback should succeed";
5729 
5730     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5731     glBeginTransformFeedback(GL_TRIANGLES);
5732     glDrawArrays(GL_TRIANGLES, 0, 6);
5733     EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5734     glDrawArrays(GL_POINTS, 0, 6);
5735     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Point rendering should fail";
5736     glDrawArrays(GL_LINES, 0, 6);
5737     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5738     glPauseTransformFeedback();
5739     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, pointsXFB);
5740     glResumeTransformFeedback();
5741     glDrawArrays(GL_POINTS, 0, 6);
5742     EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5743     glDrawArrays(GL_TRIANGLES, 0, 6);
5744     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Triangle rendering should fail";
5745     glDrawArrays(GL_LINES, 0, 6);
5746     EXPECT_GL_ERROR(GL_INVALID_OPERATION) << "Lines rendering should fail";
5747 
5748     glEndTransformFeedback();
5749     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedback);
5750     glEndTransformFeedback();
5751     ASSERT_GL_NO_ERROR() << "Ending transform feeback should pass";
5752 
5753     glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
5754 
5755     glDrawArrays(GL_POINTS, 0, 6);
5756     EXPECT_GL_NO_ERROR() << "Point rendering should succeed";
5757     glDrawArrays(GL_TRIANGLES, 0, 6);
5758     EXPECT_GL_NO_ERROR() << "Triangle rendering should succeed";
5759     glDrawArrays(GL_LINES, 0, 6);
5760     EXPECT_GL_NO_ERROR() << "Line rendering should succeed";
5761 }
5762 
5763 // Tests a valid rendering setup with two textures. Followed by a draw with conflicting samplers.
TEST_P(ValidationStateChangeTest,TextureConflict)5764 TEST_P(ValidationStateChangeTest, TextureConflict)
5765 {
5766     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_storage"));
5767 
5768     GLint maxTextures = 0;
5769     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextures);
5770     ANGLE_SKIP_TEST_IF(maxTextures < 2);
5771 
5772     // Set up state.
5773     constexpr GLint kSize = 2;
5774 
5775     std::vector<GLColor> greenData(4, GLColor::green);
5776 
5777     GLTexture textureA;
5778     glBindTexture(GL_TEXTURE_2D, textureA);
5779     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
5780                  greenData.data());
5781     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5782     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5783 
5784     glActiveTexture(GL_TEXTURE1);
5785 
5786     GLTexture textureB;
5787     glBindTexture(GL_TEXTURE_CUBE_MAP, textureB);
5788     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5789                  GL_UNSIGNED_BYTE, greenData.data());
5790     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5791                  GL_UNSIGNED_BYTE, greenData.data());
5792     glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5793                  GL_UNSIGNED_BYTE, greenData.data());
5794     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5795                  GL_UNSIGNED_BYTE, greenData.data());
5796     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5797                  GL_UNSIGNED_BYTE, greenData.data());
5798     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA,
5799                  GL_UNSIGNED_BYTE, greenData.data());
5800     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5801     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5802 
5803     constexpr char kVS[] = R"(attribute vec2 position;
5804 varying mediump vec2 texCoord;
5805 void main()
5806 {
5807     gl_Position = vec4(position, 0, 1);
5808     texCoord = position * 0.5 + vec2(0.5);
5809 })";
5810 
5811     constexpr char kFS[] = R"(varying mediump vec2 texCoord;
5812 uniform sampler2D texA;
5813 uniform samplerCube texB;
5814 void main()
5815 {
5816     gl_FragColor = texture2D(texA, texCoord) + textureCube(texB, vec3(1, 0, 0));
5817 })";
5818 
5819     ANGLE_GL_PROGRAM(program, kVS, kFS);
5820     glUseProgram(program);
5821 
5822     const auto &quadVertices = GetQuadVertices();
5823 
5824     GLBuffer arrayBuffer;
5825     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5826     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
5827                  GL_STATIC_DRAW);
5828 
5829     GLint positionLoc = glGetAttribLocation(program, "position");
5830     ASSERT_NE(-1, positionLoc);
5831 
5832     GLint texALoc = glGetUniformLocation(program, "texA");
5833     ASSERT_NE(-1, texALoc);
5834 
5835     GLint texBLoc = glGetUniformLocation(program, "texB");
5836     ASSERT_NE(-1, texBLoc);
5837 
5838     glUniform1i(texALoc, 0);
5839     glUniform1i(texBLoc, 1);
5840 
5841     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5842     glEnableVertexAttribArray(positionLoc);
5843 
5844     ASSERT_GL_NO_ERROR();
5845 
5846     // First draw. Should succeed.
5847     glDrawArrays(GL_TRIANGLES, 0, 6);
5848     ASSERT_GL_NO_ERROR();
5849     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
5850 
5851     // Second draw to ensure all state changes are flushed.
5852     glDrawArrays(GL_TRIANGLES, 0, 6);
5853     ASSERT_GL_NO_ERROR();
5854 
5855     // Make the uniform use an invalid texture binding.
5856     glUniform1i(texBLoc, 0);
5857     glDrawArrays(GL_TRIANGLES, 0, 6);
5858     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5859 }
5860 
5861 // Tests that mapping the element array buffer triggers errors.
TEST_P(ValidationStateChangeTest,MapElementArrayBuffer)5862 TEST_P(ValidationStateChangeTest, MapElementArrayBuffer)
5863 {
5864     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
5865     glUseProgram(program);
5866 
5867     std::array<GLushort, 6> quadIndices = GetQuadIndices();
5868     std::array<Vector3, 4> quadVertices = GetIndexedQuadVertices();
5869 
5870     GLsizei elementBufferSize = sizeof(quadIndices[0]) * quadIndices.size();
5871 
5872     GLBuffer elementArrayBuffer;
5873     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
5874     glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBufferSize, quadIndices.data(), GL_STATIC_DRAW);
5875 
5876     GLBuffer arrayBuffer;
5877     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5878     glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices[0]) * quadVertices.size(),
5879                  quadVertices.data(), GL_STATIC_DRAW);
5880 
5881     GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
5882     ASSERT_NE(-1, positionLoc);
5883     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5884     glEnableVertexAttribArray(positionLoc);
5885 
5886     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5887     ASSERT_GL_NO_ERROR();
5888 
5889     void *ptr = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, elementBufferSize, GL_MAP_READ_BIT);
5890     ASSERT_NE(nullptr, ptr);
5891 
5892     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5893     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5894 
5895     glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
5896 
5897     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5898     ASSERT_GL_NO_ERROR();
5899     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5900 }
5901 
5902 // Tests that deleting a non-active texture does not reset the current texture cache.
TEST_P(SimpleStateChangeTest,DeleteNonActiveTextureThenDraw)5903 TEST_P(SimpleStateChangeTest, DeleteNonActiveTextureThenDraw)
5904 {
5905     constexpr char kFS[] =
5906         "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
5907     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5908     glUseProgram(program);
5909     GLint loc = glGetUniformLocation(program, "us");
5910     ASSERT_EQ(0, loc);
5911 
5912     auto quadVertices = GetQuadVertices();
5913     GLint posLoc      = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
5914     ASSERT_EQ(0, posLoc);
5915 
5916     GLBuffer buffer;
5917     glBindBuffer(GL_ARRAY_BUFFER, buffer);
5918     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
5919                  quadVertices.data(), GL_STATIC_DRAW);
5920     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5921     glEnableVertexAttribArray(posLoc);
5922 
5923     constexpr size_t kSize = 2;
5924     std::vector<GLColor> red(kSize * kSize, GLColor::red);
5925 
5926     GLTexture tex;
5927     glBindTexture(GL_TEXTURE_2D, tex);
5928     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
5929     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5930     glUniform1i(loc, 0);
5931 
5932     glDrawArrays(GL_TRIANGLES, 0, 3);
5933     ASSERT_GL_NO_ERROR();
5934     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5935 
5936     // Deleting TEXTURE_CUBE_MAP[0] should not affect TEXTURE_2D[0].
5937     GLTexture tex2;
5938     glBindTexture(GL_TEXTURE_CUBE_MAP, tex2);
5939     tex2.reset();
5940 
5941     glDrawArrays(GL_TRIANGLES, 0, 3);
5942     ASSERT_GL_NO_ERROR();
5943     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
5944 
5945     // Deleting TEXTURE_2D[0] should start "sampling" from the default/zero texture.
5946     tex.reset();
5947 
5948     glDrawArrays(GL_TRIANGLES, 0, 3);
5949     ASSERT_GL_NO_ERROR();
5950     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5951 }
5952 
5953 // Tests that deleting a texture successfully binds the zero texture.
TEST_P(SimpleStateChangeTest,DeleteTextureThenDraw)5954 TEST_P(SimpleStateChangeTest, DeleteTextureThenDraw)
5955 {
5956     constexpr char kFS[] =
5957         "uniform sampler2D us; void main() { gl_FragColor = texture2D(us, vec2(0)); }";
5958     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
5959     glUseProgram(program);
5960     GLint loc = glGetUniformLocation(program, "us");
5961     ASSERT_EQ(0, loc);
5962 
5963     auto quadVertices = GetQuadVertices();
5964     GLint posLoc      = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
5965     ASSERT_EQ(0, posLoc);
5966 
5967     GLBuffer buffer;
5968     glBindBuffer(GL_ARRAY_BUFFER, buffer);
5969     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(quadVertices[0]),
5970                  quadVertices.data(), GL_STATIC_DRAW);
5971     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
5972     glEnableVertexAttribArray(posLoc);
5973 
5974     constexpr size_t kSize = 2;
5975     std::vector<GLColor> red(kSize * kSize, GLColor::red);
5976 
5977     GLTexture tex;
5978     glBindTexture(GL_TEXTURE_2D, tex);
5979     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, red.data());
5980     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5981     glUniform1i(loc, 1);
5982     tex.reset();
5983 
5984     glDrawArrays(GL_TRIANGLES, 0, 3);
5985     ASSERT_GL_NO_ERROR();
5986     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
5987 }
5988 
bindTextureToFbo(GLFramebuffer & fbo,GLTexture & texture)5989 void SimpleStateChangeTest::bindTextureToFbo(GLFramebuffer &fbo, GLTexture &texture)
5990 {
5991     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5992     glBindTexture(GL_TEXTURE_2D, texture);
5993     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
5994                  GL_UNSIGNED_BYTE, nullptr);
5995     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5996     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5997     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
5998     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
5999 }
6000 
drawToFboWithCulling(const GLenum frontFace,bool earlyFrontFaceDirty)6001 void SimpleStateChangeTest::drawToFboWithCulling(const GLenum frontFace, bool earlyFrontFaceDirty)
6002 {
6003     // Render to an FBO
6004     GLFramebuffer fbo1;
6005     GLTexture texture1;
6006 
6007     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6008     ANGLE_GL_PROGRAM(textureProgram, essl1_shaders::vs::Texture2D(),
6009                      essl1_shaders::fs::Texture2D());
6010 
6011     bindTextureToFbo(fbo1, texture1);
6012 
6013     // Clear the surface FBO to initialize it to a known value
6014     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6015     glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6016     glClear(GL_COLOR_BUFFER_BIT);
6017     ASSERT_GL_NO_ERROR();
6018     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6019     glFlush();
6020 
6021     // Draw to FBO 1 to initialize it to a known value
6022     glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
6023 
6024     if (earlyFrontFaceDirty)
6025     {
6026         glEnable(GL_CULL_FACE);
6027         // Make sure we don't cull
6028         glCullFace(frontFace == GL_CCW ? GL_BACK : GL_FRONT);
6029         glFrontFace(frontFace);
6030     }
6031     else
6032     {
6033         glDisable(GL_CULL_FACE);
6034     }
6035 
6036     glUseProgram(greenProgram);
6037     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6038     ASSERT_GL_NO_ERROR();
6039     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6040 
6041     // Draw into FBO 0 using FBO 1's texture to determine if culling is working or not
6042     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6043     glBindTexture(GL_TEXTURE_2D, texture1);
6044 
6045     glCullFace(GL_BACK);
6046     if (!earlyFrontFaceDirty)
6047     {
6048         // Set the culling we want to test
6049         glEnable(GL_CULL_FACE);
6050         glFrontFace(frontFace);
6051     }
6052 
6053     glUseProgram(textureProgram);
6054     drawQuad(textureProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6055     ASSERT_GL_NO_ERROR();
6056 
6057     if (frontFace == GL_CCW)
6058     {
6059         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6060     }
6061     else
6062     {
6063         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6064     }
6065 
6066     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6067     glBindTexture(GL_TEXTURE_2D, 0);
6068 }
6069 
6070 // Validates if culling rasterization states work with FBOs using CCW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCCWState)6071 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCCWState)
6072 {
6073     drawToFboWithCulling(GL_CCW, true);
6074 }
6075 
6076 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboEarlyCullFaceBackCWState)6077 TEST_P(SimpleStateChangeTest, FboEarlyCullFaceBackCWState)
6078 {
6079     drawToFboWithCulling(GL_CW, true);
6080 }
6081 
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCCWState)6082 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCCWState)
6083 {
6084     drawToFboWithCulling(GL_CCW, false);
6085 }
6086 
6087 // Validates if culling rasterization states work with FBOs using CW winding.
TEST_P(SimpleStateChangeTest,FboLateCullFaceBackCWState)6088 TEST_P(SimpleStateChangeTest, FboLateCullFaceBackCWState)
6089 {
6090     drawToFboWithCulling(GL_CW, false);
6091 }
6092 
6093 // Test that vertex attribute translation is still kept after binding it to another buffer then
6094 // binding back to the previous buffer.
TEST_P(SimpleStateChangeTest,RebindTranslatedAttribute)6095 TEST_P(SimpleStateChangeTest, RebindTranslatedAttribute)
6096 {
6097     // http://anglebug.com/5379
6098     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
6099 
6100     constexpr char kVS[] = R"(attribute vec4 a_position;
6101 attribute float a_attrib;
6102 varying float v_attrib;
6103 void main()
6104 {
6105     v_attrib = a_attrib;
6106     gl_Position = a_position;
6107 })";
6108 
6109     constexpr char kFS[] = R"(precision mediump float;
6110 varying float v_attrib;
6111 void main()
6112 {
6113     gl_FragColor = vec4(v_attrib, 0, 0, 1);
6114 })";
6115 
6116     ANGLE_GL_PROGRAM(program, kVS, kFS);
6117     glBindAttribLocation(program, 0, "a_position");
6118     glBindAttribLocation(program, 1, "a_attrib");
6119     glLinkProgram(program);
6120     glUseProgram(program);
6121     ASSERT_GL_NO_ERROR();
6122 
6123     // Set up color data so red is drawn
6124     std::vector<GLushort> data(1000, 0xffff);
6125 
6126     GLBuffer redBuffer;
6127     glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6128     glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
6129     // Use offset not multiple of 4 GLushorts, this could force vertex translation in Metal backend.
6130     glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6131                           reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6132     glBindBuffer(GL_ARRAY_BUFFER, 0);
6133     glEnableVertexAttribArray(1);
6134 
6135     drawQuad(program, "a_position", 0.5f);
6136     // Verify red was drawn
6137     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6138 
6139     glClearColor(0, 1, 0, 1);
6140     glClear(GL_COLOR_BUFFER_BIT);
6141     // Verify that green was drawn
6142     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6143 
6144     // Bind black color buffer to the same attribute with zero offset
6145     std::vector<GLfloat> black(6, 0.0f);
6146     GLBuffer blackBuffer;
6147     glBindBuffer(GL_ARRAY_BUFFER, blackBuffer);
6148     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * black.size(), black.data(), GL_STATIC_DRAW);
6149     glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0);
6150 
6151     drawQuad(program, "a_position", 0.5f);
6152     // Verify black was drawn
6153     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6154 
6155     // Rebind the old buffer & offset
6156     glBindBuffer(GL_ARRAY_BUFFER, redBuffer);
6157     // Use offset not multiple of 4 GLushorts
6158     glVertexAttribPointer(1, 4, GL_UNSIGNED_SHORT, GL_TRUE, 0,
6159                           reinterpret_cast<const void *>(sizeof(GLushort) * 97));
6160 
6161     drawQuad(program, "a_position", 0.5f);
6162     // Verify red was drawn
6163     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6164 }
6165 
6166 // Test that switching between programs that only contain default uniforms is correct.
TEST_P(SimpleStateChangeTest,TwoProgramsWithOnlyDefaultUniforms)6167 TEST_P(SimpleStateChangeTest, TwoProgramsWithOnlyDefaultUniforms)
6168 {
6169     constexpr char kVS[] = R"(attribute vec4 a_position;
6170 varying float v_attrib;
6171 uniform float u_value;
6172 void main()
6173 {
6174     v_attrib = u_value;
6175     gl_Position = a_position;
6176 })";
6177 
6178     constexpr char kFS[] = R"(precision mediump float;
6179 varying float v_attrib;
6180 void main()
6181 {
6182     gl_FragColor = vec4(v_attrib, 0, 0, 1);
6183 })";
6184 
6185     ANGLE_GL_PROGRAM(program1, kVS, kFS);
6186     ANGLE_GL_PROGRAM(program2, kVS, kFS);
6187 
6188     // Don't use drawQuad so there's no state changes between the draw calls other than the program
6189     // binding.
6190 
6191     constexpr size_t kProgramCount = 2;
6192     GLuint programs[kProgramCount] = {program1, program2};
6193     for (size_t i = 0; i < kProgramCount; ++i)
6194     {
6195         glUseProgram(programs[i]);
6196         GLint uniformLoc = glGetUniformLocation(programs[i], "u_value");
6197         ASSERT_NE(uniformLoc, -1);
6198 
6199         glUniform1f(uniformLoc, static_cast<float>(i + 1) / static_cast<float>(kProgramCount));
6200 
6201         // Ensure position is at location 0 in both programs.
6202         GLint positionLocation = glGetAttribLocation(programs[i], "a_position");
6203         ASSERT_EQ(positionLocation, 0);
6204     }
6205     ASSERT_GL_NO_ERROR();
6206 
6207     std::array<Vector3, 6> quadVertices = GetQuadVertices();
6208     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
6209     glEnableVertexAttribArray(0);
6210 
6211     // Draw once with each so their uniforms are updated.
6212     // The first draw will clear the screen to 255, 0, 0, 255
6213     glUseProgram(program2);
6214     glDrawArrays(GL_TRIANGLES, 0, 6);
6215     // The second draw will clear the screen to 127, 0, 0, 255
6216     glUseProgram(program1);
6217     glDrawArrays(GL_TRIANGLES, 0, 6);
6218 
6219     // Draw with the previous program again, to make sure its default uniforms are bound again.
6220     glUseProgram(program2);
6221     glDrawArrays(GL_TRIANGLES, 0, 6);
6222 
6223     // Verify red was drawn
6224     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6225 }
6226 
6227 // Test that glDrawArrays when an empty-sized element array buffer is bound doesn't crash.
6228 // Regression test for crbug.com/1172577.
TEST_P(SimpleStateChangeTest,DrawArraysWithZeroSizedElementArrayBuffer)6229 TEST_P(SimpleStateChangeTest, DrawArraysWithZeroSizedElementArrayBuffer)
6230 {
6231     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6232 
6233     GLBuffer indexBuffer;
6234     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6235     glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW);
6236     drawQuad(greenProgram, essl1_shaders::PositionAttrib(), 0.0f);
6237     ASSERT_GL_NO_ERROR();
6238 
6239     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6240 }
6241 
6242 // Validates GL_RASTERIZER_DISCARD state is tracked correctly
TEST_P(SimpleStateChangeTestES3,RasterizerDiscardState)6243 TEST_P(SimpleStateChangeTestES3, RasterizerDiscardState)
6244 {
6245     glClearColor(GLColor::red.R, GLColor::red.G, GLColor::red.B, GLColor::red.A);
6246     glClear(GL_COLOR_BUFFER_BIT);
6247     ASSERT_GL_NO_ERROR();
6248     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6249 
6250     ANGLE_GL_PROGRAM(greenProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
6251     ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6252 
6253     // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6254     glEnable(GL_RASTERIZER_DISCARD);
6255     glUseProgram(greenProgram);
6256     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6257     ASSERT_GL_NO_ERROR();
6258     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6259 
6260     // The drawQuad() should draw something with GL_RASTERIZER_DISCARD disabled
6261     glDisable(GL_RASTERIZER_DISCARD);
6262     glUseProgram(greenProgram);
6263     drawQuad(greenProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6264     ASSERT_GL_NO_ERROR();
6265     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6266 
6267     // The drawQuad() should have no effect with GL_RASTERIZER_DISCARD enabled
6268     glEnable(GL_RASTERIZER_DISCARD);
6269     glUseProgram(blueProgram);
6270     drawQuad(blueProgram.get(), std::string(essl1_shaders::PositionAttrib()), 0.0f);
6271     ASSERT_GL_NO_ERROR();
6272     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
6273 }
6274 
6275 class ImageRespecificationTest : public ANGLETest
6276 {
6277   protected:
ImageRespecificationTest()6278     ImageRespecificationTest()
6279     {
6280         setWindowWidth(128);
6281         setWindowHeight(128);
6282         setConfigRedBits(8);
6283         setConfigGreenBits(8);
6284         setConfigBlueBits(8);
6285         setConfigAlphaBits(8);
6286         setConfigDepthBits(24);
6287     }
6288 
testSetUp()6289     void testSetUp() override
6290     {
6291         constexpr char kVS[] = R"(precision highp float;
6292 attribute vec4 position;
6293 varying vec2 texcoord;
6294 
6295 void main()
6296 {
6297     gl_Position = position;
6298     texcoord = (position.xy * 0.5) + 0.5;
6299 })";
6300 
6301         constexpr char kFS[] = R"(precision highp float;
6302 uniform sampler2D tex;
6303 varying vec2 texcoord;
6304 
6305 void main()
6306 {
6307     gl_FragColor = texture2D(tex, texcoord);
6308 })";
6309 
6310         mProgram = CompileProgram(kVS, kFS);
6311         ASSERT_NE(0u, mProgram);
6312 
6313         mTextureUniformLocation = glGetUniformLocation(mProgram, "tex");
6314         ASSERT_NE(-1, mTextureUniformLocation);
6315 
6316         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6317         ASSERT_GL_NO_ERROR();
6318     }
6319 
testTearDown()6320     void testTearDown() override
6321     {
6322         if (mProgram != 0)
6323         {
6324             glDeleteProgram(mProgram);
6325         }
6326     }
6327 
6328     template <typename T>
init2DSourceTexture(GLenum internalFormat,GLenum dataFormat,GLenum dataType,const T * data)6329     void init2DSourceTexture(GLenum internalFormat,
6330                              GLenum dataFormat,
6331                              GLenum dataType,
6332                              const T *data)
6333     {
6334         glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6335         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6336 
6337         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6338         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6339 
6340         glBindTexture(GL_TEXTURE_2D, 0);
6341     }
6342 
attachTargetTextureToFramebuffer()6343     void attachTargetTextureToFramebuffer()
6344     {
6345         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6346         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexture,
6347                                0);
6348 
6349         ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6350         ASSERT_GL_NO_ERROR();
6351 
6352         glBindFramebuffer(GL_FRAMEBUFFER, 0);
6353     }
6354 
renderToTargetTexture()6355     void renderToTargetTexture()
6356     {
6357         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6358 
6359         glActiveTexture(GL_TEXTURE0);
6360         glBindTexture(GL_TEXTURE_2D, mSourceTexture);
6361 
6362         glUseProgram(mProgram);
6363         glUniform1i(mTextureUniformLocation, 0);
6364 
6365         drawQuad(mProgram, "position", 0.5f);
6366         ASSERT_GL_NO_ERROR();
6367 
6368         glBindFramebuffer(GL_FRAMEBUFFER, 0);
6369         glBindTexture(GL_TEXTURE_2D, 0);
6370         glUseProgram(0);
6371     }
6372 
renderToDefaultFramebuffer(GLColor * expectedData)6373     void renderToDefaultFramebuffer(GLColor *expectedData)
6374     {
6375         glBindFramebuffer(GL_FRAMEBUFFER, 0);
6376         glUseProgram(mProgram);
6377         glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6378         glUniform1i(mTextureUniformLocation, 0);
6379 
6380         glClear(GL_COLOR_BUFFER_BIT);
6381         drawQuad(mProgram, "position", 0.5f);
6382         ASSERT_GL_NO_ERROR();
6383 
6384         EXPECT_PIXEL_COLOR_EQ(0, 0, *expectedData);
6385 
6386         glBindTexture(GL_TEXTURE_2D, 0);
6387         glUseProgram(0);
6388     }
6389 
6390     GLuint mProgram;
6391     GLint mTextureUniformLocation;
6392 
6393     GLTexture mSourceTexture;
6394     GLTexture mTargetTexture;
6395 
6396     GLFramebuffer mFramebuffer;
6397 };
6398 
6399 // Verify that a swizzle on an active sampler is handled appropriately
TEST_P(ImageRespecificationTest,Swizzle)6400 TEST_P(ImageRespecificationTest, Swizzle)
6401 {
6402     GLubyte data[] = {1, 64, 128, 200};
6403     GLColor expectedData(data[0], data[1], data[2], data[3]);
6404 
6405     // Create the source and target texture
6406     init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6407 
6408     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6409     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
6410 
6411     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6412     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6413 
6414     glBindTexture(GL_TEXTURE_2D, 0);
6415 
6416     // Create a framebuffer and the target texture is attached to the framebuffer.
6417     attachTargetTextureToFramebuffer();
6418 
6419     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6420     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6421     glClear(GL_COLOR_BUFFER_BIT);
6422     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6423 
6424     // Render content of source texture to target texture
6425     // This command triggers the creation of -
6426     //     - draw imageviews of the texture
6427     //     - VkFramebuffer object of the framebuffer
6428     renderToTargetTexture();
6429 
6430     // This swizzle operation should cause the read imageviews of the texture to be released
6431     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6432     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
6433     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
6434     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
6435     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
6436     glBindTexture(GL_TEXTURE_2D, 0);
6437 
6438     // Draw using the newly created read imageviews
6439     renderToDefaultFramebuffer(&expectedData);
6440 
6441     // Render content of source texture to target texture, again
6442     renderToTargetTexture();
6443 
6444     // Make sure the content rendered to target texture is correct
6445     renderToDefaultFramebuffer(&expectedData);
6446 }
6447 
6448 // Verify that when a texture is respecified through glEGLImageTargetTexture2DOES,
6449 // the Framebuffer that has the texture as a color attachment is recreated before next use.
TEST_P(ImageRespecificationTest,ImageTarget2DOESSwitch)6450 TEST_P(ImageRespecificationTest, ImageTarget2DOESSwitch)
6451 {
6452     // This is the specific problem on the Vulkan backend and needs some extensions
6453     ANGLE_SKIP_TEST_IF(
6454         !IsGLExtensionEnabled("GL_OES_EGL_image_external") ||
6455         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
6456 
6457     GLubyte data[] = {1, 64, 128, 200};
6458     GLColor expectedData(data[0], data[1], data[2], data[3]);
6459 
6460     // Create the source texture
6461     init2DSourceTexture(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, data);
6462 
6463     // Create the first EGL image to attach the framebuffer through the texture
6464     GLTexture firstTexture;
6465 
6466     glBindTexture(GL_TEXTURE_2D, firstTexture);
6467     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6468 
6469     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6470     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6471 
6472     glBindTexture(GL_TEXTURE_2D, 0);
6473 
6474     EGLWindow *window = getEGLWindow();
6475     EGLint attribs[]  = {
6476         EGL_IMAGE_PRESERVED,
6477         EGL_TRUE,
6478         EGL_NONE,
6479     };
6480     EGLImageKHR firstEGLImage =
6481         eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6482                           reinterpret_cast<EGLClientBuffer>(firstTexture.get()), attribs);
6483     ASSERT_EGL_SUCCESS();
6484 
6485     // Create the target texture and attach it to the framebuffer
6486     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6487     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6488 
6489     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6490     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6491 
6492     glBindTexture(GL_TEXTURE_2D, 0);
6493 
6494     attachTargetTextureToFramebuffer();
6495 
6496     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6497 
6498     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6499     glClear(GL_COLOR_BUFFER_BIT);
6500 
6501     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6502 
6503     // Render content of source texture to target texture
6504     // This command triggers the creation of -
6505     //     - draw imageviews of the texture
6506     //     - VkFramebuffer object of the framebuffer
6507     renderToTargetTexture();
6508 
6509     // Make sure the content rendered to target texture is correct
6510     renderToDefaultFramebuffer(&expectedData);
6511 
6512     // Create the second EGL image
6513     GLTexture secondTexture;
6514 
6515     glBindTexture(GL_TEXTURE_2D, secondTexture);
6516     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6517 
6518     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6519     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6520 
6521     glBindTexture(GL_TEXTURE_2D, 0);
6522 
6523     EGLImageKHR secondEGLImage =
6524         eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
6525                           reinterpret_cast<EGLClientBuffer>(secondTexture.get()), attribs);
6526     ASSERT_EGL_SUCCESS();
6527 
6528     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6529     // This will release all the imageviews related to the first EGL image
6530     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, secondEGLImage);
6531 
6532     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6533     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6534 
6535     glBindTexture(GL_TEXTURE_2D, 0);
6536 
6537     // Attach the first EGL image to the target texture again
6538     glBindTexture(GL_TEXTURE_2D, mTargetTexture);
6539     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, firstEGLImage);
6540 
6541     // This is for checking this code can deal with the problem even if both ORPHAN and
6542     // COLOR_ATTACHMENT dirty bits are set.
6543     GLTexture tempTexture;
6544 
6545     glBindTexture(GL_TEXTURE_2D, tempTexture);
6546     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
6547 
6548     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6549     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6550 
6551     glBindTexture(GL_TEXTURE_2D, 0);
6552 
6553     // This sets COLOR_ATTACHMENT dirty bit
6554     glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
6555     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tempTexture, 0);
6556     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6557 
6558     // The released imageviews related to "secondEGLImage" will be garbage collected
6559     renderToDefaultFramebuffer(&expectedData);
6560 
6561     // Process both OPPHAN and COLOR_ATTACHMENT dirty bits
6562     renderToTargetTexture();
6563 
6564     // Make sure the content rendered to target texture is correct
6565     renderToDefaultFramebuffer(&expectedData);
6566 
6567     // Render content of source texture to target texture
6568     attachTargetTextureToFramebuffer();
6569     renderToTargetTexture();
6570 
6571     // Make sure the content rendered to target texture is correct
6572     renderToDefaultFramebuffer(&expectedData);
6573 
6574     eglDestroyImageKHR(window->getDisplay(), firstEGLImage);
6575     eglDestroyImageKHR(window->getDisplay(), secondEGLImage);
6576 }
6577 
6578 // Covers a bug where sometimes we wouldn't catch invalid element buffer sizes.
TEST_P(WebGL2ValidationStateChangeTest,DeleteElementArrayBufferValidation)6579 TEST_P(WebGL2ValidationStateChangeTest, DeleteElementArrayBufferValidation)
6580 {
6581     GLushort indexData[] = {0, 1, 2, 3};
6582 
6583     GLBuffer elementArrayBuffer;
6584     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffer);
6585     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_STATIC_DRAW);
6586 
6587     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Zero(), essl1_shaders::fs::Red());
6588     glUseProgram(program);
6589 
6590     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, 0);
6591 
6592     elementArrayBuffer.reset();
6593 
6594     // Must use a non-0 offset and a multiple of the type size.
6595     glDrawElements(GL_POINTS, 4, GL_UNSIGNED_SHORT, reinterpret_cast<const void *>(0x4));
6596     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6597 }
6598 
6599 // Covers a bug in the D3D11 back-end related to how buffers are translated.
TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest,BindZeroSizeBufferThenDeleteBufferBug)6600 TEST_P(RobustBufferAccessWebGL2ValidationStateChangeTest, BindZeroSizeBufferThenDeleteBufferBug)
6601 {
6602     // SwiftShader does not currently support robustness.
6603     ANGLE_SKIP_TEST_IF(isSwiftshader());
6604 
6605     // http://anglebug.com/4872
6606     ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
6607 
6608     // no intent to follow up on this failure.
6609     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
6610 
6611     // no intent to follow up on this failure.
6612     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
6613 
6614     // no intent to follow up on this failure.
6615     ANGLE_SKIP_TEST_IF(IsOSX());
6616 
6617     // Mali does not support robustness now.
6618     ANGLE_SKIP_TEST_IF(IsARM());
6619 
6620     // TODO(anglebug.com/5491)
6621     ANGLE_SKIP_TEST_IF(IsIOS() && IsOpenGLES());
6622 
6623     std::vector<GLubyte> data(48, 1);
6624 
6625     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::Red());
6626     glUseProgram(program);
6627 
6628     // First bind and draw with a buffer with a format we know to be "Direct" in D3D11.
6629     GLBuffer arrayBuffer;
6630     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
6631     glBufferData(GL_ARRAY_BUFFER, 48, data.data(), GL_STATIC_DRAW);
6632     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
6633     glEnableVertexAttribArray(0);
6634     glDrawArrays(GL_TRIANGLES, 0, 3);
6635 
6636     // Then bind a zero size buffer and draw.
6637     GLBuffer secondBuffer;
6638     glBindBuffer(GL_ARRAY_BUFFER, secondBuffer);
6639     glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 1, 0);
6640     glDrawArrays(GL_TRIANGLES, 0, 3);
6641 
6642     // Finally delete the original buffer. This triggers the bug.
6643     arrayBuffer.reset();
6644     glDrawArrays(GL_TRIANGLES, 0, 3);
6645     ASSERT_GL_NO_ERROR();
6646 }
6647 
6648 // Tests DrawElements with an empty buffer using a VAO.
TEST_P(WebGL2ValidationStateChangeTest,DrawElementsEmptyVertexArray)6649 TEST_P(WebGL2ValidationStateChangeTest, DrawElementsEmptyVertexArray)
6650 {
6651     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
6652 
6653     glUseProgram(program);
6654 
6655     // Draw with empty buffer. Out of range but valid.
6656     GLBuffer buffer;
6657     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
6658     glDrawElements(GL_TRIANGLES, 0, GL_UNSIGNED_SHORT, reinterpret_cast<const GLvoid *>(0x1000));
6659 
6660     // Switch VAO. No buffer bound, should be an error.
6661     GLVertexArray vao;
6662     glBindVertexArray(vao);
6663     glDrawElements(GL_LINE_STRIP, 0x1000, GL_UNSIGNED_SHORT,
6664                    reinterpret_cast<const GLvoid *>(0x1000));
6665     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
6666 }
6667 
6668 // Test that closing the render pass due to an update to UBO data then drawing non-indexed followed
6669 // by indexed works.
TEST_P(SimpleStateChangeTestES31,DrawThenUpdateUBOThenDrawThenDrawIndexed)6670 TEST_P(SimpleStateChangeTestES31, DrawThenUpdateUBOThenDrawThenDrawIndexed)
6671 {
6672     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
6673     // bit.
6674     GLBuffer indexBuffer;
6675     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6676 
6677     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6678     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6679 
6680     // Setup vertices.
6681     const std::array<GLfloat, 6> kVertices = {
6682         -1, -1, 3, -1, -1, 3,
6683     };
6684     GLBuffer vertexBuffer;
6685     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6686     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6687     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6688     glEnableVertexAttribArray(0);
6689 
6690     // Create a uniform buffer that will get modified.  This is used to break the render pass.
6691     const std::array<GLuint, 4> kUboData1 = {0x12345678u, 0, 0, 0};
6692 
6693     GLBuffer ubo;
6694     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
6695     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
6696     glBufferData(GL_UNIFORM_BUFFER, sizeof(kUboData1), kUboData1.data(), GL_DYNAMIC_DRAW);
6697 
6698     // Set up a program.  The same program is used for all draw calls to avoid state change due to
6699     // program change.
6700     constexpr char kFS[] = R"(#version 300 es
6701 precision mediump float;
6702 uniform block { uint data; } ubo;
6703 uniform uint expect;
6704 uniform vec4 successColor;
6705 out vec4 colorOut;
6706 void main()
6707 {
6708     colorOut = ubo.data == expect ? successColor : colorOut = vec4(0, 0, 0, 0);
6709 })";
6710 
6711     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6712     glUseProgram(program);
6713 
6714     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6715     const GLint expectLoc   = glGetUniformLocation(program, "expect");
6716     const GLint successLoc  = glGetUniformLocation(program, "successColor");
6717     ASSERT_NE(-1, positionLoc);
6718     ASSERT_NE(-1, expectLoc);
6719     ASSERT_NE(-1, successLoc);
6720 
6721     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6722     glEnableVertexAttribArray(positionLoc);
6723 
6724     glUniform1ui(expectLoc, kUboData1[0]);
6725     glUniform4f(successLoc, 0, 0, 0, 1);
6726     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6727     EXPECT_GL_NO_ERROR();
6728 
6729     // Then upload data to the UBO so on next use the render pass has to break.  This draw call is
6730     // not indexed.
6731     constexpr GLuint kUboData2 = 0x87654321u;
6732     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kUboData2), &kUboData2);
6733 
6734     glEnable(GL_BLEND);
6735     glBlendFunc(GL_ONE, GL_ONE);
6736     glUniform1ui(expectLoc, kUboData2);
6737     glUniform4f(successLoc, 0, 1, 0, 0);
6738     glDrawArrays(GL_TRIANGLES, 0, 3);
6739 
6740     // Issue another draw call that is indexed.  The index buffer should be bound correctly on the
6741     // new render pass.
6742     glUniform4f(successLoc, 0, 0, 1, 0);
6743     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6744     EXPECT_GL_NO_ERROR();
6745 
6746     // Ensure correct rendering.
6747     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6748 }
6749 
6750 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenDrawIndexed)6751 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenDrawIndexed)
6752 {
6753     // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6754     glClearColor(0, 0, 0, 1);
6755     glClear(GL_COLOR_BUFFER_BIT);
6756     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6757 
6758     GLFramebuffer fbo;
6759     GLTexture texture;
6760 
6761     glBindTexture(GL_TEXTURE_2D, texture);
6762     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6763     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6764     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6765 
6766     glClear(GL_COLOR_BUFFER_BIT);
6767     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6768 
6769     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6770 
6771     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
6772     // bit.
6773     GLBuffer indexBuffer;
6774     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6775 
6776     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6777     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6778 
6779     // Setup vertices.
6780     const std::array<GLfloat, 6> kVertices = {
6781         -1, -1, 3, -1, -1, 3,
6782     };
6783     GLBuffer vertexBuffer;
6784     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6785     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6786     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6787     glEnableVertexAttribArray(0);
6788 
6789     // Set up a program.  The same program is used for all draw calls to avoid state change due to
6790     // program change.
6791     constexpr char kFS[] = R"(#version 300 es
6792 precision mediump float;
6793 uniform vec4 colorIn;
6794 out vec4 colorOut;
6795 void main()
6796 {
6797     colorOut = colorIn;
6798 })";
6799 
6800     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6801     glUseProgram(program);
6802 
6803     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6804     const GLint colorLoc    = glGetUniformLocation(program, "colorIn");
6805     ASSERT_NE(-1, positionLoc);
6806     ASSERT_NE(-1, colorLoc);
6807 
6808     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6809     glEnableVertexAttribArray(positionLoc);
6810 
6811     glUniform4f(colorLoc, 1, 0, 0, 1);
6812     glEnable(GL_BLEND);
6813     glBlendFunc(GL_ONE, GL_ONE);
6814     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6815     EXPECT_GL_NO_ERROR();
6816 
6817     // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6818     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6819     glUniform4f(colorLoc, 0, 1, 0, 0);
6820     glDrawArrays(GL_TRIANGLES, 0, 3);
6821 
6822     glUniform4f(colorLoc, 0, 0, 1, 0);
6823     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6824     EXPECT_GL_NO_ERROR();
6825 
6826     // Ensure correct rendering.
6827     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6828 
6829     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6830     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6831 }
6832 
6833 // Test that switching framebuffers then a non-indexed draw followed by an indexed one works, with
6834 // another context flushing work in between the two draw calls.
TEST_P(SimpleStateChangeTestES31,DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)6835 TEST_P(SimpleStateChangeTestES31, DrawThenChangeFBOThenDrawThenFlushInAnotherThreadThenDrawIndexed)
6836 {
6837     // Create a framebuffer, and make sure it and the default framebuffer are fully synced.
6838     glClearColor(0, 0, 0, 1);
6839     glClear(GL_COLOR_BUFFER_BIT);
6840     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6841 
6842     GLFramebuffer fbo;
6843     GLTexture texture;
6844 
6845     glBindTexture(GL_TEXTURE_2D, texture);
6846     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6847     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 16, 16);
6848     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
6849 
6850     glClear(GL_COLOR_BUFFER_BIT);
6851     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
6852 
6853     glBindFramebuffer(GL_FRAMEBUFFER, 0);
6854 
6855     // First, create the index buffer and issue an indexed draw call.  This clears the index dirty
6856     // bit.
6857     GLBuffer indexBuffer;
6858     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
6859 
6860     const std::array<GLuint, 4> kIndexData = {0, 1, 2, 0};
6861     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexData), kIndexData.data(), GL_STATIC_DRAW);
6862 
6863     // Setup vertices.
6864     const std::array<GLfloat, 6> kVertices = {
6865         -1, -1, 3, -1, -1, 3,
6866     };
6867     GLBuffer vertexBuffer;
6868     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
6869     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices.data(), GL_STATIC_DRAW);
6870     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6871     glEnableVertexAttribArray(0);
6872 
6873     // Set up a program.  The same program is used for all draw calls to avoid state change due to
6874     // program change.
6875     constexpr char kFS[] = R"(#version 300 es
6876 precision mediump float;
6877 uniform vec4 colorIn;
6878 out vec4 colorOut;
6879 void main()
6880 {
6881     colorOut = colorIn;
6882 })";
6883 
6884     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
6885     glUseProgram(program);
6886 
6887     const GLint positionLoc = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
6888     const GLint colorLoc    = glGetUniformLocation(program, "colorIn");
6889     ASSERT_NE(-1, positionLoc);
6890     ASSERT_NE(-1, colorLoc);
6891 
6892     glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
6893     glEnableVertexAttribArray(positionLoc);
6894 
6895     glUniform4f(colorLoc, 0, 0, 0, 1);
6896     glEnable(GL_BLEND);
6897     glBlendFunc(GL_ONE, GL_ONE);
6898     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6899     EXPECT_GL_NO_ERROR();
6900 
6901     // Then switch to fbo and issue a non-indexed draw call followed by an indexed one.
6902     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6903     glUniform4f(colorLoc, 0, 1, 0, 0);
6904     glDrawArrays(GL_TRIANGLES, 0, 3);
6905 
6906     // In between the two calls, make sure the first render pass is submitted, so the primary
6907     // command buffer is reset.
6908     {
6909         EGLWindow *window          = getEGLWindow();
6910         EGLDisplay dpy             = window->getDisplay();
6911         EGLConfig config           = window->getConfig();
6912         EGLint pbufferAttributes[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
6913         EGLSurface surface         = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
6914         EGLContext ctx             = window->createContext(EGL_NO_CONTEXT);
6915         EXPECT_EGL_SUCCESS();
6916         std::thread flushThread = std::thread([&]() {
6917             EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, ctx));
6918             EXPECT_EGL_SUCCESS();
6919 
6920             glClearColor(1, 0, 0, 1);
6921             glClear(GL_COLOR_BUFFER_BIT);
6922             EXPECT_GL_NO_ERROR();
6923 
6924             EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
6925         });
6926         flushThread.join();
6927 
6928         eglDestroySurface(dpy, surface);
6929         eglDestroyContext(dpy, ctx);
6930     }
6931 
6932     glUniform4f(colorLoc, 0, 0, 1, 0);
6933     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
6934     EXPECT_GL_NO_ERROR();
6935 
6936     // Ensure correct rendering.
6937     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
6938 }
6939 }  // anonymous namespace
6940 
6941 ANGLE_INSTANTIATE_TEST_ES2(StateChangeTest);
6942 ANGLE_INSTANTIATE_TEST_ES2(LineLoopStateChangeTest);
6943 ANGLE_INSTANTIATE_TEST_ES2(StateChangeRenderTest);
6944 
6945 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeTestES3);
6946 ANGLE_INSTANTIATE_TEST_ES3(StateChangeTestES3);
6947 
6948 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StateChangeRenderTestES3);
6949 ANGLE_INSTANTIATE_TEST_ES3(StateChangeRenderTestES3);
6950 
6951 ANGLE_INSTANTIATE_TEST_ES2(SimpleStateChangeTest);
6952 
6953 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES3);
6954 ANGLE_INSTANTIATE_TEST_ES3(SimpleStateChangeTestES3);
6955 
6956 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageRespecificationTest);
6957 ANGLE_INSTANTIATE_TEST_ES3(ImageRespecificationTest);
6958 
6959 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestES31);
6960 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestES31);
6961 
6962 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31);
6963 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31);
6964 
6965 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SimpleStateChangeTestComputeES31PPO);
6966 ANGLE_INSTANTIATE_TEST_ES31(SimpleStateChangeTestComputeES31PPO);
6967 
6968 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTest);
6969 ANGLE_INSTANTIATE_TEST_ES3(ValidationStateChangeTest);
6970 
6971 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ValidationStateChangeTest);
6972 ANGLE_INSTANTIATE_TEST_ES3(WebGL2ValidationStateChangeTest);
6973 
6974 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RobustBufferAccessWebGL2ValidationStateChangeTest);
6975 ANGLE_INSTANTIATE_TEST_ES3(RobustBufferAccessWebGL2ValidationStateChangeTest);
6976 
6977 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ValidationStateChangeTestES31);
6978 ANGLE_INSTANTIATE_TEST_ES31(ValidationStateChangeTestES31);
6979 
6980 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGLComputeValidationStateChangeTest);
6981 ANGLE_INSTANTIATE_TEST_ES31(WebGLComputeValidationStateChangeTest);
6982