177 lines
5.4 KiB
C++
177 lines
5.4 KiB
C++
#include <mbgl/gl/vertex_attribute_gl.hpp>
|
|
|
|
#include <mbgl/gl/defines.hpp>
|
|
#include <mbgl/platform/gl_functions.hpp>
|
|
#include <mbgl/shaders/gl/shader_program_gl.hpp>
|
|
|
|
#include <cstring>
|
|
#include <sstream>
|
|
#include <mbgl/util/logging.hpp>
|
|
|
|
namespace mbgl {
|
|
namespace gl {
|
|
|
|
class VertexAttributeArrayGL;
|
|
|
|
using namespace platform;
|
|
|
|
int VertexAttributeGL::getSize(GLenum glType) {
|
|
switch (glType) {
|
|
case GL_FLOAT:
|
|
return 4 * 1;
|
|
case GL_FLOAT_VEC2:
|
|
return 4 * 2;
|
|
case GL_FLOAT_VEC3:
|
|
return 4 * 3;
|
|
case GL_FLOAT_VEC4:
|
|
return 4 * 4;
|
|
case GL_FLOAT_MAT2:
|
|
return 4 * 4;
|
|
case GL_INT:
|
|
return 4 * 1;
|
|
case GL_UNSIGNED_INT:
|
|
return 4 * 1;
|
|
case GL_INT_VEC2:
|
|
return 4 * 2;
|
|
case GL_INT_VEC3:
|
|
return 4 * 3;
|
|
case GL_INT_VEC4:
|
|
return 4 * 4;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int VertexAttributeGL::getStride(GLenum glType) {
|
|
switch (glType) {
|
|
case GL_FLOAT:
|
|
return 4 * 1;
|
|
case GL_FLOAT_VEC2:
|
|
return 4 * 2;
|
|
case GL_FLOAT_VEC3:
|
|
return 4 * 4;
|
|
case GL_FLOAT_VEC4:
|
|
return 4 * 4;
|
|
case GL_FLOAT_MAT2:
|
|
return 4 * 4;
|
|
case GL_INT:
|
|
return 4 * 1;
|
|
case GL_UNSIGNED_INT:
|
|
return 4 * 1;
|
|
case GL_INT_VEC2:
|
|
return 4 * 2;
|
|
case GL_INT_VEC3:
|
|
return 4 * 4;
|
|
case GL_INT_VEC4:
|
|
return 4 * 4;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Copy the transformed type into the buffer, returning true if it works.
|
|
template <typename T, typename R>
|
|
static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer, std::function<R(T)> f) {
|
|
if (auto* p = std::get_if<T>(&element)) {
|
|
*reinterpret_cast<R*>(buffer) = f(*p);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Copy the value into the buffer with a simple cast, returning true if it works.
|
|
template <typename T, typename R>
|
|
static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer) {
|
|
return get<T, R>(element, buffer, [](T x) -> R { return static_cast<R>(x); });
|
|
}
|
|
|
|
// Copy a particular type from the variant into the specified buffer, returning true if it works.
|
|
template <typename T>
|
|
static bool get(const gfx::VertexAttribute::ElementType& element, uint8_t* buffer) {
|
|
return get<T, T>(element, buffer, [](T x) -> T { return x; });
|
|
}
|
|
|
|
template <typename T, typename R>
|
|
R cast(T x) {
|
|
return static_cast<R>(x);
|
|
}
|
|
|
|
// Copy the variant value into the buffer, converting the type if necessary and possible
|
|
bool VertexAttributeGL::get(const gfx::VertexAttribute::ElementType& element, GLenum glType, uint8_t* buffer) {
|
|
// TODO: do we need to handle unsigned inputs?
|
|
switch (glType) {
|
|
case GL_FLOAT:
|
|
return gl::get<float>(element, buffer) || gl::get<float, std::int32_t>(element, buffer);
|
|
case GL_FLOAT_VEC2:
|
|
return gl::get<float2>(element, buffer) || gl::get<int2, float2>(element, buffer, [](int2 x) {
|
|
return float2{(float)x[0], (float)x[1]};
|
|
});
|
|
case GL_FLOAT_VEC3:
|
|
return gl::get<float3>(element, buffer);
|
|
case GL_FLOAT_VEC4:
|
|
case GL_FLOAT_MAT2:
|
|
return gl::get<float4>(element, buffer) ||
|
|
gl::get<int4, float4>(element, buffer, [](int4 x) {
|
|
return float4{(float)x[0], (float)x[1], (float)x[2], (float)x[3]};
|
|
});
|
|
case GL_INT:
|
|
return gl::get<std::int32_t>(element, buffer) || gl::get<float, std::int32_t>(element, buffer);
|
|
case GL_UNSIGNED_INT:
|
|
return gl::get<std::int32_t, std::uint32_t>(element, buffer) ||
|
|
gl::get<float, std::uint32_t>(element, buffer);
|
|
case GL_INT_VEC2:
|
|
return gl::get<int2>(element, buffer) || gl::get<float2, int2>(element, buffer, [](float2 x) {
|
|
return int2{(std::int32_t)x[0], (std::int32_t)x[1]};
|
|
});
|
|
case GL_UNSIGNED_INT_VEC2:
|
|
return false; // TODO
|
|
case GL_INT_VEC3:
|
|
return gl::get<int3>(element, buffer);
|
|
case GL_UNSIGNED_INT_VEC3:
|
|
return false; // TODO
|
|
case GL_INT_VEC4:
|
|
return gl::get<int4>(element, buffer);
|
|
case GL_UNSIGNED_INT_VEC4:
|
|
return false; // TODO
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void VertexAttributeGL::setGLType(platform::GLenum value) {
|
|
glType = value;
|
|
stride = getStride(glType);
|
|
}
|
|
|
|
std::size_t VertexAttributeGL::getStride() const {
|
|
return getStride(getGLType());
|
|
}
|
|
|
|
const std::vector<std::uint8_t>& VertexAttributeGL::getRaw(platform::GLenum type) const {
|
|
if (dirty || rawType != type) {
|
|
const auto count = getCount();
|
|
// const auto size_ = getSize(type);
|
|
const auto stride_ = getStride(type);
|
|
|
|
rawData.resize(stride_ * count);
|
|
std::fill(rawData.begin(), rawData.end(), 0);
|
|
|
|
if (!rawData.empty()) {
|
|
std::uint8_t* outPtr = rawData.data();
|
|
for (std::size_t i = 0; i < count; ++i) {
|
|
if (!get(items[i], type, outPtr)) {
|
|
// throw?
|
|
}
|
|
outPtr += stride_;
|
|
}
|
|
}
|
|
|
|
dirty = false;
|
|
rawType = type;
|
|
}
|
|
return rawData;
|
|
}
|
|
|
|
} // namespace gl
|
|
} // namespace mbgl
|