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