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