xref: /aosp_15_r20/external/deqp/framework/opengl/gluDrawUtil.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL Utilities
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 Draw call utilities.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
30*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker #include <vector>
33*35238bceSAndroid Build Coastguard Worker #include <set>
34*35238bceSAndroid Build Coastguard Worker #include <iterator>
35*35238bceSAndroid Build Coastguard Worker 
36*35238bceSAndroid Build Coastguard Worker namespace glu
37*35238bceSAndroid Build Coastguard Worker {
38*35238bceSAndroid Build Coastguard Worker namespace
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker 
41*35238bceSAndroid Build Coastguard Worker struct VertexAttributeDescriptor
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker     int location;
44*35238bceSAndroid Build Coastguard Worker     VertexComponentType componentType;
45*35238bceSAndroid Build Coastguard Worker     VertexComponentConversion convert;
46*35238bceSAndroid Build Coastguard Worker     int numComponents;
47*35238bceSAndroid Build Coastguard Worker     int numElements;
48*35238bceSAndroid Build Coastguard Worker     int stride;          //!< Stride or 0 if using default stride.
49*35238bceSAndroid Build Coastguard Worker     const void *pointer; //!< Pointer or offset.
50*35238bceSAndroid Build Coastguard Worker 
VertexAttributeDescriptorglu::__anonf067fd160111::VertexAttributeDescriptor51*35238bceSAndroid Build Coastguard Worker     VertexAttributeDescriptor(int location_, VertexComponentType componentType_, VertexComponentConversion convert_,
52*35238bceSAndroid Build Coastguard Worker                               int numComponents_, int numElements_, int stride_, const void *pointer_)
53*35238bceSAndroid Build Coastguard Worker         : location(location_)
54*35238bceSAndroid Build Coastguard Worker         , componentType(componentType_)
55*35238bceSAndroid Build Coastguard Worker         , convert(convert_)
56*35238bceSAndroid Build Coastguard Worker         , numComponents(numComponents_)
57*35238bceSAndroid Build Coastguard Worker         , numElements(numElements_)
58*35238bceSAndroid Build Coastguard Worker         , stride(stride_)
59*35238bceSAndroid Build Coastguard Worker         , pointer(pointer_)
60*35238bceSAndroid Build Coastguard Worker     {
61*35238bceSAndroid Build Coastguard Worker     }
62*35238bceSAndroid Build Coastguard Worker 
VertexAttributeDescriptorglu::__anonf067fd160111::VertexAttributeDescriptor63*35238bceSAndroid Build Coastguard Worker     VertexAttributeDescriptor(void)
64*35238bceSAndroid Build Coastguard Worker         : location(0)
65*35238bceSAndroid Build Coastguard Worker         , componentType(VTX_COMP_TYPE_LAST)
66*35238bceSAndroid Build Coastguard Worker         , convert(VTX_COMP_CONVERT_LAST)
67*35238bceSAndroid Build Coastguard Worker         , numComponents(0)
68*35238bceSAndroid Build Coastguard Worker         , numElements(0)
69*35238bceSAndroid Build Coastguard Worker         , stride(0)
70*35238bceSAndroid Build Coastguard Worker         , pointer(0)
71*35238bceSAndroid Build Coastguard Worker     {
72*35238bceSAndroid Build Coastguard Worker     }
73*35238bceSAndroid Build Coastguard Worker };
74*35238bceSAndroid Build Coastguard Worker 
75*35238bceSAndroid Build Coastguard Worker struct VertexBufferLayout
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     int size;
78*35238bceSAndroid Build Coastguard Worker     std::vector<VertexAttributeDescriptor> attributes;
79*35238bceSAndroid Build Coastguard Worker 
VertexBufferLayoutglu::__anonf067fd160111::VertexBufferLayout80*35238bceSAndroid Build Coastguard Worker     VertexBufferLayout(int size_ = 0) : size(size_)
81*35238bceSAndroid Build Coastguard Worker     {
82*35238bceSAndroid Build Coastguard Worker     }
83*35238bceSAndroid Build Coastguard Worker };
84*35238bceSAndroid Build Coastguard Worker 
85*35238bceSAndroid Build Coastguard Worker struct VertexBufferDescriptor
86*35238bceSAndroid Build Coastguard Worker {
87*35238bceSAndroid Build Coastguard Worker     uint32_t buffer;
88*35238bceSAndroid Build Coastguard Worker     std::vector<VertexAttributeDescriptor> attributes;
89*35238bceSAndroid Build Coastguard Worker 
VertexBufferDescriptorglu::__anonf067fd160111::VertexBufferDescriptor90*35238bceSAndroid Build Coastguard Worker     VertexBufferDescriptor(uint32_t buffer_ = 0) : buffer(buffer_)
91*35238bceSAndroid Build Coastguard Worker     {
92*35238bceSAndroid Build Coastguard Worker     }
93*35238bceSAndroid Build Coastguard Worker };
94*35238bceSAndroid Build Coastguard Worker 
95*35238bceSAndroid Build Coastguard Worker class VertexBuffer : public Buffer
96*35238bceSAndroid Build Coastguard Worker {
97*35238bceSAndroid Build Coastguard Worker public:
98*35238bceSAndroid Build Coastguard Worker     enum Type
99*35238bceSAndroid Build Coastguard Worker     {
100*35238bceSAndroid Build Coastguard Worker         TYPE_PLANAR = 0, //!< Data for each vertex array resides in a separate contiguous block in buffer.
101*35238bceSAndroid Build Coastguard Worker         TYPE_STRIDED,    //!< Vertex arrays are interleaved.
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker         TYPE_LAST
104*35238bceSAndroid Build Coastguard Worker     };
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     VertexBuffer(const RenderContext &context, int numBindings, const VertexArrayBinding *bindings,
107*35238bceSAndroid Build Coastguard Worker                  Type type = TYPE_PLANAR);
108*35238bceSAndroid Build Coastguard Worker     ~VertexBuffer(void);
109*35238bceSAndroid Build Coastguard Worker 
getDescriptor(void) const110*35238bceSAndroid Build Coastguard Worker     const VertexBufferDescriptor &getDescriptor(void) const
111*35238bceSAndroid Build Coastguard Worker     {
112*35238bceSAndroid Build Coastguard Worker         return m_layout;
113*35238bceSAndroid Build Coastguard Worker     }
114*35238bceSAndroid Build Coastguard Worker 
115*35238bceSAndroid Build Coastguard Worker private:
116*35238bceSAndroid Build Coastguard Worker     VertexBuffer(const VertexBuffer &other);
117*35238bceSAndroid Build Coastguard Worker     VertexBuffer &operator=(const VertexBuffer &other);
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker     VertexBufferDescriptor m_layout;
120*35238bceSAndroid Build Coastguard Worker };
121*35238bceSAndroid Build Coastguard Worker 
122*35238bceSAndroid Build Coastguard Worker class IndexBuffer : public Buffer
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker public:
125*35238bceSAndroid Build Coastguard Worker     IndexBuffer(const RenderContext &context, IndexType indexType, int numIndices, const void *indices);
126*35238bceSAndroid Build Coastguard Worker     ~IndexBuffer(void);
127*35238bceSAndroid Build Coastguard Worker 
128*35238bceSAndroid Build Coastguard Worker private:
129*35238bceSAndroid Build Coastguard Worker     IndexBuffer(const IndexBuffer &other);
130*35238bceSAndroid Build Coastguard Worker     IndexBuffer &operator=(const IndexBuffer &other);
131*35238bceSAndroid Build Coastguard Worker };
132*35238bceSAndroid Build Coastguard Worker 
getVtxCompGLType(VertexComponentType type)133*35238bceSAndroid Build Coastguard Worker static uint32_t getVtxCompGLType(VertexComponentType type)
134*35238bceSAndroid Build Coastguard Worker {
135*35238bceSAndroid Build Coastguard Worker     switch (type)
136*35238bceSAndroid Build Coastguard Worker     {
137*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT8:
138*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_BYTE;
139*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT16:
140*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_SHORT;
141*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT32:
142*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_INT;
143*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT8:
144*35238bceSAndroid Build Coastguard Worker         return GL_BYTE;
145*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT16:
146*35238bceSAndroid Build Coastguard Worker         return GL_SHORT;
147*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT32:
148*35238bceSAndroid Build Coastguard Worker         return GL_INT;
149*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_FIXED:
150*35238bceSAndroid Build Coastguard Worker         return GL_FIXED;
151*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_HALF_FLOAT:
152*35238bceSAndroid Build Coastguard Worker         return GL_HALF_FLOAT;
153*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_FLOAT:
154*35238bceSAndroid Build Coastguard Worker         return GL_FLOAT;
155*35238bceSAndroid Build Coastguard Worker     default:
156*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
157*35238bceSAndroid Build Coastguard Worker         return GL_NONE;
158*35238bceSAndroid Build Coastguard Worker     }
159*35238bceSAndroid Build Coastguard Worker }
160*35238bceSAndroid Build Coastguard Worker 
getVtxCompSize(VertexComponentType type)161*35238bceSAndroid Build Coastguard Worker static int getVtxCompSize(VertexComponentType type)
162*35238bceSAndroid Build Coastguard Worker {
163*35238bceSAndroid Build Coastguard Worker     switch (type)
164*35238bceSAndroid Build Coastguard Worker     {
165*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT8:
166*35238bceSAndroid Build Coastguard Worker         return 1;
167*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT16:
168*35238bceSAndroid Build Coastguard Worker         return 2;
169*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_UNSIGNED_INT32:
170*35238bceSAndroid Build Coastguard Worker         return 4;
171*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT8:
172*35238bceSAndroid Build Coastguard Worker         return 1;
173*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT16:
174*35238bceSAndroid Build Coastguard Worker         return 2;
175*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_SIGNED_INT32:
176*35238bceSAndroid Build Coastguard Worker         return 4;
177*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_FIXED:
178*35238bceSAndroid Build Coastguard Worker         return 4;
179*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_HALF_FLOAT:
180*35238bceSAndroid Build Coastguard Worker         return 2;
181*35238bceSAndroid Build Coastguard Worker     case VTX_COMP_FLOAT:
182*35238bceSAndroid Build Coastguard Worker         return 4;
183*35238bceSAndroid Build Coastguard Worker     default:
184*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
185*35238bceSAndroid Build Coastguard Worker         return 0;
186*35238bceSAndroid Build Coastguard Worker     }
187*35238bceSAndroid Build Coastguard Worker }
188*35238bceSAndroid Build Coastguard Worker 
getIndexGLType(IndexType type)189*35238bceSAndroid Build Coastguard Worker static uint32_t getIndexGLType(IndexType type)
190*35238bceSAndroid Build Coastguard Worker {
191*35238bceSAndroid Build Coastguard Worker     switch (type)
192*35238bceSAndroid Build Coastguard Worker     {
193*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT8:
194*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_BYTE;
195*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT16:
196*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_SHORT;
197*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT32:
198*35238bceSAndroid Build Coastguard Worker         return GL_UNSIGNED_INT;
199*35238bceSAndroid Build Coastguard Worker     default:
200*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
201*35238bceSAndroid Build Coastguard Worker         return 0;
202*35238bceSAndroid Build Coastguard Worker     }
203*35238bceSAndroid Build Coastguard Worker }
204*35238bceSAndroid Build Coastguard Worker 
getIndexSize(IndexType type)205*35238bceSAndroid Build Coastguard Worker static int getIndexSize(IndexType type)
206*35238bceSAndroid Build Coastguard Worker {
207*35238bceSAndroid Build Coastguard Worker     switch (type)
208*35238bceSAndroid Build Coastguard Worker     {
209*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT8:
210*35238bceSAndroid Build Coastguard Worker         return 1;
211*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT16:
212*35238bceSAndroid Build Coastguard Worker         return 2;
213*35238bceSAndroid Build Coastguard Worker     case INDEXTYPE_UINT32:
214*35238bceSAndroid Build Coastguard Worker         return 4;
215*35238bceSAndroid Build Coastguard Worker     default:
216*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
217*35238bceSAndroid Build Coastguard Worker         return 0;
218*35238bceSAndroid Build Coastguard Worker     }
219*35238bceSAndroid Build Coastguard Worker }
220*35238bceSAndroid Build Coastguard Worker 
getPrimitiveGLType(PrimitiveType type)221*35238bceSAndroid Build Coastguard Worker static uint32_t getPrimitiveGLType(PrimitiveType type)
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker     switch (type)
224*35238bceSAndroid Build Coastguard Worker     {
225*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_TRIANGLES:
226*35238bceSAndroid Build Coastguard Worker         return GL_TRIANGLES;
227*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_TRIANGLE_STRIP:
228*35238bceSAndroid Build Coastguard Worker         return GL_TRIANGLE_STRIP;
229*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_TRIANGLE_FAN:
230*35238bceSAndroid Build Coastguard Worker         return GL_TRIANGLE_FAN;
231*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_LINES:
232*35238bceSAndroid Build Coastguard Worker         return GL_LINES;
233*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_LINE_STRIP:
234*35238bceSAndroid Build Coastguard Worker         return GL_LINE_STRIP;
235*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_LINE_LOOP:
236*35238bceSAndroid Build Coastguard Worker         return GL_LINE_LOOP;
237*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_POINTS:
238*35238bceSAndroid Build Coastguard Worker         return GL_POINTS;
239*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_PATCHES:
240*35238bceSAndroid Build Coastguard Worker         return GL_PATCHES;
241*35238bceSAndroid Build Coastguard Worker     default:
242*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
243*35238bceSAndroid Build Coastguard Worker         return 0;
244*35238bceSAndroid Build Coastguard Worker     }
245*35238bceSAndroid Build Coastguard Worker }
246*35238bceSAndroid Build Coastguard Worker 
247*35238bceSAndroid Build Coastguard Worker //! Lower named bindings to locations and eliminate bindings that are not used by program.
248*35238bceSAndroid Build Coastguard Worker template <typename InputIter, typename OutputIter>
namedBindingsToProgramLocations(const glw::Functions & gl,uint32_t program,InputIter first,InputIter end,OutputIter out)249*35238bceSAndroid Build Coastguard Worker static OutputIter namedBindingsToProgramLocations(const glw::Functions &gl, uint32_t program, InputIter first,
250*35238bceSAndroid Build Coastguard Worker                                                   InputIter end, OutputIter out)
251*35238bceSAndroid Build Coastguard Worker {
252*35238bceSAndroid Build Coastguard Worker     for (InputIter cur = first; cur != end; ++cur)
253*35238bceSAndroid Build Coastguard Worker     {
254*35238bceSAndroid Build Coastguard Worker         const BindingPoint &binding = cur->binding;
255*35238bceSAndroid Build Coastguard Worker         if (binding.type == BindingPoint::BPTYPE_NAME)
256*35238bceSAndroid Build Coastguard Worker         {
257*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(binding.location >= 0);
258*35238bceSAndroid Build Coastguard Worker             int location = gl.getAttribLocation(program, binding.name.c_str());
259*35238bceSAndroid Build Coastguard Worker             if (location >= 0)
260*35238bceSAndroid Build Coastguard Worker             {
261*35238bceSAndroid Build Coastguard Worker                 // Add binding.location as an offset to accommodate matrices.
262*35238bceSAndroid Build Coastguard Worker                 *out = VertexArrayBinding(BindingPoint(location + binding.location), cur->pointer);
263*35238bceSAndroid Build Coastguard Worker                 ++out;
264*35238bceSAndroid Build Coastguard Worker             }
265*35238bceSAndroid Build Coastguard Worker         }
266*35238bceSAndroid Build Coastguard Worker         else
267*35238bceSAndroid Build Coastguard Worker         {
268*35238bceSAndroid Build Coastguard Worker             *out = *cur;
269*35238bceSAndroid Build Coastguard Worker             ++out;
270*35238bceSAndroid Build Coastguard Worker         }
271*35238bceSAndroid Build Coastguard Worker     }
272*35238bceSAndroid Build Coastguard Worker 
273*35238bceSAndroid Build Coastguard Worker     return out;
274*35238bceSAndroid Build Coastguard Worker }
275*35238bceSAndroid Build Coastguard Worker 
getMinimumAlignment(const VertexArrayPointer & pointer)276*35238bceSAndroid Build Coastguard Worker static uint32_t getMinimumAlignment(const VertexArrayPointer &pointer)
277*35238bceSAndroid Build Coastguard Worker {
278*35238bceSAndroid Build Coastguard Worker     // \todo [2013-05-07 pyry] What is the actual min?
279*35238bceSAndroid Build Coastguard Worker     DE_UNREF(pointer);
280*35238bceSAndroid Build Coastguard Worker     return (uint32_t)sizeof(float);
281*35238bceSAndroid Build Coastguard Worker }
282*35238bceSAndroid Build Coastguard Worker 
283*35238bceSAndroid Build Coastguard Worker template <typename BindingIter>
areVertexArrayLocationsValid(BindingIter first,BindingIter end)284*35238bceSAndroid Build Coastguard Worker static bool areVertexArrayLocationsValid(BindingIter first, BindingIter end)
285*35238bceSAndroid Build Coastguard Worker {
286*35238bceSAndroid Build Coastguard Worker     std::set<int> usedLocations;
287*35238bceSAndroid Build Coastguard Worker     for (BindingIter cur = first; cur != end; ++cur)
288*35238bceSAndroid Build Coastguard Worker     {
289*35238bceSAndroid Build Coastguard Worker         const BindingPoint &binding = cur->binding;
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker         if (binding.type != BindingPoint::BPTYPE_LOCATION)
292*35238bceSAndroid Build Coastguard Worker             return false;
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker         if (usedLocations.find(binding.location) != usedLocations.end())
295*35238bceSAndroid Build Coastguard Worker             return false;
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker         usedLocations.insert(binding.location);
298*35238bceSAndroid Build Coastguard Worker     }
299*35238bceSAndroid Build Coastguard Worker 
300*35238bceSAndroid Build Coastguard Worker     return true;
301*35238bceSAndroid Build Coastguard Worker }
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker // \todo [2013-05-08 pyry] Buffer upload should try to match pointers to reduce dataset size.
304*35238bceSAndroid Build Coastguard Worker 
appendAttributeNonStrided(VertexBufferLayout & layout,const VertexArrayBinding & va)305*35238bceSAndroid Build Coastguard Worker static void appendAttributeNonStrided(VertexBufferLayout &layout, const VertexArrayBinding &va)
306*35238bceSAndroid Build Coastguard Worker {
307*35238bceSAndroid Build Coastguard Worker     const int offset      = deAlign32(layout.size, getMinimumAlignment(va.pointer));
308*35238bceSAndroid Build Coastguard Worker     const int elementSize = getVtxCompSize(va.pointer.componentType) * va.pointer.numComponents;
309*35238bceSAndroid Build Coastguard Worker     const int size        = elementSize * va.pointer.numElements;
310*35238bceSAndroid Build Coastguard Worker 
311*35238bceSAndroid Build Coastguard Worker     // Must be assigned to location at this point.
312*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(va.binding.type == BindingPoint::BPTYPE_LOCATION);
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker     layout.attributes.push_back(VertexAttributeDescriptor(va.binding.location, va.pointer.componentType,
315*35238bceSAndroid Build Coastguard Worker                                                           va.pointer.convert, va.pointer.numComponents,
316*35238bceSAndroid Build Coastguard Worker                                                           va.pointer.numElements,
317*35238bceSAndroid Build Coastguard Worker                                                           0, // default stride
318*35238bceSAndroid Build Coastguard Worker                                                           (const void *)(uintptr_t)offset));
319*35238bceSAndroid Build Coastguard Worker     layout.size = offset + size;
320*35238bceSAndroid Build Coastguard Worker }
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker template <typename BindingIter>
computeNonStridedBufferLayout(VertexBufferLayout & layout,BindingIter first,BindingIter end)323*35238bceSAndroid Build Coastguard Worker static void computeNonStridedBufferLayout(VertexBufferLayout &layout, BindingIter first, BindingIter end)
324*35238bceSAndroid Build Coastguard Worker {
325*35238bceSAndroid Build Coastguard Worker     for (BindingIter iter = first; iter != end; ++iter)
326*35238bceSAndroid Build Coastguard Worker         appendAttributeNonStrided(layout, *iter);
327*35238bceSAndroid Build Coastguard Worker }
328*35238bceSAndroid Build Coastguard Worker 
copyToLayout(void * dstBasePtr,const VertexAttributeDescriptor & dstVA,const VertexArrayPointer & srcPtr)329*35238bceSAndroid Build Coastguard Worker static void copyToLayout(void *dstBasePtr, const VertexAttributeDescriptor &dstVA, const VertexArrayPointer &srcPtr)
330*35238bceSAndroid Build Coastguard Worker {
331*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(dstVA.componentType == srcPtr.componentType && dstVA.numComponents == srcPtr.numComponents &&
332*35238bceSAndroid Build Coastguard Worker               dstVA.numElements == srcPtr.numElements);
333*35238bceSAndroid Build Coastguard Worker 
334*35238bceSAndroid Build Coastguard Worker     const int elementSize         = getVtxCompSize(dstVA.componentType) * dstVA.numComponents;
335*35238bceSAndroid Build Coastguard Worker     const bool srcHasCustomStride = srcPtr.stride != 0 && srcPtr.stride != elementSize;
336*35238bceSAndroid Build Coastguard Worker     const bool dstHasCustomStride = dstVA.stride != 0 && dstVA.stride != elementSize;
337*35238bceSAndroid Build Coastguard Worker 
338*35238bceSAndroid Build Coastguard Worker     if (srcHasCustomStride || dstHasCustomStride)
339*35238bceSAndroid Build Coastguard Worker     {
340*35238bceSAndroid Build Coastguard Worker         const int dstStride = dstVA.stride != 0 ? dstVA.stride : elementSize;
341*35238bceSAndroid Build Coastguard Worker         const int srcStride = srcPtr.stride != 0 ? srcPtr.stride : elementSize;
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < dstVA.numElements; ndx++)
344*35238bceSAndroid Build Coastguard Worker             deMemcpy((uint8_t *)dstBasePtr + (uintptr_t)dstVA.pointer + ndx * dstStride,
345*35238bceSAndroid Build Coastguard Worker                      (const uint8_t *)srcPtr.data + ndx * srcStride, elementSize);
346*35238bceSAndroid Build Coastguard Worker     }
347*35238bceSAndroid Build Coastguard Worker     else
348*35238bceSAndroid Build Coastguard Worker         deMemcpy((uint8_t *)dstBasePtr + (uintptr_t)dstVA.pointer, srcPtr.data, elementSize * dstVA.numElements);
349*35238bceSAndroid Build Coastguard Worker }
350*35238bceSAndroid Build Coastguard Worker 
uploadBufferData(const glw::Functions & gl,uint32_t buffer,uint32_t usage,const VertexBufferLayout & layout,const VertexArrayPointer * srcArrays)351*35238bceSAndroid Build Coastguard Worker void uploadBufferData(const glw::Functions &gl, uint32_t buffer, uint32_t usage, const VertexBufferLayout &layout,
352*35238bceSAndroid Build Coastguard Worker                       const VertexArrayPointer *srcArrays)
353*35238bceSAndroid Build Coastguard Worker {
354*35238bceSAndroid Build Coastguard Worker     // Create temporary data buffer for upload.
355*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> localBuf(layout.size);
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker     for (int attrNdx = 0; attrNdx < (int)layout.attributes.size(); ++attrNdx)
358*35238bceSAndroid Build Coastguard Worker         copyToLayout(&localBuf[0], layout.attributes[attrNdx], srcArrays[attrNdx]);
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
361*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (int)localBuf.size(), &localBuf[0], usage);
362*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
363*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading buffer data failed");
364*35238bceSAndroid Build Coastguard Worker }
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker // VertexBuffer
367*35238bceSAndroid Build Coastguard Worker 
VertexBuffer(const RenderContext & context,int numBindings,const VertexArrayBinding * bindings,Type type)368*35238bceSAndroid Build Coastguard Worker VertexBuffer::VertexBuffer(const RenderContext &context, int numBindings, const VertexArrayBinding *bindings, Type type)
369*35238bceSAndroid Build Coastguard Worker     : Buffer(context)
370*35238bceSAndroid Build Coastguard Worker {
371*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = context.getFunctions();
372*35238bceSAndroid Build Coastguard Worker     const uint32_t usage     = GL_STATIC_DRAW;
373*35238bceSAndroid Build Coastguard Worker     VertexBufferLayout layout;
374*35238bceSAndroid Build Coastguard Worker 
375*35238bceSAndroid Build Coastguard Worker     if (!areVertexArrayLocationsValid(bindings, bindings + numBindings))
376*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("Invalid vertex array locations");
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker     if (type == TYPE_PLANAR)
379*35238bceSAndroid Build Coastguard Worker         computeNonStridedBufferLayout(layout, bindings, bindings + numBindings);
380*35238bceSAndroid Build Coastguard Worker     else
381*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Strided layout is not yet supported");
382*35238bceSAndroid Build Coastguard Worker 
383*35238bceSAndroid Build Coastguard Worker     std::vector<VertexArrayPointer> srcPtrs(numBindings);
384*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numBindings; ndx++)
385*35238bceSAndroid Build Coastguard Worker         srcPtrs[ndx] = bindings[ndx].pointer;
386*35238bceSAndroid Build Coastguard Worker 
387*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(srcPtrs.size() == layout.attributes.size());
388*35238bceSAndroid Build Coastguard Worker     if (!srcPtrs.empty())
389*35238bceSAndroid Build Coastguard Worker         uploadBufferData(gl, m_object, usage, layout, &srcPtrs[0]);
390*35238bceSAndroid Build Coastguard Worker 
391*35238bceSAndroid Build Coastguard Worker     // Construct descriptor.
392*35238bceSAndroid Build Coastguard Worker     m_layout.buffer     = m_object;
393*35238bceSAndroid Build Coastguard Worker     m_layout.attributes = layout.attributes;
394*35238bceSAndroid Build Coastguard Worker }
395*35238bceSAndroid Build Coastguard Worker 
~VertexBuffer(void)396*35238bceSAndroid Build Coastguard Worker VertexBuffer::~VertexBuffer(void)
397*35238bceSAndroid Build Coastguard Worker {
398*35238bceSAndroid Build Coastguard Worker }
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker // IndexBuffer
401*35238bceSAndroid Build Coastguard Worker 
IndexBuffer(const RenderContext & context,IndexType indexType,int numIndices,const void * indices)402*35238bceSAndroid Build Coastguard Worker IndexBuffer::IndexBuffer(const RenderContext &context, IndexType indexType, int numIndices, const void *indices)
403*35238bceSAndroid Build Coastguard Worker     : Buffer(context)
404*35238bceSAndroid Build Coastguard Worker {
405*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = context.getFunctions();
406*35238bceSAndroid Build Coastguard Worker     const uint32_t usage     = GL_STATIC_DRAW;
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_object);
409*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * getIndexSize(indexType), indices, usage);
410*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
411*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading index data failed");
412*35238bceSAndroid Build Coastguard Worker }
413*35238bceSAndroid Build Coastguard Worker 
~IndexBuffer(void)414*35238bceSAndroid Build Coastguard Worker IndexBuffer::~IndexBuffer(void)
415*35238bceSAndroid Build Coastguard Worker {
416*35238bceSAndroid Build Coastguard Worker }
417*35238bceSAndroid Build Coastguard Worker 
getUserPointerDescriptor(const VertexArrayBinding & vertexArray)418*35238bceSAndroid Build Coastguard Worker static inline VertexAttributeDescriptor getUserPointerDescriptor(const VertexArrayBinding &vertexArray)
419*35238bceSAndroid Build Coastguard Worker {
420*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(vertexArray.binding.type == BindingPoint::BPTYPE_LOCATION);
421*35238bceSAndroid Build Coastguard Worker 
422*35238bceSAndroid Build Coastguard Worker     return VertexAttributeDescriptor(vertexArray.binding.location, vertexArray.pointer.componentType,
423*35238bceSAndroid Build Coastguard Worker                                      vertexArray.pointer.convert, vertexArray.pointer.numComponents,
424*35238bceSAndroid Build Coastguard Worker                                      vertexArray.pointer.numElements, vertexArray.pointer.stride,
425*35238bceSAndroid Build Coastguard Worker                                      vertexArray.pointer.data);
426*35238bceSAndroid Build Coastguard Worker }
427*35238bceSAndroid Build Coastguard Worker 
428*35238bceSAndroid Build Coastguard Worker //! Setup VA according to allocation spec. Assumes that other state (VAO binding, buffer) is set already.
setVertexAttribPointer(const glw::Functions & gl,const VertexAttributeDescriptor & va)429*35238bceSAndroid Build Coastguard Worker static void setVertexAttribPointer(const glw::Functions &gl, const VertexAttributeDescriptor &va)
430*35238bceSAndroid Build Coastguard Worker {
431*35238bceSAndroid Build Coastguard Worker     const bool isIntType      = de::inRange<int>(va.componentType, VTX_COMP_UNSIGNED_INT8, VTX_COMP_SIGNED_INT32);
432*35238bceSAndroid Build Coastguard Worker     const bool isSpecialType  = de::inRange<int>(va.componentType, VTX_COMP_FIXED, VTX_COMP_FLOAT);
433*35238bceSAndroid Build Coastguard Worker     const uint32_t compTypeGL = getVtxCompGLType(va.componentType);
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isIntType != isSpecialType);                       // Must be either int or special type.
436*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isIntType || va.convert == VTX_COMP_CONVERT_NONE); // Conversion allowed only for special types.
437*35238bceSAndroid Build Coastguard Worker     DE_UNREF(isSpecialType);
438*35238bceSAndroid Build Coastguard Worker 
439*35238bceSAndroid Build Coastguard Worker     gl.enableVertexAttribArray(va.location);
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker     if (isIntType && va.convert == VTX_COMP_CONVERT_NONE)
442*35238bceSAndroid Build Coastguard Worker         gl.vertexAttribIPointer(va.location, va.numComponents, compTypeGL, va.stride, va.pointer);
443*35238bceSAndroid Build Coastguard Worker     else
444*35238bceSAndroid Build Coastguard Worker         gl.vertexAttribPointer(va.location, va.numComponents, compTypeGL,
445*35238bceSAndroid Build Coastguard Worker                                va.convert == VTX_COMP_CONVERT_NORMALIZE_TO_FLOAT ? GL_TRUE : GL_FALSE, va.stride,
446*35238bceSAndroid Build Coastguard Worker                                va.pointer);
447*35238bceSAndroid Build Coastguard Worker }
448*35238bceSAndroid Build Coastguard Worker 
449*35238bceSAndroid Build Coastguard Worker //! Setup vertex buffer and attributes.
setVertexBufferAttributes(const glw::Functions & gl,const VertexBufferDescriptor & buffer)450*35238bceSAndroid Build Coastguard Worker static void setVertexBufferAttributes(const glw::Functions &gl, const VertexBufferDescriptor &buffer)
451*35238bceSAndroid Build Coastguard Worker {
452*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, buffer.buffer);
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker     for (std::vector<VertexAttributeDescriptor>::const_iterator vaIter = buffer.attributes.begin();
455*35238bceSAndroid Build Coastguard Worker          vaIter != buffer.attributes.end(); ++vaIter)
456*35238bceSAndroid Build Coastguard Worker         setVertexAttribPointer(gl, *vaIter);
457*35238bceSAndroid Build Coastguard Worker 
458*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
459*35238bceSAndroid Build Coastguard Worker }
460*35238bceSAndroid Build Coastguard Worker 
disableVertexArrays(const glw::Functions & gl,const std::vector<VertexArrayBinding> & bindings)461*35238bceSAndroid Build Coastguard Worker static void disableVertexArrays(const glw::Functions &gl, const std::vector<VertexArrayBinding> &bindings)
462*35238bceSAndroid Build Coastguard Worker {
463*35238bceSAndroid Build Coastguard Worker     for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindings.begin(); vaIter != bindings.end(); ++vaIter)
464*35238bceSAndroid Build Coastguard Worker     {
465*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(vaIter->binding.type == BindingPoint::BPTYPE_LOCATION);
466*35238bceSAndroid Build Coastguard Worker         gl.disableVertexAttribArray(vaIter->binding.location);
467*35238bceSAndroid Build Coastguard Worker     }
468*35238bceSAndroid Build Coastguard Worker }
469*35238bceSAndroid Build Coastguard Worker 
470*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
isProgramActive(const RenderContext & context,uint32_t program)471*35238bceSAndroid Build Coastguard Worker static bool isProgramActive(const RenderContext &context, uint32_t program)
472*35238bceSAndroid Build Coastguard Worker {
473*35238bceSAndroid Build Coastguard Worker     // \todo [2013-05-08 pyry] Is this query broken?
474*35238bceSAndroid Build Coastguard Worker     /*    uint32_t activeProgram = 0;
475*35238bceSAndroid Build Coastguard Worker         context.getFunctions().getIntegerv(GL_ACTIVE_PROGRAM, (int*)&activeProgram);
476*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(context.getFunctions().getError(), "oh");
477*35238bceSAndroid Build Coastguard Worker         return activeProgram == program;*/
478*35238bceSAndroid Build Coastguard Worker     DE_UNREF(context);
479*35238bceSAndroid Build Coastguard Worker     DE_UNREF(program);
480*35238bceSAndroid Build Coastguard Worker     return true;
481*35238bceSAndroid Build Coastguard Worker }
482*35238bceSAndroid Build Coastguard Worker 
isDrawCallValid(int numVertexArrays,const VertexArrayBinding * vertexArrays,const PrimitiveList & primitives)483*35238bceSAndroid Build Coastguard Worker static bool isDrawCallValid(int numVertexArrays, const VertexArrayBinding *vertexArrays,
484*35238bceSAndroid Build Coastguard Worker                             const PrimitiveList &primitives)
485*35238bceSAndroid Build Coastguard Worker {
486*35238bceSAndroid Build Coastguard Worker     if (numVertexArrays < 0)
487*35238bceSAndroid Build Coastguard Worker         return false;
488*35238bceSAndroid Build Coastguard Worker 
489*35238bceSAndroid Build Coastguard Worker     if ((primitives.indexType == INDEXTYPE_LAST) != (primitives.indices == 0))
490*35238bceSAndroid Build Coastguard Worker         return false;
491*35238bceSAndroid Build Coastguard Worker 
492*35238bceSAndroid Build Coastguard Worker     if (primitives.numElements < 0)
493*35238bceSAndroid Build Coastguard Worker         return false;
494*35238bceSAndroid Build Coastguard Worker 
495*35238bceSAndroid Build Coastguard Worker     if (!primitives.indices)
496*35238bceSAndroid Build Coastguard Worker     {
497*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < numVertexArrays; ndx++)
498*35238bceSAndroid Build Coastguard Worker         {
499*35238bceSAndroid Build Coastguard Worker             if (primitives.numElements > vertexArrays[ndx].pointer.numElements)
500*35238bceSAndroid Build Coastguard Worker                 return false;
501*35238bceSAndroid Build Coastguard Worker         }
502*35238bceSAndroid Build Coastguard Worker     }
503*35238bceSAndroid Build Coastguard Worker     // \todo [2013-05-08 pyry] We could walk whole index array and determine index range
504*35238bceSAndroid Build Coastguard Worker 
505*35238bceSAndroid Build Coastguard Worker     return true;
506*35238bceSAndroid Build Coastguard Worker }
507*35238bceSAndroid Build Coastguard Worker #endif // DE_DEBUG
508*35238bceSAndroid Build Coastguard Worker 
drawNonIndexed(const glw::Functions & gl,PrimitiveType type,int numElements)509*35238bceSAndroid Build Coastguard Worker static inline void drawNonIndexed(const glw::Functions &gl, PrimitiveType type, int numElements)
510*35238bceSAndroid Build Coastguard Worker {
511*35238bceSAndroid Build Coastguard Worker     uint32_t mode = getPrimitiveGLType(type);
512*35238bceSAndroid Build Coastguard Worker     gl.drawArrays(mode, 0, numElements);
513*35238bceSAndroid Build Coastguard Worker }
514*35238bceSAndroid Build Coastguard Worker 
drawIndexed(const glw::Functions & gl,PrimitiveType type,int numElements,IndexType indexType,const void * indexPtr)515*35238bceSAndroid Build Coastguard Worker static inline void drawIndexed(const glw::Functions &gl, PrimitiveType type, int numElements, IndexType indexType,
516*35238bceSAndroid Build Coastguard Worker                                const void *indexPtr)
517*35238bceSAndroid Build Coastguard Worker {
518*35238bceSAndroid Build Coastguard Worker     uint32_t mode        = getPrimitiveGLType(type);
519*35238bceSAndroid Build Coastguard Worker     uint32_t indexGLType = getIndexGLType(indexType);
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker     gl.drawElements(mode, numElements, indexGLType, indexPtr);
522*35238bceSAndroid Build Coastguard Worker }
523*35238bceSAndroid Build Coastguard Worker 
524*35238bceSAndroid Build Coastguard Worker } // namespace
525*35238bceSAndroid Build Coastguard Worker 
drawFromUserPointers(const RenderContext & context,uint32_t program,int numVertexArrays,const VertexArrayBinding * vertexArrays,const PrimitiveList & primitives,DrawUtilCallback * callback)526*35238bceSAndroid Build Coastguard Worker void drawFromUserPointers(const RenderContext &context, uint32_t program, int numVertexArrays,
527*35238bceSAndroid Build Coastguard Worker                           const VertexArrayBinding *vertexArrays, const PrimitiveList &primitives,
528*35238bceSAndroid Build Coastguard Worker                           DrawUtilCallback *callback)
529*35238bceSAndroid Build Coastguard Worker {
530*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = context.getFunctions();
531*35238bceSAndroid Build Coastguard Worker     std::vector<VertexArrayBinding> bindingsWithLocations;
532*35238bceSAndroid Build Coastguard Worker 
533*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
534*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isProgramActive(context, program));
535*35238bceSAndroid Build Coastguard Worker 
536*35238bceSAndroid Build Coastguard Worker     // Lower bindings to locations.
537*35238bceSAndroid Build Coastguard Worker     namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays + numVertexArrays,
538*35238bceSAndroid Build Coastguard Worker                                     std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));
539*35238bceSAndroid Build Coastguard Worker 
540*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));
541*35238bceSAndroid Build Coastguard Worker 
542*35238bceSAndroid Build Coastguard Worker     // Set VA state.
543*35238bceSAndroid Build Coastguard Worker     for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin();
544*35238bceSAndroid Build Coastguard Worker          vaIter != bindingsWithLocations.end(); ++vaIter)
545*35238bceSAndroid Build Coastguard Worker         setVertexAttribPointer(gl, getUserPointerDescriptor(*vaIter));
546*35238bceSAndroid Build Coastguard Worker 
547*35238bceSAndroid Build Coastguard Worker     if (callback)
548*35238bceSAndroid Build Coastguard Worker         callback->beforeDrawCall();
549*35238bceSAndroid Build Coastguard Worker 
550*35238bceSAndroid Build Coastguard Worker     if (primitives.indices)
551*35238bceSAndroid Build Coastguard Worker         drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, primitives.indices);
552*35238bceSAndroid Build Coastguard Worker     else
553*35238bceSAndroid Build Coastguard Worker         drawNonIndexed(gl, primitives.type, primitives.numElements);
554*35238bceSAndroid Build Coastguard Worker 
555*35238bceSAndroid Build Coastguard Worker     if (callback)
556*35238bceSAndroid Build Coastguard Worker         callback->afterDrawCall();
557*35238bceSAndroid Build Coastguard Worker 
558*35238bceSAndroid Build Coastguard Worker     // Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
559*35238bceSAndroid Build Coastguard Worker     disableVertexArrays(gl, bindingsWithLocations);
560*35238bceSAndroid Build Coastguard Worker }
561*35238bceSAndroid Build Coastguard Worker 
drawFromBuffers(const RenderContext & context,uint32_t program,int numVertexArrays,const VertexArrayBinding * vertexArrays,const PrimitiveList & primitives,DrawUtilCallback * callback)562*35238bceSAndroid Build Coastguard Worker void drawFromBuffers(const RenderContext &context, uint32_t program, int numVertexArrays,
563*35238bceSAndroid Build Coastguard Worker                      const VertexArrayBinding *vertexArrays, const PrimitiveList &primitives,
564*35238bceSAndroid Build Coastguard Worker                      DrawUtilCallback *callback)
565*35238bceSAndroid Build Coastguard Worker {
566*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = context.getFunctions();
567*35238bceSAndroid Build Coastguard Worker     std::vector<VertexArrayBinding> bindingsWithLocations;
568*35238bceSAndroid Build Coastguard Worker 
569*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
570*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isProgramActive(context, program));
571*35238bceSAndroid Build Coastguard Worker 
572*35238bceSAndroid Build Coastguard Worker     // Lower bindings to locations.
573*35238bceSAndroid Build Coastguard Worker     namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays + numVertexArrays,
574*35238bceSAndroid Build Coastguard Worker                                     std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));
577*35238bceSAndroid Build Coastguard Worker 
578*35238bceSAndroid Build Coastguard Worker     // Create buffers for duration of draw call.
579*35238bceSAndroid Build Coastguard Worker     {
580*35238bceSAndroid Build Coastguard Worker         VertexBuffer vertexBuffer(context, (int)bindingsWithLocations.size(),
581*35238bceSAndroid Build Coastguard Worker                                   (bindingsWithLocations.empty()) ? (DE_NULL) : (&bindingsWithLocations[0]));
582*35238bceSAndroid Build Coastguard Worker 
583*35238bceSAndroid Build Coastguard Worker         // Set state.
584*35238bceSAndroid Build Coastguard Worker         setVertexBufferAttributes(gl, vertexBuffer.getDescriptor());
585*35238bceSAndroid Build Coastguard Worker 
586*35238bceSAndroid Build Coastguard Worker         if (primitives.indices)
587*35238bceSAndroid Build Coastguard Worker         {
588*35238bceSAndroid Build Coastguard Worker             IndexBuffer indexBuffer(context, primitives.indexType, primitives.numElements, primitives.indices);
589*35238bceSAndroid Build Coastguard Worker 
590*35238bceSAndroid Build Coastguard Worker             gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer);
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker             if (callback)
593*35238bceSAndroid Build Coastguard Worker                 callback->beforeDrawCall();
594*35238bceSAndroid Build Coastguard Worker 
595*35238bceSAndroid Build Coastguard Worker             drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, 0);
596*35238bceSAndroid Build Coastguard Worker 
597*35238bceSAndroid Build Coastguard Worker             if (callback)
598*35238bceSAndroid Build Coastguard Worker                 callback->afterDrawCall();
599*35238bceSAndroid Build Coastguard Worker 
600*35238bceSAndroid Build Coastguard Worker             gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
601*35238bceSAndroid Build Coastguard Worker         }
602*35238bceSAndroid Build Coastguard Worker         else
603*35238bceSAndroid Build Coastguard Worker         {
604*35238bceSAndroid Build Coastguard Worker             if (callback)
605*35238bceSAndroid Build Coastguard Worker                 callback->beforeDrawCall();
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker             drawNonIndexed(gl, primitives.type, primitives.numElements);
608*35238bceSAndroid Build Coastguard Worker 
609*35238bceSAndroid Build Coastguard Worker             if (callback)
610*35238bceSAndroid Build Coastguard Worker                 callback->afterDrawCall();
611*35238bceSAndroid Build Coastguard Worker         }
612*35238bceSAndroid Build Coastguard Worker     }
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     // Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
615*35238bceSAndroid Build Coastguard Worker     for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin();
616*35238bceSAndroid Build Coastguard Worker          vaIter != bindingsWithLocations.end(); ++vaIter)
617*35238bceSAndroid Build Coastguard Worker         gl.disableVertexAttribArray(vaIter->binding.location);
618*35238bceSAndroid Build Coastguard Worker }
619*35238bceSAndroid Build Coastguard Worker 
drawFromVAOBuffers(const RenderContext & context,uint32_t program,int numVertexArrays,const VertexArrayBinding * vertexArrays,const PrimitiveList & primitives,DrawUtilCallback * callback)620*35238bceSAndroid Build Coastguard Worker void drawFromVAOBuffers(const RenderContext &context, uint32_t program, int numVertexArrays,
621*35238bceSAndroid Build Coastguard Worker                         const VertexArrayBinding *vertexArrays, const PrimitiveList &primitives,
622*35238bceSAndroid Build Coastguard Worker                         DrawUtilCallback *callback)
623*35238bceSAndroid Build Coastguard Worker {
624*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = context.getFunctions();
625*35238bceSAndroid Build Coastguard Worker     VertexArray vao(context);
626*35238bceSAndroid Build Coastguard Worker 
627*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(*vao);
628*35238bceSAndroid Build Coastguard Worker     drawFromBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
629*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(0);
630*35238bceSAndroid Build Coastguard Worker }
631*35238bceSAndroid Build Coastguard Worker 
draw(const RenderContext & context,uint32_t program,int numVertexArrays,const VertexArrayBinding * vertexArrays,const PrimitiveList & primitives,DrawUtilCallback * callback)632*35238bceSAndroid Build Coastguard Worker void draw(const RenderContext &context, uint32_t program, int numVertexArrays, const VertexArrayBinding *vertexArrays,
633*35238bceSAndroid Build Coastguard Worker           const PrimitiveList &primitives, DrawUtilCallback *callback)
634*35238bceSAndroid Build Coastguard Worker {
635*35238bceSAndroid Build Coastguard Worker     const glu::ContextType ctxType = context.getType();
636*35238bceSAndroid Build Coastguard Worker 
637*35238bceSAndroid Build Coastguard Worker     if (isContextTypeGLCore(ctxType) || contextSupports(ctxType, ApiType::es(3, 1)))
638*35238bceSAndroid Build Coastguard Worker         drawFromVAOBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
639*35238bceSAndroid Build Coastguard Worker     else
640*35238bceSAndroid Build Coastguard Worker     {
641*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(isContextTypeES(ctxType));
642*35238bceSAndroid Build Coastguard Worker         drawFromUserPointers(context, program, numVertexArrays, vertexArrays, primitives, callback);
643*35238bceSAndroid Build Coastguard Worker     }
644*35238bceSAndroid Build Coastguard Worker }
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker } // namespace glu
647