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