xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fVertexAttributeBindingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Vertex attribute binding tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fVertexAttributeBindingTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluCallLogWrapper.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker namespace deqp
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker namespace gles31
41*35238bceSAndroid Build Coastguard Worker {
42*35238bceSAndroid Build Coastguard Worker namespace Functional
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker namespace
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker 
47*35238bceSAndroid Build Coastguard Worker static const char *const s_colorFragmentShader = "#version 310 es\n"
48*35238bceSAndroid Build Coastguard Worker                                                  "in mediump vec4 v_color;\n"
49*35238bceSAndroid Build Coastguard Worker                                                  "layout(location = 0) out mediump vec4 fragColor;\n"
50*35238bceSAndroid Build Coastguard Worker                                                  "void main (void)\n"
51*35238bceSAndroid Build Coastguard Worker                                                  "{\n"
52*35238bceSAndroid Build Coastguard Worker                                                  "    fragColor = v_color;\n"
53*35238bceSAndroid Build Coastguard Worker                                                  "}\n";
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker static const char *const s_positionColorShader = "#version 310 es\n"
56*35238bceSAndroid Build Coastguard Worker                                                  "in highp vec4 a_position;\n"
57*35238bceSAndroid Build Coastguard Worker                                                  "in highp vec4 a_color;\n"
58*35238bceSAndroid Build Coastguard Worker                                                  "out highp vec4 v_color;\n"
59*35238bceSAndroid Build Coastguard Worker                                                  "void main (void)\n"
60*35238bceSAndroid Build Coastguard Worker                                                  "{\n"
61*35238bceSAndroid Build Coastguard Worker                                                  "    gl_Position = a_position;\n"
62*35238bceSAndroid Build Coastguard Worker                                                  "    v_color = a_color;\n"
63*35238bceSAndroid Build Coastguard Worker                                                  "}\n";
64*35238bceSAndroid Build Coastguard Worker 
65*35238bceSAndroid Build Coastguard Worker static const char *const s_positionColorOffsetShader = "#version 310 es\n"
66*35238bceSAndroid Build Coastguard Worker                                                        "in highp vec4 a_position;\n"
67*35238bceSAndroid Build Coastguard Worker                                                        "in highp vec4 a_offset;\n"
68*35238bceSAndroid Build Coastguard Worker                                                        "in highp vec4 a_color;\n"
69*35238bceSAndroid Build Coastguard Worker                                                        "out highp vec4 v_color;\n"
70*35238bceSAndroid Build Coastguard Worker                                                        "void main (void)\n"
71*35238bceSAndroid Build Coastguard Worker                                                        "{\n"
72*35238bceSAndroid Build Coastguard Worker                                                        "    gl_Position = a_position + a_offset;\n"
73*35238bceSAndroid Build Coastguard Worker                                                        "    v_color = a_color;\n"
74*35238bceSAndroid Build Coastguard Worker                                                        "}\n";
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker // Verifies image contains only yellow or greeen, or a linear combination
77*35238bceSAndroid Build Coastguard Worker // of these colors.
verifyImageYellowGreen(const tcu::Surface & image,tcu::TestLog & log,bool logImageOnSuccess)78*35238bceSAndroid Build Coastguard Worker static bool verifyImageYellowGreen(const tcu::Surface &image, tcu::TestLog &log, bool logImageOnSuccess)
79*35238bceSAndroid Build Coastguard Worker {
80*35238bceSAndroid Build Coastguard Worker     using tcu::TestLog;
81*35238bceSAndroid Build Coastguard Worker 
82*35238bceSAndroid Build Coastguard Worker     const int colorThreshold = 20;
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker     tcu::Surface error(image.getWidth(), image.getHeight());
85*35238bceSAndroid Build Coastguard Worker     bool isOk = true;
86*35238bceSAndroid Build Coastguard Worker 
87*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Verifying image contents." << TestLog::EndMessage;
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < image.getHeight(); y++)
90*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < image.getWidth(); x++)
91*35238bceSAndroid Build Coastguard Worker         {
92*35238bceSAndroid Build Coastguard Worker             const tcu::RGBA pixel = image.getPixel(x, y);
93*35238bceSAndroid Build Coastguard Worker             bool pixelOk          = true;
94*35238bceSAndroid Build Coastguard Worker 
95*35238bceSAndroid Build Coastguard Worker             // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
96*35238bceSAndroid Build Coastguard Worker             if (de::abs(pixel.getGreen() - 255) > colorThreshold)
97*35238bceSAndroid Build Coastguard Worker                 pixelOk = false;
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker             // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
100*35238bceSAndroid Build Coastguard Worker             if (de::abs(pixel.getBlue() - 0) > colorThreshold)
101*35238bceSAndroid Build Coastguard Worker                 pixelOk = false;
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker             error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
104*35238bceSAndroid Build Coastguard Worker             isOk = isOk && pixelOk;
105*35238bceSAndroid Build Coastguard Worker         }
106*35238bceSAndroid Build Coastguard Worker 
107*35238bceSAndroid Build Coastguard Worker     if (!isOk)
108*35238bceSAndroid Build Coastguard Worker     {
109*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
110*35238bceSAndroid Build Coastguard Worker         log << TestLog::ImageSet("Verfication result", "Result of rendering")
111*35238bceSAndroid Build Coastguard Worker             << TestLog::Image("Result", "Result", image) << TestLog::Image("ErrorMask", "Error mask", error)
112*35238bceSAndroid Build Coastguard Worker             << TestLog::EndImageSet;
113*35238bceSAndroid Build Coastguard Worker     }
114*35238bceSAndroid Build Coastguard Worker     else
115*35238bceSAndroid Build Coastguard Worker     {
116*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "Image verification passed." << TestLog::EndMessage;
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker         if (logImageOnSuccess)
119*35238bceSAndroid Build Coastguard Worker             log << TestLog::ImageSet("Verfication result", "Result of rendering")
120*35238bceSAndroid Build Coastguard Worker                 << TestLog::Image("Result", "Result", image) << TestLog::EndImageSet;
121*35238bceSAndroid Build Coastguard Worker     }
122*35238bceSAndroid Build Coastguard Worker 
123*35238bceSAndroid Build Coastguard Worker     return isOk;
124*35238bceSAndroid Build Coastguard Worker }
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker class BindingRenderCase : public TestCase
127*35238bceSAndroid Build Coastguard Worker {
128*35238bceSAndroid Build Coastguard Worker public:
129*35238bceSAndroid Build Coastguard Worker     enum
130*35238bceSAndroid Build Coastguard Worker     {
131*35238bceSAndroid Build Coastguard Worker         TEST_RENDER_SIZE = 64
132*35238bceSAndroid Build Coastguard Worker     };
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker     BindingRenderCase(Context &ctx, const char *name, const char *desc, bool unalignedData);
135*35238bceSAndroid Build Coastguard Worker     virtual ~BindingRenderCase(void);
136*35238bceSAndroid Build Coastguard Worker 
137*35238bceSAndroid Build Coastguard Worker     virtual void init(void);
138*35238bceSAndroid Build Coastguard Worker     virtual void deinit(void);
139*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
140*35238bceSAndroid Build Coastguard Worker 
141*35238bceSAndroid Build Coastguard Worker private:
142*35238bceSAndroid Build Coastguard Worker     virtual void renderTo(tcu::Surface &dst) = 0;
143*35238bceSAndroid Build Coastguard Worker     virtual void createBuffers(void)         = 0;
144*35238bceSAndroid Build Coastguard Worker     virtual void createShader(void)          = 0;
145*35238bceSAndroid Build Coastguard Worker 
146*35238bceSAndroid Build Coastguard Worker protected:
147*35238bceSAndroid Build Coastguard Worker     const bool m_unalignedData;
148*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_vao;
149*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram *m_program;
150*35238bceSAndroid Build Coastguard Worker };
151*35238bceSAndroid Build Coastguard Worker 
BindingRenderCase(Context & ctx,const char * name,const char * desc,bool unalignedData)152*35238bceSAndroid Build Coastguard Worker BindingRenderCase::BindingRenderCase(Context &ctx, const char *name, const char *desc, bool unalignedData)
153*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name, desc)
154*35238bceSAndroid Build Coastguard Worker     , m_unalignedData(unalignedData)
155*35238bceSAndroid Build Coastguard Worker     , m_vao(0)
156*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker }
159*35238bceSAndroid Build Coastguard Worker 
~BindingRenderCase(void)160*35238bceSAndroid Build Coastguard Worker BindingRenderCase::~BindingRenderCase(void)
161*35238bceSAndroid Build Coastguard Worker {
162*35238bceSAndroid Build Coastguard Worker     deinit();
163*35238bceSAndroid Build Coastguard Worker }
164*35238bceSAndroid Build Coastguard Worker 
init(void)165*35238bceSAndroid Build Coastguard Worker void BindingRenderCase::init(void)
166*35238bceSAndroid Build Coastguard Worker {
167*35238bceSAndroid Build Coastguard Worker     // check requirements
168*35238bceSAndroid Build Coastguard Worker     if (m_context.getRenderTarget().getWidth() < TEST_RENDER_SIZE ||
169*35238bceSAndroid Build Coastguard Worker         m_context.getRenderTarget().getHeight() < TEST_RENDER_SIZE)
170*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Test requires at least " + de::toString<int>(TEST_RENDER_SIZE) + "x" +
171*35238bceSAndroid Build Coastguard Worker                                      de::toString<int>(TEST_RENDER_SIZE) + " render target");
172*35238bceSAndroid Build Coastguard Worker 
173*35238bceSAndroid Build Coastguard Worker     // resources
174*35238bceSAndroid Build Coastguard Worker     m_context.getRenderContext().getFunctions().genVertexArrays(1, &m_vao);
175*35238bceSAndroid Build Coastguard Worker     if (m_context.getRenderContext().getFunctions().getError() != GL_NO_ERROR)
176*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not gen vao");
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker     createBuffers();
179*35238bceSAndroid Build Coastguard Worker     createShader();
180*35238bceSAndroid Build Coastguard Worker }
181*35238bceSAndroid Build Coastguard Worker 
deinit(void)182*35238bceSAndroid Build Coastguard Worker void BindingRenderCase::deinit(void)
183*35238bceSAndroid Build Coastguard Worker {
184*35238bceSAndroid Build Coastguard Worker     if (m_vao)
185*35238bceSAndroid Build Coastguard Worker     {
186*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
187*35238bceSAndroid Build Coastguard Worker         m_vao = 0;
188*35238bceSAndroid Build Coastguard Worker     }
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker     delete m_program;
191*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
192*35238bceSAndroid Build Coastguard Worker }
193*35238bceSAndroid Build Coastguard Worker 
iterate(void)194*35238bceSAndroid Build Coastguard Worker BindingRenderCase::IterateResult BindingRenderCase::iterate(void)
195*35238bceSAndroid Build Coastguard Worker {
196*35238bceSAndroid Build Coastguard Worker     tcu::Surface surface(TEST_RENDER_SIZE, TEST_RENDER_SIZE);
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker     // draw pattern
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker     renderTo(surface);
201*35238bceSAndroid Build Coastguard Worker 
202*35238bceSAndroid Build Coastguard Worker     // verify results
203*35238bceSAndroid Build Coastguard Worker 
204*35238bceSAndroid Build Coastguard Worker     if (verifyImageYellowGreen(surface, m_testCtx.getLog(), false))
205*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
206*35238bceSAndroid Build Coastguard Worker     else if (m_unalignedData)
207*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned data");
208*35238bceSAndroid Build Coastguard Worker     else
209*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
210*35238bceSAndroid Build Coastguard Worker 
211*35238bceSAndroid Build Coastguard Worker     return STOP;
212*35238bceSAndroid Build Coastguard Worker }
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker class SingleBindingCase : public BindingRenderCase
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker public:
217*35238bceSAndroid Build Coastguard Worker     enum CaseFlag
218*35238bceSAndroid Build Coastguard Worker     {
219*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIB_UNALIGNED = (1 << 0), // !< unalign attributes with relativeOffset
220*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIB_ALIGNED =
221*35238bceSAndroid Build Coastguard Worker             (1 << 1), // !< align attributes with relativeOffset to the buffer begin (and not buffer offset)
222*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIBS_MULTIPLE_ELEMS = (1 << 2), // !< use multiple attribute elements
223*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIBS_SHARED_ELEMS =
224*35238bceSAndroid Build Coastguard Worker             (1 << 3), // !< use multiple shared attribute elements. xyzw & rgba stored as (x, y, zr, wg, b, a)
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_ALIGNED_OFFSET   = (1 << 4), // !< use aligned offset to the buffer object
227*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_UNALIGNED_OFFSET = (1 << 5), // !< use unaligned offset to the buffer object
228*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_UNALIGNED_STRIDE = (1 << 6), // !< unalign buffer elements
229*35238bceSAndroid Build Coastguard Worker     };
230*35238bceSAndroid Build Coastguard Worker     SingleBindingCase(Context &ctx, const char *name, int flags);
231*35238bceSAndroid Build Coastguard Worker     ~SingleBindingCase(void);
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker     void init(void);
234*35238bceSAndroid Build Coastguard Worker     void deinit(void);
235*35238bceSAndroid Build Coastguard Worker 
236*35238bceSAndroid Build Coastguard Worker private:
237*35238bceSAndroid Build Coastguard Worker     struct TestSpec
238*35238bceSAndroid Build Coastguard Worker     {
239*35238bceSAndroid Build Coastguard Worker         int bufferOffset;
240*35238bceSAndroid Build Coastguard Worker         int bufferStride;
241*35238bceSAndroid Build Coastguard Worker         int positionAttrOffset;
242*35238bceSAndroid Build Coastguard Worker         int colorAttrOffset;
243*35238bceSAndroid Build Coastguard Worker         bool hasColorAttr;
244*35238bceSAndroid Build Coastguard Worker     };
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker     enum
247*35238bceSAndroid Build Coastguard Worker     {
248*35238bceSAndroid Build Coastguard Worker         GRID_SIZE = 20
249*35238bceSAndroid Build Coastguard Worker     };
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker     void renderTo(tcu::Surface &dst);
252*35238bceSAndroid Build Coastguard Worker 
253*35238bceSAndroid Build Coastguard Worker     static TestSpec genTestSpec(int flags);
254*35238bceSAndroid Build Coastguard Worker     static std::string genTestDescription(int flags);
255*35238bceSAndroid Build Coastguard Worker     static bool isDataUnaligned(int flags);
256*35238bceSAndroid Build Coastguard Worker 
257*35238bceSAndroid Build Coastguard Worker     void createBuffers(void);
258*35238bceSAndroid Build Coastguard Worker     void createShader(void);
259*35238bceSAndroid Build Coastguard Worker     std::string genVertexSource(void);
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker     const TestSpec m_spec;
262*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_buf;
263*35238bceSAndroid Build Coastguard Worker };
264*35238bceSAndroid Build Coastguard Worker 
SingleBindingCase(Context & ctx,const char * name,int flags)265*35238bceSAndroid Build Coastguard Worker SingleBindingCase::SingleBindingCase(Context &ctx, const char *name, int flags)
266*35238bceSAndroid Build Coastguard Worker     : BindingRenderCase(ctx, name, genTestDescription(flags).c_str(), isDataUnaligned(flags))
267*35238bceSAndroid Build Coastguard Worker     , m_spec(genTestSpec(flags))
268*35238bceSAndroid Build Coastguard Worker     , m_buf(0)
269*35238bceSAndroid Build Coastguard Worker {
270*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!((flags & FLAG_ATTRIB_UNALIGNED) && (flags & FLAG_ATTRIB_ALIGNED)));
271*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!((flags & FLAG_ATTRIB_ALIGNED) && (flags & FLAG_BUF_UNALIGNED_STRIDE)));
272*35238bceSAndroid Build Coastguard Worker 
273*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!isDataUnaligned(flags));
274*35238bceSAndroid Build Coastguard Worker }
275*35238bceSAndroid Build Coastguard Worker 
~SingleBindingCase(void)276*35238bceSAndroid Build Coastguard Worker SingleBindingCase::~SingleBindingCase(void)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker     deinit();
279*35238bceSAndroid Build Coastguard Worker }
280*35238bceSAndroid Build Coastguard Worker 
init(void)281*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::init(void)
282*35238bceSAndroid Build Coastguard Worker {
283*35238bceSAndroid Build Coastguard Worker     // log what we are trying to do
284*35238bceSAndroid Build Coastguard Worker 
285*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << (int)GRID_SIZE << "x" << (int)GRID_SIZE << " grid.\n"
286*35238bceSAndroid Build Coastguard Worker                        << "Buffer format:\n"
287*35238bceSAndroid Build Coastguard Worker                        << "    bufferOffset: " << m_spec.bufferOffset << "\n"
288*35238bceSAndroid Build Coastguard Worker                        << "    bufferStride: " << m_spec.bufferStride << "\n"
289*35238bceSAndroid Build Coastguard Worker                        << "Vertex position format:\n"
290*35238bceSAndroid Build Coastguard Worker                        << "    type: float4\n"
291*35238bceSAndroid Build Coastguard Worker                        << "    offset: " << m_spec.positionAttrOffset << "\n"
292*35238bceSAndroid Build Coastguard Worker                        << "    total offset: " << m_spec.bufferOffset + m_spec.positionAttrOffset << "\n"
293*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
294*35238bceSAndroid Build Coastguard Worker 
295*35238bceSAndroid Build Coastguard Worker     if (m_spec.hasColorAttr)
296*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Color:\n"
297*35238bceSAndroid Build Coastguard Worker                            << "    type: float4\n"
298*35238bceSAndroid Build Coastguard Worker                            << "    offset: " << m_spec.colorAttrOffset << "\n"
299*35238bceSAndroid Build Coastguard Worker                            << "    total offset: " << m_spec.bufferOffset + m_spec.colorAttrOffset << "\n"
300*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
301*35238bceSAndroid Build Coastguard Worker     // init
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::init();
304*35238bceSAndroid Build Coastguard Worker }
305*35238bceSAndroid Build Coastguard Worker 
deinit(void)306*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::deinit(void)
307*35238bceSAndroid Build Coastguard Worker {
308*35238bceSAndroid Build Coastguard Worker     if (m_buf)
309*35238bceSAndroid Build Coastguard Worker     {
310*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buf);
311*35238bceSAndroid Build Coastguard Worker         m_buf = 0;
312*35238bceSAndroid Build Coastguard Worker     }
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::deinit();
315*35238bceSAndroid Build Coastguard Worker }
316*35238bceSAndroid Build Coastguard Worker 
renderTo(tcu::Surface & dst)317*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::renderTo(tcu::Surface &dst)
318*35238bceSAndroid Build Coastguard Worker {
319*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
320*35238bceSAndroid Build Coastguard Worker     const int positionLoc     = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
321*35238bceSAndroid Build Coastguard Worker     const int colorLoc        = gl.glGetAttribLocation(m_program->getProgram(), "a_color");
322*35238bceSAndroid Build Coastguard Worker     const int colorUniformLoc = gl.glGetUniformLocation(m_program->getProgram(), "u_color");
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
327*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
328*35238bceSAndroid Build Coastguard Worker     gl.glViewport(0, 0, dst.getWidth(), dst.getHeight());
329*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(m_vao);
330*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set vao");
331*35238bceSAndroid Build Coastguard Worker 
332*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
333*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
334*35238bceSAndroid Build Coastguard Worker 
335*35238bceSAndroid Build Coastguard Worker     if (m_spec.hasColorAttr)
336*35238bceSAndroid Build Coastguard Worker     {
337*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(3, m_buf, m_spec.bufferOffset, m_spec.bufferStride);
338*35238bceSAndroid Build Coastguard Worker 
339*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, 3);
340*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, m_spec.positionAttrOffset);
341*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(colorLoc, 3);
344*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, m_spec.colorAttrOffset);
345*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(colorLoc);
346*35238bceSAndroid Build Coastguard Worker 
347*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
348*35238bceSAndroid Build Coastguard Worker 
349*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, GRID_SIZE * GRID_SIZE * 6);
350*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
351*35238bceSAndroid Build Coastguard Worker     }
352*35238bceSAndroid Build Coastguard Worker     else
353*35238bceSAndroid Build Coastguard Worker     {
354*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(3, m_buf, m_spec.bufferOffset, m_spec.bufferStride);
355*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, 3);
356*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, m_spec.positionAttrOffset);
357*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
358*35238bceSAndroid Build Coastguard Worker 
359*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
360*35238bceSAndroid Build Coastguard Worker         gl.glUniform4f(colorUniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, GRID_SIZE * GRID_SIZE * 6);
363*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
364*35238bceSAndroid Build Coastguard Worker     }
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
367*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(0);
368*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(0);
369*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "clean");
370*35238bceSAndroid Build Coastguard Worker 
371*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
372*35238bceSAndroid Build Coastguard Worker }
373*35238bceSAndroid Build Coastguard Worker 
genTestSpec(int flags)374*35238bceSAndroid Build Coastguard Worker SingleBindingCase::TestSpec SingleBindingCase::genTestSpec(int flags)
375*35238bceSAndroid Build Coastguard Worker {
376*35238bceSAndroid Build Coastguard Worker     const int datumSize          = 4;
377*35238bceSAndroid Build Coastguard Worker     const int bufferOffset       = (flags & FLAG_BUF_ALIGNED_OFFSET)   ? (32) :
378*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_BUF_UNALIGNED_OFFSET) ? (19) :
379*35238bceSAndroid Build Coastguard Worker                                                                          (0);
380*35238bceSAndroid Build Coastguard Worker     const int attrBufAlignment   = ((bufferOffset % datumSize) == 0) ? (0) : (datumSize - (bufferOffset % datumSize));
381*35238bceSAndroid Build Coastguard Worker     const int positionAttrOffset = (flags & FLAG_ATTRIB_UNALIGNED) ? (3) :
382*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_ATTRIB_ALIGNED)   ? (attrBufAlignment) :
383*35238bceSAndroid Build Coastguard Worker                                                                      (0);
384*35238bceSAndroid Build Coastguard Worker     const bool hasColorAttr      = (flags & FLAG_ATTRIBS_SHARED_ELEMS) || (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS);
385*35238bceSAndroid Build Coastguard Worker     const int colorAttrOffset    = (flags & FLAG_ATTRIBS_SHARED_ELEMS)   ? (2 * datumSize) :
386*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS) ? (4 * datumSize) :
387*35238bceSAndroid Build Coastguard Worker                                                                            (-1);
388*35238bceSAndroid Build Coastguard Worker 
389*35238bceSAndroid Build Coastguard Worker     const int bufferStrideBase = de::max(positionAttrOffset + 4 * datumSize, colorAttrOffset + 4 * datumSize);
390*35238bceSAndroid Build Coastguard Worker     const int bufferStrideAlignment =
391*35238bceSAndroid Build Coastguard Worker         ((bufferStrideBase % datumSize) == 0) ? (0) : (datumSize - (bufferStrideBase % datumSize));
392*35238bceSAndroid Build Coastguard Worker     const int bufferStridePadding =
393*35238bceSAndroid Build Coastguard Worker         ((flags & FLAG_BUF_UNALIGNED_STRIDE) && deIsAligned32(bufferStrideBase, datumSize)) ? (13) :
394*35238bceSAndroid Build Coastguard Worker         (!(flags & FLAG_BUF_UNALIGNED_STRIDE) && !deIsAligned32(bufferStrideBase, datumSize)) ?
395*35238bceSAndroid Build Coastguard Worker                                                                                               (bufferStrideAlignment) :
396*35238bceSAndroid Build Coastguard Worker                                                                                               (0);
397*35238bceSAndroid Build Coastguard Worker 
398*35238bceSAndroid Build Coastguard Worker     TestSpec spec;
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker     spec.bufferOffset       = bufferOffset;
401*35238bceSAndroid Build Coastguard Worker     spec.bufferStride       = bufferStrideBase + bufferStridePadding;
402*35238bceSAndroid Build Coastguard Worker     spec.positionAttrOffset = positionAttrOffset;
403*35238bceSAndroid Build Coastguard Worker     spec.colorAttrOffset    = colorAttrOffset;
404*35238bceSAndroid Build Coastguard Worker     spec.hasColorAttr       = hasColorAttr;
405*35238bceSAndroid Build Coastguard Worker 
406*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
407*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!deIsAligned32(spec.bufferOffset + spec.positionAttrOffset, datumSize));
408*35238bceSAndroid Build Coastguard Worker     else if (flags & FLAG_ATTRIB_ALIGNED)
409*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(deIsAligned32(spec.bufferOffset + spec.positionAttrOffset, datumSize));
410*35238bceSAndroid Build Coastguard Worker 
411*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_STRIDE)
412*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!deIsAligned32(spec.bufferStride, datumSize));
413*35238bceSAndroid Build Coastguard Worker     else
414*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(deIsAligned32(spec.bufferStride, datumSize));
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker     return spec;
417*35238bceSAndroid Build Coastguard Worker }
418*35238bceSAndroid Build Coastguard Worker 
genTestDescription(int flags)419*35238bceSAndroid Build Coastguard Worker std::string SingleBindingCase::genTestDescription(int flags)
420*35238bceSAndroid Build Coastguard Worker {
421*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
422*35238bceSAndroid Build Coastguard Worker     buf << "draw test pattern";
423*35238bceSAndroid Build Coastguard Worker 
424*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
425*35238bceSAndroid Build Coastguard Worker         buf << ", attribute offset (unaligned)";
426*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_ALIGNED)
427*35238bceSAndroid Build Coastguard Worker         buf << ", attribute offset (aligned)";
428*35238bceSAndroid Build Coastguard Worker 
429*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS)
430*35238bceSAndroid Build Coastguard Worker         buf << ", 2 attributes";
431*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIBS_SHARED_ELEMS)
432*35238bceSAndroid Build Coastguard Worker         buf << ", 2 attributes (some components shared)";
433*35238bceSAndroid Build Coastguard Worker 
434*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_ALIGNED_OFFSET)
435*35238bceSAndroid Build Coastguard Worker         buf << ", buffer offset aligned";
436*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_OFFSET)
437*35238bceSAndroid Build Coastguard Worker         buf << ", buffer offset unaligned";
438*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_STRIDE)
439*35238bceSAndroid Build Coastguard Worker         buf << ", buffer stride unaligned";
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker     return buf.str();
442*35238bceSAndroid Build Coastguard Worker }
443*35238bceSAndroid Build Coastguard Worker 
isDataUnaligned(int flags)444*35238bceSAndroid Build Coastguard Worker bool SingleBindingCase::isDataUnaligned(int flags)
445*35238bceSAndroid Build Coastguard Worker {
446*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
447*35238bceSAndroid Build Coastguard Worker         return true;
448*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_ALIGNED)
449*35238bceSAndroid Build Coastguard Worker         return false;
450*35238bceSAndroid Build Coastguard Worker 
451*35238bceSAndroid Build Coastguard Worker     return (flags & FLAG_BUF_UNALIGNED_OFFSET) || (flags & FLAG_BUF_UNALIGNED_STRIDE);
452*35238bceSAndroid Build Coastguard Worker }
453*35238bceSAndroid Build Coastguard Worker 
createBuffers(void)454*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::createBuffers(void)
455*35238bceSAndroid Build Coastguard Worker {
456*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
457*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> dataBuf(m_spec.bufferOffset + m_spec.bufferStride * GRID_SIZE * GRID_SIZE * 6);
458*35238bceSAndroid Build Coastguard Worker 
459*35238bceSAndroid Build Coastguard Worker     // In interleaved mode color rg and position zw are the same. Select "good" values for r and g
460*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 colorA(0.0f, 1.0f, 0.0f, 1.0f);
461*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 colorB(0.5f, 1.0f, 0.0f, 1.0f);
462*35238bceSAndroid Build Coastguard Worker 
463*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < GRID_SIZE; ++y)
464*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < GRID_SIZE; ++x)
465*35238bceSAndroid Build Coastguard Worker         {
466*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 &color       = ((x + y) % 2 == 0) ? (colorA) : (colorB);
467*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 positions[6] = {
468*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
469*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
470*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
471*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
472*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
473*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
474*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
475*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
476*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
477*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
478*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
479*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
480*35238bceSAndroid Build Coastguard Worker             };
481*35238bceSAndroid Build Coastguard Worker 
482*35238bceSAndroid Build Coastguard Worker             // copy cell vertices to the buffer.
483*35238bceSAndroid Build Coastguard Worker             for (int v = 0; v < 6; ++v)
484*35238bceSAndroid Build Coastguard Worker                 memcpy(&dataBuf[m_spec.bufferOffset + m_spec.positionAttrOffset +
485*35238bceSAndroid Build Coastguard Worker                                 m_spec.bufferStride * ((y * GRID_SIZE + x) * 6 + v)],
486*35238bceSAndroid Build Coastguard Worker                        positions[v].getPtr(), sizeof(positions[v]));
487*35238bceSAndroid Build Coastguard Worker 
488*35238bceSAndroid Build Coastguard Worker             // copy color to buffer
489*35238bceSAndroid Build Coastguard Worker             if (m_spec.hasColorAttr)
490*35238bceSAndroid Build Coastguard Worker                 for (int v = 0; v < 6; ++v)
491*35238bceSAndroid Build Coastguard Worker                     memcpy(&dataBuf[m_spec.bufferOffset + m_spec.colorAttrOffset +
492*35238bceSAndroid Build Coastguard Worker                                     m_spec.bufferStride * ((y * GRID_SIZE + x) * 6 + v)],
493*35238bceSAndroid Build Coastguard Worker                            color.getPtr(), sizeof(color));
494*35238bceSAndroid Build Coastguard Worker         }
495*35238bceSAndroid Build Coastguard Worker 
496*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_buf);
497*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_buf);
498*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)dataBuf.size(), &dataBuf[0], GL_STATIC_DRAW);
499*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
500*35238bceSAndroid Build Coastguard Worker 
501*35238bceSAndroid Build Coastguard Worker     if (gl.getError() != GL_NO_ERROR)
502*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not init buffer");
503*35238bceSAndroid Build Coastguard Worker }
504*35238bceSAndroid Build Coastguard Worker 
createShader(void)505*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::createShader(void)
506*35238bceSAndroid Build Coastguard Worker {
507*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
508*35238bceSAndroid Build Coastguard Worker                                                                          << glu::VertexSource(genVertexSource())
509*35238bceSAndroid Build Coastguard Worker                                                                          << glu::FragmentSource(s_colorFragmentShader));
510*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
511*35238bceSAndroid Build Coastguard Worker 
512*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
513*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build shader");
514*35238bceSAndroid Build Coastguard Worker }
515*35238bceSAndroid Build Coastguard Worker 
genVertexSource(void)516*35238bceSAndroid Build Coastguard Worker std::string SingleBindingCase::genVertexSource(void)
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker     const bool useUniformColor = !m_spec.hasColorAttr;
519*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker     buf << "#version 310 es\n"
522*35238bceSAndroid Build Coastguard Worker            "in highp vec4 a_position;\n";
523*35238bceSAndroid Build Coastguard Worker 
524*35238bceSAndroid Build Coastguard Worker     if (!useUniformColor)
525*35238bceSAndroid Build Coastguard Worker         buf << "in highp vec4 a_color;\n";
526*35238bceSAndroid Build Coastguard Worker     else
527*35238bceSAndroid Build Coastguard Worker         buf << "uniform highp vec4 u_color;\n";
528*35238bceSAndroid Build Coastguard Worker 
529*35238bceSAndroid Build Coastguard Worker     buf << "out highp vec4 v_color;\n"
530*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
531*35238bceSAndroid Build Coastguard Worker            "{\n"
532*35238bceSAndroid Build Coastguard Worker            "    gl_Position = a_position;\n"
533*35238bceSAndroid Build Coastguard Worker            "    v_color = "
534*35238bceSAndroid Build Coastguard Worker         << ((useUniformColor) ? ("u_color") : ("a_color"))
535*35238bceSAndroid Build Coastguard Worker         << ";\n"
536*35238bceSAndroid Build Coastguard Worker            "}\n";
537*35238bceSAndroid Build Coastguard Worker 
538*35238bceSAndroid Build Coastguard Worker     return buf.str();
539*35238bceSAndroid Build Coastguard Worker }
540*35238bceSAndroid Build Coastguard Worker 
541*35238bceSAndroid Build Coastguard Worker class MultipleBindingCase : public BindingRenderCase
542*35238bceSAndroid Build Coastguard Worker {
543*35238bceSAndroid Build Coastguard Worker public:
544*35238bceSAndroid Build Coastguard Worker     enum CaseFlag
545*35238bceSAndroid Build Coastguard Worker     {
546*35238bceSAndroid Build Coastguard Worker         FLAG_ZERO_STRIDE      = (1 << 0), // !< set a buffer stride to zero
547*35238bceSAndroid Build Coastguard Worker         FLAG_INSTANCED        = (1 << 1), // !< set a buffer instance divisor to non-zero
548*35238bceSAndroid Build Coastguard Worker         FLAG_ALIASING_BUFFERS = (1 << 2), // !< bind buffer to multiple binding points
549*35238bceSAndroid Build Coastguard Worker     };
550*35238bceSAndroid Build Coastguard Worker 
551*35238bceSAndroid Build Coastguard Worker     MultipleBindingCase(Context &ctx, const char *name, int flags);
552*35238bceSAndroid Build Coastguard Worker     ~MultipleBindingCase(void);
553*35238bceSAndroid Build Coastguard Worker 
554*35238bceSAndroid Build Coastguard Worker     void init(void);
555*35238bceSAndroid Build Coastguard Worker     void deinit(void);
556*35238bceSAndroid Build Coastguard Worker 
557*35238bceSAndroid Build Coastguard Worker private:
558*35238bceSAndroid Build Coastguard Worker     struct TestSpec
559*35238bceSAndroid Build Coastguard Worker     {
560*35238bceSAndroid Build Coastguard Worker         bool zeroStride;
561*35238bceSAndroid Build Coastguard Worker         bool instanced;
562*35238bceSAndroid Build Coastguard Worker         bool aliasingBuffers;
563*35238bceSAndroid Build Coastguard Worker     };
564*35238bceSAndroid Build Coastguard Worker 
565*35238bceSAndroid Build Coastguard Worker     enum
566*35238bceSAndroid Build Coastguard Worker     {
567*35238bceSAndroid Build Coastguard Worker         GRID_SIZE = 20
568*35238bceSAndroid Build Coastguard Worker     };
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker     void renderTo(tcu::Surface &dst);
571*35238bceSAndroid Build Coastguard Worker 
572*35238bceSAndroid Build Coastguard Worker     TestSpec genTestSpec(int flags) const;
573*35238bceSAndroid Build Coastguard Worker     std::string genTestDescription(int flags) const;
574*35238bceSAndroid Build Coastguard Worker     void createBuffers(void);
575*35238bceSAndroid Build Coastguard Worker     void createShader(void);
576*35238bceSAndroid Build Coastguard Worker 
577*35238bceSAndroid Build Coastguard Worker     const TestSpec m_spec;
578*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_primitiveBuf;
579*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_colorOffsetBuf;
580*35238bceSAndroid Build Coastguard Worker };
581*35238bceSAndroid Build Coastguard Worker 
MultipleBindingCase(Context & ctx,const char * name,int flags)582*35238bceSAndroid Build Coastguard Worker MultipleBindingCase::MultipleBindingCase(Context &ctx, const char *name, int flags)
583*35238bceSAndroid Build Coastguard Worker     : BindingRenderCase(ctx, name, genTestDescription(flags).c_str(), false)
584*35238bceSAndroid Build Coastguard Worker     , m_spec(genTestSpec(flags))
585*35238bceSAndroid Build Coastguard Worker     , m_primitiveBuf(0)
586*35238bceSAndroid Build Coastguard Worker     , m_colorOffsetBuf(0)
587*35238bceSAndroid Build Coastguard Worker {
588*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!(m_spec.instanced && m_spec.zeroStride));
589*35238bceSAndroid Build Coastguard Worker }
590*35238bceSAndroid Build Coastguard Worker 
~MultipleBindingCase(void)591*35238bceSAndroid Build Coastguard Worker MultipleBindingCase::~MultipleBindingCase(void)
592*35238bceSAndroid Build Coastguard Worker {
593*35238bceSAndroid Build Coastguard Worker     deinit();
594*35238bceSAndroid Build Coastguard Worker }
595*35238bceSAndroid Build Coastguard Worker 
init(void)596*35238bceSAndroid Build Coastguard Worker void MultipleBindingCase::init(void)
597*35238bceSAndroid Build Coastguard Worker {
598*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::init();
599*35238bceSAndroid Build Coastguard Worker 
600*35238bceSAndroid Build Coastguard Worker     // log what we are trying to do
601*35238bceSAndroid Build Coastguard Worker 
602*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << (int)GRID_SIZE << "x" << (int)GRID_SIZE << " grid.\n"
603*35238bceSAndroid Build Coastguard Worker                        << "Vertex positions:\n"
604*35238bceSAndroid Build Coastguard Worker                        << "    binding point: 1\n"
605*35238bceSAndroid Build Coastguard Worker                        << "Vertex offsets:\n"
606*35238bceSAndroid Build Coastguard Worker                        << "    binding point: 2\n"
607*35238bceSAndroid Build Coastguard Worker                        << "Vertex colors:\n"
608*35238bceSAndroid Build Coastguard Worker                        << "    binding point: 2\n"
609*35238bceSAndroid Build Coastguard Worker                        << "Binding point 1:\n"
610*35238bceSAndroid Build Coastguard Worker                        << "    buffer object: " << m_primitiveBuf << "\n"
611*35238bceSAndroid Build Coastguard Worker                        << "Binding point 2:\n"
612*35238bceSAndroid Build Coastguard Worker                        << "    buffer object: " << ((m_spec.aliasingBuffers) ? (m_primitiveBuf) : (m_colorOffsetBuf))
613*35238bceSAndroid Build Coastguard Worker                        << "\n"
614*35238bceSAndroid Build Coastguard Worker                        << "    instance divisor: " << ((m_spec.instanced) ? (1) : (0)) << "\n"
615*35238bceSAndroid Build Coastguard Worker                        << "    stride: " << ((m_spec.zeroStride) ? (0) : (4 * 4 * 2)) << "\n"
616*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
617*35238bceSAndroid Build Coastguard Worker }
618*35238bceSAndroid Build Coastguard Worker 
deinit(void)619*35238bceSAndroid Build Coastguard Worker void MultipleBindingCase::deinit(void)
620*35238bceSAndroid Build Coastguard Worker {
621*35238bceSAndroid Build Coastguard Worker     if (m_primitiveBuf)
622*35238bceSAndroid Build Coastguard Worker     {
623*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_primitiveBuf);
624*35238bceSAndroid Build Coastguard Worker         m_primitiveBuf = DE_NULL;
625*35238bceSAndroid Build Coastguard Worker     }
626*35238bceSAndroid Build Coastguard Worker 
627*35238bceSAndroid Build Coastguard Worker     if (m_colorOffsetBuf)
628*35238bceSAndroid Build Coastguard Worker     {
629*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_colorOffsetBuf);
630*35238bceSAndroid Build Coastguard Worker         m_colorOffsetBuf = DE_NULL;
631*35238bceSAndroid Build Coastguard Worker     }
632*35238bceSAndroid Build Coastguard Worker 
633*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::deinit();
634*35238bceSAndroid Build Coastguard Worker }
635*35238bceSAndroid Build Coastguard Worker 
renderTo(tcu::Surface & dst)636*35238bceSAndroid Build Coastguard Worker void MultipleBindingCase::renderTo(tcu::Surface &dst)
637*35238bceSAndroid Build Coastguard Worker {
638*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
639*35238bceSAndroid Build Coastguard Worker     const int positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
640*35238bceSAndroid Build Coastguard Worker     const int colorLoc    = gl.glGetAttribLocation(m_program->getProgram(), "a_color");
641*35238bceSAndroid Build Coastguard Worker     const int offsetLoc   = gl.glGetAttribLocation(m_program->getProgram(), "a_offset");
642*35238bceSAndroid Build Coastguard Worker 
643*35238bceSAndroid Build Coastguard Worker     const int positionBinding    = 1;
644*35238bceSAndroid Build Coastguard Worker     const int colorOffsetBinding = 2;
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
647*35238bceSAndroid Build Coastguard Worker 
648*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
649*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
650*35238bceSAndroid Build Coastguard Worker     gl.glViewport(0, 0, dst.getWidth(), dst.getHeight());
651*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(m_vao);
652*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set vao");
653*35238bceSAndroid Build Coastguard Worker 
654*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
655*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
656*35238bceSAndroid Build Coastguard Worker 
657*35238bceSAndroid Build Coastguard Worker     // Setup format & binding
658*35238bceSAndroid Build Coastguard Worker 
659*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(positionLoc);
660*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(colorLoc);
661*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(offsetLoc);
662*35238bceSAndroid Build Coastguard Worker 
663*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
664*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, 0);
665*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribFormat(offsetLoc, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4));
666*35238bceSAndroid Build Coastguard Worker 
667*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribBinding(positionLoc, positionBinding);
668*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribBinding(colorLoc, colorOffsetBinding);
669*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribBinding(offsetLoc, colorOffsetBinding);
670*35238bceSAndroid Build Coastguard Worker 
671*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup attribs");
672*35238bceSAndroid Build Coastguard Worker 
673*35238bceSAndroid Build Coastguard Worker     // setup binding points
674*35238bceSAndroid Build Coastguard Worker 
675*35238bceSAndroid Build Coastguard Worker     gl.glVertexBindingDivisor(positionBinding, 0);
676*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexBuffer(positionBinding, m_primitiveBuf, 0, sizeof(tcu::Vec4));
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker     {
679*35238bceSAndroid Build Coastguard Worker         const int stride         = (m_spec.zeroStride) ? (0) : (2 * (int)sizeof(tcu::Vec4));
680*35238bceSAndroid Build Coastguard Worker         const int offset         = (!m_spec.aliasingBuffers) ? (0) :
681*35238bceSAndroid Build Coastguard Worker                                    (m_spec.instanced)        ? (6 * (int)sizeof(tcu::Vec4)) :
682*35238bceSAndroid Build Coastguard Worker                                                                (6 * GRID_SIZE * GRID_SIZE * (int)sizeof(tcu::Vec4));
683*35238bceSAndroid Build Coastguard Worker         const glw::GLuint buffer = (m_spec.aliasingBuffers) ? (m_primitiveBuf) : (m_colorOffsetBuf);
684*35238bceSAndroid Build Coastguard Worker         const int divisor        = (m_spec.instanced) ? (1) : (0);
685*35238bceSAndroid Build Coastguard Worker 
686*35238bceSAndroid Build Coastguard Worker         gl.glVertexBindingDivisor(colorOffsetBinding, divisor);
687*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(colorOffsetBinding, buffer, offset, (glw::GLsizei)stride);
688*35238bceSAndroid Build Coastguard Worker     }
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set binding points");
691*35238bceSAndroid Build Coastguard Worker 
692*35238bceSAndroid Build Coastguard Worker     if (m_spec.instanced)
693*35238bceSAndroid Build Coastguard Worker         gl.glDrawArraysInstanced(GL_TRIANGLES, 0, 6, GRID_SIZE * GRID_SIZE);
694*35238bceSAndroid Build Coastguard Worker     else
695*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, GRID_SIZE * GRID_SIZE * 6);
696*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
697*35238bceSAndroid Build Coastguard Worker 
698*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
699*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(0);
700*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(0);
701*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "clean");
702*35238bceSAndroid Build Coastguard Worker 
703*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
704*35238bceSAndroid Build Coastguard Worker }
705*35238bceSAndroid Build Coastguard Worker 
genTestSpec(int flags) const706*35238bceSAndroid Build Coastguard Worker MultipleBindingCase::TestSpec MultipleBindingCase::genTestSpec(int flags) const
707*35238bceSAndroid Build Coastguard Worker {
708*35238bceSAndroid Build Coastguard Worker     MultipleBindingCase::TestSpec spec;
709*35238bceSAndroid Build Coastguard Worker 
710*35238bceSAndroid Build Coastguard Worker     spec.zeroStride      = !!(flags & FLAG_ZERO_STRIDE);
711*35238bceSAndroid Build Coastguard Worker     spec.instanced       = !!(flags & FLAG_INSTANCED);
712*35238bceSAndroid Build Coastguard Worker     spec.aliasingBuffers = !!(flags & FLAG_ALIASING_BUFFERS);
713*35238bceSAndroid Build Coastguard Worker 
714*35238bceSAndroid Build Coastguard Worker     return spec;
715*35238bceSAndroid Build Coastguard Worker }
716*35238bceSAndroid Build Coastguard Worker 
genTestDescription(int flags) const717*35238bceSAndroid Build Coastguard Worker std::string MultipleBindingCase::genTestDescription(int flags) const
718*35238bceSAndroid Build Coastguard Worker {
719*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
720*35238bceSAndroid Build Coastguard Worker     buf << "draw test pattern";
721*35238bceSAndroid Build Coastguard Worker 
722*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ZERO_STRIDE)
723*35238bceSAndroid Build Coastguard Worker         buf << ", zero stride";
724*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_INSTANCED)
725*35238bceSAndroid Build Coastguard Worker         buf << ", instanced binding point";
726*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ALIASING_BUFFERS)
727*35238bceSAndroid Build Coastguard Worker         buf << ", binding points share buffer object";
728*35238bceSAndroid Build Coastguard Worker 
729*35238bceSAndroid Build Coastguard Worker     return buf.str();
730*35238bceSAndroid Build Coastguard Worker }
731*35238bceSAndroid Build Coastguard Worker 
createBuffers(void)732*35238bceSAndroid Build Coastguard Worker void MultipleBindingCase::createBuffers(void)
733*35238bceSAndroid Build Coastguard Worker {
734*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
735*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 green    = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
736*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 yellow   = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
737*35238bceSAndroid Build Coastguard Worker 
738*35238bceSAndroid Build Coastguard Worker     const int vertexDataSize     = (m_spec.instanced) ? (6) : (6 * GRID_SIZE * GRID_SIZE);
739*35238bceSAndroid Build Coastguard Worker     const int offsetColorSize    = (m_spec.zeroStride) ? (2) :
740*35238bceSAndroid Build Coastguard Worker                                    (m_spec.instanced)  ? (2 * GRID_SIZE * GRID_SIZE) :
741*35238bceSAndroid Build Coastguard Worker                                                          (2 * 6 * GRID_SIZE * GRID_SIZE);
742*35238bceSAndroid Build Coastguard Worker     const int primitiveBufSize   = (m_spec.aliasingBuffers) ? (vertexDataSize + offsetColorSize) : (vertexDataSize);
743*35238bceSAndroid Build Coastguard Worker     const int colorOffsetBufSize = (m_spec.aliasingBuffers) ? (0) : (offsetColorSize);
744*35238bceSAndroid Build Coastguard Worker 
745*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> primitiveData(primitiveBufSize);
746*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> colorOffsetData(colorOffsetBufSize);
747*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 *colorOffsetWritePtr = DE_NULL;
748*35238bceSAndroid Build Coastguard Worker 
749*35238bceSAndroid Build Coastguard Worker     if (m_spec.aliasingBuffers)
750*35238bceSAndroid Build Coastguard Worker     {
751*35238bceSAndroid Build Coastguard Worker         if (m_spec.instanced)
752*35238bceSAndroid Build Coastguard Worker             colorOffsetWritePtr = &primitiveData[6];
753*35238bceSAndroid Build Coastguard Worker         else
754*35238bceSAndroid Build Coastguard Worker             colorOffsetWritePtr = &primitiveData[GRID_SIZE * GRID_SIZE * 6];
755*35238bceSAndroid Build Coastguard Worker     }
756*35238bceSAndroid Build Coastguard Worker     else
757*35238bceSAndroid Build Coastguard Worker         colorOffsetWritePtr = &colorOffsetData[0];
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker     // write vertex position
760*35238bceSAndroid Build Coastguard Worker 
761*35238bceSAndroid Build Coastguard Worker     if (m_spec.instanced)
762*35238bceSAndroid Build Coastguard Worker     {
763*35238bceSAndroid Build Coastguard Worker         // store single basic primitive
764*35238bceSAndroid Build Coastguard Worker         primitiveData[0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
765*35238bceSAndroid Build Coastguard Worker         primitiveData[1] = tcu::Vec4(0.0f, 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
766*35238bceSAndroid Build Coastguard Worker         primitiveData[2] = tcu::Vec4(2.0f / float(GRID_SIZE), 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
767*35238bceSAndroid Build Coastguard Worker         primitiveData[3] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
768*35238bceSAndroid Build Coastguard Worker         primitiveData[4] = tcu::Vec4(2.0f / float(GRID_SIZE), 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
769*35238bceSAndroid Build Coastguard Worker         primitiveData[5] = tcu::Vec4(2.0f / float(GRID_SIZE), 0.0f, 0.0f, 1.0f);
770*35238bceSAndroid Build Coastguard Worker     }
771*35238bceSAndroid Build Coastguard Worker     else
772*35238bceSAndroid Build Coastguard Worker     {
773*35238bceSAndroid Build Coastguard Worker         // store whole grid
774*35238bceSAndroid Build Coastguard Worker         for (int y = 0; y < GRID_SIZE; ++y)
775*35238bceSAndroid Build Coastguard Worker             for (int x = 0; x < GRID_SIZE; ++x)
776*35238bceSAndroid Build Coastguard Worker             {
777*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 0] =
778*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
779*35238bceSAndroid Build Coastguard Worker                               float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
780*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 1] =
781*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
782*35238bceSAndroid Build Coastguard Worker                               float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
783*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 2] =
784*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
785*35238bceSAndroid Build Coastguard Worker                               float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
786*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 3] =
787*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
788*35238bceSAndroid Build Coastguard Worker                               float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
789*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 4] =
790*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
791*35238bceSAndroid Build Coastguard Worker                               float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
792*35238bceSAndroid Build Coastguard Worker                 primitiveData[(y * GRID_SIZE + x) * 6 + 5] =
793*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
794*35238bceSAndroid Build Coastguard Worker                               float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 1.0f);
795*35238bceSAndroid Build Coastguard Worker             }
796*35238bceSAndroid Build Coastguard Worker     }
797*35238bceSAndroid Build Coastguard Worker 
798*35238bceSAndroid Build Coastguard Worker     // store color&offset
799*35238bceSAndroid Build Coastguard Worker 
800*35238bceSAndroid Build Coastguard Worker     if (m_spec.zeroStride)
801*35238bceSAndroid Build Coastguard Worker     {
802*35238bceSAndroid Build Coastguard Worker         colorOffsetWritePtr[0] = green;
803*35238bceSAndroid Build Coastguard Worker         colorOffsetWritePtr[1] = tcu::Vec4(0.0f);
804*35238bceSAndroid Build Coastguard Worker     }
805*35238bceSAndroid Build Coastguard Worker     else if (m_spec.instanced)
806*35238bceSAndroid Build Coastguard Worker     {
807*35238bceSAndroid Build Coastguard Worker         for (int y = 0; y < GRID_SIZE; ++y)
808*35238bceSAndroid Build Coastguard Worker             for (int x = 0; x < GRID_SIZE; ++x)
809*35238bceSAndroid Build Coastguard Worker             {
810*35238bceSAndroid Build Coastguard Worker                 const tcu::Vec4 &color = ((x + y) % 2 == 0) ? (green) : (yellow);
811*35238bceSAndroid Build Coastguard Worker 
812*35238bceSAndroid Build Coastguard Worker                 colorOffsetWritePtr[(y * GRID_SIZE + x) * 2 + 0] = color;
813*35238bceSAndroid Build Coastguard Worker                 colorOffsetWritePtr[(y * GRID_SIZE + x) * 2 + 1] = tcu::Vec4(
814*35238bceSAndroid Build Coastguard Worker                     float(x) / float(GRID_SIZE) * 2.0f - 1.0f, float(y) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 0.0f);
815*35238bceSAndroid Build Coastguard Worker             }
816*35238bceSAndroid Build Coastguard Worker     }
817*35238bceSAndroid Build Coastguard Worker     else
818*35238bceSAndroid Build Coastguard Worker     {
819*35238bceSAndroid Build Coastguard Worker         for (int y = 0; y < GRID_SIZE; ++y)
820*35238bceSAndroid Build Coastguard Worker             for (int x = 0; x < GRID_SIZE; ++x)
821*35238bceSAndroid Build Coastguard Worker                 for (int v = 0; v < 6; ++v)
822*35238bceSAndroid Build Coastguard Worker                 {
823*35238bceSAndroid Build Coastguard Worker                     const tcu::Vec4 &color = ((x + y) % 2 == 0) ? (green) : (yellow);
824*35238bceSAndroid Build Coastguard Worker 
825*35238bceSAndroid Build Coastguard Worker                     colorOffsetWritePtr[((y * GRID_SIZE + x) * 6 + v) * 2 + 0] = color;
826*35238bceSAndroid Build Coastguard Worker                     colorOffsetWritePtr[((y * GRID_SIZE + x) * 6 + v) * 2 + 1] = tcu::Vec4(0.0f);
827*35238bceSAndroid Build Coastguard Worker                 }
828*35238bceSAndroid Build Coastguard Worker     }
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     // upload vertex data
831*35238bceSAndroid Build Coastguard Worker 
832*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_primitiveBuf);
833*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_primitiveBuf);
834*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (int)(primitiveData.size() * sizeof(tcu::Vec4)), primitiveData[0].getPtr(),
835*35238bceSAndroid Build Coastguard Worker                   GL_STATIC_DRAW);
836*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "upload data");
837*35238bceSAndroid Build Coastguard Worker 
838*35238bceSAndroid Build Coastguard Worker     if (!m_spec.aliasingBuffers)
839*35238bceSAndroid Build Coastguard Worker     {
840*35238bceSAndroid Build Coastguard Worker         // upload color & offset data
841*35238bceSAndroid Build Coastguard Worker 
842*35238bceSAndroid Build Coastguard Worker         gl.genBuffers(1, &m_colorOffsetBuf);
843*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_ARRAY_BUFFER, m_colorOffsetBuf);
844*35238bceSAndroid Build Coastguard Worker         gl.bufferData(GL_ARRAY_BUFFER, (int)(colorOffsetData.size() * sizeof(tcu::Vec4)), colorOffsetData[0].getPtr(),
845*35238bceSAndroid Build Coastguard Worker                       GL_STATIC_DRAW);
846*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "upload colordata");
847*35238bceSAndroid Build Coastguard Worker     }
848*35238bceSAndroid Build Coastguard Worker }
849*35238bceSAndroid Build Coastguard Worker 
createShader(void)850*35238bceSAndroid Build Coastguard Worker void MultipleBindingCase::createShader(void)
851*35238bceSAndroid Build Coastguard Worker {
852*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
853*35238bceSAndroid Build Coastguard Worker                                        glu::ProgramSources() << glu::VertexSource(s_positionColorOffsetShader)
854*35238bceSAndroid Build Coastguard Worker                                                              << glu::FragmentSource(s_colorFragmentShader));
855*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
856*35238bceSAndroid Build Coastguard Worker 
857*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
858*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build shader");
859*35238bceSAndroid Build Coastguard Worker }
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker class MixedBindingCase : public BindingRenderCase
862*35238bceSAndroid Build Coastguard Worker {
863*35238bceSAndroid Build Coastguard Worker public:
864*35238bceSAndroid Build Coastguard Worker     enum CaseType
865*35238bceSAndroid Build Coastguard Worker     {
866*35238bceSAndroid Build Coastguard Worker         CASE_BASIC = 0,
867*35238bceSAndroid Build Coastguard Worker         CASE_INSTANCED_BINDING,
868*35238bceSAndroid Build Coastguard Worker         CASE_INSTANCED_ATTRIB,
869*35238bceSAndroid Build Coastguard Worker 
870*35238bceSAndroid Build Coastguard Worker         CASE_LAST
871*35238bceSAndroid Build Coastguard Worker     };
872*35238bceSAndroid Build Coastguard Worker 
873*35238bceSAndroid Build Coastguard Worker     MixedBindingCase(Context &ctx, const char *name, const char *desc, CaseType caseType);
874*35238bceSAndroid Build Coastguard Worker     ~MixedBindingCase(void);
875*35238bceSAndroid Build Coastguard Worker 
876*35238bceSAndroid Build Coastguard Worker     void init(void);
877*35238bceSAndroid Build Coastguard Worker     void deinit(void);
878*35238bceSAndroid Build Coastguard Worker 
879*35238bceSAndroid Build Coastguard Worker private:
880*35238bceSAndroid Build Coastguard Worker     enum
881*35238bceSAndroid Build Coastguard Worker     {
882*35238bceSAndroid Build Coastguard Worker         GRID_SIZE = 20
883*35238bceSAndroid Build Coastguard Worker     };
884*35238bceSAndroid Build Coastguard Worker 
885*35238bceSAndroid Build Coastguard Worker     void renderTo(tcu::Surface &dst);
886*35238bceSAndroid Build Coastguard Worker     void createBuffers(void);
887*35238bceSAndroid Build Coastguard Worker     void createShader(void);
888*35238bceSAndroid Build Coastguard Worker 
889*35238bceSAndroid Build Coastguard Worker     const CaseType m_case;
890*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_posBuffer;
891*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_colorOffsetBuffer;
892*35238bceSAndroid Build Coastguard Worker };
893*35238bceSAndroid Build Coastguard Worker 
MixedBindingCase(Context & ctx,const char * name,const char * desc,CaseType caseType)894*35238bceSAndroid Build Coastguard Worker MixedBindingCase::MixedBindingCase(Context &ctx, const char *name, const char *desc, CaseType caseType)
895*35238bceSAndroid Build Coastguard Worker     : BindingRenderCase(ctx, name, desc, false)
896*35238bceSAndroid Build Coastguard Worker     , m_case(caseType)
897*35238bceSAndroid Build Coastguard Worker     , m_posBuffer(0)
898*35238bceSAndroid Build Coastguard Worker     , m_colorOffsetBuffer(0)
899*35238bceSAndroid Build Coastguard Worker {
900*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(caseType < CASE_LAST);
901*35238bceSAndroid Build Coastguard Worker }
902*35238bceSAndroid Build Coastguard Worker 
~MixedBindingCase(void)903*35238bceSAndroid Build Coastguard Worker MixedBindingCase::~MixedBindingCase(void)
904*35238bceSAndroid Build Coastguard Worker {
905*35238bceSAndroid Build Coastguard Worker     deinit();
906*35238bceSAndroid Build Coastguard Worker }
907*35238bceSAndroid Build Coastguard Worker 
init(void)908*35238bceSAndroid Build Coastguard Worker void MixedBindingCase::init(void)
909*35238bceSAndroid Build Coastguard Worker {
910*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::init();
911*35238bceSAndroid Build Coastguard Worker }
912*35238bceSAndroid Build Coastguard Worker 
deinit(void)913*35238bceSAndroid Build Coastguard Worker void MixedBindingCase::deinit(void)
914*35238bceSAndroid Build Coastguard Worker {
915*35238bceSAndroid Build Coastguard Worker     if (m_posBuffer)
916*35238bceSAndroid Build Coastguard Worker     {
917*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_posBuffer);
918*35238bceSAndroid Build Coastguard Worker         m_posBuffer = DE_NULL;
919*35238bceSAndroid Build Coastguard Worker     }
920*35238bceSAndroid Build Coastguard Worker 
921*35238bceSAndroid Build Coastguard Worker     if (m_colorOffsetBuffer)
922*35238bceSAndroid Build Coastguard Worker     {
923*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_colorOffsetBuffer);
924*35238bceSAndroid Build Coastguard Worker         m_colorOffsetBuffer = DE_NULL;
925*35238bceSAndroid Build Coastguard Worker     }
926*35238bceSAndroid Build Coastguard Worker 
927*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::deinit();
928*35238bceSAndroid Build Coastguard Worker }
929*35238bceSAndroid Build Coastguard Worker 
renderTo(tcu::Surface & dst)930*35238bceSAndroid Build Coastguard Worker void MixedBindingCase::renderTo(tcu::Surface &dst)
931*35238bceSAndroid Build Coastguard Worker {
932*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
933*35238bceSAndroid Build Coastguard Worker     const int positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
934*35238bceSAndroid Build Coastguard Worker     const int colorLoc    = gl.glGetAttribLocation(m_program->getProgram(), "a_color");
935*35238bceSAndroid Build Coastguard Worker     const int offsetLoc   = gl.glGetAttribLocation(m_program->getProgram(), "a_offset");
936*35238bceSAndroid Build Coastguard Worker 
937*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
938*35238bceSAndroid Build Coastguard Worker 
939*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
940*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
941*35238bceSAndroid Build Coastguard Worker     gl.glViewport(0, 0, dst.getWidth(), dst.getHeight());
942*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(m_vao);
943*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set vao");
944*35238bceSAndroid Build Coastguard Worker 
945*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
946*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
947*35238bceSAndroid Build Coastguard Worker 
948*35238bceSAndroid Build Coastguard Worker     switch (m_case)
949*35238bceSAndroid Build Coastguard Worker     {
950*35238bceSAndroid Build Coastguard Worker     case CASE_BASIC:
951*35238bceSAndroid Build Coastguard Worker     {
952*35238bceSAndroid Build Coastguard Worker         // bind position using vertex_attrib_binding api
953*35238bceSAndroid Build Coastguard Worker 
954*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(positionLoc, m_posBuffer, 0, (glw::GLsizei)sizeof(tcu::Vec4));
955*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, positionLoc);
956*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
957*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set binding");
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker         // bind color using old api
960*35238bceSAndroid Build Coastguard Worker 
961*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_colorOffsetBuffer);
962*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, glw::GLsizei(2 * sizeof(tcu::Vec4)), DE_NULL);
963*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(offsetLoc, 4, GL_FLOAT, GL_FALSE, glw::GLsizei(2 * sizeof(tcu::Vec4)),
964*35238bceSAndroid Build Coastguard Worker                                  glu::BufferOffsetAsPointer(sizeof(tcu::Vec4)));
965*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
966*35238bceSAndroid Build Coastguard Worker 
967*35238bceSAndroid Build Coastguard Worker         // draw
968*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
969*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(colorLoc);
970*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(offsetLoc);
971*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, 6 * GRID_SIZE * GRID_SIZE);
972*35238bceSAndroid Build Coastguard Worker         break;
973*35238bceSAndroid Build Coastguard Worker     }
974*35238bceSAndroid Build Coastguard Worker 
975*35238bceSAndroid Build Coastguard Worker     case CASE_INSTANCED_BINDING:
976*35238bceSAndroid Build Coastguard Worker     {
977*35238bceSAndroid Build Coastguard Worker         // bind position using old api
978*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_posBuffer);
979*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
980*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
981*35238bceSAndroid Build Coastguard Worker 
982*35238bceSAndroid Build Coastguard Worker         // bind color using vertex_attrib_binding api
983*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(colorLoc, m_colorOffsetBuffer, 0, (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
984*35238bceSAndroid Build Coastguard Worker         gl.glVertexBindingDivisor(colorLoc, 1);
985*35238bceSAndroid Build Coastguard Worker 
986*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(colorLoc, colorLoc);
987*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(offsetLoc, colorLoc);
988*35238bceSAndroid Build Coastguard Worker 
989*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, 0);
990*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(offsetLoc, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4));
991*35238bceSAndroid Build Coastguard Worker 
992*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set binding");
993*35238bceSAndroid Build Coastguard Worker 
994*35238bceSAndroid Build Coastguard Worker         // draw
995*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
996*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(colorLoc);
997*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(offsetLoc);
998*35238bceSAndroid Build Coastguard Worker         gl.glDrawArraysInstanced(GL_TRIANGLES, 0, 6, GRID_SIZE * GRID_SIZE);
999*35238bceSAndroid Build Coastguard Worker         break;
1000*35238bceSAndroid Build Coastguard Worker     }
1001*35238bceSAndroid Build Coastguard Worker 
1002*35238bceSAndroid Build Coastguard Worker     case CASE_INSTANCED_ATTRIB:
1003*35238bceSAndroid Build Coastguard Worker     {
1004*35238bceSAndroid Build Coastguard Worker         // bind position using vertex_attrib_binding api
1005*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(positionLoc, m_posBuffer, 0, (glw::GLsizei)sizeof(tcu::Vec4));
1006*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, positionLoc);
1007*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
1008*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set binding");
1009*35238bceSAndroid Build Coastguard Worker 
1010*35238bceSAndroid Build Coastguard Worker         // bind color using old api
1011*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_colorOffsetBuffer);
1012*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, glw::GLsizei(2 * sizeof(tcu::Vec4)), DE_NULL);
1013*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(offsetLoc, 4, GL_FLOAT, GL_FALSE, glw::GLsizei(2 * sizeof(tcu::Vec4)),
1014*35238bceSAndroid Build Coastguard Worker                                  glu::BufferOffsetAsPointer(sizeof(tcu::Vec4)));
1015*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribDivisor(colorLoc, 1);
1016*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribDivisor(offsetLoc, 1);
1017*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
1018*35238bceSAndroid Build Coastguard Worker 
1019*35238bceSAndroid Build Coastguard Worker         // draw
1020*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
1021*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(colorLoc);
1022*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(offsetLoc);
1023*35238bceSAndroid Build Coastguard Worker         gl.glDrawArraysInstanced(GL_TRIANGLES, 0, 6, GRID_SIZE * GRID_SIZE);
1024*35238bceSAndroid Build Coastguard Worker         break;
1025*35238bceSAndroid Build Coastguard Worker     }
1026*35238bceSAndroid Build Coastguard Worker 
1027*35238bceSAndroid Build Coastguard Worker     default:
1028*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1029*35238bceSAndroid Build Coastguard Worker     }
1030*35238bceSAndroid Build Coastguard Worker 
1031*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
1032*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(0);
1033*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(0);
1034*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "clean");
1035*35238bceSAndroid Build Coastguard Worker 
1036*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
1037*35238bceSAndroid Build Coastguard Worker }
1038*35238bceSAndroid Build Coastguard Worker 
createBuffers(void)1039*35238bceSAndroid Build Coastguard Worker void MixedBindingCase::createBuffers(void)
1040*35238bceSAndroid Build Coastguard Worker {
1041*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1042*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 green    = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1043*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 yellow   = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
1044*35238bceSAndroid Build Coastguard Worker 
1045*35238bceSAndroid Build Coastguard Worker     // draw grid. In instanced mode, each cell is an instance
1046*35238bceSAndroid Build Coastguard Worker     const bool instanced                 = (m_case == CASE_INSTANCED_BINDING) || (m_case == CASE_INSTANCED_ATTRIB);
1047*35238bceSAndroid Build Coastguard Worker     const int numCells                   = GRID_SIZE * GRID_SIZE;
1048*35238bceSAndroid Build Coastguard Worker     const int numPositionCells           = (instanced) ? (1) : (numCells);
1049*35238bceSAndroid Build Coastguard Worker     const int numPositionElements        = 6 * numPositionCells;
1050*35238bceSAndroid Build Coastguard Worker     const int numInstanceElementsPerCell = (instanced) ? (1) : (6);
1051*35238bceSAndroid Build Coastguard Worker     const int numColorOffsetElements     = numInstanceElementsPerCell * numCells;
1052*35238bceSAndroid Build Coastguard Worker 
1053*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> positionData(numPositionElements);
1054*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> colorOffsetData(2 * numColorOffsetElements);
1055*35238bceSAndroid Build Coastguard Worker 
1056*35238bceSAndroid Build Coastguard Worker     // positions
1057*35238bceSAndroid Build Coastguard Worker 
1058*35238bceSAndroid Build Coastguard Worker     for (int primNdx = 0; primNdx < numPositionCells; ++primNdx)
1059*35238bceSAndroid Build Coastguard Worker     {
1060*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1061*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 1] = tcu::Vec4(0.0f, 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
1062*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 2] = tcu::Vec4(2.0f / float(GRID_SIZE), 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
1063*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 3] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1064*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 4] = tcu::Vec4(2.0f / float(GRID_SIZE), 2.0f / float(GRID_SIZE), 0.0f, 1.0f);
1065*35238bceSAndroid Build Coastguard Worker         positionData[primNdx * 6 + 5] = tcu::Vec4(2.0f / float(GRID_SIZE), 0.0f, 0.0f, 1.0f);
1066*35238bceSAndroid Build Coastguard Worker     }
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker     // color & offset
1069*35238bceSAndroid Build Coastguard Worker 
1070*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < GRID_SIZE; ++y)
1071*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < GRID_SIZE; ++x)
1072*35238bceSAndroid Build Coastguard Worker         {
1073*35238bceSAndroid Build Coastguard Worker             for (int v = 0; v < numInstanceElementsPerCell; ++v)
1074*35238bceSAndroid Build Coastguard Worker             {
1075*35238bceSAndroid Build Coastguard Worker                 const tcu::Vec4 &color = ((x + y) % 2 == 0) ? (green) : (yellow);
1076*35238bceSAndroid Build Coastguard Worker 
1077*35238bceSAndroid Build Coastguard Worker                 colorOffsetData[((y * GRID_SIZE + x) * numInstanceElementsPerCell + v) * 2 + 0] = color;
1078*35238bceSAndroid Build Coastguard Worker                 colorOffsetData[((y * GRID_SIZE + x) * numInstanceElementsPerCell + v) * 2 + 1] = tcu::Vec4(
1079*35238bceSAndroid Build Coastguard Worker                     float(x) / float(GRID_SIZE) * 2.0f - 1.0f, float(y) / float(GRID_SIZE) * 2.0f - 1.0f, 0.0f, 0.0f);
1080*35238bceSAndroid Build Coastguard Worker             }
1081*35238bceSAndroid Build Coastguard Worker         }
1082*35238bceSAndroid Build Coastguard Worker 
1083*35238bceSAndroid Build Coastguard Worker     // upload vertex data
1084*35238bceSAndroid Build Coastguard Worker 
1085*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_posBuffer);
1086*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_posBuffer);
1087*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (int)(positionData.size() * sizeof(tcu::Vec4)), positionData[0].getPtr(),
1088*35238bceSAndroid Build Coastguard Worker                   GL_STATIC_DRAW);
1089*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "upload position data");
1090*35238bceSAndroid Build Coastguard Worker 
1091*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_colorOffsetBuffer);
1092*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_colorOffsetBuffer);
1093*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (int)(colorOffsetData.size() * sizeof(tcu::Vec4)), colorOffsetData[0].getPtr(),
1094*35238bceSAndroid Build Coastguard Worker                   GL_STATIC_DRAW);
1095*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "upload position data");
1096*35238bceSAndroid Build Coastguard Worker }
1097*35238bceSAndroid Build Coastguard Worker 
createShader(void)1098*35238bceSAndroid Build Coastguard Worker void MixedBindingCase::createShader(void)
1099*35238bceSAndroid Build Coastguard Worker {
1100*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
1101*35238bceSAndroid Build Coastguard Worker                                        glu::ProgramSources() << glu::VertexSource(s_positionColorOffsetShader)
1102*35238bceSAndroid Build Coastguard Worker                                                              << glu::FragmentSource(s_colorFragmentShader));
1103*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
1104*35238bceSAndroid Build Coastguard Worker 
1105*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
1106*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build shader");
1107*35238bceSAndroid Build Coastguard Worker }
1108*35238bceSAndroid Build Coastguard Worker 
1109*35238bceSAndroid Build Coastguard Worker class MixedApiCase : public BindingRenderCase
1110*35238bceSAndroid Build Coastguard Worker {
1111*35238bceSAndroid Build Coastguard Worker public:
1112*35238bceSAndroid Build Coastguard Worker     enum CaseType
1113*35238bceSAndroid Build Coastguard Worker     {
1114*35238bceSAndroid Build Coastguard Worker         CASE_CHANGE_BUFFER = 0,
1115*35238bceSAndroid Build Coastguard Worker         CASE_CHANGE_BUFFER_OFFSET,
1116*35238bceSAndroid Build Coastguard Worker         CASE_CHANGE_BUFFER_STRIDE,
1117*35238bceSAndroid Build Coastguard Worker         CASE_CHANGE_BINDING_POINT,
1118*35238bceSAndroid Build Coastguard Worker 
1119*35238bceSAndroid Build Coastguard Worker         CASE_LAST
1120*35238bceSAndroid Build Coastguard Worker     };
1121*35238bceSAndroid Build Coastguard Worker 
1122*35238bceSAndroid Build Coastguard Worker     MixedApiCase(Context &ctx, const char *name, const char *desc, CaseType caseType);
1123*35238bceSAndroid Build Coastguard Worker     ~MixedApiCase(void);
1124*35238bceSAndroid Build Coastguard Worker 
1125*35238bceSAndroid Build Coastguard Worker     void init(void);
1126*35238bceSAndroid Build Coastguard Worker     void deinit(void);
1127*35238bceSAndroid Build Coastguard Worker 
1128*35238bceSAndroid Build Coastguard Worker private:
1129*35238bceSAndroid Build Coastguard Worker     enum
1130*35238bceSAndroid Build Coastguard Worker     {
1131*35238bceSAndroid Build Coastguard Worker         GRID_SIZE = 20
1132*35238bceSAndroid Build Coastguard Worker     };
1133*35238bceSAndroid Build Coastguard Worker 
1134*35238bceSAndroid Build Coastguard Worker     void renderTo(tcu::Surface &dst);
1135*35238bceSAndroid Build Coastguard Worker     void createBuffers(void);
1136*35238bceSAndroid Build Coastguard Worker     void createShader(void);
1137*35238bceSAndroid Build Coastguard Worker 
1138*35238bceSAndroid Build Coastguard Worker     const CaseType m_case;
1139*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_buffer;
1140*35238bceSAndroid Build Coastguard Worker };
1141*35238bceSAndroid Build Coastguard Worker 
MixedApiCase(Context & ctx,const char * name,const char * desc,CaseType caseType)1142*35238bceSAndroid Build Coastguard Worker MixedApiCase::MixedApiCase(Context &ctx, const char *name, const char *desc, CaseType caseType)
1143*35238bceSAndroid Build Coastguard Worker     : BindingRenderCase(ctx, name, desc, false)
1144*35238bceSAndroid Build Coastguard Worker     , m_case(caseType)
1145*35238bceSAndroid Build Coastguard Worker     , m_buffer(0)
1146*35238bceSAndroid Build Coastguard Worker {
1147*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(caseType < CASE_LAST);
1148*35238bceSAndroid Build Coastguard Worker }
1149*35238bceSAndroid Build Coastguard Worker 
~MixedApiCase(void)1150*35238bceSAndroid Build Coastguard Worker MixedApiCase::~MixedApiCase(void)
1151*35238bceSAndroid Build Coastguard Worker {
1152*35238bceSAndroid Build Coastguard Worker     deinit();
1153*35238bceSAndroid Build Coastguard Worker }
1154*35238bceSAndroid Build Coastguard Worker 
init(void)1155*35238bceSAndroid Build Coastguard Worker void MixedApiCase::init(void)
1156*35238bceSAndroid Build Coastguard Worker {
1157*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::init();
1158*35238bceSAndroid Build Coastguard Worker }
1159*35238bceSAndroid Build Coastguard Worker 
deinit(void)1160*35238bceSAndroid Build Coastguard Worker void MixedApiCase::deinit(void)
1161*35238bceSAndroid Build Coastguard Worker {
1162*35238bceSAndroid Build Coastguard Worker     if (m_buffer)
1163*35238bceSAndroid Build Coastguard Worker     {
1164*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffer);
1165*35238bceSAndroid Build Coastguard Worker         m_buffer = DE_NULL;
1166*35238bceSAndroid Build Coastguard Worker     }
1167*35238bceSAndroid Build Coastguard Worker 
1168*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::deinit();
1169*35238bceSAndroid Build Coastguard Worker }
1170*35238bceSAndroid Build Coastguard Worker 
renderTo(tcu::Surface & dst)1171*35238bceSAndroid Build Coastguard Worker void MixedApiCase::renderTo(tcu::Surface &dst)
1172*35238bceSAndroid Build Coastguard Worker {
1173*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
1174*35238bceSAndroid Build Coastguard Worker     const int positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
1175*35238bceSAndroid Build Coastguard Worker     const int colorLoc    = gl.glGetAttribLocation(m_program->getProgram(), "a_color");
1176*35238bceSAndroid Build Coastguard Worker     glu::Buffer unusedBuffer(m_context.getRenderContext());
1177*35238bceSAndroid Build Coastguard Worker 
1178*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
1179*35238bceSAndroid Build Coastguard Worker 
1180*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1181*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
1182*35238bceSAndroid Build Coastguard Worker     gl.glViewport(0, 0, dst.getWidth(), dst.getHeight());
1183*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(m_vao);
1184*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set vao");
1185*35238bceSAndroid Build Coastguard Worker 
1186*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
1187*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
1188*35238bceSAndroid Build Coastguard Worker 
1189*35238bceSAndroid Build Coastguard Worker     switch (m_case)
1190*35238bceSAndroid Build Coastguard Worker     {
1191*35238bceSAndroid Build Coastguard Worker     case CASE_CHANGE_BUFFER:
1192*35238bceSAndroid Build Coastguard Worker     {
1193*35238bceSAndroid Build Coastguard Worker         // bind data using old api
1194*35238bceSAndroid Build Coastguard Worker 
1195*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, *unusedBuffer);
1196*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1197*35238bceSAndroid Build Coastguard Worker                                  (const uint8_t *)DE_NULL);
1198*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1199*35238bceSAndroid Build Coastguard Worker                                  glu::BufferOffsetAsPointer(sizeof(tcu::Vec4)));
1200*35238bceSAndroid Build Coastguard Worker 
1201*35238bceSAndroid Build Coastguard Worker         // change buffer with vertex_attrib_binding
1202*35238bceSAndroid Build Coastguard Worker 
1203*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(positionLoc, m_buffer, 0, (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1204*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(colorLoc, m_buffer, sizeof(tcu::Vec4), (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1205*35238bceSAndroid Build Coastguard Worker 
1206*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1207*35238bceSAndroid Build Coastguard Worker         break;
1208*35238bceSAndroid Build Coastguard Worker     }
1209*35238bceSAndroid Build Coastguard Worker 
1210*35238bceSAndroid Build Coastguard Worker     case CASE_CHANGE_BUFFER_OFFSET:
1211*35238bceSAndroid Build Coastguard Worker     {
1212*35238bceSAndroid Build Coastguard Worker         // bind data using old api
1213*35238bceSAndroid Build Coastguard Worker 
1214*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
1215*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1216*35238bceSAndroid Build Coastguard Worker                                  (const uint8_t *)DE_NULL);
1217*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1218*35238bceSAndroid Build Coastguard Worker                                  (const uint8_t *)DE_NULL);
1219*35238bceSAndroid Build Coastguard Worker 
1220*35238bceSAndroid Build Coastguard Worker         // change buffer offset with vertex_attrib_binding
1221*35238bceSAndroid Build Coastguard Worker 
1222*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(positionLoc, m_buffer, 0, (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1223*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(colorLoc, m_buffer, sizeof(tcu::Vec4), (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1224*35238bceSAndroid Build Coastguard Worker 
1225*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1226*35238bceSAndroid Build Coastguard Worker         break;
1227*35238bceSAndroid Build Coastguard Worker     }
1228*35238bceSAndroid Build Coastguard Worker 
1229*35238bceSAndroid Build Coastguard Worker     case CASE_CHANGE_BUFFER_STRIDE:
1230*35238bceSAndroid Build Coastguard Worker     {
1231*35238bceSAndroid Build Coastguard Worker         // bind data using old api
1232*35238bceSAndroid Build Coastguard Worker 
1233*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
1234*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 8, (const uint8_t *)DE_NULL);
1235*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 4, (const uint8_t *)DE_NULL);
1236*35238bceSAndroid Build Coastguard Worker 
1237*35238bceSAndroid Build Coastguard Worker         // change buffer stride with vertex_attrib_binding
1238*35238bceSAndroid Build Coastguard Worker 
1239*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(positionLoc, m_buffer, 0, (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1240*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(colorLoc, m_buffer, sizeof(tcu::Vec4), (glw::GLsizei)(2 * sizeof(tcu::Vec4)));
1241*35238bceSAndroid Build Coastguard Worker 
1242*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1243*35238bceSAndroid Build Coastguard Worker         break;
1244*35238bceSAndroid Build Coastguard Worker     }
1245*35238bceSAndroid Build Coastguard Worker 
1246*35238bceSAndroid Build Coastguard Worker     case CASE_CHANGE_BINDING_POINT:
1247*35238bceSAndroid Build Coastguard Worker     {
1248*35238bceSAndroid Build Coastguard Worker         const int maxUsedLocation = de::max(positionLoc, colorLoc);
1249*35238bceSAndroid Build Coastguard Worker         const int bindingPoint1   = maxUsedLocation + 1;
1250*35238bceSAndroid Build Coastguard Worker         const int bindingPoint2   = maxUsedLocation + 2;
1251*35238bceSAndroid Build Coastguard Worker 
1252*35238bceSAndroid Build Coastguard Worker         // bind data using old api
1253*35238bceSAndroid Build Coastguard Worker 
1254*35238bceSAndroid Build Coastguard Worker         gl.glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
1255*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(bindingPoint1, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1256*35238bceSAndroid Build Coastguard Worker                                  (const uint8_t *)DE_NULL);
1257*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribPointer(bindingPoint2, 4, GL_FLOAT, GL_FALSE, (glw::GLsizei)(2 * sizeof(tcu::Vec4)),
1258*35238bceSAndroid Build Coastguard Worker                                  glu::BufferOffsetAsPointer(sizeof(tcu::Vec4)));
1259*35238bceSAndroid Build Coastguard Worker 
1260*35238bceSAndroid Build Coastguard Worker         // change buffer binding point with vertex_attrib_binding
1261*35238bceSAndroid Build Coastguard Worker 
1262*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
1263*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, 0);
1264*35238bceSAndroid Build Coastguard Worker 
1265*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, bindingPoint1);
1266*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(colorLoc, bindingPoint2);
1267*35238bceSAndroid Build Coastguard Worker 
1268*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1269*35238bceSAndroid Build Coastguard Worker         break;
1270*35238bceSAndroid Build Coastguard Worker     }
1271*35238bceSAndroid Build Coastguard Worker 
1272*35238bceSAndroid Build Coastguard Worker     default:
1273*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1274*35238bceSAndroid Build Coastguard Worker     }
1275*35238bceSAndroid Build Coastguard Worker 
1276*35238bceSAndroid Build Coastguard Worker     // draw
1277*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(positionLoc);
1278*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(colorLoc);
1279*35238bceSAndroid Build Coastguard Worker     gl.glDrawArrays(GL_TRIANGLES, 0, 6 * GRID_SIZE * GRID_SIZE);
1280*35238bceSAndroid Build Coastguard Worker 
1281*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
1282*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(0);
1283*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(0);
1284*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "clean");
1285*35238bceSAndroid Build Coastguard Worker 
1286*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
1287*35238bceSAndroid Build Coastguard Worker }
1288*35238bceSAndroid Build Coastguard Worker 
createBuffers(void)1289*35238bceSAndroid Build Coastguard Worker void MixedApiCase::createBuffers(void)
1290*35238bceSAndroid Build Coastguard Worker {
1291*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 green  = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1292*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 yellow = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
1293*35238bceSAndroid Build Coastguard Worker 
1294*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1295*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> vertexData(12 * GRID_SIZE * GRID_SIZE);
1296*35238bceSAndroid Build Coastguard Worker 
1297*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < GRID_SIZE; ++y)
1298*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < GRID_SIZE; ++x)
1299*35238bceSAndroid Build Coastguard Worker         {
1300*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 &color = ((x + y) % 2 == 0) ? (green) : (yellow);
1301*35238bceSAndroid Build Coastguard Worker 
1302*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 0] =
1303*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
1304*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1305*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 1] = color;
1306*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 2] =
1307*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
1308*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1309*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 3] = color;
1310*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 4] =
1311*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
1312*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1313*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 5] = color;
1314*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 6] =
1315*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
1316*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1317*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 7] = color;
1318*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 8] =
1319*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
1320*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1321*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 9] = color;
1322*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 10] =
1323*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
1324*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f);
1325*35238bceSAndroid Build Coastguard Worker             vertexData[(y * GRID_SIZE + x) * 12 + 11] = color;
1326*35238bceSAndroid Build Coastguard Worker         }
1327*35238bceSAndroid Build Coastguard Worker 
1328*35238bceSAndroid Build Coastguard Worker     // upload vertex data
1329*35238bceSAndroid Build Coastguard Worker 
1330*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_buffer);
1331*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
1332*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (int)(vertexData.size() * sizeof(tcu::Vec4)), vertexData[0].getPtr(),
1333*35238bceSAndroid Build Coastguard Worker                   GL_STATIC_DRAW);
1334*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "upload data");
1335*35238bceSAndroid Build Coastguard Worker }
1336*35238bceSAndroid Build Coastguard Worker 
createShader(void)1337*35238bceSAndroid Build Coastguard Worker void MixedApiCase::createShader(void)
1338*35238bceSAndroid Build Coastguard Worker {
1339*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
1340*35238bceSAndroid Build Coastguard Worker                                                                          << glu::VertexSource(s_positionColorShader)
1341*35238bceSAndroid Build Coastguard Worker                                                                          << glu::FragmentSource(s_colorFragmentShader));
1342*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
1343*35238bceSAndroid Build Coastguard Worker 
1344*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
1345*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build shader");
1346*35238bceSAndroid Build Coastguard Worker }
1347*35238bceSAndroid Build Coastguard Worker 
1348*35238bceSAndroid Build Coastguard Worker class DefaultVAOCase : public TestCase
1349*35238bceSAndroid Build Coastguard Worker {
1350*35238bceSAndroid Build Coastguard Worker public:
1351*35238bceSAndroid Build Coastguard Worker     enum CaseType
1352*35238bceSAndroid Build Coastguard Worker     {
1353*35238bceSAndroid Build Coastguard Worker         CASE_BIND_VERTEX_BUFFER,
1354*35238bceSAndroid Build Coastguard Worker         CASE_VERTEX_ATTRIB_FORMAT,
1355*35238bceSAndroid Build Coastguard Worker         CASE_VERTEX_ATTRIB_I_FORMAT,
1356*35238bceSAndroid Build Coastguard Worker         CASE_VERTEX_ATTRIB_BINDING,
1357*35238bceSAndroid Build Coastguard Worker         CASE_VERTEX_BINDING_DIVISOR,
1358*35238bceSAndroid Build Coastguard Worker 
1359*35238bceSAndroid Build Coastguard Worker         CASE_LAST
1360*35238bceSAndroid Build Coastguard Worker     };
1361*35238bceSAndroid Build Coastguard Worker 
1362*35238bceSAndroid Build Coastguard Worker     DefaultVAOCase(Context &ctx, const char *name, const char *desc, CaseType caseType);
1363*35238bceSAndroid Build Coastguard Worker     ~DefaultVAOCase(void);
1364*35238bceSAndroid Build Coastguard Worker 
1365*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1366*35238bceSAndroid Build Coastguard Worker 
1367*35238bceSAndroid Build Coastguard Worker private:
1368*35238bceSAndroid Build Coastguard Worker     const CaseType m_caseType;
1369*35238bceSAndroid Build Coastguard Worker };
1370*35238bceSAndroid Build Coastguard Worker 
DefaultVAOCase(Context & ctx,const char * name,const char * desc,CaseType caseType)1371*35238bceSAndroid Build Coastguard Worker DefaultVAOCase::DefaultVAOCase(Context &ctx, const char *name, const char *desc, CaseType caseType)
1372*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name, desc)
1373*35238bceSAndroid Build Coastguard Worker     , m_caseType(caseType)
1374*35238bceSAndroid Build Coastguard Worker {
1375*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(caseType < CASE_LAST);
1376*35238bceSAndroid Build Coastguard Worker }
1377*35238bceSAndroid Build Coastguard Worker 
~DefaultVAOCase(void)1378*35238bceSAndroid Build Coastguard Worker DefaultVAOCase::~DefaultVAOCase(void)
1379*35238bceSAndroid Build Coastguard Worker {
1380*35238bceSAndroid Build Coastguard Worker }
1381*35238bceSAndroid Build Coastguard Worker 
iterate(void)1382*35238bceSAndroid Build Coastguard Worker DefaultVAOCase::IterateResult DefaultVAOCase::iterate(void)
1383*35238bceSAndroid Build Coastguard Worker {
1384*35238bceSAndroid Build Coastguard Worker     glw::GLenum error = 0;
1385*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1386*35238bceSAndroid Build Coastguard Worker 
1387*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
1388*35238bceSAndroid Build Coastguard Worker 
1389*35238bceSAndroid Build Coastguard Worker     switch (m_caseType)
1390*35238bceSAndroid Build Coastguard Worker     {
1391*35238bceSAndroid Build Coastguard Worker     case CASE_BIND_VERTEX_BUFFER:
1392*35238bceSAndroid Build Coastguard Worker     {
1393*35238bceSAndroid Build Coastguard Worker         glu::Buffer buffer(m_context.getRenderContext());
1394*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(0, *buffer, 0, 0);
1395*35238bceSAndroid Build Coastguard Worker         break;
1396*35238bceSAndroid Build Coastguard Worker     }
1397*35238bceSAndroid Build Coastguard Worker 
1398*35238bceSAndroid Build Coastguard Worker     case CASE_VERTEX_ATTRIB_FORMAT:
1399*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
1400*35238bceSAndroid Build Coastguard Worker         break;
1401*35238bceSAndroid Build Coastguard Worker 
1402*35238bceSAndroid Build Coastguard Worker     case CASE_VERTEX_ATTRIB_I_FORMAT:
1403*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribIFormat(0, 4, GL_INT, 0);
1404*35238bceSAndroid Build Coastguard Worker         break;
1405*35238bceSAndroid Build Coastguard Worker 
1406*35238bceSAndroid Build Coastguard Worker     case CASE_VERTEX_ATTRIB_BINDING:
1407*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(0, 0);
1408*35238bceSAndroid Build Coastguard Worker         break;
1409*35238bceSAndroid Build Coastguard Worker 
1410*35238bceSAndroid Build Coastguard Worker     case CASE_VERTEX_BINDING_DIVISOR:
1411*35238bceSAndroid Build Coastguard Worker         gl.glVertexBindingDivisor(0, 1);
1412*35238bceSAndroid Build Coastguard Worker         break;
1413*35238bceSAndroid Build Coastguard Worker 
1414*35238bceSAndroid Build Coastguard Worker     default:
1415*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1416*35238bceSAndroid Build Coastguard Worker     }
1417*35238bceSAndroid Build Coastguard Worker 
1418*35238bceSAndroid Build Coastguard Worker     error = gl.glGetError();
1419*35238bceSAndroid Build Coastguard Worker 
1420*35238bceSAndroid Build Coastguard Worker     if (error != GL_INVALID_OPERATION)
1421*35238bceSAndroid Build Coastguard Worker     {
1422*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Expected GL_INVALID_OPERATION, got "
1423*35238bceSAndroid Build Coastguard Worker                            << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
1424*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error");
1425*35238bceSAndroid Build Coastguard Worker     }
1426*35238bceSAndroid Build Coastguard Worker     else
1427*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1428*35238bceSAndroid Build Coastguard Worker 
1429*35238bceSAndroid Build Coastguard Worker     return STOP;
1430*35238bceSAndroid Build Coastguard Worker }
1431*35238bceSAndroid Build Coastguard Worker 
1432*35238bceSAndroid Build Coastguard Worker class BindToCreateCase : public TestCase
1433*35238bceSAndroid Build Coastguard Worker {
1434*35238bceSAndroid Build Coastguard Worker public:
1435*35238bceSAndroid Build Coastguard Worker     BindToCreateCase(Context &ctx, const char *name, const char *desc);
1436*35238bceSAndroid Build Coastguard Worker     ~BindToCreateCase(void);
1437*35238bceSAndroid Build Coastguard Worker 
1438*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1439*35238bceSAndroid Build Coastguard Worker };
1440*35238bceSAndroid Build Coastguard Worker 
BindToCreateCase(Context & ctx,const char * name,const char * desc)1441*35238bceSAndroid Build Coastguard Worker BindToCreateCase::BindToCreateCase(Context &ctx, const char *name, const char *desc) : TestCase(ctx, name, desc)
1442*35238bceSAndroid Build Coastguard Worker {
1443*35238bceSAndroid Build Coastguard Worker }
1444*35238bceSAndroid Build Coastguard Worker 
~BindToCreateCase(void)1445*35238bceSAndroid Build Coastguard Worker BindToCreateCase::~BindToCreateCase(void)
1446*35238bceSAndroid Build Coastguard Worker {
1447*35238bceSAndroid Build Coastguard Worker }
1448*35238bceSAndroid Build Coastguard Worker 
iterate(void)1449*35238bceSAndroid Build Coastguard Worker BindToCreateCase::IterateResult BindToCreateCase::iterate(void)
1450*35238bceSAndroid Build Coastguard Worker {
1451*35238bceSAndroid Build Coastguard Worker     glw::GLuint buffer = 0;
1452*35238bceSAndroid Build Coastguard Worker     glw::GLenum error;
1453*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1454*35238bceSAndroid Build Coastguard Worker     glu::VertexArray vao(m_context.getRenderContext());
1455*35238bceSAndroid Build Coastguard Worker 
1456*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
1457*35238bceSAndroid Build Coastguard Worker 
1458*35238bceSAndroid Build Coastguard Worker     gl.glGenBuffers(1, &buffer);
1459*35238bceSAndroid Build Coastguard Worker     gl.glDeleteBuffers(1, &buffer);
1460*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1461*35238bceSAndroid Build Coastguard Worker 
1462*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(*vao);
1463*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexBuffer(0, buffer, 0, 0);
1464*35238bceSAndroid Build Coastguard Worker 
1465*35238bceSAndroid Build Coastguard Worker     error = gl.glGetError();
1466*35238bceSAndroid Build Coastguard Worker 
1467*35238bceSAndroid Build Coastguard Worker     if (error != GL_INVALID_OPERATION)
1468*35238bceSAndroid Build Coastguard Worker     {
1469*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Expected GL_INVALID_OPERATION, got "
1470*35238bceSAndroid Build Coastguard Worker                            << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
1471*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error");
1472*35238bceSAndroid Build Coastguard Worker     }
1473*35238bceSAndroid Build Coastguard Worker     else
1474*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1475*35238bceSAndroid Build Coastguard Worker 
1476*35238bceSAndroid Build Coastguard Worker     return STOP;
1477*35238bceSAndroid Build Coastguard Worker }
1478*35238bceSAndroid Build Coastguard Worker 
1479*35238bceSAndroid Build Coastguard Worker class NegativeApiCase : public TestCase
1480*35238bceSAndroid Build Coastguard Worker {
1481*35238bceSAndroid Build Coastguard Worker public:
1482*35238bceSAndroid Build Coastguard Worker     enum CaseType
1483*35238bceSAndroid Build Coastguard Worker     {
1484*35238bceSAndroid Build Coastguard Worker         CASE_LARGE_OFFSET,
1485*35238bceSAndroid Build Coastguard Worker         CASE_LARGE_STRIDE,
1486*35238bceSAndroid Build Coastguard Worker         CASE_NEGATIVE_STRIDE,
1487*35238bceSAndroid Build Coastguard Worker         CASE_NEGATIVE_OFFSET,
1488*35238bceSAndroid Build Coastguard Worker         CASE_INVALID_ATTR,
1489*35238bceSAndroid Build Coastguard Worker         CASE_INVALID_BINDING,
1490*35238bceSAndroid Build Coastguard Worker 
1491*35238bceSAndroid Build Coastguard Worker         CASE_LAST
1492*35238bceSAndroid Build Coastguard Worker     };
1493*35238bceSAndroid Build Coastguard Worker     NegativeApiCase(Context &ctx, const char *name, const char *desc, CaseType caseType);
1494*35238bceSAndroid Build Coastguard Worker     ~NegativeApiCase(void);
1495*35238bceSAndroid Build Coastguard Worker 
1496*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1497*35238bceSAndroid Build Coastguard Worker 
1498*35238bceSAndroid Build Coastguard Worker private:
1499*35238bceSAndroid Build Coastguard Worker     const CaseType m_caseType;
1500*35238bceSAndroid Build Coastguard Worker };
1501*35238bceSAndroid Build Coastguard Worker 
NegativeApiCase(Context & ctx,const char * name,const char * desc,CaseType caseType)1502*35238bceSAndroid Build Coastguard Worker NegativeApiCase::NegativeApiCase(Context &ctx, const char *name, const char *desc, CaseType caseType)
1503*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name, desc)
1504*35238bceSAndroid Build Coastguard Worker     , m_caseType(caseType)
1505*35238bceSAndroid Build Coastguard Worker {
1506*35238bceSAndroid Build Coastguard Worker }
1507*35238bceSAndroid Build Coastguard Worker 
~NegativeApiCase(void)1508*35238bceSAndroid Build Coastguard Worker NegativeApiCase::~NegativeApiCase(void)
1509*35238bceSAndroid Build Coastguard Worker {
1510*35238bceSAndroid Build Coastguard Worker }
1511*35238bceSAndroid Build Coastguard Worker 
iterate(void)1512*35238bceSAndroid Build Coastguard Worker NegativeApiCase::IterateResult NegativeApiCase::iterate(void)
1513*35238bceSAndroid Build Coastguard Worker {
1514*35238bceSAndroid Build Coastguard Worker     glw::GLenum error;
1515*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1516*35238bceSAndroid Build Coastguard Worker     glu::VertexArray vao(m_context.getRenderContext());
1517*35238bceSAndroid Build Coastguard Worker 
1518*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
1519*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(*vao);
1520*35238bceSAndroid Build Coastguard Worker 
1521*35238bceSAndroid Build Coastguard Worker     switch (m_caseType)
1522*35238bceSAndroid Build Coastguard Worker     {
1523*35238bceSAndroid Build Coastguard Worker     case CASE_LARGE_OFFSET:
1524*35238bceSAndroid Build Coastguard Worker     {
1525*35238bceSAndroid Build Coastguard Worker         glw::GLint maxOffset = -1;
1526*35238bceSAndroid Build Coastguard Worker         glw::GLint largeOffset;
1527*35238bceSAndroid Build Coastguard Worker 
1528*35238bceSAndroid Build Coastguard Worker         gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxOffset);
1529*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1530*35238bceSAndroid Build Coastguard Worker 
1531*35238bceSAndroid Build Coastguard Worker         largeOffset = maxOffset + 1;
1532*35238bceSAndroid Build Coastguard Worker 
1533*35238bceSAndroid Build Coastguard Worker         // skip if maximum unsigned or signed values
1534*35238bceSAndroid Build Coastguard Worker         if (maxOffset == -1 || maxOffset == 0x7FFFFFFF)
1535*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Implementation supports all offsets");
1536*35238bceSAndroid Build Coastguard Worker 
1537*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, largeOffset);
1538*35238bceSAndroid Build Coastguard Worker         break;
1539*35238bceSAndroid Build Coastguard Worker     }
1540*35238bceSAndroid Build Coastguard Worker 
1541*35238bceSAndroid Build Coastguard Worker     case CASE_LARGE_STRIDE:
1542*35238bceSAndroid Build Coastguard Worker     {
1543*35238bceSAndroid Build Coastguard Worker         glu::Buffer buffer(m_context.getRenderContext());
1544*35238bceSAndroid Build Coastguard Worker         glw::GLint maxStride = -1;
1545*35238bceSAndroid Build Coastguard Worker         glw::GLint largeStride;
1546*35238bceSAndroid Build Coastguard Worker 
1547*35238bceSAndroid Build Coastguard Worker         gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
1548*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1549*35238bceSAndroid Build Coastguard Worker 
1550*35238bceSAndroid Build Coastguard Worker         largeStride = maxStride + 1;
1551*35238bceSAndroid Build Coastguard Worker 
1552*35238bceSAndroid Build Coastguard Worker         // skip if maximum unsigned or signed values
1553*35238bceSAndroid Build Coastguard Worker         if (maxStride == -1 || maxStride == 0x7FFFFFFF)
1554*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Implementation supports all strides");
1555*35238bceSAndroid Build Coastguard Worker 
1556*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(0, *buffer, 0, largeStride);
1557*35238bceSAndroid Build Coastguard Worker         break;
1558*35238bceSAndroid Build Coastguard Worker     }
1559*35238bceSAndroid Build Coastguard Worker 
1560*35238bceSAndroid Build Coastguard Worker     case CASE_NEGATIVE_STRIDE:
1561*35238bceSAndroid Build Coastguard Worker     {
1562*35238bceSAndroid Build Coastguard Worker         glu::Buffer buffer(m_context.getRenderContext());
1563*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(0, *buffer, 0, -20);
1564*35238bceSAndroid Build Coastguard Worker         break;
1565*35238bceSAndroid Build Coastguard Worker     }
1566*35238bceSAndroid Build Coastguard Worker 
1567*35238bceSAndroid Build Coastguard Worker     case CASE_NEGATIVE_OFFSET:
1568*35238bceSAndroid Build Coastguard Worker     {
1569*35238bceSAndroid Build Coastguard Worker         glu::Buffer buffer(m_context.getRenderContext());
1570*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(0, *buffer, -20, 0);
1571*35238bceSAndroid Build Coastguard Worker         break;
1572*35238bceSAndroid Build Coastguard Worker     }
1573*35238bceSAndroid Build Coastguard Worker 
1574*35238bceSAndroid Build Coastguard Worker     case CASE_INVALID_ATTR:
1575*35238bceSAndroid Build Coastguard Worker     {
1576*35238bceSAndroid Build Coastguard Worker         glw::GLint maxIndex = -1;
1577*35238bceSAndroid Build Coastguard Worker         glw::GLint largeIndex;
1578*35238bceSAndroid Build Coastguard Worker 
1579*35238bceSAndroid Build Coastguard Worker         gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxIndex);
1580*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1581*35238bceSAndroid Build Coastguard Worker 
1582*35238bceSAndroid Build Coastguard Worker         largeIndex = maxIndex + 1;
1583*35238bceSAndroid Build Coastguard Worker 
1584*35238bceSAndroid Build Coastguard Worker         // skip if maximum unsigned or signed values
1585*35238bceSAndroid Build Coastguard Worker         if (maxIndex == -1 || maxIndex == 0x7FFFFFFF)
1586*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Implementation supports any attribute index");
1587*35238bceSAndroid Build Coastguard Worker 
1588*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(largeIndex, 0);
1589*35238bceSAndroid Build Coastguard Worker         break;
1590*35238bceSAndroid Build Coastguard Worker     }
1591*35238bceSAndroid Build Coastguard Worker 
1592*35238bceSAndroid Build Coastguard Worker     case CASE_INVALID_BINDING:
1593*35238bceSAndroid Build Coastguard Worker     {
1594*35238bceSAndroid Build Coastguard Worker         glw::GLint maxBindings = -1;
1595*35238bceSAndroid Build Coastguard Worker         glw::GLint largeBinding;
1596*35238bceSAndroid Build Coastguard Worker 
1597*35238bceSAndroid Build Coastguard Worker         gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &maxBindings);
1598*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "");
1599*35238bceSAndroid Build Coastguard Worker 
1600*35238bceSAndroid Build Coastguard Worker         largeBinding = maxBindings + 1;
1601*35238bceSAndroid Build Coastguard Worker 
1602*35238bceSAndroid Build Coastguard Worker         // skip if maximum unsigned or signed values
1603*35238bceSAndroid Build Coastguard Worker         if (maxBindings == -1 || maxBindings == 0x7FFFFFFF)
1604*35238bceSAndroid Build Coastguard Worker             throw tcu::NotSupportedError("Implementation supports any binding");
1605*35238bceSAndroid Build Coastguard Worker 
1606*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(0, largeBinding);
1607*35238bceSAndroid Build Coastguard Worker         break;
1608*35238bceSAndroid Build Coastguard Worker     }
1609*35238bceSAndroid Build Coastguard Worker 
1610*35238bceSAndroid Build Coastguard Worker     default:
1611*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1612*35238bceSAndroid Build Coastguard Worker     }
1613*35238bceSAndroid Build Coastguard Worker 
1614*35238bceSAndroid Build Coastguard Worker     error = gl.glGetError();
1615*35238bceSAndroid Build Coastguard Worker 
1616*35238bceSAndroid Build Coastguard Worker     if (error != GL_INVALID_VALUE)
1617*35238bceSAndroid Build Coastguard Worker     {
1618*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR! Expected GL_INVALID_VALUE, got "
1619*35238bceSAndroid Build Coastguard Worker                            << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
1620*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid error");
1621*35238bceSAndroid Build Coastguard Worker     }
1622*35238bceSAndroid Build Coastguard Worker     else
1623*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1624*35238bceSAndroid Build Coastguard Worker 
1625*35238bceSAndroid Build Coastguard Worker     return STOP;
1626*35238bceSAndroid Build Coastguard Worker }
1627*35238bceSAndroid Build Coastguard Worker 
1628*35238bceSAndroid Build Coastguard Worker } // namespace
1629*35238bceSAndroid Build Coastguard Worker 
VertexAttributeBindingTests(Context & context)1630*35238bceSAndroid Build Coastguard Worker VertexAttributeBindingTests::VertexAttributeBindingTests(Context &context)
1631*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "vertex_attribute_binding", "Test vertex attribute binding")
1632*35238bceSAndroid Build Coastguard Worker {
1633*35238bceSAndroid Build Coastguard Worker }
1634*35238bceSAndroid Build Coastguard Worker 
~VertexAttributeBindingTests(void)1635*35238bceSAndroid Build Coastguard Worker VertexAttributeBindingTests::~VertexAttributeBindingTests(void)
1636*35238bceSAndroid Build Coastguard Worker {
1637*35238bceSAndroid Build Coastguard Worker }
1638*35238bceSAndroid Build Coastguard Worker 
init(void)1639*35238bceSAndroid Build Coastguard Worker void VertexAttributeBindingTests::init(void)
1640*35238bceSAndroid Build Coastguard Worker {
1641*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *const usageGroup    = new tcu::TestCaseGroup(m_testCtx, "usage", "Test using binding points");
1642*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *const negativeGroup = new tcu::TestCaseGroup(m_testCtx, "negative", "Negative test");
1643*35238bceSAndroid Build Coastguard Worker 
1644*35238bceSAndroid Build Coastguard Worker     addChild(usageGroup);
1645*35238bceSAndroid Build Coastguard Worker     addChild(negativeGroup);
1646*35238bceSAndroid Build Coastguard Worker 
1647*35238bceSAndroid Build Coastguard Worker     // .usage
1648*35238bceSAndroid Build Coastguard Worker     {
1649*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const singleGroup =
1650*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "single_binding", "Test using single binding point");
1651*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const multipleGroup =
1652*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "multiple_bindings", "Test using multiple binding points");
1653*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const mixedGroup = new tcu::TestCaseGroup(
1654*35238bceSAndroid Build Coastguard Worker             m_testCtx, "mixed_usage", "Test using binding point and non binding point api variants");
1655*35238bceSAndroid Build Coastguard Worker 
1656*35238bceSAndroid Build Coastguard Worker         usageGroup->addChild(singleGroup);
1657*35238bceSAndroid Build Coastguard Worker         usageGroup->addChild(multipleGroup);
1658*35238bceSAndroid Build Coastguard Worker         usageGroup->addChild(mixedGroup);
1659*35238bceSAndroid Build Coastguard Worker 
1660*35238bceSAndroid Build Coastguard Worker         // single binding
1661*35238bceSAndroid Build Coastguard Worker 
1662*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(new SingleBindingCase(m_context, "elements_1", 0));
1663*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(
1664*35238bceSAndroid Build Coastguard Worker             new SingleBindingCase(m_context, "elements_2", SingleBindingCase::FLAG_ATTRIBS_MULTIPLE_ELEMS));
1665*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(new SingleBindingCase(m_context, "elements_2_share_elements",
1666*35238bceSAndroid Build Coastguard Worker                                                     SingleBindingCase::FLAG_ATTRIBS_SHARED_ELEMS));
1667*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(
1668*35238bceSAndroid Build Coastguard Worker             new SingleBindingCase(m_context, "offset_elements_1", SingleBindingCase::FLAG_BUF_ALIGNED_OFFSET | 0));
1669*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(new SingleBindingCase(m_context, "offset_elements_2",
1670*35238bceSAndroid Build Coastguard Worker                                                     SingleBindingCase::FLAG_BUF_ALIGNED_OFFSET |
1671*35238bceSAndroid Build Coastguard Worker                                                         SingleBindingCase::FLAG_ATTRIBS_MULTIPLE_ELEMS));
1672*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(new SingleBindingCase(m_context, "offset_elements_2_share_elements",
1673*35238bceSAndroid Build Coastguard Worker                                                     SingleBindingCase::FLAG_BUF_ALIGNED_OFFSET |
1674*35238bceSAndroid Build Coastguard Worker                                                         SingleBindingCase::FLAG_ATTRIBS_SHARED_ELEMS));
1675*35238bceSAndroid Build Coastguard Worker         singleGroup->addChild(
1676*35238bceSAndroid Build Coastguard Worker             new SingleBindingCase(m_context, "unaligned_offset_elements_1_aligned_elements",
1677*35238bceSAndroid Build Coastguard Worker                                   SingleBindingCase::FLAG_BUF_UNALIGNED_OFFSET |
1678*35238bceSAndroid Build Coastguard Worker                                       SingleBindingCase::FLAG_ATTRIB_ALIGNED)); // !< total offset is aligned
1679*35238bceSAndroid Build Coastguard Worker 
1680*35238bceSAndroid Build Coastguard Worker         // multiple bindings
1681*35238bceSAndroid Build Coastguard Worker 
1682*35238bceSAndroid Build Coastguard Worker         multipleGroup->addChild(new MultipleBindingCase(m_context, "basic", 0));
1683*35238bceSAndroid Build Coastguard Worker         multipleGroup->addChild(
1684*35238bceSAndroid Build Coastguard Worker             new MultipleBindingCase(m_context, "zero_stride", MultipleBindingCase::FLAG_ZERO_STRIDE));
1685*35238bceSAndroid Build Coastguard Worker         multipleGroup->addChild(new MultipleBindingCase(m_context, "instanced", MultipleBindingCase::FLAG_INSTANCED));
1686*35238bceSAndroid Build Coastguard Worker         multipleGroup->addChild(new MultipleBindingCase(m_context, "aliasing_buffer_zero_stride",
1687*35238bceSAndroid Build Coastguard Worker                                                         MultipleBindingCase::FLAG_ALIASING_BUFFERS |
1688*35238bceSAndroid Build Coastguard Worker                                                             MultipleBindingCase::FLAG_ZERO_STRIDE));
1689*35238bceSAndroid Build Coastguard Worker         multipleGroup->addChild(
1690*35238bceSAndroid Build Coastguard Worker             new MultipleBindingCase(m_context, "aliasing_buffer_instanced",
1691*35238bceSAndroid Build Coastguard Worker                                     MultipleBindingCase::FLAG_ALIASING_BUFFERS | MultipleBindingCase::FLAG_INSTANCED));
1692*35238bceSAndroid Build Coastguard Worker 
1693*35238bceSAndroid Build Coastguard Worker         // mixed cases
1694*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedBindingCase(m_context, "mixed_attribs_basic",
1695*35238bceSAndroid Build Coastguard Worker                                                   "Use different api for different attributes",
1696*35238bceSAndroid Build Coastguard Worker                                                   MixedBindingCase::CASE_BASIC));
1697*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedBindingCase(m_context, "mixed_attribs_instanced_binding",
1698*35238bceSAndroid Build Coastguard Worker                                                   "Use different api for different attributes",
1699*35238bceSAndroid Build Coastguard Worker                                                   MixedBindingCase::CASE_INSTANCED_BINDING));
1700*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedBindingCase(m_context, "mixed_attribs_instanced_attrib",
1701*35238bceSAndroid Build Coastguard Worker                                                   "Use different api for different attributes",
1702*35238bceSAndroid Build Coastguard Worker                                                   MixedBindingCase::CASE_INSTANCED_ATTRIB));
1703*35238bceSAndroid Build Coastguard Worker 
1704*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedApiCase(m_context, "mixed_api_change_buffer",
1705*35238bceSAndroid Build Coastguard Worker                                               "change buffer with vertex_attrib_binding api",
1706*35238bceSAndroid Build Coastguard Worker                                               MixedApiCase::CASE_CHANGE_BUFFER));
1707*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedApiCase(m_context, "mixed_api_change_buffer_offset",
1708*35238bceSAndroid Build Coastguard Worker                                               "change buffer offset with vertex_attrib_binding api",
1709*35238bceSAndroid Build Coastguard Worker                                               MixedApiCase::CASE_CHANGE_BUFFER_OFFSET));
1710*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedApiCase(m_context, "mixed_api_change_buffer_stride",
1711*35238bceSAndroid Build Coastguard Worker                                               "change buffer stride with vertex_attrib_binding api",
1712*35238bceSAndroid Build Coastguard Worker                                               MixedApiCase::CASE_CHANGE_BUFFER_STRIDE));
1713*35238bceSAndroid Build Coastguard Worker         mixedGroup->addChild(new MixedApiCase(m_context, "mixed_api_change_binding_point",
1714*35238bceSAndroid Build Coastguard Worker                                               "change binding point with vertex_attrib_binding api",
1715*35238bceSAndroid Build Coastguard Worker                                               MixedApiCase::CASE_CHANGE_BINDING_POINT));
1716*35238bceSAndroid Build Coastguard Worker     }
1717*35238bceSAndroid Build Coastguard Worker 
1718*35238bceSAndroid Build Coastguard Worker     // negative
1719*35238bceSAndroid Build Coastguard Worker     {
1720*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new DefaultVAOCase(m_context, "default_vao_bind_vertex_buffer", "use with default vao",
1721*35238bceSAndroid Build Coastguard Worker                                                    DefaultVAOCase::CASE_BIND_VERTEX_BUFFER));
1722*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new DefaultVAOCase(m_context, "default_vao_vertex_attrib_format",
1723*35238bceSAndroid Build Coastguard Worker                                                    "use with default vao", DefaultVAOCase::CASE_VERTEX_ATTRIB_FORMAT));
1724*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new DefaultVAOCase(m_context, "default_vao_vertex_attrib_i_format",
1725*35238bceSAndroid Build Coastguard Worker                                                    "use with default vao",
1726*35238bceSAndroid Build Coastguard Worker                                                    DefaultVAOCase::CASE_VERTEX_ATTRIB_I_FORMAT));
1727*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new DefaultVAOCase(m_context, "default_vao_vertex_attrib_binding",
1728*35238bceSAndroid Build Coastguard Worker                                                    "use with default vao", DefaultVAOCase::CASE_VERTEX_ATTRIB_BINDING));
1729*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new DefaultVAOCase(m_context, "default_vao_vertex_binding_divisor",
1730*35238bceSAndroid Build Coastguard Worker                                                    "use with default vao",
1731*35238bceSAndroid Build Coastguard Worker                                                    DefaultVAOCase::CASE_VERTEX_BINDING_DIVISOR));
1732*35238bceSAndroid Build Coastguard Worker 
1733*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new BindToCreateCase(m_context, "bind_create_new_buffer", "bind not existing buffer"));
1734*35238bceSAndroid Build Coastguard Worker 
1735*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "vertex_attrib_format_large_offset",
1736*35238bceSAndroid Build Coastguard Worker                                                     "large relative offset", NegativeApiCase::CASE_LARGE_OFFSET));
1737*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "bind_vertex_buffer_large_stride", "large stride",
1738*35238bceSAndroid Build Coastguard Worker                                                     NegativeApiCase::CASE_LARGE_STRIDE));
1739*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "bind_vertex_buffer_negative_stride", "negative stride",
1740*35238bceSAndroid Build Coastguard Worker                                                     NegativeApiCase::CASE_NEGATIVE_STRIDE));
1741*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "bind_vertex_buffer_negative_offset", "negative offset",
1742*35238bceSAndroid Build Coastguard Worker                                                     NegativeApiCase::CASE_NEGATIVE_OFFSET));
1743*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "vertex_attrib_binding_invalid_attr",
1744*35238bceSAndroid Build Coastguard Worker                                                     "bind invalid attr", NegativeApiCase::CASE_INVALID_ATTR));
1745*35238bceSAndroid Build Coastguard Worker         negativeGroup->addChild(new NegativeApiCase(m_context, "vertex_attrib_binding_invalid_binding",
1746*35238bceSAndroid Build Coastguard Worker                                                     "bind invalid binding", NegativeApiCase::CASE_INVALID_BINDING));
1747*35238bceSAndroid Build Coastguard Worker     }
1748*35238bceSAndroid Build Coastguard Worker }
1749*35238bceSAndroid Build Coastguard Worker 
1750*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1751*35238bceSAndroid Build Coastguard Worker } // namespace gles31
1752*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1753