• 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 // SimpleOperationTest:
7 //   Basic GL commands such as linking a program, initializing a buffer, etc.
8 
9 #include "test_utils/ANGLETest.h"
10 
11 #include <vector>
12 
13 #include "test_utils/gl_raii.h"
14 #include "util/EGLWindow.h"
15 #include "util/random_utils.h"
16 
17 using namespace angle;
18 
19 namespace
20 {
21 constexpr char kBasicVertexShader[] =
22     R"(attribute vec3 position;
23 void main()
24 {
25     gl_Position = vec4(position, 1);
26 })";
27 
28 constexpr char kGreenFragmentShader[] =
29     R"(void main()
30 {
31     gl_FragColor = vec4(0, 1, 0, 1);
32 })";
33 
34 class SimpleOperationTest : public ANGLETest
35 {
36   protected:
SimpleOperationTest()37     SimpleOperationTest()
38     {
39         setWindowWidth(128);
40         setWindowHeight(128);
41         setConfigRedBits(8);
42         setConfigGreenBits(8);
43         setConfigBlueBits(8);
44         setConfigAlphaBits(8);
45     }
46 
47     void verifyBuffer(const std::vector<uint8_t> &data, GLenum binding);
48 
49     template <typename T>
50     void testDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,
51                                                        int windowWidth,
52                                                        int windowHeight);
53 };
54 
verifyBuffer(const std::vector<uint8_t> & data,GLenum binding)55 void SimpleOperationTest::verifyBuffer(const std::vector<uint8_t> &data, GLenum binding)
56 {
57     if (!IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
58     {
59         return;
60     }
61 
62     uint8_t *mapPointer =
63         static_cast<uint8_t *>(glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 1024, GL_MAP_READ_BIT));
64     ASSERT_GL_NO_ERROR();
65 
66     std::vector<uint8_t> readbackData(data.size());
67     memcpy(readbackData.data(), mapPointer, data.size());
68     glUnmapBufferOES(GL_ARRAY_BUFFER);
69 
70     EXPECT_EQ(data, readbackData);
71 }
72 
73 // Validates if culling rasterization states work. Simply draws a quad with
74 // cull face enabled and make sure we still render correctly.
TEST_P(SimpleOperationTest,CullFaceEnabledState)75 TEST_P(SimpleOperationTest, CullFaceEnabledState)
76 {
77     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
78     glUseProgram(program);
79 
80     glClear(GL_COLOR_BUFFER_BIT);
81     glEnable(GL_CULL_FACE);
82 
83     drawQuad(program.get(), "position", 0.0f, 1.0f, true);
84 
85     ASSERT_GL_NO_ERROR();
86 
87     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
88 }
89 
90 // Validates if culling rasterization states work. Simply draws a quad with
91 // cull face enabled with cullface front and make sure the face have not been rendered.
TEST_P(SimpleOperationTest,CullFaceFrontEnabledState)92 TEST_P(SimpleOperationTest, CullFaceFrontEnabledState)
93 {
94     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
95     glUseProgram(program);
96 
97     glClear(GL_COLOR_BUFFER_BIT);
98     glEnable(GL_CULL_FACE);
99 
100     // Should make the quad disappear since we draw it front facing.
101     glCullFace(GL_FRONT);
102 
103     drawQuad(program.get(), "position", 0.0f, 1.0f, true);
104 
105     ASSERT_GL_NO_ERROR();
106 
107     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
108 }
109 
110 // Validates if blending render states work. Simply draws twice and verify the color have been
111 // added in the final output.
TEST_P(SimpleOperationTest,BlendingRenderState)112 TEST_P(SimpleOperationTest, BlendingRenderState)
113 {
114     // The precision when blending isn't perfect and some tests fail with a color of 254 instead
115     // of 255 on the green component. This is why we need 0.51 green instead of .5
116     constexpr char halfGreenFragmentShader[] =
117         R"(void main()
118 {
119     gl_FragColor = vec4(0, 0.51, 0, 1);
120 })";
121 
122     ANGLE_GL_PROGRAM(program, kBasicVertexShader, halfGreenFragmentShader);
123     glUseProgram(program);
124 
125     glClear(GL_COLOR_BUFFER_BIT);
126     glEnable(GL_BLEND);
127     glBlendFunc(GL_ONE, GL_ONE);
128     glBlendEquation(GL_FUNC_ADD);
129 
130     auto vertices = GetQuadVertices();
131 
132     const GLint positionLocation = glGetAttribLocation(program, "position");
133     ASSERT_NE(-1, positionLocation);
134 
135     GLBuffer vertexBuffer;
136     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
137     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
138                  GL_STATIC_DRAW);
139     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
140 
141     glEnableVertexAttribArray(positionLocation);
142 
143     // Drawing a quad once will give 0.51 green, but if we enable blending
144     // with additive function we should end up with full green of 1.0 with
145     // a clamping func of 1.0.
146     glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vertices.size()));
147     glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(vertices.size()));
148 
149     ASSERT_GL_NO_ERROR();
150 
151     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
152 }
153 
TEST_P(SimpleOperationTest,CompileVertexShader)154 TEST_P(SimpleOperationTest, CompileVertexShader)
155 {
156     GLuint shader = CompileShader(GL_VERTEX_SHADER, kBasicVertexShader);
157     EXPECT_NE(shader, 0u);
158     glDeleteShader(shader);
159 
160     ASSERT_GL_NO_ERROR();
161 }
162 
TEST_P(SimpleOperationTest,CompileFragmentShaderSingleVaryingInput)163 TEST_P(SimpleOperationTest, CompileFragmentShaderSingleVaryingInput)
164 {
165     constexpr char kFS[] = R"(precision mediump float;
166 varying vec4 v_input;
167 void main()
168 {
169     gl_FragColor = v_input;
170 })";
171 
172     GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
173     EXPECT_NE(shader, 0u);
174     glDeleteShader(shader);
175 
176     ASSERT_GL_NO_ERROR();
177 }
178 
179 // Covers a simple bug in Vulkan to do with dependencies between the Surface and the default
180 // Framebuffer.
TEST_P(SimpleOperationTest,ClearAndSwap)181 TEST_P(SimpleOperationTest, ClearAndSwap)
182 {
183     glClearColor(1.0, 0.0, 0.0, 1.0);
184     glClear(GL_COLOR_BUFFER_BIT);
185     swapBuffers();
186 
187     // Can't check the pixel result after the swap, and checking the pixel result affects the
188     // behaviour of the test on the Vulkan back-end, so don't bother checking correctness.
189     ASSERT_GL_NO_ERROR();
190     ASSERT_FALSE(getGLWindow()->hasError());
191 }
192 
193 // Simple case of setting a scissor, enabled or disabled.
TEST_P(SimpleOperationTest,ScissorTest)194 TEST_P(SimpleOperationTest, ScissorTest)
195 {
196     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
197 
198     glClear(GL_COLOR_BUFFER_BIT);
199     glEnable(GL_SCISSOR_TEST);
200     glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
201               getWindowHeight() / 2);
202 
203     // Fill the whole screen with a quad.
204     drawQuad(program.get(), "position", 0.0f, 1.0f, true);
205 
206     ASSERT_GL_NO_ERROR();
207 
208     // Test outside the scissor test, pitch black.
209     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
210 
211     // Test inside, green of the fragment shader.
212     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
213 }
214 
TEST_P(SimpleOperationTest,LinkProgramShadersNoInputs)215 TEST_P(SimpleOperationTest, LinkProgramShadersNoInputs)
216 {
217     constexpr char kVS[] = "void main() { gl_Position = vec4(1.0, 1.0, 1.0, 1.0); }";
218     constexpr char kFS[] = "void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }";
219 
220     ANGLE_GL_PROGRAM(program, kVS, kFS);
221     ASSERT_GL_NO_ERROR();
222 }
223 
TEST_P(SimpleOperationTest,LinkProgramWithUniforms)224 TEST_P(SimpleOperationTest, LinkProgramWithUniforms)
225 {
226     constexpr char kVS[] = R"(void main()
227 {
228     gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
229 })";
230     constexpr char kFS[] = R"(precision mediump float;
231 uniform vec4 u_input;
232 void main()
233 {
234     gl_FragColor = u_input;
235 })";
236 
237     ANGLE_GL_PROGRAM(program, kVS, kFS);
238 
239     const GLint uniformLoc = glGetUniformLocation(program, "u_input");
240     EXPECT_NE(-1, uniformLoc);
241 
242     ASSERT_GL_NO_ERROR();
243 }
244 
TEST_P(SimpleOperationTest,LinkProgramWithAttributes)245 TEST_P(SimpleOperationTest, LinkProgramWithAttributes)
246 {
247     constexpr char kVS[] = R"(attribute vec4 a_input;
248 void main()
249 {
250     gl_Position = a_input;
251 })";
252 
253     ANGLE_GL_PROGRAM(program, kVS, kGreenFragmentShader);
254 
255     const GLint attribLoc = glGetAttribLocation(program, "a_input");
256     EXPECT_NE(-1, attribLoc);
257 
258     ASSERT_GL_NO_ERROR();
259 }
260 
TEST_P(SimpleOperationTest,BufferDataWithData)261 TEST_P(SimpleOperationTest, BufferDataWithData)
262 {
263     GLBuffer buffer;
264     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
265 
266     std::vector<uint8_t> data(1024);
267     FillVectorWithRandomUBytes(&data);
268     glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW);
269 
270     verifyBuffer(data, GL_ARRAY_BUFFER);
271 
272     ASSERT_GL_NO_ERROR();
273 }
274 
TEST_P(SimpleOperationTest,BufferDataWithNoData)275 TEST_P(SimpleOperationTest, BufferDataWithNoData)
276 {
277     GLBuffer buffer;
278     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
279     glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
280 
281     ASSERT_GL_NO_ERROR();
282 }
283 
TEST_P(SimpleOperationTest,BufferSubData)284 TEST_P(SimpleOperationTest, BufferSubData)
285 {
286     GLBuffer buffer;
287     glBindBuffer(GL_ARRAY_BUFFER, buffer.get());
288 
289     constexpr size_t bufferSize = 1024;
290     std::vector<uint8_t> data(bufferSize);
291     FillVectorWithRandomUBytes(&data);
292 
293     glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
294 
295     constexpr size_t subDataCount = 16;
296     constexpr size_t sliceSize    = bufferSize / subDataCount;
297     for (size_t i = 0; i < subDataCount; i++)
298     {
299         size_t offset = i * sliceSize;
300         glBufferSubData(GL_ARRAY_BUFFER, offset, sliceSize, &data[offset]);
301     }
302 
303     verifyBuffer(data, GL_ARRAY_BUFFER);
304 
305     ASSERT_GL_NO_ERROR();
306 }
307 
308 // Simple quad test.
TEST_P(SimpleOperationTest,DrawQuad)309 TEST_P(SimpleOperationTest, DrawQuad)
310 {
311     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
312 
313     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
314 
315     ASSERT_GL_NO_ERROR();
316 
317     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
318 }
319 
320 // Simple quad test with data in client memory, not vertex buffer.
TEST_P(SimpleOperationTest,DrawQuadFromClientMemory)321 TEST_P(SimpleOperationTest, DrawQuadFromClientMemory)
322 {
323     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
324 
325     drawQuad(program.get(), "position", 0.5f, 1.0f, false);
326 
327     ASSERT_GL_NO_ERROR();
328 
329     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
330 }
331 
332 // Simple double quad test.
TEST_P(SimpleOperationTest,DrawQuadTwice)333 TEST_P(SimpleOperationTest, DrawQuadTwice)
334 {
335     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
336 
337     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
338     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
339 
340     ASSERT_GL_NO_ERROR();
341 
342     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
343 }
344 
345 // Simple line test.
TEST_P(SimpleOperationTest,DrawLine)346 TEST_P(SimpleOperationTest, DrawLine)
347 {
348     // We assume in the test the width and height are equal and we are tracing
349     // the line from bottom left to top right. Verify that all pixels along that line
350     // have been traced with green.
351     ASSERT_EQ(getWindowWidth(), getWindowHeight());
352 
353     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
354     glUseProgram(program);
355 
356     std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}};
357 
358     const GLint positionLocation = glGetAttribLocation(program, "position");
359     ASSERT_NE(-1, positionLocation);
360 
361     GLBuffer vertexBuffer;
362     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
363     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
364                  GL_STATIC_DRAW);
365     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
366     glEnableVertexAttribArray(positionLocation);
367 
368     glClear(GL_COLOR_BUFFER_BIT);
369     glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertices.size()));
370 
371     glDisableVertexAttribArray(positionLocation);
372 
373     ASSERT_GL_NO_ERROR();
374 
375     for (int x = 0; x < getWindowWidth(); x++)
376     {
377         EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
378     }
379 }
380 
381 // Simple line test that will use a very large offset in the vertex attributes.
TEST_P(SimpleOperationTest,DrawLineWithLargeAttribPointerOffset)382 TEST_P(SimpleOperationTest, DrawLineWithLargeAttribPointerOffset)
383 {
384     // We assume in the test the width and height are equal and we are tracing
385     // the line from bottom left to top right. Verify that all pixels along that line
386     // have been traced with green.
387     ASSERT_EQ(getWindowWidth(), getWindowHeight());
388 
389     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
390     glUseProgram(program);
391 
392     int kOffset = 3315;
393     std::vector<Vector3> vertices(kOffset);
394     Vector3 vector1{-1.0f, -1.0f, 0.0f};
395     Vector3 vector2{1.0f, 1.0f, 0.0f};
396     vertices.emplace_back(vector1);
397     vertices.emplace_back(vector2);
398 
399     const GLint positionLocation = glGetAttribLocation(program, "position");
400     ASSERT_NE(-1, positionLocation);
401 
402     GLBuffer vertexBuffer;
403     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
404     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
405                  GL_STATIC_DRAW);
406     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0,
407                           reinterpret_cast<const void *>(kOffset * sizeof(vertices[0])));
408     glEnableVertexAttribArray(positionLocation);
409 
410     glClear(GL_COLOR_BUFFER_BIT);
411     glDrawArrays(GL_LINES, 0, 2);
412 
413     glDisableVertexAttribArray(positionLocation);
414 
415     ASSERT_GL_NO_ERROR();
416 
417     for (auto x = 0; x < getWindowWidth(); x++)
418     {
419         EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
420     }
421 }
422 
423 // Simple line strip test.
TEST_P(SimpleOperationTest,DrawLineStrip)424 TEST_P(SimpleOperationTest, DrawLineStrip)
425 {
426     // We assume in the test the width and height are equal and we are tracing
427     // the line from bottom left to center, then from center to bottom right.
428     // Verify that all pixels along these lines have been traced with green.
429     ASSERT_EQ(getWindowWidth(), getWindowHeight());
430 
431     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
432     glUseProgram(program);
433 
434     auto vertices =
435         std::vector<Vector3>{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
436 
437     const GLint positionLocation = glGetAttribLocation(program, "position");
438     ASSERT_NE(-1, positionLocation);
439 
440     GLBuffer vertexBuffer;
441     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
442     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
443                  GL_STATIC_DRAW);
444     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
445 
446     glEnableVertexAttribArray(positionLocation);
447 
448     glClear(GL_COLOR_BUFFER_BIT);
449     glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(vertices.size()));
450 
451     ASSERT_GL_NO_ERROR();
452 
453     const auto centerX = getWindowWidth() / 2;
454     const auto centerY = getWindowHeight() / 2;
455 
456     for (auto x = 0; x < centerX; x++)
457     {
458         EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
459     }
460 
461     for (auto x = centerX, y = centerY - 1; x < getWindowWidth() && y >= 0; x++, y--)
462     {
463         EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
464     }
465 }
466 
467 // Simple triangle fans test.
TEST_P(SimpleOperationTest,DrawTriangleFan)468 TEST_P(SimpleOperationTest, DrawTriangleFan)
469 {
470     // We assume in the test the width and height are equal and we are tracing
471     // 2 triangles to cover half the surface like this:
472     ASSERT_EQ(getWindowWidth(), getWindowHeight());
473 
474     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
475     glUseProgram(program);
476 
477     auto vertices = std::vector<Vector3>{
478         {-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}};
479 
480     const GLint positionLocation = glGetAttribLocation(program, "position");
481     ASSERT_NE(-1, positionLocation);
482 
483     GLBuffer vertexBuffer;
484     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer.get());
485     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
486                  GL_STATIC_DRAW);
487     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
488     glEnableVertexAttribArray(positionLocation);
489 
490     glClear(GL_COLOR_BUFFER_BIT);
491     glDrawArrays(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(vertices.size()));
492 
493     glDisableVertexAttribArray(positionLocation);
494 
495     EXPECT_GL_NO_ERROR();
496 
497     // Check 4 lines accross de triangles to make sure we filled it.
498     // Don't check every pixel as it would slow down our tests.
499     for (auto x = 0; x < getWindowWidth(); x++)
500     {
501         EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
502     }
503 
504     for (auto x = getWindowWidth() / 3, y = 0; x < getWindowWidth(); x++, y++)
505     {
506         EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
507     }
508 
509     for (auto x = getWindowWidth() / 2, y = 0; x < getWindowWidth(); x++, y++)
510     {
511         EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
512     }
513 
514     for (auto x = (getWindowWidth() / 4) * 3, y = 0; x < getWindowWidth(); x++, y++)
515     {
516         EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
517     }
518 }
519 
520 // Simple repeated draw and swap test.
TEST_P(SimpleOperationTest,DrawQuadAndSwap)521 TEST_P(SimpleOperationTest, DrawQuadAndSwap)
522 {
523     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
524 
525     for (int i = 0; i < 8; ++i)
526     {
527         drawQuad(program.get(), "position", 0.5f, 1.0f, true);
528         ASSERT_GL_NO_ERROR();
529         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
530         swapBuffers();
531     }
532 
533     ASSERT_GL_NO_ERROR();
534 }
535 
536 // Simple indexed quad test.
TEST_P(SimpleOperationTest,DrawIndexedQuad)537 TEST_P(SimpleOperationTest, DrawIndexedQuad)
538 {
539     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
540 
541     drawIndexedQuad(program.get(), "position", 0.5f, 1.0f, true);
542 
543     ASSERT_GL_NO_ERROR();
544     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
545 }
546 
547 // Simple repeated indexed draw and swap test.
TEST_P(SimpleOperationTest,DrawIndexedQuadAndSwap)548 TEST_P(SimpleOperationTest, DrawIndexedQuadAndSwap)
549 {
550     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
551 
552     // 32 iterations is an arbitrary number. The more iterations, the more flaky syncronization
553     // issues will reproduce consistently.
554     for (int i = 0; i < 32; ++i)
555     {
556         drawIndexedQuad(program.get(), "position", 0.5f, 1.0f, true);
557         ASSERT_GL_NO_ERROR();
558         EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
559         swapBuffers();
560     }
561 
562     ASSERT_GL_NO_ERROR();
563 }
564 
565 // Draw with a fragment uniform.
TEST_P(SimpleOperationTest,DrawQuadWithFragmentUniform)566 TEST_P(SimpleOperationTest, DrawQuadWithFragmentUniform)
567 {
568     constexpr char kFS[] =
569         "uniform mediump vec4 color;\n"
570         "void main()\n"
571         "{\n"
572         "    gl_FragColor = color;\n"
573         "}";
574     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFS);
575 
576     GLint location = glGetUniformLocation(program, "color");
577     ASSERT_NE(-1, location);
578 
579     glUseProgram(program);
580     glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);
581 
582     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
583 
584     ASSERT_GL_NO_ERROR();
585     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
586 }
587 
588 // Draw with a vertex uniform.
TEST_P(SimpleOperationTest,DrawQuadWithVertexUniform)589 TEST_P(SimpleOperationTest, DrawQuadWithVertexUniform)
590 {
591     constexpr char kVS[] =
592         "attribute vec3 position;\n"
593         "uniform vec4 color;\n"
594         "varying vec4 vcolor;\n"
595         "void main()\n"
596         "{\n"
597         "    gl_Position = vec4(position, 1);\n"
598         "    vcolor = color;\n"
599         "}";
600     constexpr char kFS[] =
601         "varying mediump vec4 vcolor;\n"
602         "void main()\n"
603         "{\n"
604         "    gl_FragColor = vcolor;\n"
605         "}";
606     ANGLE_GL_PROGRAM(program, kVS, kFS);
607 
608     const GLint location = glGetUniformLocation(program, "color");
609     ASSERT_NE(-1, location);
610 
611     glUseProgram(program);
612     glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);
613 
614     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
615 
616     ASSERT_GL_NO_ERROR();
617     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
618 }
619 
620 // Draw with two uniforms.
TEST_P(SimpleOperationTest,DrawQuadWithTwoUniforms)621 TEST_P(SimpleOperationTest, DrawQuadWithTwoUniforms)
622 {
623     constexpr char kVS[] =
624         "attribute vec3 position;\n"
625         "uniform vec4 color1;\n"
626         "varying vec4 vcolor1;\n"
627         "void main()\n"
628         "{\n"
629         "    gl_Position = vec4(position, 1);\n"
630         "    vcolor1 = color1;\n"
631         "}";
632     constexpr char kFS[] =
633         "uniform mediump vec4 color2;\n"
634         "varying mediump vec4 vcolor1;\n"
635         "void main()\n"
636         "{\n"
637         "    gl_FragColor = vcolor1 + color2;\n"
638         "}";
639     ANGLE_GL_PROGRAM(program, kVS, kFS);
640 
641     const GLint location1 = glGetUniformLocation(program, "color1");
642     ASSERT_NE(-1, location1);
643 
644     const GLint location2 = glGetUniformLocation(program, "color2");
645     ASSERT_NE(-1, location2);
646 
647     glUseProgram(program);
648     glUniform4f(location1, 0.0f, 1.0f, 0.0f, 1.0f);
649     glUniform4f(location2, 1.0f, 0.0f, 0.0f, 1.0f);
650 
651     drawQuad(program.get(), "position", 0.5f, 1.0f, true);
652 
653     ASSERT_GL_NO_ERROR();
654     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
655 }
656 
657 // Tests a shader program with more than one vertex attribute, with vertex buffers.
TEST_P(SimpleOperationTest,ThreeVertexAttributes)658 TEST_P(SimpleOperationTest, ThreeVertexAttributes)
659 {
660     constexpr char kVS[] = R"(attribute vec2 position;
661 attribute vec4 color1;
662 attribute vec4 color2;
663 varying vec4 color;
664 void main()
665 {
666     gl_Position = vec4(position, 0, 1);
667     color = color1 + color2;
668 })";
669 
670     constexpr char kFS[] = R"(precision mediump float;
671 varying vec4 color;
672 void main()
673 {
674     gl_FragColor = color;
675 }
676 )";
677 
678     ANGLE_GL_PROGRAM(program, kVS, kFS);
679 
680     glUseProgram(program);
681 
682     const GLint color1Loc = glGetAttribLocation(program, "color1");
683     const GLint color2Loc = glGetAttribLocation(program, "color2");
684     ASSERT_NE(-1, color1Loc);
685     ASSERT_NE(-1, color2Loc);
686 
687     const auto &indices = GetQuadIndices();
688 
689     // Make colored corners with red == x or 1 -x , and green = y or 1 - y.
690 
691     std::array<GLColor, 4> baseColors1 = {
692         {GLColor::black, GLColor::red, GLColor::green, GLColor::yellow}};
693     std::array<GLColor, 4> baseColors2 = {
694         {GLColor::yellow, GLColor::green, GLColor::red, GLColor::black}};
695 
696     std::vector<GLColor> colors1;
697     std::vector<GLColor> colors2;
698 
699     for (GLushort index : indices)
700     {
701         colors1.push_back(baseColors1[index]);
702         colors2.push_back(baseColors2[index]);
703     }
704 
705     GLBuffer color1Buffer;
706     glBindBuffer(GL_ARRAY_BUFFER, color1Buffer);
707     glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLColor), colors1.data(), GL_STATIC_DRAW);
708     glVertexAttribPointer(color1Loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
709     glEnableVertexAttribArray(color1Loc);
710 
711     GLBuffer color2Buffer;
712     glBindBuffer(GL_ARRAY_BUFFER, color2Buffer);
713     glBufferData(GL_ARRAY_BUFFER, colors2.size() * sizeof(GLColor), colors2.data(), GL_STATIC_DRAW);
714     glVertexAttribPointer(color2Loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
715     glEnableVertexAttribArray(color2Loc);
716 
717     // Draw a non-indexed quad with all vertex buffers. Should draw yellow to the entire window.
718     drawQuad(program, "position", 0.5f, 1.0f, true);
719     ASSERT_GL_NO_ERROR();
720     EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
721 }
722 
723 // Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest,CreateTexture2DNoData)724 TEST_P(SimpleOperationTest, CreateTexture2DNoData)
725 {
726     GLTexture texture;
727     glBindTexture(GL_TEXTURE_2D, texture);
728     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
729     ASSERT_GL_NO_ERROR();
730 }
731 
732 // Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest,CreateTexture2DWithData)733 TEST_P(SimpleOperationTest, CreateTexture2DWithData)
734 {
735     std::vector<GLColor> colors(16 * 16, GLColor::red);
736 
737     GLTexture texture;
738     glBindTexture(GL_TEXTURE_2D, texture);
739     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
740     ASSERT_GL_NO_ERROR();
741 }
742 
743 // Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest,CreateTextureCubeNoData)744 TEST_P(SimpleOperationTest, CreateTextureCubeNoData)
745 {
746     GLTexture texture;
747     glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
748     for (GLenum cubeFace : kCubeFaces)
749     {
750         glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
751     }
752     ASSERT_GL_NO_ERROR();
753 }
754 
755 // Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest,CreateTextureCubeWithData)756 TEST_P(SimpleOperationTest, CreateTextureCubeWithData)
757 {
758     std::vector<GLColor> colors(16 * 16, GLColor::red);
759 
760     GLTexture texture;
761     glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
762     for (GLenum cubeFace : kCubeFaces)
763     {
764         glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
765     }
766     ASSERT_GL_NO_ERROR();
767 }
768 
769 // Creates a program with a texture.
TEST_P(SimpleOperationTest,LinkProgramWithTexture)770 TEST_P(SimpleOperationTest, LinkProgramWithTexture)
771 {
772     ASSERT_NE(0u, get2DTexturedQuadProgram());
773     ASSERT_GL_NO_ERROR();
774 }
775 
776 // Creates a program with a 2D texture and renders with it.
TEST_P(SimpleOperationTest,DrawWith2DTexture)777 TEST_P(SimpleOperationTest, DrawWith2DTexture)
778 {
779     std::array<GLColor, 4> colors = {
780         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
781 
782     GLTexture tex;
783     glBindTexture(GL_TEXTURE_2D, tex);
784     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
785     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
786     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
787 
788     draw2DTexturedQuad(0.5f, 1.0f, true);
789     ASSERT_GL_NO_ERROR();
790 
791     int w = getWindowWidth() - 2;
792     int h = getWindowHeight() - 2;
793 
794     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
795     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
796     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
797     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
798 }
799 
800 template <typename T>
testDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,int windowWidth,int windowHeight)801 void SimpleOperationTest::testDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,
802                                                                         int windowWidth,
803                                                                         int windowHeight)
804 {
805     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
806     glUseProgram(program);
807 
808     // We expect to draw a square with these 4 vertices with a drawArray call.
809     std::vector<Vector3> vertices;
810     CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, windowWidth,
811                                   windowHeight, &vertices);
812 
813     // If we use these indices to draw however, we should be drawing an hourglass.
814     std::vector<T> indices{3, 2, 1, 0};
815 
816     GLint positionLocation = glGetAttribLocation(program, "position");
817     ASSERT_NE(-1, positionLocation);
818 
819     GLBuffer vertexBuffer;
820     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
821     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
822                  GL_STATIC_DRAW);
823 
824     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
825     glEnableVertexAttribArray(positionLocation);
826     glClear(GL_COLOR_BUFFER_BIT);
827     glDrawElements(GL_LINE_LOOP, 4, indexType, indices.data());
828     glDisableVertexAttribArray(positionLocation);
829 
830     ASSERT_GL_NO_ERROR();
831 
832     int quarterWidth  = windowWidth / 4;
833     int quarterHeight = windowHeight / 4;
834 
835     // Bottom left
836     EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
837 
838     // Top left
839     EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::green);
840 
841     // Top right
842     EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::green);
843 
844     // Verify line is closed between the 2 last vertices
845     EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
846 }
847 
848 // Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest,DrawElementsLineLoopUsingUShortClientSideMemory)849 TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUShortClientSideMemory)
850 {
851     testDrawElementsLineLoopUsingClientSideMemory<GLushort>(GL_UNSIGNED_SHORT, getWindowWidth(),
852                                                             getWindowHeight());
853 }
854 
855 // Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest,DrawElementsLineLoopUsingUByteClientSideMemory)856 TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUByteClientSideMemory)
857 {
858     testDrawElementsLineLoopUsingClientSideMemory<GLubyte>(GL_UNSIGNED_BYTE, getWindowWidth(),
859                                                            getWindowHeight());
860 }
861 
862 // Creates a program with a cube texture and renders with it.
TEST_P(SimpleOperationTest,DrawWithCubeTexture)863 TEST_P(SimpleOperationTest, DrawWithCubeTexture)
864 {
865     std::array<Vector2, 6 * 4> positions = {{
866         {0, 1}, {1, 1}, {1, 2}, {0, 2} /* first face */,
867         {1, 0}, {2, 0}, {2, 1}, {1, 1} /* second face */,
868         {1, 1}, {2, 1}, {2, 2}, {1, 2} /* third face */,
869         {1, 2}, {2, 2}, {2, 3}, {1, 3} /* fourth face */,
870         {2, 1}, {3, 1}, {3, 2}, {2, 2} /* fifth face */,
871         {3, 1}, {4, 1}, {4, 2}, {3, 2} /* sixth face */,
872     }};
873 
874     const float w4 = 1.0f / 4.0f;
875     const float h3 = 1.0f / 3.0f;
876 
877     // This draws a "T" shape based on the four faces of the cube. The window is divided into four
878     // tiles horizontally and three tiles vertically (hence the w4 and h3 variable naming).
879     for (Vector2 &pos : positions)
880     {
881         pos.data()[0] = pos.data()[0] * w4 * 2.0f - 1.0f;
882         pos.data()[1] = pos.data()[1] * h3 * 2.0f - 1.0f;
883     }
884 
885     const Vector3 posX(1, 0, 0);
886     const Vector3 negX(-1, 0, 0);
887     const Vector3 posY(0, 1, 0);
888     const Vector3 negY(0, -1, 0);
889     const Vector3 posZ(0, 0, 1);
890     const Vector3 negZ(0, 0, -1);
891 
892     std::array<Vector3, 6 * 4> coords = {{
893         posX, posX, posX, posX /* first face */, negX, negX, negX, negX /* second face */,
894         posY, posY, posY, posY /* third face */, negY, negY, negY, negY /* fourth face */,
895         posZ, posZ, posZ, posZ /* fifth face */, negZ, negZ, negZ, negZ /* sixth face */,
896     }};
897 
898     const std::array<std::array<GLColor, 4>, 6> colors = {{
899         {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
900         {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
901         {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
902         {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
903         {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
904         {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
905     }};
906 
907     GLTexture texture;
908     glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
909 
910     for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
911     {
912         glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
913                      colors[faceIndex].data());
914     }
915     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
916     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
917 
918     constexpr char kVertexShader[] = R"(attribute vec2 pos;
919 attribute vec3 coord;
920 varying vec3 texCoord;
921 void main()
922 {
923     gl_Position = vec4(pos, 0, 1);
924     texCoord = coord;
925 })";
926 
927     constexpr char kFragmentShader[] = R"(precision mediump float;
928 varying vec3 texCoord;
929 uniform samplerCube tex;
930 void main()
931 {
932     gl_FragColor = textureCube(tex, texCoord);
933 })";
934 
935     ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
936     GLint samplerLoc = glGetUniformLocation(program, "tex");
937     ASSERT_EQ(samplerLoc, 0);
938 
939     glUseProgram(program);
940 
941     GLint posLoc = glGetAttribLocation(program, "pos");
942     ASSERT_NE(-1, posLoc);
943 
944     GLint coordLoc = glGetAttribLocation(program, "coord");
945     ASSERT_NE(-1, coordLoc);
946 
947     GLBuffer posBuffer;
948     glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
949     glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(Vector2), positions.data(),
950                  GL_STATIC_DRAW);
951     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
952     glEnableVertexAttribArray(posLoc);
953 
954     GLBuffer coordBuffer;
955     glBindBuffer(GL_ARRAY_BUFFER, coordBuffer);
956     glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(Vector3), coords.data(), GL_STATIC_DRAW);
957     glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
958     glEnableVertexAttribArray(coordLoc);
959 
960     auto quadIndices = GetQuadIndices();
961     std::array<GLushort, 6 * 6> kElementsData;
962     for (GLushort quadIndex = 0; quadIndex < 6; ++quadIndex)
963     {
964         for (GLushort elementIndex = 0; elementIndex < 6; ++elementIndex)
965         {
966             kElementsData[quadIndex * 6 + elementIndex] = quadIndices[elementIndex] + 4 * quadIndex;
967         }
968     }
969 
970     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
971     glClear(GL_COLOR_BUFFER_BIT);
972 
973     GLBuffer elementBuffer;
974     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
975     glBufferData(GL_ELEMENT_ARRAY_BUFFER, kElementsData.size() * sizeof(GLushort),
976                  kElementsData.data(), GL_STATIC_DRAW);
977     glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(kElementsData.size()), GL_UNSIGNED_SHORT,
978                    nullptr);
979     ASSERT_GL_NO_ERROR();
980 
981     for (int faceIndex = 0; faceIndex < 6; ++faceIndex)
982     {
983         int index      = faceIndex * 4;
984         Vector2 center = (positions[index] + positions[index + 1] + positions[index + 2] +
985                           positions[index + 3]) /
986                          4.0f;
987         center *= 0.5f;
988         center += Vector2(0.5f);
989         center *= Vector2(getWindowWidth(), getWindowHeight());
990         EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(center.x()), static_cast<GLint>(center.y()),
991                               colors[faceIndex][0]);
992     }
993 }
994 
995 // Tests rendering to a user framebuffer.
TEST_P(SimpleOperationTest,RenderToTexture)996 TEST_P(SimpleOperationTest, RenderToTexture)
997 {
998     constexpr int kSize = 16;
999 
1000     GLTexture texture;
1001     glBindTexture(GL_TEXTURE_2D, texture);
1002     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1003     ASSERT_GL_NO_ERROR();
1004 
1005     GLFramebuffer framebuffer;
1006     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1007     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1008     ASSERT_GL_NO_ERROR();
1009     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1010 
1011     glViewport(0, 0, kSize, kSize);
1012 
1013     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1014     drawQuad(program, "position", 0.5f, 1.0f, true);
1015     ASSERT_GL_NO_ERROR();
1016     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1017 }
1018 
1019 // Create a simple basic Renderbuffer.
TEST_P(SimpleOperationTest,CreateRenderbuffer)1020 TEST_P(SimpleOperationTest, CreateRenderbuffer)
1021 {
1022     GLRenderbuffer renderbuffer;
1023     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1024     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
1025     ASSERT_GL_NO_ERROR();
1026 }
1027 
1028 // Render to a simple color Renderbuffer.
TEST_P(SimpleOperationTest,RenderbufferAttachment)1029 TEST_P(SimpleOperationTest, RenderbufferAttachment)
1030 {
1031     constexpr int kSize = 16;
1032 
1033     GLRenderbuffer renderbuffer;
1034     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1035     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
1036 
1037     GLFramebuffer framebuffer;
1038     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1039     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
1040     ASSERT_GL_NO_ERROR();
1041     ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1042 
1043     glViewport(0, 0, kSize, kSize);
1044 
1045     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1046     drawQuad(program, "position", 0.5f, 1.0f, true);
1047     ASSERT_GL_NO_ERROR();
1048     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1049 }
1050 
1051 // Tests that using desktop GL_QUADS/GL_POLYGONS enums generate the correct error.
TEST_P(SimpleOperationTest,PrimitiveModeNegativeTest)1052 TEST_P(SimpleOperationTest, PrimitiveModeNegativeTest)
1053 {
1054     // Draw a correct quad.
1055     ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1056     glUseProgram(program);
1057 
1058     GLint positionLocation = glGetAttribLocation(program, "position");
1059     ASSERT_NE(-1, positionLocation);
1060 
1061     setupQuadVertexBuffer(0.5f, 1.0f);
1062     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1063     glEnableVertexAttribArray(positionLocation);
1064 
1065     // Tests that TRIANGLES works.
1066     glDrawArrays(GL_TRIANGLES, 0, 6);
1067     ASSERT_GL_NO_ERROR();
1068     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1069 
1070     // Tests that specific invalid enums don't work.
1071     glDrawArrays(static_cast<GLenum>(7), 0, 6);
1072     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1073 
1074     glDrawArrays(static_cast<GLenum>(8), 0, 6);
1075     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1076 
1077     glDrawArrays(static_cast<GLenum>(9), 0, 6);
1078     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1079 }
1080 
1081 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1082 // tests should be run against.
1083 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(SimpleOperationTest);
1084 
1085 }  // namespace
1086