xref: /aosp_15_r20/external/angle/src/tests/gl_tests/MultiDrawTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // MultiDrawTest: Tests of GL_ANGLE_multi_draw
8*8975f5c5SAndroid Build Coastguard Worker // MultiDrawIndirectTest: Tests of GL_EXT_multi_draw_indirect
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
11*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker namespace
16*8975f5c5SAndroid Build Coastguard Worker {
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker // Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
19*8975f5c5SAndroid Build Coastguard Worker // each containing a quad partially covering each tile
20*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kWidth                  = 256;
21*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kHeight                 = 256;
22*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kCountX                 = 8;
23*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kCountY                 = 8;
24*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kQuadCount              = kCountX * kCountY;
25*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kTriCount               = kQuadCount * 2;
26*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<GLfloat, 2> kTileSize = {
27*8975f5c5SAndroid Build Coastguard Worker     1.f / static_cast<GLfloat>(kCountX),
28*8975f5c5SAndroid Build Coastguard Worker     1.f / static_cast<GLfloat>(kCountY),
29*8975f5c5SAndroid Build Coastguard Worker };
30*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<uint32_t, 2> kTilePixelSize  = {kWidth / kCountX, kHeight / kCountY};
31*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<GLfloat, 2> kQuadRadius      = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
32*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<uint32_t, 2> kPixelCheckSize = {
33*8975f5c5SAndroid Build Coastguard Worker     static_cast<uint32_t>(kQuadRadius[0] * kWidth),
34*8975f5c5SAndroid Build Coastguard Worker     static_cast<uint32_t>(kQuadRadius[1] * kHeight)};
35*8975f5c5SAndroid Build Coastguard Worker 
getTileCenter(uint32_t x,uint32_t y)36*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<GLfloat, 2> getTileCenter(uint32_t x, uint32_t y)
37*8975f5c5SAndroid Build Coastguard Worker {
38*8975f5c5SAndroid Build Coastguard Worker     return {
39*8975f5c5SAndroid Build Coastguard Worker         kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
40*8975f5c5SAndroid Build Coastguard Worker         kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
41*8975f5c5SAndroid Build Coastguard Worker     };
42*8975f5c5SAndroid Build Coastguard Worker }
getQuadVertices(uint32_t x,uint32_t y)43*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<std::array<GLfloat, 3>, 4> getQuadVertices(uint32_t x, uint32_t y)
44*8975f5c5SAndroid Build Coastguard Worker {
45*8975f5c5SAndroid Build Coastguard Worker     const auto center = getTileCenter(x, y);
46*8975f5c5SAndroid Build Coastguard Worker     return {
47*8975f5c5SAndroid Build Coastguard Worker         std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
48*8975f5c5SAndroid Build Coastguard Worker         std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
49*8975f5c5SAndroid Build Coastguard Worker         std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
50*8975f5c5SAndroid Build Coastguard Worker         std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
51*8975f5c5SAndroid Build Coastguard Worker     };
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker 
54*8975f5c5SAndroid Build Coastguard Worker enum class DrawIDOption
55*8975f5c5SAndroid Build Coastguard Worker {
56*8975f5c5SAndroid Build Coastguard Worker     NoDrawID,
57*8975f5c5SAndroid Build Coastguard Worker     UseDrawID,
58*8975f5c5SAndroid Build Coastguard Worker };
59*8975f5c5SAndroid Build Coastguard Worker 
60*8975f5c5SAndroid Build Coastguard Worker enum class InstancingOption
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker     NoInstancing,
63*8975f5c5SAndroid Build Coastguard Worker     UseInstancing,
64*8975f5c5SAndroid Build Coastguard Worker };
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker enum class BufferDataUsageOption
67*8975f5c5SAndroid Build Coastguard Worker {
68*8975f5c5SAndroid Build Coastguard Worker     StaticDraw,
69*8975f5c5SAndroid Build Coastguard Worker     DynamicDraw
70*8975f5c5SAndroid Build Coastguard Worker };
71*8975f5c5SAndroid Build Coastguard Worker 
72*8975f5c5SAndroid Build Coastguard Worker using MultiDrawTestParams =
73*8975f5c5SAndroid Build Coastguard Worker     std::tuple<angle::PlatformParameters, DrawIDOption, InstancingOption, BufferDataUsageOption>;
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker using MultiDrawIndirectTestParams = angle::PlatformParameters;
76*8975f5c5SAndroid Build Coastguard Worker 
77*8975f5c5SAndroid Build Coastguard Worker struct PrintToStringParamName
78*8975f5c5SAndroid Build Coastguard Worker {
operator ()__anon0e40ab140111::PrintToStringParamName79*8975f5c5SAndroid Build Coastguard Worker     std::string operator()(const ::testing::TestParamInfo<MultiDrawTestParams> &info) const
80*8975f5c5SAndroid Build Coastguard Worker     {
81*8975f5c5SAndroid Build Coastguard Worker         ::std::stringstream ss;
82*8975f5c5SAndroid Build Coastguard Worker         ss << std::get<0>(info.param)
83*8975f5c5SAndroid Build Coastguard Worker            << (std::get<3>(info.param) == BufferDataUsageOption::StaticDraw ? "__StaticDraw"
84*8975f5c5SAndroid Build Coastguard Worker                                                                             : "__DynamicDraw")
85*8975f5c5SAndroid Build Coastguard Worker            << (std::get<2>(info.param) == InstancingOption::UseInstancing ? "__Instanced" : "")
86*8975f5c5SAndroid Build Coastguard Worker            << (std::get<1>(info.param) == DrawIDOption::UseDrawID ? "__DrawID" : "");
87*8975f5c5SAndroid Build Coastguard Worker         return ss.str();
88*8975f5c5SAndroid Build Coastguard Worker     }
89*8975f5c5SAndroid Build Coastguard Worker };
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker struct DrawArraysIndirectCommand
92*8975f5c5SAndroid Build Coastguard Worker {
DrawArraysIndirectCommand__anon0e40ab140111::DrawArraysIndirectCommand93*8975f5c5SAndroid Build Coastguard Worker     DrawArraysIndirectCommand() : count(0u), instanceCount(0u), first(0u), baseInstance(0u) {}
DrawArraysIndirectCommand__anon0e40ab140111::DrawArraysIndirectCommand94*8975f5c5SAndroid Build Coastguard Worker     DrawArraysIndirectCommand(GLuint count, GLuint instanceCount, GLuint first, GLuint baseInstance)
95*8975f5c5SAndroid Build Coastguard Worker         : count(count), instanceCount(instanceCount), first(first), baseInstance(baseInstance)
96*8975f5c5SAndroid Build Coastguard Worker     {}
97*8975f5c5SAndroid Build Coastguard Worker     GLuint count;
98*8975f5c5SAndroid Build Coastguard Worker     GLuint instanceCount;
99*8975f5c5SAndroid Build Coastguard Worker     GLuint first;
100*8975f5c5SAndroid Build Coastguard Worker     GLuint baseInstance;
101*8975f5c5SAndroid Build Coastguard Worker };
102*8975f5c5SAndroid Build Coastguard Worker 
103*8975f5c5SAndroid Build Coastguard Worker struct DrawElementsIndirectCommand
104*8975f5c5SAndroid Build Coastguard Worker {
DrawElementsIndirectCommand__anon0e40ab140111::DrawElementsIndirectCommand105*8975f5c5SAndroid Build Coastguard Worker     DrawElementsIndirectCommand()
106*8975f5c5SAndroid Build Coastguard Worker         : count(0), primCount(0), firstIndex(0), baseVertex(0), baseInstance(0)
107*8975f5c5SAndroid Build Coastguard Worker     {}
DrawElementsIndirectCommand__anon0e40ab140111::DrawElementsIndirectCommand108*8975f5c5SAndroid Build Coastguard Worker     DrawElementsIndirectCommand(GLuint count,
109*8975f5c5SAndroid Build Coastguard Worker                                 GLuint primCount,
110*8975f5c5SAndroid Build Coastguard Worker                                 GLuint firstIndex,
111*8975f5c5SAndroid Build Coastguard Worker                                 GLint baseVertex,
112*8975f5c5SAndroid Build Coastguard Worker                                 GLuint baseInstance)
113*8975f5c5SAndroid Build Coastguard Worker         : count(count),
114*8975f5c5SAndroid Build Coastguard Worker           primCount(primCount),
115*8975f5c5SAndroid Build Coastguard Worker           firstIndex(firstIndex),
116*8975f5c5SAndroid Build Coastguard Worker           baseVertex(baseVertex),
117*8975f5c5SAndroid Build Coastguard Worker           baseInstance(baseInstance)
118*8975f5c5SAndroid Build Coastguard Worker     {}
119*8975f5c5SAndroid Build Coastguard Worker     GLuint count;
120*8975f5c5SAndroid Build Coastguard Worker     GLuint primCount;
121*8975f5c5SAndroid Build Coastguard Worker     GLuint firstIndex;
122*8975f5c5SAndroid Build Coastguard Worker     GLint baseVertex;
123*8975f5c5SAndroid Build Coastguard Worker     GLuint baseInstance;
124*8975f5c5SAndroid Build Coastguard Worker };
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker // The tests in MultiDrawTest and MultiDrawNoInstancingSupportTest check the correctness
127*8975f5c5SAndroid Build Coastguard Worker // of the ANGLE_multi_draw extension.
128*8975f5c5SAndroid Build Coastguard Worker // An array of quads is drawn across the screen.
129*8975f5c5SAndroid Build Coastguard Worker // gl_DrawID is checked by using it to select the color of the draw.
130*8975f5c5SAndroid Build Coastguard Worker // MultiDraw*Instanced entrypoints use the existing instancing APIs which are
131*8975f5c5SAndroid Build Coastguard Worker // more fully tested in InstancingTest.cpp.
132*8975f5c5SAndroid Build Coastguard Worker // Correct interaction with the instancing APIs is tested here by using scaling
133*8975f5c5SAndroid Build Coastguard Worker // and then instancing the array of quads over four quadrants on the screen.
134*8975f5c5SAndroid Build Coastguard Worker class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam<MultiDrawTestParams>
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker   protected:
MultiDrawTest()137*8975f5c5SAndroid Build Coastguard Worker     MultiDrawTest()
138*8975f5c5SAndroid Build Coastguard Worker         : ANGLETestBase(std::get<0>(GetParam())),
139*8975f5c5SAndroid Build Coastguard Worker           mNonIndexedVertexBuffer(0u),
140*8975f5c5SAndroid Build Coastguard Worker           mVertexBuffer(0u),
141*8975f5c5SAndroid Build Coastguard Worker           mIndexBuffer(0u),
142*8975f5c5SAndroid Build Coastguard Worker           mInstanceBuffer(0u),
143*8975f5c5SAndroid Build Coastguard Worker           mProgram(0u),
144*8975f5c5SAndroid Build Coastguard Worker           mPositionLoc(0u),
145*8975f5c5SAndroid Build Coastguard Worker           mInstanceLoc(0u)
146*8975f5c5SAndroid Build Coastguard Worker     {
147*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(kWidth);
148*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(kHeight);
149*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
150*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
151*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
152*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
153*8975f5c5SAndroid Build Coastguard Worker     }
154*8975f5c5SAndroid Build Coastguard Worker 
SetUp()155*8975f5c5SAndroid Build Coastguard Worker     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
156*8975f5c5SAndroid Build Coastguard Worker 
IsDrawIDTest() const157*8975f5c5SAndroid Build Coastguard Worker     bool IsDrawIDTest() const { return std::get<1>(GetParam()) == DrawIDOption::UseDrawID; }
158*8975f5c5SAndroid Build Coastguard Worker 
IsInstancedTest() const159*8975f5c5SAndroid Build Coastguard Worker     bool IsInstancedTest() const
160*8975f5c5SAndroid Build Coastguard Worker     {
161*8975f5c5SAndroid Build Coastguard Worker         return std::get<2>(GetParam()) == InstancingOption::UseInstancing;
162*8975f5c5SAndroid Build Coastguard Worker     }
163*8975f5c5SAndroid Build Coastguard Worker 
getBufferDataUsage() const164*8975f5c5SAndroid Build Coastguard Worker     GLenum getBufferDataUsage() const
165*8975f5c5SAndroid Build Coastguard Worker     {
166*8975f5c5SAndroid Build Coastguard Worker         return std::get<3>(GetParam()) == BufferDataUsageOption::StaticDraw ? GL_STATIC_DRAW
167*8975f5c5SAndroid Build Coastguard Worker                                                                             : GL_DYNAMIC_DRAW;
168*8975f5c5SAndroid Build Coastguard Worker     }
169*8975f5c5SAndroid Build Coastguard Worker 
VertexShaderSource()170*8975f5c5SAndroid Build Coastguard Worker     std::string VertexShaderSource()
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker 
173*8975f5c5SAndroid Build Coastguard Worker         std::stringstream shader;
174*8975f5c5SAndroid Build Coastguard Worker         shader << (IsDrawIDTest() ? "#extension GL_ANGLE_multi_draw : require\n" : "")
175*8975f5c5SAndroid Build Coastguard Worker                << (IsInstancedTest() ? "attribute float vInstance;" : "") << R"(
176*8975f5c5SAndroid Build Coastguard Worker attribute vec2 vPosition;
177*8975f5c5SAndroid Build Coastguard Worker varying vec4 color;
178*8975f5c5SAndroid Build Coastguard Worker void main()
179*8975f5c5SAndroid Build Coastguard Worker {
180*8975f5c5SAndroid Build Coastguard Worker     int id = )" << (IsDrawIDTest() ? "gl_DrawID" : "0")
181*8975f5c5SAndroid Build Coastguard Worker                << ";" << R"(
182*8975f5c5SAndroid Build Coastguard Worker     float quad_id = float(id / 2);
183*8975f5c5SAndroid Build Coastguard Worker     float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
184*8975f5c5SAndroid Build Coastguard Worker     if (color_id == 0.0) {
185*8975f5c5SAndroid Build Coastguard Worker       color = vec4(1, 0, 0, 1);
186*8975f5c5SAndroid Build Coastguard Worker     } else if (color_id == 1.0) {
187*8975f5c5SAndroid Build Coastguard Worker       color = vec4(0, 1, 0, 1);
188*8975f5c5SAndroid Build Coastguard Worker     } else {
189*8975f5c5SAndroid Build Coastguard Worker       color = vec4(0, 0, 1, 1);
190*8975f5c5SAndroid Build Coastguard Worker     }
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker     mat3 transform = mat3(1.0);
193*8975f5c5SAndroid Build Coastguard Worker )"
194*8975f5c5SAndroid Build Coastguard Worker                << (IsInstancedTest() ? R"(
195*8975f5c5SAndroid Build Coastguard Worker     transform[0][0] = 0.5;
196*8975f5c5SAndroid Build Coastguard Worker     transform[1][1] = 0.5;
197*8975f5c5SAndroid Build Coastguard Worker     if (vInstance == 0.0) {
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker     } else if (vInstance == 1.0) {
200*8975f5c5SAndroid Build Coastguard Worker         transform[2][0] = 0.5;
201*8975f5c5SAndroid Build Coastguard Worker     } else if (vInstance == 2.0) {
202*8975f5c5SAndroid Build Coastguard Worker         transform[2][1] = 0.5;
203*8975f5c5SAndroid Build Coastguard Worker     } else if (vInstance == 3.0) {
204*8975f5c5SAndroid Build Coastguard Worker         transform[2][0] = 0.5;
205*8975f5c5SAndroid Build Coastguard Worker         transform[2][1] = 0.5;
206*8975f5c5SAndroid Build Coastguard Worker     }
207*8975f5c5SAndroid Build Coastguard Worker )"
208*8975f5c5SAndroid Build Coastguard Worker                                      : "")
209*8975f5c5SAndroid Build Coastguard Worker                << R"(
210*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
211*8975f5c5SAndroid Build Coastguard Worker })";
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker         return shader.str();
214*8975f5c5SAndroid Build Coastguard Worker     }
215*8975f5c5SAndroid Build Coastguard Worker 
FragmentShaderSource()216*8975f5c5SAndroid Build Coastguard Worker     std::string FragmentShaderSource()
217*8975f5c5SAndroid Build Coastguard Worker     {
218*8975f5c5SAndroid Build Coastguard Worker         return
219*8975f5c5SAndroid Build Coastguard Worker             R"(precision mediump float;
220*8975f5c5SAndroid Build Coastguard Worker             varying vec4 color;
221*8975f5c5SAndroid Build Coastguard Worker             void main()
222*8975f5c5SAndroid Build Coastguard Worker             {
223*8975f5c5SAndroid Build Coastguard Worker                 gl_FragColor = color;
224*8975f5c5SAndroid Build Coastguard Worker             })";
225*8975f5c5SAndroid Build Coastguard Worker     }
226*8975f5c5SAndroid Build Coastguard Worker 
SetupProgram()227*8975f5c5SAndroid Build Coastguard Worker     void SetupProgram()
228*8975f5c5SAndroid Build Coastguard Worker     {
229*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(VertexShaderSource().c_str(), FragmentShaderSource().c_str());
230*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
231*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GE(mProgram, 1u);
232*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram);
233*8975f5c5SAndroid Build Coastguard Worker         mPositionLoc = glGetAttribLocation(mProgram, "vPosition");
234*8975f5c5SAndroid Build Coastguard Worker         mInstanceLoc = glGetAttribLocation(mProgram, "vInstance");
235*8975f5c5SAndroid Build Coastguard Worker     }
236*8975f5c5SAndroid Build Coastguard Worker 
SetupBuffers()237*8975f5c5SAndroid Build Coastguard Worker     void SetupBuffers()
238*8975f5c5SAndroid Build Coastguard Worker     {
239*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t y = 0; y < kCountY; ++y)
240*8975f5c5SAndroid Build Coastguard Worker         {
241*8975f5c5SAndroid Build Coastguard Worker             for (uint32_t x = 0; x < kCountX; ++x)
242*8975f5c5SAndroid Build Coastguard Worker             {
243*8975f5c5SAndroid Build Coastguard Worker                 // v3 ---- v2
244*8975f5c5SAndroid Build Coastguard Worker                 // |       |
245*8975f5c5SAndroid Build Coastguard Worker                 // |       |
246*8975f5c5SAndroid Build Coastguard Worker                 // v0 ---- v1
247*8975f5c5SAndroid Build Coastguard Worker                 uint32_t quadIndex         = y * kCountX + x;
248*8975f5c5SAndroid Build Coastguard Worker                 GLushort starting_index    = static_cast<GLushort>(4 * quadIndex);
249*8975f5c5SAndroid Build Coastguard Worker                 std::array<GLushort, 6> is = {0, 1, 2, 0, 2, 3};
250*8975f5c5SAndroid Build Coastguard Worker                 const auto vs              = getQuadVertices(x, y);
251*8975f5c5SAndroid Build Coastguard Worker                 for (GLushort i : is)
252*8975f5c5SAndroid Build Coastguard Worker                 {
253*8975f5c5SAndroid Build Coastguard Worker                     mIndices.push_back(starting_index + i);
254*8975f5c5SAndroid Build Coastguard Worker                 }
255*8975f5c5SAndroid Build Coastguard Worker 
256*8975f5c5SAndroid Build Coastguard Worker                 for (const auto &v : vs)
257*8975f5c5SAndroid Build Coastguard Worker                 {
258*8975f5c5SAndroid Build Coastguard Worker                     mVertices.insert(mVertices.end(), v.begin(), v.end());
259*8975f5c5SAndroid Build Coastguard Worker                 }
260*8975f5c5SAndroid Build Coastguard Worker 
261*8975f5c5SAndroid Build Coastguard Worker                 for (GLushort i : is)
262*8975f5c5SAndroid Build Coastguard Worker                 {
263*8975f5c5SAndroid Build Coastguard Worker                     mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(),
264*8975f5c5SAndroid Build Coastguard Worker                                                vs[i].end());
265*8975f5c5SAndroid Build Coastguard Worker                 }
266*8975f5c5SAndroid Build Coastguard Worker             }
267*8975f5c5SAndroid Build Coastguard Worker         }
268*8975f5c5SAndroid Build Coastguard Worker 
269*8975f5c5SAndroid Build Coastguard Worker         std::array<GLfloat, 4> instances{0, 1, 2, 3};
270*8975f5c5SAndroid Build Coastguard Worker 
271*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mNonIndexedVertexBuffer);
272*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
273*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
274*8975f5c5SAndroid Build Coastguard Worker                      mNonIndexedVertices.data(), getBufferDataUsage());
275*8975f5c5SAndroid Build Coastguard Worker 
276*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mVertexBuffer);
277*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
278*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
279*8975f5c5SAndroid Build Coastguard Worker                      getBufferDataUsage());
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mIndexBuffer);
282*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
283*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
284*8975f5c5SAndroid Build Coastguard Worker                      getBufferDataUsage());
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mInstanceBuffer);
287*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
288*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * instances.size(), instances.data(),
289*8975f5c5SAndroid Build Coastguard Worker                      getBufferDataUsage());
290*8975f5c5SAndroid Build Coastguard Worker 
291*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
292*8975f5c5SAndroid Build Coastguard Worker     }
293*8975f5c5SAndroid Build Coastguard Worker 
DoVertexAttribDivisor(GLint location,GLuint divisor)294*8975f5c5SAndroid Build Coastguard Worker     void DoVertexAttribDivisor(GLint location, GLuint divisor)
295*8975f5c5SAndroid Build Coastguard Worker     {
296*8975f5c5SAndroid Build Coastguard Worker         if (getClientMajorVersion() <= 2)
297*8975f5c5SAndroid Build Coastguard Worker         {
298*8975f5c5SAndroid Build Coastguard Worker             ASSERT_TRUE(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
299*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisorANGLE(location, divisor);
300*8975f5c5SAndroid Build Coastguard Worker         }
301*8975f5c5SAndroid Build Coastguard Worker         else
302*8975f5c5SAndroid Build Coastguard Worker         {
303*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribDivisor(location, divisor);
304*8975f5c5SAndroid Build Coastguard Worker         }
305*8975f5c5SAndroid Build Coastguard Worker     }
306*8975f5c5SAndroid Build Coastguard Worker 
DoDrawArrays()307*8975f5c5SAndroid Build Coastguard Worker     void DoDrawArrays()
308*8975f5c5SAndroid Build Coastguard Worker     {
309*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
311*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(mPositionLoc);
312*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
313*8975f5c5SAndroid Build Coastguard Worker 
314*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLint> firsts(kTriCount);
315*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLsizei> counts(kTriCount, 3);
316*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t i = 0; i < kTriCount; ++i)
317*8975f5c5SAndroid Build Coastguard Worker         {
318*8975f5c5SAndroid Build Coastguard Worker             firsts[i] = i * 3;
319*8975f5c5SAndroid Build Coastguard Worker         }
320*8975f5c5SAndroid Build Coastguard Worker 
321*8975f5c5SAndroid Build Coastguard Worker         if (IsInstancedTest())
322*8975f5c5SAndroid Build Coastguard Worker         {
323*8975f5c5SAndroid Build Coastguard Worker             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
324*8975f5c5SAndroid Build Coastguard Worker             glEnableVertexAttribArray(mInstanceLoc);
325*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
326*8975f5c5SAndroid Build Coastguard Worker             DoVertexAttribDivisor(mInstanceLoc, 1);
327*8975f5c5SAndroid Build Coastguard Worker             std::vector<GLsizei> instanceCounts(kTriCount, 4);
328*8975f5c5SAndroid Build Coastguard Worker             glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
329*8975f5c5SAndroid Build Coastguard Worker                                             instanceCounts.data(), kTriCount);
330*8975f5c5SAndroid Build Coastguard Worker         }
331*8975f5c5SAndroid Build Coastguard Worker         else
332*8975f5c5SAndroid Build Coastguard Worker         {
333*8975f5c5SAndroid Build Coastguard Worker             glMultiDrawArraysANGLE(GL_TRIANGLES, firsts.data(), counts.data(), kTriCount);
334*8975f5c5SAndroid Build Coastguard Worker         }
335*8975f5c5SAndroid Build Coastguard Worker     }
336*8975f5c5SAndroid Build Coastguard Worker 
DoDrawElements()337*8975f5c5SAndroid Build Coastguard Worker     void DoDrawElements()
338*8975f5c5SAndroid Build Coastguard Worker     {
339*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
340*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
341*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
342*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(mPositionLoc);
343*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
344*8975f5c5SAndroid Build Coastguard Worker 
345*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLsizei> counts(kTriCount, 3);
346*8975f5c5SAndroid Build Coastguard Worker         std::vector<const GLvoid *> indices(kTriCount);
347*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t i = 0; i < kTriCount; ++i)
348*8975f5c5SAndroid Build Coastguard Worker         {
349*8975f5c5SAndroid Build Coastguard Worker             indices[i] = reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * 2));
350*8975f5c5SAndroid Build Coastguard Worker         }
351*8975f5c5SAndroid Build Coastguard Worker 
352*8975f5c5SAndroid Build Coastguard Worker         if (IsInstancedTest())
353*8975f5c5SAndroid Build Coastguard Worker         {
354*8975f5c5SAndroid Build Coastguard Worker             glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
355*8975f5c5SAndroid Build Coastguard Worker             glEnableVertexAttribArray(mInstanceLoc);
356*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
357*8975f5c5SAndroid Build Coastguard Worker             DoVertexAttribDivisor(mInstanceLoc, 1);
358*8975f5c5SAndroid Build Coastguard Worker             std::vector<GLsizei> instanceCounts(kTriCount, 4);
359*8975f5c5SAndroid Build Coastguard Worker             glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT,
360*8975f5c5SAndroid Build Coastguard Worker                                               indices.data(), instanceCounts.data(), kTriCount);
361*8975f5c5SAndroid Build Coastguard Worker         }
362*8975f5c5SAndroid Build Coastguard Worker         else
363*8975f5c5SAndroid Build Coastguard Worker         {
364*8975f5c5SAndroid Build Coastguard Worker             glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, indices.data(),
365*8975f5c5SAndroid Build Coastguard Worker                                      kTriCount);
366*8975f5c5SAndroid Build Coastguard Worker         }
367*8975f5c5SAndroid Build Coastguard Worker     }
368*8975f5c5SAndroid Build Coastguard Worker 
369*8975f5c5SAndroid Build Coastguard Worker     enum class DrawIDOptionOverride
370*8975f5c5SAndroid Build Coastguard Worker     {
371*8975f5c5SAndroid Build Coastguard Worker         Default,
372*8975f5c5SAndroid Build Coastguard Worker         NoDrawID,
373*8975f5c5SAndroid Build Coastguard Worker         UseDrawID,
374*8975f5c5SAndroid Build Coastguard Worker     };
375*8975f5c5SAndroid Build Coastguard Worker 
CheckDrawResult(DrawIDOptionOverride overrideDrawID)376*8975f5c5SAndroid Build Coastguard Worker     void CheckDrawResult(DrawIDOptionOverride overrideDrawID)
377*8975f5c5SAndroid Build Coastguard Worker     {
378*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t y = 0; y < kCountY; ++y)
379*8975f5c5SAndroid Build Coastguard Worker         {
380*8975f5c5SAndroid Build Coastguard Worker             for (uint32_t x = 0; x < kCountX; ++x)
381*8975f5c5SAndroid Build Coastguard Worker             {
382*8975f5c5SAndroid Build Coastguard Worker                 uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
383*8975f5c5SAndroid Build Coastguard Worker                 uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
384*8975f5c5SAndroid Build Coastguard Worker                 uint32_t quadID = IsDrawIDTest() && overrideDrawID != DrawIDOptionOverride::NoDrawID
385*8975f5c5SAndroid Build Coastguard Worker                                       ? y * kCountX + x
386*8975f5c5SAndroid Build Coastguard Worker                                       : 0;
387*8975f5c5SAndroid Build Coastguard Worker                 uint32_t colorID              = quadID % 3u;
388*8975f5c5SAndroid Build Coastguard Worker                 std::array<GLColor, 3> colors = {GLColor(255, 0, 0, 255), GLColor(0, 255, 0, 255),
389*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor(0, 0, 255, 255)};
390*8975f5c5SAndroid Build Coastguard Worker                 GLColor expected              = colors[colorID];
391*8975f5c5SAndroid Build Coastguard Worker 
392*8975f5c5SAndroid Build Coastguard Worker                 if (IsInstancedTest())
393*8975f5c5SAndroid Build Coastguard Worker                 {
394*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
395*8975f5c5SAndroid Build Coastguard Worker                                          center_y / 2 - kPixelCheckSize[1] / 4,
396*8975f5c5SAndroid Build Coastguard Worker                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
397*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
398*8975f5c5SAndroid Build Coastguard Worker                                          center_y / 2 - kPixelCheckSize[1] / 4,
399*8975f5c5SAndroid Build Coastguard Worker                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
400*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
401*8975f5c5SAndroid Build Coastguard Worker                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
402*8975f5c5SAndroid Build Coastguard Worker                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
403*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
404*8975f5c5SAndroid Build Coastguard Worker                                          center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
405*8975f5c5SAndroid Build Coastguard Worker                                          kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
406*8975f5c5SAndroid Build Coastguard Worker                 }
407*8975f5c5SAndroid Build Coastguard Worker                 else
408*8975f5c5SAndroid Build Coastguard Worker                 {
409*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT_EQ(center_x - kPixelCheckSize[0] / 2,
410*8975f5c5SAndroid Build Coastguard Worker                                          center_y - kPixelCheckSize[1] / 2, kPixelCheckSize[0],
411*8975f5c5SAndroid Build Coastguard Worker                                          kPixelCheckSize[1], expected);
412*8975f5c5SAndroid Build Coastguard Worker                 }
413*8975f5c5SAndroid Build Coastguard Worker             }
414*8975f5c5SAndroid Build Coastguard Worker         }
415*8975f5c5SAndroid Build Coastguard Worker     }
416*8975f5c5SAndroid Build Coastguard Worker 
TearDown()417*8975f5c5SAndroid Build Coastguard Worker     void TearDown() override
418*8975f5c5SAndroid Build Coastguard Worker     {
419*8975f5c5SAndroid Build Coastguard Worker         if (mNonIndexedVertexBuffer != 0u)
420*8975f5c5SAndroid Build Coastguard Worker         {
421*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mNonIndexedVertexBuffer);
422*8975f5c5SAndroid Build Coastguard Worker         }
423*8975f5c5SAndroid Build Coastguard Worker         if (mVertexBuffer != 0u)
424*8975f5c5SAndroid Build Coastguard Worker         {
425*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mVertexBuffer);
426*8975f5c5SAndroid Build Coastguard Worker         }
427*8975f5c5SAndroid Build Coastguard Worker         if (mIndexBuffer != 0u)
428*8975f5c5SAndroid Build Coastguard Worker         {
429*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mIndexBuffer);
430*8975f5c5SAndroid Build Coastguard Worker         }
431*8975f5c5SAndroid Build Coastguard Worker         if (mInstanceBuffer != 0u)
432*8975f5c5SAndroid Build Coastguard Worker         {
433*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mInstanceBuffer);
434*8975f5c5SAndroid Build Coastguard Worker         }
435*8975f5c5SAndroid Build Coastguard Worker         if (mProgram != 0)
436*8975f5c5SAndroid Build Coastguard Worker         {
437*8975f5c5SAndroid Build Coastguard Worker             glDeleteProgram(mProgram);
438*8975f5c5SAndroid Build Coastguard Worker         }
439*8975f5c5SAndroid Build Coastguard Worker         ANGLETestBase::ANGLETestTearDown();
440*8975f5c5SAndroid Build Coastguard Worker     }
441*8975f5c5SAndroid Build Coastguard Worker 
requestMultiDrawExtension()442*8975f5c5SAndroid Build Coastguard Worker     bool requestMultiDrawExtension() { return EnsureGLExtensionEnabled("GL_ANGLE_multi_draw"); }
443*8975f5c5SAndroid Build Coastguard Worker 
requestInstancedExtension()444*8975f5c5SAndroid Build Coastguard Worker     bool requestInstancedExtension()
445*8975f5c5SAndroid Build Coastguard Worker     {
446*8975f5c5SAndroid Build Coastguard Worker         return EnsureGLExtensionEnabled("GL_ANGLE_instanced_arrays");
447*8975f5c5SAndroid Build Coastguard Worker     }
448*8975f5c5SAndroid Build Coastguard Worker 
requestExtensions()449*8975f5c5SAndroid Build Coastguard Worker     bool requestExtensions()
450*8975f5c5SAndroid Build Coastguard Worker     {
451*8975f5c5SAndroid Build Coastguard Worker         if (IsInstancedTest() && getClientMajorVersion() <= 2)
452*8975f5c5SAndroid Build Coastguard Worker         {
453*8975f5c5SAndroid Build Coastguard Worker             if (!requestInstancedExtension())
454*8975f5c5SAndroid Build Coastguard Worker             {
455*8975f5c5SAndroid Build Coastguard Worker                 return false;
456*8975f5c5SAndroid Build Coastguard Worker             }
457*8975f5c5SAndroid Build Coastguard Worker         }
458*8975f5c5SAndroid Build Coastguard Worker         return requestMultiDrawExtension();
459*8975f5c5SAndroid Build Coastguard Worker     }
460*8975f5c5SAndroid Build Coastguard Worker 
461*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLushort> mIndices;
462*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> mVertices;
463*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> mNonIndexedVertices;
464*8975f5c5SAndroid Build Coastguard Worker     GLuint mNonIndexedVertexBuffer;
465*8975f5c5SAndroid Build Coastguard Worker     GLuint mVertexBuffer;
466*8975f5c5SAndroid Build Coastguard Worker     GLuint mIndexBuffer;
467*8975f5c5SAndroid Build Coastguard Worker     GLuint mInstanceBuffer;
468*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
469*8975f5c5SAndroid Build Coastguard Worker     GLint mPositionLoc;
470*8975f5c5SAndroid Build Coastguard Worker     GLint mInstanceLoc;
471*8975f5c5SAndroid Build Coastguard Worker };
472*8975f5c5SAndroid Build Coastguard Worker 
473*8975f5c5SAndroid Build Coastguard Worker class MultiDrawTestES3 : public MultiDrawTest
474*8975f5c5SAndroid Build Coastguard Worker {};
475*8975f5c5SAndroid Build Coastguard Worker 
476*8975f5c5SAndroid Build Coastguard Worker class MultiDrawNoInstancingSupportTest : public MultiDrawTest
477*8975f5c5SAndroid Build Coastguard Worker {
SetUp()478*8975f5c5SAndroid Build Coastguard Worker     void SetUp() override
479*8975f5c5SAndroid Build Coastguard Worker     {
480*8975f5c5SAndroid Build Coastguard Worker         ASSERT_LE(getClientMajorVersion(), 2);
481*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(IsInstancedTest());
482*8975f5c5SAndroid Build Coastguard Worker         MultiDrawTest::SetUp();
483*8975f5c5SAndroid Build Coastguard Worker     }
484*8975f5c5SAndroid Build Coastguard Worker };
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker // The tests in MultiDrawIndirectTest check the correctness
487*8975f5c5SAndroid Build Coastguard Worker // of the EXT_multi_draw_indirect extension.
488*8975f5c5SAndroid Build Coastguard Worker // 4 magenta triangles are drawn at the corners of the screen
489*8975f5c5SAndroid Build Coastguard Worker // in different orders from the same vertex and index arrays.
490*8975f5c5SAndroid Build Coastguard Worker class MultiDrawIndirectTest : public ANGLETestBase,
491*8975f5c5SAndroid Build Coastguard Worker                               public ::testing::TestWithParam<MultiDrawIndirectTestParams>
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker   protected:
MultiDrawIndirectTest()494*8975f5c5SAndroid Build Coastguard Worker     MultiDrawIndirectTest()
495*8975f5c5SAndroid Build Coastguard Worker         : ANGLETestBase(GetParam()),
496*8975f5c5SAndroid Build Coastguard Worker           mPositionLoc(0u),
497*8975f5c5SAndroid Build Coastguard Worker           mColorLoc(0u),
498*8975f5c5SAndroid Build Coastguard Worker           mVertexBuffer(0u),
499*8975f5c5SAndroid Build Coastguard Worker           mColorBuffer(0u),
500*8975f5c5SAndroid Build Coastguard Worker           mIndexBuffer(0u),
501*8975f5c5SAndroid Build Coastguard Worker           mIndirectBuffer(0u),
502*8975f5c5SAndroid Build Coastguard Worker           mProgram(0u)
503*8975f5c5SAndroid Build Coastguard Worker     {
504*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(kWidth);
505*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(kHeight);
506*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
507*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
508*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
509*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
510*8975f5c5SAndroid Build Coastguard Worker     }
511*8975f5c5SAndroid Build Coastguard Worker 
SetUp()512*8975f5c5SAndroid Build Coastguard Worker     void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
513*8975f5c5SAndroid Build Coastguard Worker 
SetupProgramIndirect(bool isMultiColor)514*8975f5c5SAndroid Build Coastguard Worker     void SetupProgramIndirect(bool isMultiColor)
515*8975f5c5SAndroid Build Coastguard Worker     {
516*8975f5c5SAndroid Build Coastguard Worker         // Define the vertex and fragment shaders
517*8975f5c5SAndroid Build Coastguard Worker         std::stringstream kVS;
518*8975f5c5SAndroid Build Coastguard Worker         kVS << R"(#version 310 es
519*8975f5c5SAndroid Build Coastguard Worker in vec3 aPos;
520*8975f5c5SAndroid Build Coastguard Worker )"
521*8975f5c5SAndroid Build Coastguard Worker             << (isMultiColor ? R"(in vec4 aColor;
522*8975f5c5SAndroid Build Coastguard Worker out vec4 vColor;)"
523*8975f5c5SAndroid Build Coastguard Worker                              : "")
524*8975f5c5SAndroid Build Coastguard Worker             << R"(
525*8975f5c5SAndroid Build Coastguard Worker void main()
526*8975f5c5SAndroid Build Coastguard Worker {
527*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(aPos.x, aPos.y, 0, 1);
528*8975f5c5SAndroid Build Coastguard Worker )" << (isMultiColor ? R"(vColor = vec4(aColor.x, aColor.y, aColor.z, 1.0);)" : "")
529*8975f5c5SAndroid Build Coastguard Worker             << R"(
530*8975f5c5SAndroid Build Coastguard Worker })";
531*8975f5c5SAndroid Build Coastguard Worker 
532*8975f5c5SAndroid Build Coastguard Worker         std::stringstream kFS;
533*8975f5c5SAndroid Build Coastguard Worker         kFS << R"(#version 310 es
534*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
535*8975f5c5SAndroid Build Coastguard Worker )"
536*8975f5c5SAndroid Build Coastguard Worker             << (isMultiColor ? R"(in vec4 vColor;
537*8975f5c5SAndroid Build Coastguard Worker )"
538*8975f5c5SAndroid Build Coastguard Worker                              : "")
539*8975f5c5SAndroid Build Coastguard Worker             << R"(
540*8975f5c5SAndroid Build Coastguard Worker out vec4 colorOut;
541*8975f5c5SAndroid Build Coastguard Worker void main()
542*8975f5c5SAndroid Build Coastguard Worker {
543*8975f5c5SAndroid Build Coastguard Worker )" << (isMultiColor ? R"(colorOut = vColor;)" : R"(colorOut = vec4(1.0, 0.0, 1.0, 1.0);)")
544*8975f5c5SAndroid Build Coastguard Worker             << R"(
545*8975f5c5SAndroid Build Coastguard Worker })";
546*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(kVS.str().c_str(), kFS.str().c_str());
547*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
548*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GE(mProgram, 1u);
549*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram);
550*8975f5c5SAndroid Build Coastguard Worker         mPositionLoc = glGetAttribLocation(mProgram, "aPos");
551*8975f5c5SAndroid Build Coastguard Worker         mColorLoc    = glGetAttribLocation(mProgram, "aColor");
552*8975f5c5SAndroid Build Coastguard Worker     }
553*8975f5c5SAndroid Build Coastguard Worker 
TearDown()554*8975f5c5SAndroid Build Coastguard Worker     void TearDown() override
555*8975f5c5SAndroid Build Coastguard Worker     {
556*8975f5c5SAndroid Build Coastguard Worker         if (mVertexBuffer != 0u)
557*8975f5c5SAndroid Build Coastguard Worker         {
558*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mVertexBuffer);
559*8975f5c5SAndroid Build Coastguard Worker         }
560*8975f5c5SAndroid Build Coastguard Worker         if (mColorBuffer != 0u)
561*8975f5c5SAndroid Build Coastguard Worker         {
562*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mColorBuffer);
563*8975f5c5SAndroid Build Coastguard Worker         }
564*8975f5c5SAndroid Build Coastguard Worker         if (mIndexBuffer != 0u)
565*8975f5c5SAndroid Build Coastguard Worker         {
566*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mIndexBuffer);
567*8975f5c5SAndroid Build Coastguard Worker         }
568*8975f5c5SAndroid Build Coastguard Worker         if (mProgram != 0)
569*8975f5c5SAndroid Build Coastguard Worker         {
570*8975f5c5SAndroid Build Coastguard Worker             glDeleteProgram(mProgram);
571*8975f5c5SAndroid Build Coastguard Worker         }
572*8975f5c5SAndroid Build Coastguard Worker         if (mIndirectBuffer != 0u)
573*8975f5c5SAndroid Build Coastguard Worker         {
574*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mIndirectBuffer);
575*8975f5c5SAndroid Build Coastguard Worker         }
576*8975f5c5SAndroid Build Coastguard Worker         ANGLETestBase::ANGLETestTearDown();
577*8975f5c5SAndroid Build Coastguard Worker     }
578*8975f5c5SAndroid Build Coastguard Worker 
579*8975f5c5SAndroid Build Coastguard Worker     GLint mPositionLoc;
580*8975f5c5SAndroid Build Coastguard Worker     GLint mColorLoc;
581*8975f5c5SAndroid Build Coastguard Worker     GLuint mVertexBuffer;
582*8975f5c5SAndroid Build Coastguard Worker     GLuint mColorBuffer;
583*8975f5c5SAndroid Build Coastguard Worker     GLuint mIndexBuffer;
584*8975f5c5SAndroid Build Coastguard Worker     GLuint mIndirectBuffer;
585*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
586*8975f5c5SAndroid Build Coastguard Worker };
587*8975f5c5SAndroid Build Coastguard Worker 
588*8975f5c5SAndroid Build Coastguard Worker // Test that compile a program with the extension succeeds
TEST_P(MultiDrawTest,CanCompile)589*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawTest, CanCompile)
590*8975f5c5SAndroid Build Coastguard Worker {
591*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!requestExtensions());
592*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
593*8975f5c5SAndroid Build Coastguard Worker }
594*8975f5c5SAndroid Build Coastguard Worker 
595*8975f5c5SAndroid Build Coastguard Worker // Tests basic functionality of glMultiDrawArraysANGLE
TEST_P(MultiDrawTest,MultiDrawArrays)596*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawTest, MultiDrawArrays)
597*8975f5c5SAndroid Build Coastguard Worker {
598*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!requestExtensions());
599*8975f5c5SAndroid Build Coastguard Worker 
600*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/40644769
601*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
602*8975f5c5SAndroid Build Coastguard Worker 
603*8975f5c5SAndroid Build Coastguard Worker     SetupBuffers();
604*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
605*8975f5c5SAndroid Build Coastguard Worker     DoDrawArrays();
606*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
607*8975f5c5SAndroid Build Coastguard Worker     CheckDrawResult(DrawIDOptionOverride::Default);
608*8975f5c5SAndroid Build Coastguard Worker }
609*8975f5c5SAndroid Build Coastguard Worker 
610*8975f5c5SAndroid Build Coastguard Worker // Tests basic functionality of glMultiDrawArraysANGLE after a failed program relink
TEST_P(MultiDrawTestES3,MultiDrawArraysAfterFailedRelink)611*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawTestES3, MultiDrawArraysAfterFailedRelink)
612*8975f5c5SAndroid Build Coastguard Worker {
613*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!requestExtensions());
614*8975f5c5SAndroid Build Coastguard Worker 
615*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/40644769
616*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
617*8975f5c5SAndroid Build Coastguard Worker 
618*8975f5c5SAndroid Build Coastguard Worker     SetupBuffers();
619*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
620*8975f5c5SAndroid Build Coastguard Worker 
621*8975f5c5SAndroid Build Coastguard Worker     // mProgram is already installed.  Destroy its state by a failed relink.
622*8975f5c5SAndroid Build Coastguard Worker     const char *tfVaryings = "invalidvaryingname";
623*8975f5c5SAndroid Build Coastguard Worker     glTransformFeedbackVaryings(mProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
624*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mProgram);
625*8975f5c5SAndroid Build Coastguard Worker     GLint linkStatus = 0;
626*8975f5c5SAndroid Build Coastguard Worker     glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
627*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
628*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(linkStatus, GL_FALSE);
629*8975f5c5SAndroid Build Coastguard Worker 
630*8975f5c5SAndroid Build Coastguard Worker     DoDrawArrays();
631*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
632*8975f5c5SAndroid Build Coastguard Worker     CheckDrawResult(DrawIDOptionOverride::Default);
633*8975f5c5SAndroid Build Coastguard Worker }
634*8975f5c5SAndroid Build Coastguard Worker 
635*8975f5c5SAndroid Build Coastguard Worker // Tests basic functionality of glMultiDrawElementsANGLE
TEST_P(MultiDrawTest,MultiDrawElements)636*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawTest, MultiDrawElements)
637*8975f5c5SAndroid Build Coastguard Worker {
638*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!requestExtensions());
639*8975f5c5SAndroid Build Coastguard Worker     SetupBuffers();
640*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
641*8975f5c5SAndroid Build Coastguard Worker     DoDrawElements();
642*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
643*8975f5c5SAndroid Build Coastguard Worker     CheckDrawResult(DrawIDOptionOverride::Default);
644*8975f5c5SAndroid Build Coastguard Worker }
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker // Tests that glMultiDrawArraysANGLE followed by glDrawArrays works.  gl_DrawID in the second call
647*8975f5c5SAndroid Build Coastguard Worker // must be 0.
TEST_P(MultiDrawTest,MultiDrawArraysThenDrawArrays)648*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawTest, MultiDrawArraysThenDrawArrays)
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!requestExtensions());
651*8975f5c5SAndroid Build Coastguard Worker 
652*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/40644769
653*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsInstancedTest() && IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
654*8975f5c5SAndroid Build Coastguard Worker 
655*8975f5c5SAndroid Build Coastguard Worker     SetupBuffers();
656*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
657*8975f5c5SAndroid Build Coastguard Worker     DoDrawArrays();
658*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
659*8975f5c5SAndroid Build Coastguard Worker     CheckDrawResult(DrawIDOptionOverride::Default);
660*8975f5c5SAndroid Build Coastguard Worker 
661*8975f5c5SAndroid Build Coastguard Worker     if (IsInstancedTest())
662*8975f5c5SAndroid Build Coastguard Worker     {
663*8975f5c5SAndroid Build Coastguard Worker         ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_instanced_arrays") &&
664*8975f5c5SAndroid Build Coastguard Worker                            !IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
665*8975f5c5SAndroid Build Coastguard Worker         if (IsGLExtensionEnabled("GL_EXT_instanced_arrays"))
666*8975f5c5SAndroid Build Coastguard Worker         {
667*8975f5c5SAndroid Build Coastguard Worker             glDrawArraysInstancedEXT(GL_TRIANGLES, 0, 3 * kTriCount, 4);
668*8975f5c5SAndroid Build Coastguard Worker         }
669*8975f5c5SAndroid Build Coastguard Worker         else
670*8975f5c5SAndroid Build Coastguard Worker         {
671*8975f5c5SAndroid Build Coastguard Worker             glDrawArraysInstancedANGLE(GL_TRIANGLES, 0, 3 * kTriCount, 4);
672*8975f5c5SAndroid Build Coastguard Worker         }
673*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
674*8975f5c5SAndroid Build Coastguard Worker     }
675*8975f5c5SAndroid Build Coastguard Worker     else
676*8975f5c5SAndroid Build Coastguard Worker     {
677*8975f5c5SAndroid Build Coastguard Worker         glDrawArrays(GL_TRIANGLES, 0, 3 * kTriCount);
678*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
679*8975f5c5SAndroid Build Coastguard Worker     }
680*8975f5c5SAndroid Build Coastguard Worker     CheckDrawResult(DrawIDOptionOverride::NoDrawID);
681*8975f5c5SAndroid Build Coastguard Worker }
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker // Tests basic functionality of glMultiDrawArraysIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawArraysIndirect)684*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawIndirectTest, MultiDrawArraysIndirect)
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
687*8975f5c5SAndroid Build Coastguard Worker 
688*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array
689*8975f5c5SAndroid Build Coastguard Worker     const GLint triangleCount           = 4;
690*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> vertices = {
691*8975f5c5SAndroid Build Coastguard Worker         -1, 1,  0, -1, 0, 0, 0, 1,  0, 1, 1,  0, 1, 0,  0, 0, 1, 0,
692*8975f5c5SAndroid Build Coastguard Worker         -1, -1, 0, -1, 0, 0, 0, -1, 0, 1, -1, 0, 0, -1, 0, 1, 0, 0,
693*8975f5c5SAndroid Build Coastguard Worker     };
694*8975f5c5SAndroid Build Coastguard Worker 
695*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex buffer
696*8975f5c5SAndroid Build Coastguard Worker     GLVertexArray vao;
697*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
698*8975f5c5SAndroid Build Coastguard Worker 
699*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mVertexBuffer);
700*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
701*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
702*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
703*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker     // Generate program
706*8975f5c5SAndroid Build Coastguard Worker     SetupProgramIndirect(false);
707*8975f5c5SAndroid Build Coastguard Worker 
708*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array format
709*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
710*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
711*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
712*8975f5c5SAndroid Build Coastguard Worker 
713*8975f5c5SAndroid Build Coastguard Worker     // Set up the indirect data array
714*8975f5c5SAndroid Build Coastguard Worker     std::array<DrawArraysIndirectCommand, triangleCount> indirectData;
715*8975f5c5SAndroid Build Coastguard Worker     const GLsizei icSize = sizeof(DrawArraysIndirectCommand);
716*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount; i++)
717*8975f5c5SAndroid Build Coastguard Worker     {
718*8975f5c5SAndroid Build Coastguard Worker         indirectData[i] = DrawArraysIndirectCommand(3, 1, 3 * i, i);
719*8975f5c5SAndroid Build Coastguard Worker     }
720*8975f5c5SAndroid Build Coastguard Worker 
721*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndirectBuffer);
722*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
723*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
724*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
725*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
726*8975f5c5SAndroid Build Coastguard Worker 
727*8975f5c5SAndroid Build Coastguard Worker     // Invalid value check for drawcount and stride
728*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
729*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 0, 0);
730*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
731*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, -1, 0);
732*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
733*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 2);
734*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
735*8975f5c5SAndroid Build Coastguard Worker 
736*8975f5c5SAndroid Build Coastguard Worker     // Check the error from sourcing beyond the allocated buffer size
737*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
738*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(
739*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES,
740*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
741*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
742*8975f5c5SAndroid Build Coastguard Worker 
743*8975f5c5SAndroid Build Coastguard Worker     // Draw all triangles using glMultiDrawArraysIndirect
744*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
745*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, triangleCount, 0);
746*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
747*8975f5c5SAndroid Build Coastguard Worker 
748*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
749*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
750*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
751*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
752*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
753*8975f5c5SAndroid Build Coastguard Worker 
754*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles in different order
755*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
756*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 1, 0);
757*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES,
758*8975f5c5SAndroid Build Coastguard Worker                                  reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)),
759*8975f5c5SAndroid Build Coastguard Worker                                  triangleCount - 2, 0);
760*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(
761*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)), 1, 0);
762*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
763*8975f5c5SAndroid Build Coastguard Worker 
764*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
765*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
766*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
767*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
768*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
769*8975f5c5SAndroid Build Coastguard Worker 
770*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles partially using stride
771*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
772*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysIndirectEXT(GL_TRIANGLES, nullptr, 2, icSize * 3);
773*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
776*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
777*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
778*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
779*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
780*8975f5c5SAndroid Build Coastguard Worker }
781*8975f5c5SAndroid Build Coastguard Worker 
782*8975f5c5SAndroid Build Coastguard Worker // Tests basic functionality of glMultiDrawElementsIndirectEXT
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirect)783*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirect)
784*8975f5c5SAndroid Build Coastguard Worker {
785*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
786*8975f5c5SAndroid Build Coastguard Worker 
787*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array
788*8975f5c5SAndroid Build Coastguard Worker     const GLint triangleCount           = 4;
789*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> vertices = {
790*8975f5c5SAndroid Build Coastguard Worker         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
791*8975f5c5SAndroid Build Coastguard Worker     };
792*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> indices = {
793*8975f5c5SAndroid Build Coastguard Worker         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
794*8975f5c5SAndroid Build Coastguard Worker     };
795*8975f5c5SAndroid Build Coastguard Worker 
796*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex and index buffers
797*8975f5c5SAndroid Build Coastguard Worker     GLVertexArray vao;
798*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
799*8975f5c5SAndroid Build Coastguard Worker 
800*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mVertexBuffer);
801*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
802*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
803*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
804*8975f5c5SAndroid Build Coastguard Worker 
805*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndexBuffer);
806*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
807*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
808*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
809*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
810*8975f5c5SAndroid Build Coastguard Worker 
811*8975f5c5SAndroid Build Coastguard Worker     // Generate program
812*8975f5c5SAndroid Build Coastguard Worker     SetupProgramIndirect(false);
813*8975f5c5SAndroid Build Coastguard Worker 
814*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array format
815*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
816*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
817*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
818*8975f5c5SAndroid Build Coastguard Worker 
819*8975f5c5SAndroid Build Coastguard Worker     // Set up the indirect data array
820*8975f5c5SAndroid Build Coastguard Worker     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
821*8975f5c5SAndroid Build Coastguard Worker     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
822*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount; i++)
823*8975f5c5SAndroid Build Coastguard Worker     {
824*8975f5c5SAndroid Build Coastguard Worker         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
825*8975f5c5SAndroid Build Coastguard Worker     }
826*8975f5c5SAndroid Build Coastguard Worker 
827*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndirectBuffer);
828*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
829*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
830*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
831*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
832*8975f5c5SAndroid Build Coastguard Worker 
833*8975f5c5SAndroid Build Coastguard Worker     // Invalid value check for drawcount and stride
834*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
835*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 0, 0);
836*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
837*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, -1, 0);
838*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
839*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 2);
840*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
841*8975f5c5SAndroid Build Coastguard Worker 
842*8975f5c5SAndroid Build Coastguard Worker     // Check the error from sourcing beyond the allocated buffer size
843*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
844*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
845*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_INT,
846*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
847*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
848*8975f5c5SAndroid Build Coastguard Worker 
849*8975f5c5SAndroid Build Coastguard Worker     // Draw all triangles using glMultiDrawElementsIndirect
850*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
851*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
852*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
853*8975f5c5SAndroid Build Coastguard Worker 
854*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
855*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
856*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
857*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
858*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
859*8975f5c5SAndroid Build Coastguard Worker 
860*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles in a different order
861*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
862*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 1, 0);
863*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT,
864*8975f5c5SAndroid Build Coastguard Worker                                    reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)),
865*8975f5c5SAndroid Build Coastguard Worker                                    triangleCount - 2, 0);
866*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
867*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_INT,
868*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), 1, 0);
869*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
870*8975f5c5SAndroid Build Coastguard Worker 
871*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
872*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
873*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
874*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
875*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
876*8975f5c5SAndroid Build Coastguard Worker 
877*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles partially using stride
878*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
879*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 2, icSize * 3);
880*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
881*8975f5c5SAndroid Build Coastguard Worker 
882*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
883*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
884*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
885*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
886*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
887*8975f5c5SAndroid Build Coastguard Worker }
888*8975f5c5SAndroid Build Coastguard Worker 
889*8975f5c5SAndroid Build Coastguard Worker // Test functionality glMultiDrawElementsIndirectEXT with unsigned short
890*8975f5c5SAndroid Build Coastguard Worker // indices and instanced attributes.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectInstancedUshort)891*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectInstancedUshort)
892*8975f5c5SAndroid Build Coastguard Worker {
893*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
894*8975f5c5SAndroid Build Coastguard Worker 
895*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array
896*8975f5c5SAndroid Build Coastguard Worker     const GLint triangleCount           = 4;
897*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> vertices = {
898*8975f5c5SAndroid Build Coastguard Worker         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
899*8975f5c5SAndroid Build Coastguard Worker     };
900*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLushort> indices = {
901*8975f5c5SAndroid Build Coastguard Worker         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
902*8975f5c5SAndroid Build Coastguard Worker     };
903*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> instancedColor = {GLColor::white.asUint(), GLColor::red.asUint(),
904*8975f5c5SAndroid Build Coastguard Worker                                                 GLColor::green.asUint(), GLColor::blue.asUint()};
905*8975f5c5SAndroid Build Coastguard Worker 
906*8975f5c5SAndroid Build Coastguard Worker     // Generate program
907*8975f5c5SAndroid Build Coastguard Worker     SetupProgramIndirect(true);
908*8975f5c5SAndroid Build Coastguard Worker 
909*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex and index buffers
910*8975f5c5SAndroid Build Coastguard Worker     GLVertexArray vao;
911*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
912*8975f5c5SAndroid Build Coastguard Worker 
913*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mVertexBuffer);
914*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
915*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
916*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
917*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
918*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
919*8975f5c5SAndroid Build Coastguard Worker 
920*8975f5c5SAndroid Build Coastguard Worker     GLBuffer instanceBuffer;
921*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, instanceBuffer);
922*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * instancedColor.size(), instancedColor.data(),
923*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
924*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mColorLoc);
925*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mColorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
926*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribDivisor(mColorLoc, 1);
927*8975f5c5SAndroid Build Coastguard Worker 
928*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndexBuffer);
929*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
930*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * indices.size(), indices.data(),
931*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
932*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker     // Set up the indirect data array
935*8975f5c5SAndroid Build Coastguard Worker     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
936*8975f5c5SAndroid Build Coastguard Worker     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
937*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount; i++)
938*8975f5c5SAndroid Build Coastguard Worker     {
939*8975f5c5SAndroid Build Coastguard Worker         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
940*8975f5c5SAndroid Build Coastguard Worker     }
941*8975f5c5SAndroid Build Coastguard Worker 
942*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndirectBuffer);
943*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
944*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
945*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
946*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
947*8975f5c5SAndroid Build Coastguard Worker 
948*8975f5c5SAndroid Build Coastguard Worker     // Invalid value check for drawcount and stride
949*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
950*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 0, 0);
951*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
952*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, -1, 0);
953*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
954*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 1, 2);
955*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
956*8975f5c5SAndroid Build Coastguard Worker 
957*8975f5c5SAndroid Build Coastguard Worker     // Check the error from sourcing beyond the allocated buffer size
958*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
959*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
960*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_SHORT,
961*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * triangleCount)), 1, 0);
962*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
963*8975f5c5SAndroid Build Coastguard Worker 
964*8975f5c5SAndroid Build Coastguard Worker     // Draw all triangles using glMultiDrawElementsIndirect
965*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
966*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, triangleCount, 0);
967*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
968*8975f5c5SAndroid Build Coastguard Worker 
969*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
970*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
971*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::red);
972*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
973*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
974*8975f5c5SAndroid Build Coastguard Worker 
975*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles in a different order
976*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
977*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 1, 0);
978*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT,
979*8975f5c5SAndroid Build Coastguard Worker                                    reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize)),
980*8975f5c5SAndroid Build Coastguard Worker                                    triangleCount - 2, 0);
981*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
982*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_SHORT,
983*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), 1, 0);
984*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
985*8975f5c5SAndroid Build Coastguard Worker 
986*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
987*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
988*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::red);
989*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
990*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
991*8975f5c5SAndroid Build Coastguard Worker 
992*8975f5c5SAndroid Build Coastguard Worker     // Draw the triangles partially using stride
993*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
994*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, 2, icSize * 3);
995*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
996*8975f5c5SAndroid Build Coastguard Worker 
997*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
998*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::blue);
999*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1000*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::white);
1001*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1002*8975f5c5SAndroid Build Coastguard Worker }
1003*8975f5c5SAndroid Build Coastguard Worker 
1004*8975f5c5SAndroid Build Coastguard Worker // Tests functionality of glMultiDrawElementsIndirectEXT with more than one triangle in one element
1005*8975f5c5SAndroid Build Coastguard Worker // of the indirect buffer.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectMultipleTriangles)1006*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectMultipleTriangles)
1007*8975f5c5SAndroid Build Coastguard Worker {
1008*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
1009*8975f5c5SAndroid Build Coastguard Worker 
1010*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array
1011*8975f5c5SAndroid Build Coastguard Worker     const GLint triangleCount           = 4;
1012*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> vertices = {
1013*8975f5c5SAndroid Build Coastguard Worker         -1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
1014*8975f5c5SAndroid Build Coastguard Worker     };
1015*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> indices = {
1016*8975f5c5SAndroid Build Coastguard Worker         1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 0, 1,
1017*8975f5c5SAndroid Build Coastguard Worker     };
1018*8975f5c5SAndroid Build Coastguard Worker 
1019*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex and index buffers
1020*8975f5c5SAndroid Build Coastguard Worker     GLVertexArray vao;
1021*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
1022*8975f5c5SAndroid Build Coastguard Worker 
1023*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mVertexBuffer);
1024*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1025*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
1026*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1027*8975f5c5SAndroid Build Coastguard Worker 
1028*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndexBuffer);
1029*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1030*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
1031*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1032*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1033*8975f5c5SAndroid Build Coastguard Worker 
1034*8975f5c5SAndroid Build Coastguard Worker     // Generate program
1035*8975f5c5SAndroid Build Coastguard Worker     SetupProgramIndirect(false);
1036*8975f5c5SAndroid Build Coastguard Worker 
1037*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array format
1038*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
1039*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1040*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1041*8975f5c5SAndroid Build Coastguard Worker 
1042*8975f5c5SAndroid Build Coastguard Worker     // Set up the indirect data array; first element represents two triangles.
1043*8975f5c5SAndroid Build Coastguard Worker     std::array<DrawElementsIndirectCommand, triangleCount - 1> indirectData;
1044*8975f5c5SAndroid Build Coastguard Worker     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
1045*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount - 1; i++)
1046*8975f5c5SAndroid Build Coastguard Worker     {
1047*8975f5c5SAndroid Build Coastguard Worker         if (i == 0)
1048*8975f5c5SAndroid Build Coastguard Worker         {
1049*8975f5c5SAndroid Build Coastguard Worker             indirectData[i] = DrawElementsIndirectCommand(6, 2, 0, 0, i);
1050*8975f5c5SAndroid Build Coastguard Worker         }
1051*8975f5c5SAndroid Build Coastguard Worker         else
1052*8975f5c5SAndroid Build Coastguard Worker         {
1053*8975f5c5SAndroid Build Coastguard Worker             indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * (i + 1), 0, i);
1054*8975f5c5SAndroid Build Coastguard Worker         }
1055*8975f5c5SAndroid Build Coastguard Worker     }
1056*8975f5c5SAndroid Build Coastguard Worker 
1057*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndirectBuffer);
1058*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
1059*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
1060*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1061*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1062*8975f5c5SAndroid Build Coastguard Worker 
1063*8975f5c5SAndroid Build Coastguard Worker     // Draw all triangles using glMultiDrawElementsIndirect
1064*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1065*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount - 1, 0);
1066*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1067*8975f5c5SAndroid Build Coastguard Worker 
1068*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
1069*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::magenta);
1070*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::magenta);
1071*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::magenta);
1072*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1073*8975f5c5SAndroid Build Coastguard Worker }
1074*8975f5c5SAndroid Build Coastguard Worker 
1075*8975f5c5SAndroid Build Coastguard Worker // Tests glMultiDrawElementsIndirectEXT with glMultiDrawElementsANGLE to see if the index buffer
1076*8975f5c5SAndroid Build Coastguard Worker // offset is being reset.
TEST_P(MultiDrawIndirectTest,MultiDrawElementsIndirectCheckBufferOffset)1077*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawIndirectTest, MultiDrawElementsIndirectCheckBufferOffset)
1078*8975f5c5SAndroid Build Coastguard Worker {
1079*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multi_draw_indirect"));
1080*8975f5c5SAndroid Build Coastguard Worker 
1081*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array
1082*8975f5c5SAndroid Build Coastguard Worker     const GLint triangleCount           = 4;
1083*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> vertices = {
1084*8975f5c5SAndroid Build Coastguard Worker         -1, 0, 0, -1, 1,  0, 0, 1,  0, 0, 1,  0, 1,  1,  0, 1,  0, 0,
1085*8975f5c5SAndroid Build Coastguard Worker         1,  0, 0, 1,  -1, 0, 0, -1, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0,
1086*8975f5c5SAndroid Build Coastguard Worker     };
1087*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> colors = {
1088*8975f5c5SAndroid Build Coastguard Worker         1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0,
1089*8975f5c5SAndroid Build Coastguard Worker         0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0,
1090*8975f5c5SAndroid Build Coastguard Worker     };
1091*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> indices = {
1092*8975f5c5SAndroid Build Coastguard Worker         3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2,
1093*8975f5c5SAndroid Build Coastguard Worker     };
1094*8975f5c5SAndroid Build Coastguard Worker 
1095*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex and index buffers
1096*8975f5c5SAndroid Build Coastguard Worker     GLVertexArray vao;
1097*8975f5c5SAndroid Build Coastguard Worker     glBindVertexArray(vao);
1098*8975f5c5SAndroid Build Coastguard Worker 
1099*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mVertexBuffer);
1100*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1101*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), vertices.data(),
1102*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1103*8975f5c5SAndroid Build Coastguard Worker 
1104*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mColorBuffer);
1105*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
1106*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * colors.size(), colors.data(), GL_STATIC_DRAW);
1107*8975f5c5SAndroid Build Coastguard Worker 
1108*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndexBuffer);
1109*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1110*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(),
1111*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1112*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1113*8975f5c5SAndroid Build Coastguard Worker 
1114*8975f5c5SAndroid Build Coastguard Worker     // Generate program
1115*8975f5c5SAndroid Build Coastguard Worker     SetupProgramIndirect(true);
1116*8975f5c5SAndroid Build Coastguard Worker 
1117*8975f5c5SAndroid Build Coastguard Worker     // Set up the vertex array format
1118*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1119*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
1120*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1121*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1122*8975f5c5SAndroid Build Coastguard Worker 
1123*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mColorBuffer);
1124*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mColorLoc);
1125*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mColorLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1126*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1127*8975f5c5SAndroid Build Coastguard Worker 
1128*8975f5c5SAndroid Build Coastguard Worker     // Set up the arrays for the direct draw
1129*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLsizei> counts(triangleCount, 3);
1130*8975f5c5SAndroid Build Coastguard Worker     std::vector<const GLvoid *> indicesDirect(triangleCount);
1131*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount; i++)
1132*8975f5c5SAndroid Build Coastguard Worker     {
1133*8975f5c5SAndroid Build Coastguard Worker         indicesDirect[i] =
1134*8975f5c5SAndroid Build Coastguard Worker             reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(i * 3 * sizeof(GLuint)));
1135*8975f5c5SAndroid Build Coastguard Worker     }
1136*8975f5c5SAndroid Build Coastguard Worker 
1137*8975f5c5SAndroid Build Coastguard Worker     // Set up the indirect data array for indirect draw
1138*8975f5c5SAndroid Build Coastguard Worker     std::array<DrawElementsIndirectCommand, triangleCount> indirectData;
1139*8975f5c5SAndroid Build Coastguard Worker     const GLsizei icSize = sizeof(DrawElementsIndirectCommand);
1140*8975f5c5SAndroid Build Coastguard Worker     for (auto i = 0; i < triangleCount; i++)
1141*8975f5c5SAndroid Build Coastguard Worker     {
1142*8975f5c5SAndroid Build Coastguard Worker         indirectData[i] = DrawElementsIndirectCommand(3, 1, 3 * i, 0, i);
1143*8975f5c5SAndroid Build Coastguard Worker     }
1144*8975f5c5SAndroid Build Coastguard Worker 
1145*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &mIndirectBuffer);
1146*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_DRAW_INDIRECT_BUFFER, mIndirectBuffer);
1147*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_DRAW_INDIRECT_BUFFER, icSize * indirectData.size(), indirectData.data(),
1148*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1149*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1150*8975f5c5SAndroid Build Coastguard Worker 
1151*8975f5c5SAndroid Build Coastguard Worker     // Draw using glMultiDrawElementsIndirect
1152*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1153*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
1154*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_INT,
1155*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 2)), triangleCount - 2, 0);
1156*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1157*8975f5c5SAndroid Build Coastguard Worker 
1158*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1159*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1160*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1161*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
1162*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1163*8975f5c5SAndroid Build Coastguard Worker 
1164*8975f5c5SAndroid Build Coastguard Worker     // Draw using glMultiDrawElementsANGLE
1165*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1166*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
1167*8975f5c5SAndroid Build Coastguard Worker                              triangleCount);
1168*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1169*8975f5c5SAndroid Build Coastguard Worker 
1170*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1171*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1172*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1173*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1174*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1175*8975f5c5SAndroid Build Coastguard Worker 
1176*8975f5c5SAndroid Build Coastguard Worker     // Draw using glMultiDrawElementsANGLE again
1177*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1178*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_INT, indicesDirect.data(),
1179*8975f5c5SAndroid Build Coastguard Worker                              triangleCount - 1);
1180*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1181*8975f5c5SAndroid Build Coastguard Worker 
1182*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1183*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::transparentBlack);
1184*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1185*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1186*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1187*8975f5c5SAndroid Build Coastguard Worker 
1188*8975f5c5SAndroid Build Coastguard Worker     // Draw using glMultiDrawElementsIndirect again
1189*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1190*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(
1191*8975f5c5SAndroid Build Coastguard Worker         GL_TRIANGLES, GL_UNSIGNED_INT,
1192*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const void *>(static_cast<uintptr_t>(icSize * 3)), triangleCount - 3, 0);
1193*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1194*8975f5c5SAndroid Build Coastguard Worker 
1195*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1196*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1197*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::transparentBlack);
1198*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::transparentBlack);
1199*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1200*8975f5c5SAndroid Build Coastguard Worker 
1201*8975f5c5SAndroid Build Coastguard Worker     // Draw using glMultiDrawElementsIndirect one more time
1202*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1203*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsIndirectEXT(GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, triangleCount, 0);
1204*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1205*8975f5c5SAndroid Build Coastguard Worker 
1206*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
1207*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, kHeight - 1, GLColor::red);
1208*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, 0, GLColor::blue);
1209*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth - 1, kHeight - 1, GLColor::green);
1210*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(kWidth / 2, kHeight / 2, GLColor::transparentBlack);
1211*8975f5c5SAndroid Build Coastguard Worker }
1212*8975f5c5SAndroid Build Coastguard Worker 
1213*8975f5c5SAndroid Build Coastguard Worker // Check that glMultiDraw*Instanced without instancing support results in GL_INVALID_OPERATION
TEST_P(MultiDrawNoInstancingSupportTest,InvalidOperation)1214*8975f5c5SAndroid Build Coastguard Worker TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation)
1215*8975f5c5SAndroid Build Coastguard Worker {
1216*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_ANGLE_instanced_arrays"));
1217*8975f5c5SAndroid Build Coastguard Worker     requestMultiDrawExtension();
1218*8975f5c5SAndroid Build Coastguard Worker     SetupBuffers();
1219*8975f5c5SAndroid Build Coastguard Worker     SetupProgram();
1220*8975f5c5SAndroid Build Coastguard Worker 
1221*8975f5c5SAndroid Build Coastguard Worker     GLint first       = 0;
1222*8975f5c5SAndroid Build Coastguard Worker     GLsizei count     = 3;
1223*8975f5c5SAndroid Build Coastguard Worker     GLvoid *indices   = nullptr;
1224*8975f5c5SAndroid Build Coastguard Worker     GLsizei instances = 1;
1225*8975f5c5SAndroid Build Coastguard Worker 
1226*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1227*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
1228*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
1229*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1230*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, 1);
1231*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1232*8975f5c5SAndroid Build Coastguard Worker 
1233*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1234*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
1235*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
1236*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mPositionLoc);
1237*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1238*8975f5c5SAndroid Build Coastguard Worker     glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, &indices, &instances,
1239*8975f5c5SAndroid Build Coastguard Worker                                       1);
1240*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1241*8975f5c5SAndroid Build Coastguard Worker }
1242*8975f5c5SAndroid Build Coastguard Worker 
1243*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES2                                             \
1244*8975f5c5SAndroid Build Coastguard Worker     ES2_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),                  \
1245*8975f5c5SAndroid Build Coastguard Worker         ES2_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1246*8975f5c5SAndroid Build Coastguard Worker         ES2_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),           \
1247*8975f5c5SAndroid Build Coastguard Worker         ES2_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1248*8975f5c5SAndroid Build Coastguard Worker         ES2_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \
1249*8975f5c5SAndroid Build Coastguard Worker         ES2_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)
1250*8975f5c5SAndroid Build Coastguard Worker 
1251*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3                                             \
1252*8975f5c5SAndroid Build Coastguard Worker     ES3_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),                  \
1253*8975f5c5SAndroid Build Coastguard Worker         ES3_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1254*8975f5c5SAndroid Build Coastguard Worker         ES3_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),           \
1255*8975f5c5SAndroid Build Coastguard Worker         ES3_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1256*8975f5c5SAndroid Build Coastguard Worker         ES3_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \
1257*8975f5c5SAndroid Build Coastguard Worker         ES3_METAL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)
1258*8975f5c5SAndroid Build Coastguard Worker 
1259*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3_1                                            \
1260*8975f5c5SAndroid Build Coastguard Worker     ES31_D3D11().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),                  \
1261*8975f5c5SAndroid Build Coastguard Worker         ES31_OPENGL().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1262*8975f5c5SAndroid Build Coastguard Worker         ES31_OPENGLES().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),           \
1263*8975f5c5SAndroid Build Coastguard Worker         ES31_VULKAN().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions),             \
1264*8975f5c5SAndroid Build Coastguard Worker         ES31_VULKAN_SWIFTSHADER().enable(Feature::AlwaysEnableEmulatedMultidrawExtensions), \
1265*8975f5c5SAndroid Build Coastguard Worker         ES31_VULKAN()                                                                       \
1266*8975f5c5SAndroid Build Coastguard Worker             .enable(Feature::AlwaysEnableEmulatedMultidrawExtensions)                       \
1267*8975f5c5SAndroid Build Coastguard Worker             .disable(Feature::SupportsMultiDrawIndirect)
1268*8975f5c5SAndroid Build Coastguard Worker 
1269*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawTest,
1270*8975f5c5SAndroid Build Coastguard Worker                                  PrintToStringParamName(),
1271*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1272*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(InstancingOption::NoInstancing,
1273*8975f5c5SAndroid Build Coastguard Worker                                                  InstancingOption::UseInstancing),
1274*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(BufferDataUsageOption::StaticDraw,
1275*8975f5c5SAndroid Build Coastguard Worker                                                  BufferDataUsageOption::DynamicDraw),
1276*8975f5c5SAndroid Build Coastguard Worker                                  ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES2,
1277*8975f5c5SAndroid Build Coastguard Worker                                  ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3);
1278*8975f5c5SAndroid Build Coastguard Worker 
1279*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawNoInstancingSupportTest,
1280*8975f5c5SAndroid Build Coastguard Worker                                  PrintToStringParamName(),
1281*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1282*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(InstancingOption::UseInstancing),
1283*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(BufferDataUsageOption::StaticDraw,
1284*8975f5c5SAndroid Build Coastguard Worker                                                  BufferDataUsageOption::DynamicDraw),
1285*8975f5c5SAndroid Build Coastguard Worker                                  ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES2);
1286*8975f5c5SAndroid Build Coastguard Worker 
1287*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_COMBINE_3(MultiDrawTestES3,
1288*8975f5c5SAndroid Build Coastguard Worker                                  PrintToStringParamName(),
1289*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
1290*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(InstancingOption::NoInstancing,
1291*8975f5c5SAndroid Build Coastguard Worker                                                  InstancingOption::UseInstancing),
1292*8975f5c5SAndroid Build Coastguard Worker                                  testing::Values(BufferDataUsageOption::StaticDraw,
1293*8975f5c5SAndroid Build Coastguard Worker                                                  BufferDataUsageOption::DynamicDraw),
1294*8975f5c5SAndroid Build Coastguard Worker                                  ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3);
1295*8975f5c5SAndroid Build Coastguard Worker 
1296*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MultiDrawIndirectTest);
1297*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST(MultiDrawIndirectTest, ANGLE_ALL_MULTIDRAW_TEST_PLATFORMS_ES3_1);
1298*8975f5c5SAndroid Build Coastguard Worker }  // namespace
1299