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