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, "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, "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);
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
157 // Tests getting the GL_BLEND_EQUATION integer
TEST_P(SimpleOperationTest,BlendEquationGetInteger)158 TEST_P(SimpleOperationTest, BlendEquationGetInteger)
159 {
160 glEnable(GL_BLEND);
161 glBlendFunc(GL_ONE, GL_ONE);
162
163 constexpr std::array<GLenum, 5> equations = {GL_FUNC_ADD, GL_FUNC_SUBTRACT,
164 GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX};
165
166 for (GLenum equation : equations)
167 {
168 glBlendEquation(equation);
169
170 GLint currentEquation;
171 glGetIntegerv(GL_BLEND_EQUATION, ¤tEquation);
172 ASSERT_GL_NO_ERROR();
173
174 EXPECT_EQ(currentEquation, static_cast<GLint>(equation));
175 }
176 }
177
TEST_P(SimpleOperationTest,CompileVertexShader)178 TEST_P(SimpleOperationTest, CompileVertexShader)
179 {
180 GLuint shader = CompileShader(GL_VERTEX_SHADER, kBasicVertexShader);
181 EXPECT_NE(shader, 0u);
182 glDeleteShader(shader);
183
184 ASSERT_GL_NO_ERROR();
185 }
186
TEST_P(SimpleOperationTest,CompileFragmentShaderSingleVaryingInput)187 TEST_P(SimpleOperationTest, CompileFragmentShaderSingleVaryingInput)
188 {
189 constexpr char kFS[] = R"(precision mediump float;
190 varying vec4 v_input;
191 void main()
192 {
193 gl_FragColor = v_input;
194 })";
195
196 GLuint shader = CompileShader(GL_FRAGMENT_SHADER, kFS);
197 EXPECT_NE(shader, 0u);
198 glDeleteShader(shader);
199
200 ASSERT_GL_NO_ERROR();
201 }
202
203 // Covers a simple bug in Vulkan to do with dependencies between the Surface and the default
204 // Framebuffer.
TEST_P(SimpleOperationTest,ClearAndSwap)205 TEST_P(SimpleOperationTest, ClearAndSwap)
206 {
207 glClearColor(1.0, 0.0, 0.0, 1.0);
208 glClear(GL_COLOR_BUFFER_BIT);
209 swapBuffers();
210
211 // Can't check the pixel result after the swap, and checking the pixel result affects the
212 // behaviour of the test on the Vulkan back-end, so don't bother checking correctness.
213 ASSERT_GL_NO_ERROR();
214 ASSERT_FALSE(getGLWindow()->hasError());
215 }
216
217 // Simple case of setting a scissor, enabled or disabled.
TEST_P(SimpleOperationTest,ScissorTest)218 TEST_P(SimpleOperationTest, ScissorTest)
219 {
220 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
221
222 glClear(GL_COLOR_BUFFER_BIT);
223 glEnable(GL_SCISSOR_TEST);
224 glScissor(getWindowWidth() / 4, getWindowHeight() / 4, getWindowWidth() / 2,
225 getWindowHeight() / 2);
226
227 // Fill the whole screen with a quad.
228 drawQuad(program, "position", 0.0f, 1.0f, true);
229
230 ASSERT_GL_NO_ERROR();
231
232 // Test outside the scissor test, pitch black.
233 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
234
235 // Test inside, green of the fragment shader.
236 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green);
237 }
238
TEST_P(SimpleOperationTest,LinkProgramShadersNoInputs)239 TEST_P(SimpleOperationTest, LinkProgramShadersNoInputs)
240 {
241 constexpr char kVS[] = "void main() { gl_Position = vec4(1.0, 1.0, 1.0, 1.0); }";
242 constexpr char kFS[] = "void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }";
243
244 ANGLE_GL_PROGRAM(program, kVS, kFS);
245 ASSERT_GL_NO_ERROR();
246 }
247
TEST_P(SimpleOperationTest,LinkProgramWithUniforms)248 TEST_P(SimpleOperationTest, LinkProgramWithUniforms)
249 {
250 constexpr char kVS[] = R"(void main()
251 {
252 gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
253 })";
254 constexpr char kFS[] = R"(precision mediump float;
255 uniform vec4 u_input;
256 void main()
257 {
258 gl_FragColor = u_input;
259 })";
260
261 ANGLE_GL_PROGRAM(program, kVS, kFS);
262
263 const GLint uniformLoc = glGetUniformLocation(program, "u_input");
264 EXPECT_NE(-1, uniformLoc);
265
266 ASSERT_GL_NO_ERROR();
267 }
268
TEST_P(SimpleOperationTest,LinkProgramWithAttributes)269 TEST_P(SimpleOperationTest, LinkProgramWithAttributes)
270 {
271 constexpr char kVS[] = R"(attribute vec4 a_input;
272 void main()
273 {
274 gl_Position = a_input;
275 })";
276
277 ANGLE_GL_PROGRAM(program, kVS, kGreenFragmentShader);
278
279 const GLint attribLoc = glGetAttribLocation(program, "a_input");
280 EXPECT_NE(-1, attribLoc);
281
282 ASSERT_GL_NO_ERROR();
283 }
284
TEST_P(SimpleOperationTest,BufferDataWithData)285 TEST_P(SimpleOperationTest, BufferDataWithData)
286 {
287 GLBuffer buffer;
288 glBindBuffer(GL_ARRAY_BUFFER, buffer);
289
290 std::vector<uint8_t> data(1024);
291 FillVectorWithRandomUBytes(&data);
292 glBufferData(GL_ARRAY_BUFFER, data.size(), &data[0], GL_STATIC_DRAW);
293
294 verifyBuffer(data, GL_ARRAY_BUFFER);
295
296 ASSERT_GL_NO_ERROR();
297 }
298
TEST_P(SimpleOperationTest,BufferDataWithNoData)299 TEST_P(SimpleOperationTest, BufferDataWithNoData)
300 {
301 GLBuffer buffer;
302 glBindBuffer(GL_ARRAY_BUFFER, buffer);
303 glBufferData(GL_ARRAY_BUFFER, 1024, nullptr, GL_STATIC_DRAW);
304
305 ASSERT_GL_NO_ERROR();
306 }
307
TEST_P(SimpleOperationTest,BufferSubData)308 TEST_P(SimpleOperationTest, BufferSubData)
309 {
310 GLBuffer buffer;
311 glBindBuffer(GL_ARRAY_BUFFER, buffer);
312
313 constexpr size_t bufferSize = 1024;
314 std::vector<uint8_t> data(bufferSize);
315 FillVectorWithRandomUBytes(&data);
316
317 glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
318
319 constexpr size_t subDataCount = 16;
320 constexpr size_t sliceSize = bufferSize / subDataCount;
321 for (size_t i = 0; i < subDataCount; i++)
322 {
323 size_t offset = i * sliceSize;
324 glBufferSubData(GL_ARRAY_BUFFER, offset, sliceSize, &data[offset]);
325 }
326
327 verifyBuffer(data, GL_ARRAY_BUFFER);
328
329 ASSERT_GL_NO_ERROR();
330 }
331
332 // Simple quad test.
TEST_P(SimpleOperationTest,DrawQuad)333 TEST_P(SimpleOperationTest, DrawQuad)
334 {
335 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
336
337 drawQuad(program, "position", 0.5f, 1.0f, true);
338
339 ASSERT_GL_NO_ERROR();
340
341 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
342 }
343
344 // Simple quad test with data in client memory, not vertex buffer.
TEST_P(SimpleOperationTest,DrawQuadFromClientMemory)345 TEST_P(SimpleOperationTest, DrawQuadFromClientMemory)
346 {
347 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
348
349 drawQuad(program, "position", 0.5f, 1.0f, false);
350
351 ASSERT_GL_NO_ERROR();
352
353 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
354 }
355
356 // Simple double quad test.
TEST_P(SimpleOperationTest,DrawQuadTwice)357 TEST_P(SimpleOperationTest, DrawQuadTwice)
358 {
359 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
360
361 drawQuad(program, "position", 0.5f, 1.0f, true);
362 drawQuad(program, "position", 0.5f, 1.0f, true);
363
364 ASSERT_GL_NO_ERROR();
365
366 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
367 }
368
369 // Simple line test.
TEST_P(SimpleOperationTest,DrawLine)370 TEST_P(SimpleOperationTest, DrawLine)
371 {
372 // We assume in the test the width and height are equal and we are tracing
373 // the line from bottom left to top right. Verify that all pixels along that line
374 // have been traced with green.
375 ASSERT_EQ(getWindowWidth(), getWindowHeight());
376
377 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
378 glUseProgram(program);
379
380 std::vector<Vector3> vertices = {{-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}};
381
382 const GLint positionLocation = glGetAttribLocation(program, "position");
383 ASSERT_NE(-1, positionLocation);
384
385 GLBuffer vertexBuffer;
386 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
387 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
388 GL_STATIC_DRAW);
389 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
390 glEnableVertexAttribArray(positionLocation);
391
392 glClear(GL_COLOR_BUFFER_BIT);
393 glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(vertices.size()));
394
395 glDisableVertexAttribArray(positionLocation);
396
397 ASSERT_GL_NO_ERROR();
398
399 for (int x = 0; x < getWindowWidth(); x++)
400 {
401 EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
402 }
403 }
404
405 // Simple line test that will use a very large offset in the vertex attributes.
TEST_P(SimpleOperationTest,DrawLineWithLargeAttribPointerOffset)406 TEST_P(SimpleOperationTest, DrawLineWithLargeAttribPointerOffset)
407 {
408 // We assume in the test the width and height are equal and we are tracing
409 // the line from bottom left to top right. Verify that all pixels along that line
410 // have been traced with green.
411 ASSERT_EQ(getWindowWidth(), getWindowHeight());
412
413 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
414 glUseProgram(program);
415
416 int kOffset = 3315;
417 std::vector<Vector3> vertices(kOffset);
418 Vector3 vector1{-1.0f, -1.0f, 0.0f};
419 Vector3 vector2{1.0f, 1.0f, 0.0f};
420 vertices.emplace_back(vector1);
421 vertices.emplace_back(vector2);
422
423 const GLint positionLocation = glGetAttribLocation(program, "position");
424 ASSERT_NE(-1, positionLocation);
425
426 GLBuffer vertexBuffer;
427 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
428 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
429 GL_STATIC_DRAW);
430 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0,
431 reinterpret_cast<const void *>(kOffset * sizeof(vertices[0])));
432 glEnableVertexAttribArray(positionLocation);
433
434 glClear(GL_COLOR_BUFFER_BIT);
435 glDrawArrays(GL_LINES, 0, 2);
436
437 glDisableVertexAttribArray(positionLocation);
438
439 ASSERT_GL_NO_ERROR();
440
441 for (auto x = 0; x < getWindowWidth(); x++)
442 {
443 EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
444 }
445 }
446
447 // Simple line strip test.
TEST_P(SimpleOperationTest,DrawLineStrip)448 TEST_P(SimpleOperationTest, DrawLineStrip)
449 {
450 // We assume in the test the width and height are equal and we are tracing
451 // the line from bottom left to center, then from center to bottom right.
452 // Verify that all pixels along these lines have been traced with green.
453 ASSERT_EQ(getWindowWidth(), getWindowHeight());
454
455 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
456 glUseProgram(program);
457
458 auto vertices =
459 std::vector<Vector3>{{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, -1.0f, 0.0f}};
460
461 const GLint positionLocation = glGetAttribLocation(program, "position");
462 ASSERT_NE(-1, positionLocation);
463
464 GLBuffer vertexBuffer;
465 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
466 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
467 GL_STATIC_DRAW);
468 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
469
470 glEnableVertexAttribArray(positionLocation);
471
472 glClear(GL_COLOR_BUFFER_BIT);
473 glDrawArrays(GL_LINE_STRIP, 0, static_cast<GLsizei>(vertices.size()));
474
475 ASSERT_GL_NO_ERROR();
476
477 const auto centerX = getWindowWidth() / 2;
478 const auto centerY = getWindowHeight() / 2;
479
480 for (auto x = 0; x < centerX; x++)
481 {
482 EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
483 }
484
485 for (auto x = centerX, y = centerY - 1; x < getWindowWidth() && y >= 0; x++, y--)
486 {
487 EXPECT_PIXEL_COLOR_EQ(x, y, GLColor::green);
488 }
489 }
490
491 class TriangleFanDrawTest : public SimpleOperationTest
492 {
493 protected:
testSetUp()494 void testSetUp() override
495 {
496 // We assume in the test the width and height are equal and we are tracing
497 // 2 triangles to cover half the surface like this:
498 ASSERT_EQ(getWindowWidth(), getWindowHeight());
499
500 mProgram.makeRaster(kBasicVertexShader, kGreenFragmentShader);
501 ASSERT_TRUE(mProgram.valid());
502 glUseProgram(mProgram);
503
504 const GLint positionLocation = glGetAttribLocation(mProgram, "position");
505 ASSERT_NE(-1, positionLocation);
506
507 glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
508 glBufferData(GL_ARRAY_BUFFER, sizeof(mVertices[0]) * mVertices.size(), mVertices.data(),
509 GL_STATIC_DRAW);
510 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
511 glEnableVertexAttribArray(positionLocation);
512
513 glClearColor(1, 0, 0, 1);
514 glClear(GL_COLOR_BUFFER_BIT);
515 }
516
readPixels()517 void readPixels()
518 {
519 if (mReadPixels.empty())
520 {
521 mReadPixels.resize(getWindowWidth() * getWindowWidth());
522 }
523
524 glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
525 mReadPixels.data());
526 EXPECT_GL_NO_ERROR();
527 }
528
verifyPixelAt(int x,int y,const GLColor & expected)529 void verifyPixelAt(int x, int y, const GLColor &expected)
530 {
531 EXPECT_EQ(mReadPixels[y * getWindowWidth() + x], expected);
532 }
533
verifyTriangles()534 void verifyTriangles()
535 {
536 readPixels();
537
538 // Check 4 lines accross de triangles to make sure we filled it.
539 // Don't check every pixel as it would slow down our tests.
540 for (auto x = 0; x < getWindowWidth(); x++)
541 {
542 verifyPixelAt(x, x, GLColor::green);
543 }
544
545 for (auto x = getWindowWidth() / 3, y = 0; x < getWindowWidth(); x++, y++)
546 {
547 verifyPixelAt(x, y, GLColor::green);
548 }
549
550 for (auto x = getWindowWidth() / 2, y = 0; x < getWindowWidth(); x++, y++)
551 {
552 verifyPixelAt(x, y, GLColor::green);
553 }
554
555 for (auto x = (getWindowWidth() / 4) * 3, y = 0; x < getWindowWidth(); x++, y++)
556 {
557 verifyPixelAt(x, y, GLColor::green);
558 }
559
560 // Area outside triangles
561 for (auto x = 0; x < getWindowWidth() - 2; x++)
562 {
563 verifyPixelAt(x, x + 2, GLColor::red);
564 }
565 }
566
567 const std::vector<Vector3> mVertices = {{0.0f, 0.0f, 0.0f},
568 {-1.0f, -1.0f, 0.0f},
569 {0.0f, -1.0f, 0.0f},
570 {1.0f, -1.0f, 0.0f},
571 {1.0f, 1.0f, 0.0f}};
572
573 GLBuffer mVertexBuffer;
574 GLProgram mProgram;
575
576 std::vector<GLColor> mReadPixels;
577 };
578
579 // Simple triangle fans test.
TEST_P(TriangleFanDrawTest,DrawTriangleFan)580 TEST_P(TriangleFanDrawTest, DrawTriangleFan)
581 {
582 glClear(GL_COLOR_BUFFER_BIT);
583 glDrawArrays(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(mVertices.size()));
584
585 EXPECT_GL_NO_ERROR();
586
587 verifyTriangles();
588 }
589
590 // Triangle fans test with index buffer.
TEST_P(TriangleFanDrawTest,DrawTriangleFanElements)591 TEST_P(TriangleFanDrawTest, DrawTriangleFanElements)
592 {
593 std::vector<GLubyte> indices = {0, 1, 2, 3, 4};
594
595 GLBuffer indexBuffer;
596 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
597 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
598 GL_STATIC_DRAW);
599
600 glClear(GL_COLOR_BUFFER_BIT);
601 glDrawElements(GL_TRIANGLE_FAN, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_BYTE, 0);
602
603 EXPECT_GL_NO_ERROR();
604
605 verifyTriangles();
606 }
607
608 // Triangle fans test with primitive restart index at the middle.
TEST_P(TriangleFanDrawTest,DrawTriangleFanPrimitiveRestartAtMiddle)609 TEST_P(TriangleFanDrawTest, DrawTriangleFanPrimitiveRestartAtMiddle)
610 {
611 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
612
613 std::vector<GLubyte> indices = {0, 1, 2, 3, 0xff, 0, 4, 3};
614
615 GLBuffer indexBuffer;
616 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
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, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_BYTE, 0);
622
623 EXPECT_GL_NO_ERROR();
624
625 verifyTriangles();
626 }
627
628 // Triangle fans test with primitive restart at begin.
TEST_P(TriangleFanDrawTest,DrawTriangleFanPrimitiveRestartAtBegin)629 TEST_P(TriangleFanDrawTest, DrawTriangleFanPrimitiveRestartAtBegin)
630 {
631 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
632
633 // Primitive restart index is at middle, but we will use draw call which index offset=4.
634 std::vector<GLubyte> indices = {0, 1, 2, 3, 0xff, 0, 4, 3};
635
636 GLBuffer indexBuffer;
637 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
638 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
639 GL_STATIC_DRAW);
640 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
641
642 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_BYTE, 0);
643 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_BYTE,
644 reinterpret_cast<void *>(sizeof(indices[0]) * 4));
645
646 EXPECT_GL_NO_ERROR();
647
648 verifyTriangles();
649 }
650
651 // Triangle fans test with primitive restart at end.
TEST_P(TriangleFanDrawTest,DrawTriangleFanPrimitiveRestartAtEnd)652 TEST_P(TriangleFanDrawTest, DrawTriangleFanPrimitiveRestartAtEnd)
653 {
654 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
655
656 std::vector<GLubyte> indices = {0, 1, 2, 3, 4, 0xff};
657
658 GLBuffer indexBuffer;
659 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
660 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
661 GL_STATIC_DRAW);
662 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
663
664 glDrawElements(GL_TRIANGLE_FAN, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_BYTE, 0);
665
666 EXPECT_GL_NO_ERROR();
667
668 verifyTriangles();
669 }
670
671 // Triangle fans test with primitive restart enabled, but no indexed draw.
TEST_P(TriangleFanDrawTest,DrawTriangleFanPrimitiveRestartNonIndexedDraw)672 TEST_P(TriangleFanDrawTest, DrawTriangleFanPrimitiveRestartNonIndexedDraw)
673 {
674 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
675
676 std::vector<GLubyte> indices = {0, 1, 2, 3, 4};
677
678 GLBuffer indexBuffer;
679 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
680 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
681 GL_STATIC_DRAW);
682 glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
683
684 glDrawArrays(GL_TRIANGLE_FAN, 0, 5);
685
686 EXPECT_GL_NO_ERROR();
687
688 verifyTriangles();
689 }
690
691 // Simple repeated draw and swap test.
TEST_P(SimpleOperationTest,DrawQuadAndSwap)692 TEST_P(SimpleOperationTest, DrawQuadAndSwap)
693 {
694 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
695
696 for (int i = 0; i < 8; ++i)
697 {
698 drawQuad(program, "position", 0.5f, 1.0f, true);
699 ASSERT_GL_NO_ERROR();
700 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
701 swapBuffers();
702 }
703
704 ASSERT_GL_NO_ERROR();
705 }
706
707 // Simple indexed quad test.
TEST_P(SimpleOperationTest,DrawIndexedQuad)708 TEST_P(SimpleOperationTest, DrawIndexedQuad)
709 {
710 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
711
712 drawIndexedQuad(program, "position", 0.5f, 1.0f, true);
713
714 ASSERT_GL_NO_ERROR();
715 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
716 }
717
718 // Simple repeated indexed draw and swap test.
TEST_P(SimpleOperationTest,DrawIndexedQuadAndSwap)719 TEST_P(SimpleOperationTest, DrawIndexedQuadAndSwap)
720 {
721 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
722
723 // 32 iterations is an arbitrary number. The more iterations, the more flaky syncronization
724 // issues will reproduce consistently.
725 for (int i = 0; i < 32; ++i)
726 {
727 drawIndexedQuad(program, "position", 0.5f, 1.0f, true);
728 ASSERT_GL_NO_ERROR();
729 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
730 swapBuffers();
731 }
732
733 ASSERT_GL_NO_ERROR();
734 }
735
736 // Draw with a fragment uniform.
TEST_P(SimpleOperationTest,DrawQuadWithFragmentUniform)737 TEST_P(SimpleOperationTest, DrawQuadWithFragmentUniform)
738 {
739 constexpr char kFS[] =
740 "uniform mediump vec4 color;\n"
741 "void main()\n"
742 "{\n"
743 " gl_FragColor = color;\n"
744 "}";
745 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kFS);
746
747 GLint location = glGetUniformLocation(program, "color");
748 ASSERT_NE(-1, location);
749
750 glUseProgram(program);
751 glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);
752
753 drawQuad(program, "position", 0.5f, 1.0f, true);
754
755 ASSERT_GL_NO_ERROR();
756 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
757 }
758
759 // Draw with a vertex uniform.
TEST_P(SimpleOperationTest,DrawQuadWithVertexUniform)760 TEST_P(SimpleOperationTest, DrawQuadWithVertexUniform)
761 {
762 constexpr char kVS[] =
763 "attribute vec3 position;\n"
764 "uniform vec4 color;\n"
765 "varying vec4 vcolor;\n"
766 "void main()\n"
767 "{\n"
768 " gl_Position = vec4(position, 1);\n"
769 " vcolor = color;\n"
770 "}";
771 constexpr char kFS[] =
772 "varying mediump vec4 vcolor;\n"
773 "void main()\n"
774 "{\n"
775 " gl_FragColor = vcolor;\n"
776 "}";
777 ANGLE_GL_PROGRAM(program, kVS, kFS);
778
779 const GLint location = glGetUniformLocation(program, "color");
780 ASSERT_NE(-1, location);
781
782 glUseProgram(program);
783 glUniform4f(location, 0.0f, 1.0f, 0.0f, 1.0f);
784
785 drawQuad(program, "position", 0.5f, 1.0f, true);
786
787 ASSERT_GL_NO_ERROR();
788 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
789 }
790
791 // Draw with two uniforms.
TEST_P(SimpleOperationTest,DrawQuadWithTwoUniforms)792 TEST_P(SimpleOperationTest, DrawQuadWithTwoUniforms)
793 {
794 constexpr char kVS[] =
795 "attribute vec3 position;\n"
796 "uniform vec4 color1;\n"
797 "varying vec4 vcolor1;\n"
798 "void main()\n"
799 "{\n"
800 " gl_Position = vec4(position, 1);\n"
801 " vcolor1 = color1;\n"
802 "}";
803 constexpr char kFS[] =
804 "uniform mediump vec4 color2;\n"
805 "varying mediump vec4 vcolor1;\n"
806 "void main()\n"
807 "{\n"
808 " gl_FragColor = vcolor1 + color2;\n"
809 "}";
810 ANGLE_GL_PROGRAM(program, kVS, kFS);
811
812 const GLint location1 = glGetUniformLocation(program, "color1");
813 ASSERT_NE(-1, location1);
814
815 const GLint location2 = glGetUniformLocation(program, "color2");
816 ASSERT_NE(-1, location2);
817
818 glUseProgram(program);
819 glUniform4f(location1, 0.0f, 1.0f, 0.0f, 1.0f);
820 glUniform4f(location2, 1.0f, 0.0f, 0.0f, 1.0f);
821
822 drawQuad(program, "position", 0.5f, 1.0f, true);
823
824 ASSERT_GL_NO_ERROR();
825 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
826 }
827
828 // Tests a shader program with more than one vertex attribute, with vertex buffers.
TEST_P(SimpleOperationTest,ThreeVertexAttributes)829 TEST_P(SimpleOperationTest, ThreeVertexAttributes)
830 {
831 constexpr char kVS[] = R"(attribute vec2 position;
832 attribute vec4 color1;
833 attribute vec4 color2;
834 varying vec4 color;
835 void main()
836 {
837 gl_Position = vec4(position, 0, 1);
838 color = color1 + color2;
839 })";
840
841 constexpr char kFS[] = R"(precision mediump float;
842 varying vec4 color;
843 void main()
844 {
845 gl_FragColor = color;
846 }
847 )";
848
849 ANGLE_GL_PROGRAM(program, kVS, kFS);
850
851 glUseProgram(program);
852
853 const GLint color1Loc = glGetAttribLocation(program, "color1");
854 const GLint color2Loc = glGetAttribLocation(program, "color2");
855 ASSERT_NE(-1, color1Loc);
856 ASSERT_NE(-1, color2Loc);
857
858 const auto &indices = GetQuadIndices();
859
860 // Make colored corners with red == x or 1 -x , and green = y or 1 - y.
861
862 std::array<GLColor, 4> baseColors1 = {
863 {GLColor::black, GLColor::red, GLColor::green, GLColor::yellow}};
864 std::array<GLColor, 4> baseColors2 = {
865 {GLColor::yellow, GLColor::green, GLColor::red, GLColor::black}};
866
867 std::vector<GLColor> colors1;
868 std::vector<GLColor> colors2;
869
870 for (GLushort index : indices)
871 {
872 colors1.push_back(baseColors1[index]);
873 colors2.push_back(baseColors2[index]);
874 }
875
876 GLBuffer color1Buffer;
877 glBindBuffer(GL_ARRAY_BUFFER, color1Buffer);
878 glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLColor), colors1.data(), GL_STATIC_DRAW);
879 glVertexAttribPointer(color1Loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
880 glEnableVertexAttribArray(color1Loc);
881
882 GLBuffer color2Buffer;
883 glBindBuffer(GL_ARRAY_BUFFER, color2Buffer);
884 glBufferData(GL_ARRAY_BUFFER, colors2.size() * sizeof(GLColor), colors2.data(), GL_STATIC_DRAW);
885 glVertexAttribPointer(color2Loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
886 glEnableVertexAttribArray(color2Loc);
887
888 // Draw a non-indexed quad with all vertex buffers. Should draw yellow to the entire window.
889 drawQuad(program, "position", 0.5f, 1.0f, true);
890 ASSERT_GL_NO_ERROR();
891 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
892 }
893
894 // Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest,CreateTexture2DNoData)895 TEST_P(SimpleOperationTest, CreateTexture2DNoData)
896 {
897 GLTexture texture;
898 glBindTexture(GL_TEXTURE_2D, texture);
899 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
900 ASSERT_GL_NO_ERROR();
901 }
902
903 // Creates a 2D texture, no other operations.
TEST_P(SimpleOperationTest,CreateTexture2DWithData)904 TEST_P(SimpleOperationTest, CreateTexture2DWithData)
905 {
906 std::vector<GLColor> colors(16 * 16, GLColor::red);
907
908 GLTexture texture;
909 glBindTexture(GL_TEXTURE_2D, texture);
910 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
911 ASSERT_GL_NO_ERROR();
912 }
913
914 // Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest,CreateTextureCubeNoData)915 TEST_P(SimpleOperationTest, CreateTextureCubeNoData)
916 {
917 GLTexture texture;
918 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
919 for (GLenum cubeFace : kCubeFaces)
920 {
921 glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
922 }
923 ASSERT_GL_NO_ERROR();
924 }
925
926 // Creates a cube texture, no other operations.
TEST_P(SimpleOperationTest,CreateTextureCubeWithData)927 TEST_P(SimpleOperationTest, CreateTextureCubeWithData)
928 {
929 std::vector<GLColor> colors(16 * 16, GLColor::red);
930
931 GLTexture texture;
932 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
933 for (GLenum cubeFace : kCubeFaces)
934 {
935 glTexImage2D(cubeFace, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
936 }
937 ASSERT_GL_NO_ERROR();
938 }
939
940 // Creates a program with a texture.
TEST_P(SimpleOperationTest,LinkProgramWithTexture)941 TEST_P(SimpleOperationTest, LinkProgramWithTexture)
942 {
943 ASSERT_NE(0u, get2DTexturedQuadProgram());
944 ASSERT_GL_NO_ERROR();
945 }
946
947 // Creates a program with a 2D texture and renders with it.
TEST_P(SimpleOperationTest,DrawWith2DTexture)948 TEST_P(SimpleOperationTest, DrawWith2DTexture)
949 {
950 std::array<GLColor, 4> colors = {
951 {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
952
953 GLTexture tex;
954 glBindTexture(GL_TEXTURE_2D, tex);
955 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
956 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
957 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
958
959 draw2DTexturedQuad(0.5f, 1.0f, true);
960 ASSERT_GL_NO_ERROR();
961
962 int w = getWindowWidth() - 2;
963 int h = getWindowHeight() - 2;
964
965 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
966 EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
967 EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
968 EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
969 }
970
971 template <typename T>
testDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,int windowWidth,int windowHeight)972 void SimpleOperationTest::testDrawElementsLineLoopUsingClientSideMemory(GLenum indexType,
973 int windowWidth,
974 int windowHeight)
975 {
976 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
977 glUseProgram(program);
978
979 // We expect to draw a square with these 4 vertices with a drawArray call.
980 std::vector<Vector3> vertices;
981 CreatePixelCenterWindowCoords({{32, 96}, {32, 32}, {96, 32}, {96, 96}}, windowWidth,
982 windowHeight, &vertices);
983
984 // If we use these indices to draw however, we should be drawing an hourglass.
985 std::vector<T> indices{3, 2, 1, 0};
986
987 GLint positionLocation = glGetAttribLocation(program, "position");
988 ASSERT_NE(-1, positionLocation);
989
990 GLBuffer vertexBuffer;
991 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
992 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
993 GL_STATIC_DRAW);
994
995 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
996 glEnableVertexAttribArray(positionLocation);
997 glClear(GL_COLOR_BUFFER_BIT);
998 glDrawElements(GL_LINE_LOOP, 4, indexType, indices.data());
999 glDisableVertexAttribArray(positionLocation);
1000
1001 ASSERT_GL_NO_ERROR();
1002
1003 int quarterWidth = windowWidth / 4;
1004 int quarterHeight = windowHeight / 4;
1005
1006 // Bottom left
1007 EXPECT_PIXEL_COLOR_EQ(quarterWidth, quarterHeight, GLColor::green);
1008
1009 // Top left
1010 EXPECT_PIXEL_COLOR_EQ(quarterWidth, (quarterHeight * 3), GLColor::green);
1011
1012 // Top right
1013 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 3), (quarterHeight * 3) - 1, GLColor::green);
1014
1015 // Verify line is closed between the 2 last vertices
1016 EXPECT_PIXEL_COLOR_EQ((quarterWidth * 2), quarterHeight, GLColor::green);
1017 }
1018
1019 // Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest,DrawElementsLineLoopUsingUShortClientSideMemory)1020 TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUShortClientSideMemory)
1021 {
1022 testDrawElementsLineLoopUsingClientSideMemory<GLushort>(GL_UNSIGNED_SHORT, getWindowWidth(),
1023 getWindowHeight());
1024 }
1025
1026 // Draw a line loop using a drawElement call and client side memory.
TEST_P(SimpleOperationTest,DrawElementsLineLoopUsingUByteClientSideMemory)1027 TEST_P(SimpleOperationTest, DrawElementsLineLoopUsingUByteClientSideMemory)
1028 {
1029 testDrawElementsLineLoopUsingClientSideMemory<GLubyte>(GL_UNSIGNED_BYTE, getWindowWidth(),
1030 getWindowHeight());
1031 }
1032
1033 // Creates a program with a cube texture and renders with it.
TEST_P(SimpleOperationTest,DrawWithCubeTexture)1034 TEST_P(SimpleOperationTest, DrawWithCubeTexture)
1035 {
1036 std::array<Vector2, 6 * 4> positions = {{
1037 {0, 1}, {1, 1}, {1, 2}, {0, 2} /* first face */,
1038 {1, 0}, {2, 0}, {2, 1}, {1, 1} /* second face */,
1039 {1, 1}, {2, 1}, {2, 2}, {1, 2} /* third face */,
1040 {1, 2}, {2, 2}, {2, 3}, {1, 3} /* fourth face */,
1041 {2, 1}, {3, 1}, {3, 2}, {2, 2} /* fifth face */,
1042 {3, 1}, {4, 1}, {4, 2}, {3, 2} /* sixth face */,
1043 }};
1044
1045 const float w4 = 1.0f / 4.0f;
1046 const float h3 = 1.0f / 3.0f;
1047
1048 // This draws a "T" shape based on the four faces of the cube. The window is divided into four
1049 // tiles horizontally and three tiles vertically (hence the w4 and h3 variable naming).
1050 for (Vector2 &pos : positions)
1051 {
1052 pos.data()[0] = pos.data()[0] * w4 * 2.0f - 1.0f;
1053 pos.data()[1] = pos.data()[1] * h3 * 2.0f - 1.0f;
1054 }
1055
1056 const Vector3 posX(1, 0, 0);
1057 const Vector3 negX(-1, 0, 0);
1058 const Vector3 posY(0, 1, 0);
1059 const Vector3 negY(0, -1, 0);
1060 const Vector3 posZ(0, 0, 1);
1061 const Vector3 negZ(0, 0, -1);
1062
1063 std::array<Vector3, 6 * 4> coords = {{
1064 posX, posX, posX, posX /* first face */, negX, negX, negX, negX /* second face */,
1065 posY, posY, posY, posY /* third face */, negY, negY, negY, negY /* fourth face */,
1066 posZ, posZ, posZ, posZ /* fifth face */, negZ, negZ, negZ, negZ /* sixth face */,
1067 }};
1068
1069 const std::array<std::array<GLColor, 4>, 6> colors = {{
1070 {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
1071 {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
1072 {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
1073 {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
1074 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
1075 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
1076 }};
1077
1078 GLTexture texture;
1079 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
1080
1081 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
1082 {
1083 glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1084 colors[faceIndex].data());
1085 }
1086 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1087 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1088
1089 constexpr char kVertexShader[] = R"(attribute vec2 pos;
1090 attribute vec3 coord;
1091 varying vec3 texCoord;
1092 void main()
1093 {
1094 gl_Position = vec4(pos, 0, 1);
1095 texCoord = coord;
1096 })";
1097
1098 constexpr char kFragmentShader[] = R"(precision mediump float;
1099 varying vec3 texCoord;
1100 uniform samplerCube tex;
1101 void main()
1102 {
1103 gl_FragColor = textureCube(tex, texCoord);
1104 })";
1105
1106 ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
1107 GLint samplerLoc = glGetUniformLocation(program, "tex");
1108 ASSERT_EQ(samplerLoc, 0);
1109
1110 glUseProgram(program);
1111
1112 GLint posLoc = glGetAttribLocation(program, "pos");
1113 ASSERT_NE(-1, posLoc);
1114
1115 GLint coordLoc = glGetAttribLocation(program, "coord");
1116 ASSERT_NE(-1, coordLoc);
1117
1118 GLBuffer posBuffer;
1119 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
1120 glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(Vector2), positions.data(),
1121 GL_STATIC_DRAW);
1122 glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
1123 glEnableVertexAttribArray(posLoc);
1124
1125 GLBuffer coordBuffer;
1126 glBindBuffer(GL_ARRAY_BUFFER, coordBuffer);
1127 glBufferData(GL_ARRAY_BUFFER, coords.size() * sizeof(Vector3), coords.data(), GL_STATIC_DRAW);
1128 glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1129 glEnableVertexAttribArray(coordLoc);
1130
1131 auto quadIndices = GetQuadIndices();
1132 std::array<GLushort, 6 * 6> kElementsData;
1133 for (GLushort quadIndex = 0; quadIndex < 6; ++quadIndex)
1134 {
1135 for (GLushort elementIndex = 0; elementIndex < 6; ++elementIndex)
1136 {
1137 kElementsData[quadIndex * 6 + elementIndex] = quadIndices[elementIndex] + 4 * quadIndex;
1138 }
1139 }
1140
1141 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1142 glClear(GL_COLOR_BUFFER_BIT);
1143
1144 GLBuffer elementBuffer;
1145 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
1146 glBufferData(GL_ELEMENT_ARRAY_BUFFER, kElementsData.size() * sizeof(GLushort),
1147 kElementsData.data(), GL_STATIC_DRAW);
1148 glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(kElementsData.size()), GL_UNSIGNED_SHORT,
1149 nullptr);
1150 ASSERT_GL_NO_ERROR();
1151
1152 for (int faceIndex = 0; faceIndex < 6; ++faceIndex)
1153 {
1154 int index = faceIndex * 4;
1155 Vector2 center = (positions[index] + positions[index + 1] + positions[index + 2] +
1156 positions[index + 3]) /
1157 4.0f;
1158 center *= 0.5f;
1159 center += Vector2(0.5f);
1160 center *= Vector2(getWindowWidth(), getWindowHeight());
1161 EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(center.x()), static_cast<GLint>(center.y()),
1162 colors[faceIndex][0]);
1163 }
1164 }
1165
1166 // Tests rendering to a user framebuffer.
TEST_P(SimpleOperationTest,RenderToTexture)1167 TEST_P(SimpleOperationTest, RenderToTexture)
1168 {
1169 constexpr int kSize = 16;
1170
1171 GLTexture texture;
1172 glBindTexture(GL_TEXTURE_2D, texture);
1173 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1174 ASSERT_GL_NO_ERROR();
1175
1176 GLFramebuffer framebuffer;
1177 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1178 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1179 ASSERT_GL_NO_ERROR();
1180 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1181
1182 glViewport(0, 0, kSize, kSize);
1183
1184 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1185 drawQuad(program, "position", 0.5f, 1.0f, true);
1186 ASSERT_GL_NO_ERROR();
1187 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1188 }
1189
1190 // Create a simple basic Renderbuffer.
TEST_P(SimpleOperationTest,CreateRenderbuffer)1191 TEST_P(SimpleOperationTest, CreateRenderbuffer)
1192 {
1193 GLRenderbuffer renderbuffer;
1194 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1195 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
1196 ASSERT_GL_NO_ERROR();
1197 }
1198
1199 // Render to a simple color Renderbuffer.
TEST_P(SimpleOperationTest,RenderbufferAttachment)1200 TEST_P(SimpleOperationTest, RenderbufferAttachment)
1201 {
1202 constexpr int kSize = 16;
1203
1204 GLRenderbuffer renderbuffer;
1205 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1206 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kSize, kSize);
1207
1208 GLFramebuffer framebuffer;
1209 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1210 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
1211 ASSERT_GL_NO_ERROR();
1212 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1213
1214 glViewport(0, 0, kSize, kSize);
1215
1216 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1217 drawQuad(program, "position", 0.5f, 1.0f, true);
1218 ASSERT_GL_NO_ERROR();
1219 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1220 }
1221
1222 // Tests that using desktop GL_QUADS/GL_POLYGONS enums generate the correct error.
TEST_P(SimpleOperationTest,PrimitiveModeNegativeTest)1223 TEST_P(SimpleOperationTest, PrimitiveModeNegativeTest)
1224 {
1225 // Draw a correct quad.
1226 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1227 glUseProgram(program);
1228
1229 GLint positionLocation = glGetAttribLocation(program, "position");
1230 ASSERT_NE(-1, positionLocation);
1231
1232 setupQuadVertexBuffer(0.5f, 1.0f);
1233 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1234 glEnableVertexAttribArray(positionLocation);
1235
1236 // Tests that TRIANGLES works.
1237 glDrawArrays(GL_TRIANGLES, 0, 6);
1238 ASSERT_GL_NO_ERROR();
1239 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1240
1241 // Tests that specific invalid enums don't work.
1242 glDrawArrays(static_cast<GLenum>(7), 0, 6);
1243 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1244
1245 glDrawArrays(static_cast<GLenum>(8), 0, 6);
1246 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1247
1248 glDrawArrays(static_cast<GLenum>(9), 0, 6);
1249 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1250 }
1251
1252 // Tests that using GL_LINES_ADJACENCY should not crash the app even if the backend doesn't support
1253 // LinesAdjacent mode.
1254 // This is to verify that the crash in crbug.com/1457840 won't happen.
TEST_P(SimpleOperationTest,PrimitiveModeLinesAdjacentNegativeTest)1255 TEST_P(SimpleOperationTest, PrimitiveModeLinesAdjacentNegativeTest)
1256 {
1257 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1258 glUseProgram(program);
1259
1260 GLint positionLocation = glGetAttribLocation(program, "position");
1261 ASSERT_NE(-1, positionLocation);
1262
1263 setupQuadVertexBuffer(0.5f, 1.0f);
1264 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1265 glEnableVertexAttribArray(positionLocation);
1266
1267 {
1268 // Tests that TRIANGLES works.
1269 glDrawArrays(GL_TRIANGLES, 0, 6);
1270 ASSERT_GL_NO_ERROR();
1271 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1272 }
1273
1274 {
1275 // Drawing with GL_LINES_ADJACENCY won't crash even if the backend doesn't support it.
1276 glDrawArrays(GL_LINES_ADJACENCY, 0, 6);
1277
1278 if (IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
1279 {
1280 glDrawArraysInstancedANGLE(GL_LINES_ADJACENCY, 0, 6, 2);
1281 }
1282 }
1283
1284 // Indexed draws with GL_LINES_ADJACENCY
1285 setupIndexedQuadVertexBuffer(0.5f, 1.0f);
1286 setupIndexedQuadIndexBuffer();
1287
1288 // Clear GL error state, since ahove calls may have set GL_INVALID_ENUM.
1289 glGetError();
1290
1291 {
1292 // Tests that TRIANGLES works.
1293 glClear(GL_COLOR_BUFFER_BIT);
1294 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
1295 ASSERT_GL_NO_ERROR();
1296 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1297 }
1298
1299 {
1300 // Indexed drawing with GL_LINES_ADJACENCY won't crash even if the backend doesn't support
1301 // it.
1302 glDrawElements(GL_LINES_ADJACENCY, 6, GL_UNSIGNED_SHORT, nullptr);
1303 if (IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
1304 {
1305 glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr, 1);
1306 }
1307 }
1308 }
1309
1310 // Tests all primitive modes, including some invalid ones, with a vertex shader that receives
1311 // no data for its vertex attributes (constant values). This is a port of the test case from
1312 // crbug.com/1457840, exercising slightly different code paths.
TEST_P(SimpleOperationTest,DrawsWithNoAttributeData)1313 TEST_P(SimpleOperationTest, DrawsWithNoAttributeData)
1314 {
1315 constexpr char kTestVertexShader[] =
1316 R"(attribute vec4 vPosition;
1317 attribute vec2 texCoord0;
1318 varying vec2 texCoord;
1319 void main() {
1320 gl_Position = vPosition;
1321 texCoord = texCoord0;
1322 })";
1323 constexpr char kTestFragmentShader[] =
1324 R"(precision mediump float;
1325 uniform sampler2D tex;
1326 uniform float divisor;
1327 varying vec2 texCoord;
1328 void main() {
1329 gl_FragData[0] = texture2DProj(tex, vec3(texCoord, divisor));
1330 })";
1331
1332 constexpr std::array<GLenum, 12> kPrimitiveModes = {
1333 {GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP,
1334 GL_TRIANGLE_FAN,
1335
1336 // Illegal or possibly-illegal modes
1337 GL_QUERY_RESULT, GL_LINES_ADJACENCY, GL_LINE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY,
1338 GL_TRIANGLE_STRIP_ADJACENCY}};
1339
1340 ANGLE_GL_PROGRAM(program, kTestVertexShader, kTestFragmentShader);
1341 glUseProgram(program);
1342
1343 for (GLenum mode : kPrimitiveModes)
1344 {
1345 glDrawArrays(mode, 0, 0x8866);
1346 }
1347
1348 // If the test reaches this point then it hasn't crashed.
1349 }
1350
1351 // Verify we don't crash when attempting to draw using GL_TRIANGLES without a program bound.
TEST_P(SimpleOperationTest31,DrawTrianglesWithoutProgramBound)1352 TEST_P(SimpleOperationTest31, DrawTrianglesWithoutProgramBound)
1353 {
1354 glDrawArrays(GL_TRIANGLES, 0, 6);
1355 }
1356
1357 // Verify we don't crash when attempting to draw using GL_LINE_STRIP_ADJACENCY without a program
1358 // bound.
TEST_P(SimpleOperationTest31,DrawLineStripAdjacencyWithoutProgramBound)1359 TEST_P(SimpleOperationTest31, DrawLineStripAdjacencyWithoutProgramBound)
1360 {
1361 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1362
1363 glDrawArrays(GL_LINE_STRIP_ADJACENCY, 0, 10);
1364 }
1365
1366 // Verify instanceCount == 0 is no-op
TEST_P(SimpleOperationTest,DrawArraysZeroInstanceCountIsNoOp)1367 TEST_P(SimpleOperationTest, DrawArraysZeroInstanceCountIsNoOp)
1368 {
1369 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
1370
1371 // Draw a correct green quad.
1372 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1373 glUseProgram(program);
1374
1375 GLint positionLocation = glGetAttribLocation(program, "position");
1376 ASSERT_NE(-1, positionLocation);
1377
1378 setupQuadVertexBuffer(0.5f, 1.0f);
1379 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1380 glEnableVertexAttribArray(positionLocation);
1381
1382 // If nothing is drawn it should be red
1383 glClearColor(1.0, 0.0, 0.0, 1.0);
1384
1385 {
1386 // Non-instanced draw should draw
1387 glClear(GL_COLOR_BUFFER_BIT);
1388 glDrawArrays(GL_TRIANGLES, 0, 6);
1389 ASSERT_GL_NO_ERROR();
1390 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1391 }
1392 {
1393 // instanceCount == 0 should be no-op
1394 glClear(GL_COLOR_BUFFER_BIT);
1395 glDrawArraysInstancedANGLE(GL_TRIANGLES, 0, 6, 0);
1396 ASSERT_GL_NO_ERROR();
1397 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1398 }
1399 {
1400 // instanceCount > 0 should draw
1401 glClear(GL_COLOR_BUFFER_BIT);
1402 glDrawArraysInstancedANGLE(GL_TRIANGLES, 0, 6, 1);
1403 ASSERT_GL_NO_ERROR();
1404 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1405 }
1406 }
1407
1408 // Verify instanceCount == 0 is no-op
TEST_P(SimpleOperationTest,DrawElementsZeroInstanceCountIsNoOp)1409 TEST_P(SimpleOperationTest, DrawElementsZeroInstanceCountIsNoOp)
1410 {
1411 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
1412
1413 // Draw a correct green quad.
1414 ANGLE_GL_PROGRAM(program, kBasicVertexShader, kGreenFragmentShader);
1415 glUseProgram(program);
1416
1417 GLint positionLocation = glGetAttribLocation(program, "position");
1418 ASSERT_NE(-1, positionLocation);
1419
1420 setupIndexedQuadVertexBuffer(0.5f, 1.0f);
1421 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
1422 glEnableVertexAttribArray(positionLocation);
1423
1424 setupIndexedQuadIndexBuffer();
1425
1426 // If nothing is drawn it should be red
1427 glClearColor(1.0, 0.0, 0.0, 1.0);
1428
1429 {
1430 // Non-instanced draw should draw
1431 glClear(GL_COLOR_BUFFER_BIT);
1432 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
1433 ASSERT_GL_NO_ERROR();
1434 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1435 }
1436 {
1437 // instanceCount == 0 should be no-op
1438 glClear(GL_COLOR_BUFFER_BIT);
1439 glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr, 0);
1440 ASSERT_GL_NO_ERROR();
1441 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1442 }
1443 {
1444 // instanceCount > 0 should draw
1445 glClear(GL_COLOR_BUFFER_BIT);
1446 glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr, 1);
1447 ASSERT_GL_NO_ERROR();
1448 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1449 }
1450 }
1451
1452 // Test that sample coverage does not affect single sample rendering
TEST_P(SimpleOperationTest,DrawSingleSampleWithCoverage)1453 TEST_P(SimpleOperationTest, DrawSingleSampleWithCoverage)
1454 {
1455 GLint sampleBuffers = -1;
1456 glGetIntegerv(GL_SAMPLE_BUFFERS, &sampleBuffers);
1457 ASSERT_EQ(sampleBuffers, 0);
1458
1459 GLint samples = -1;
1460 glGetIntegerv(GL_SAMPLES, &samples);
1461 ASSERT_EQ(samples, 0);
1462
1463 glClearColor(1.0, 0.0, 1.0, 1.0);
1464 glClear(GL_COLOR_BUFFER_BIT);
1465
1466 glEnable(GL_SAMPLE_COVERAGE);
1467 glSampleCoverage(0.0f, false);
1468
1469 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1470 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
1471 ASSERT_GL_NO_ERROR();
1472
1473 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1474 }
1475
1476 // Test that sample coverage affects multi sample rendering with only one sample
TEST_P(SimpleOperationTest,DrawSingleMultiSampleWithCoverage)1477 TEST_P(SimpleOperationTest, DrawSingleMultiSampleWithCoverage)
1478 {
1479 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1480
1481 GLFramebuffer fbo;
1482 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1483
1484 GLRenderbuffer rbo;
1485 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1486 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1487 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1488 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1489
1490 GLint samples = -1;
1491 glGetIntegerv(GL_SAMPLES, &samples);
1492 ASSERT_GT(samples, 0);
1493 ANGLE_SKIP_TEST_IF(samples != 1);
1494
1495 glClearColor(0.0, 0.0, 1.0, 1.0);
1496 glClear(GL_COLOR_BUFFER_BIT);
1497
1498 glEnable(GL_SAMPLE_COVERAGE);
1499 glSampleCoverage(0.0f, false);
1500
1501 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1502 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
1503 ASSERT_GL_NO_ERROR();
1504
1505 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1506 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1507 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1508 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1509 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1510 }
1511
1512 // Test that alpha-to-coverage does not affect single-sampled rendering
TEST_P(SimpleOperationTest,DrawSingleSampleWithAlphaToCoverage)1513 TEST_P(SimpleOperationTest, DrawSingleSampleWithAlphaToCoverage)
1514 {
1515 GLint sampleBuffers = -1;
1516 glGetIntegerv(GL_SAMPLE_BUFFERS, &sampleBuffers);
1517 ASSERT_EQ(sampleBuffers, 0);
1518
1519 GLint samples = -1;
1520 glGetIntegerv(GL_SAMPLES, &samples);
1521 ASSERT_EQ(samples, 0);
1522
1523 glClearColor(1.0, 0.0, 1.0, 1.0);
1524 glClear(GL_COLOR_BUFFER_BIT);
1525
1526 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1527
1528 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1529 glUseProgram(program);
1530 glUniform4f(glGetUniformLocation(program, essl1_shaders::ColorUniform()), 0, 1, 0, 0);
1531 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
1532 ASSERT_GL_NO_ERROR();
1533
1534 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(0, 255, 0, 0));
1535 }
1536
1537 // Test that alpha-to-coverage affects multisampled rendering with only one sample
TEST_P(SimpleOperationTest,DrawSingleMultiSampleWithAlphaToCoverage)1538 TEST_P(SimpleOperationTest, DrawSingleMultiSampleWithAlphaToCoverage)
1539 {
1540 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1541
1542 GLFramebuffer fbo;
1543 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1544
1545 GLRenderbuffer rbo;
1546 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1547 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1548 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1549 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1550
1551 GLint samples = -1;
1552 glGetIntegerv(GL_SAMPLES, &samples);
1553 ASSERT_GT(samples, 0);
1554 ANGLE_SKIP_TEST_IF(samples != 1);
1555
1556 glClearColor(0.0, 0.0, 1.0, 1.0);
1557 glClear(GL_COLOR_BUFFER_BIT);
1558
1559 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
1560
1561 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1562 glUseProgram(program);
1563 glUniform4f(glGetUniformLocation(program, essl1_shaders::ColorUniform()), 0, 1, 0, 0);
1564 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0);
1565 ASSERT_GL_NO_ERROR();
1566
1567 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
1568 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1569 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1570 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1571 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1572 }
1573
1574 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1575 // tests should be run against.
1576 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
1577 SimpleOperationTest,
1578 ES3_METAL().enable(Feature::ForceBufferGPUStorage),
1579 ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
1580 WithVulkanSecondaries(ES3_VULKAN_SWIFTSHADER()));
1581
1582 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
1583 TriangleFanDrawTest,
1584 ES3_METAL().enable(Feature::ForceBufferGPUStorage),
1585 ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass));
1586
1587 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(SimpleOperationTest31);
1588
1589 } // namespace
1590