diff --git a/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp index ffdff0977..5b6c85bfc 100644 --- a/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp +++ b/Sources/OvRendering/src/OvRendering/HAL/OpenGL/GLBackend.cpp @@ -4,7 +4,11 @@ * @licence: MIT */ +#include +#include +#include #include +#include #include @@ -73,74 +77,134 @@ namespace } } - bool GetBool(uint32_t p_parameter) - { - GLboolean result; - glGetBooleanv(p_parameter, &result); - return static_cast(result); - } + /** + * Constrains the OpenGL state query helpers to the value types OpenGL can return. + */ + template + concept SupportedGetType = + std::same_as || + std::same_as || + std::same_as || + std::same_as || + std::same_as; - bool GetBool(uint32_t p_parameter, uint32_t p_index) - { - GLboolean result; - glGetBooleani_v(p_parameter, p_index, &result); - return static_cast(result); - } + /** + * Upper bound for the scratch buffer used when the requested type does not match + * the OpenGL native type (bool, and int64_t on some platforms). No such query + * returns more than four values (GL_COLOR_WRITEMASK returns four). + */ + constexpr size_t kMaximumConvertedValueCount = 4; - int GetInt(uint32_t p_parameter) + /** + * Reads one or more values for an OpenGL parameter into a caller-provided buffer. + * @param p_parameter The OpenGL parameter to query. + * @param p_output The buffer the values are written into. + */ + template + void GetValue(uint32_t p_parameter, std::span p_output) { - GLint result[4]; - glGetIntegerv(p_parameter, result); - return static_cast(result[0]); - } + if constexpr (std::same_as) + { + std::array nativeResult{}; + glGetBooleanv(p_parameter, nativeResult.data()); - int GetInt(uint32_t p_parameter, uint32_t p_index) - { - GLint result[4]; - glGetIntegeri_v(p_parameter, p_index, result); - return static_cast(result[0]); - } + for (size_t i = 0; i < p_output.size() && i < nativeResult.size(); ++i) + { + p_output[i] = static_cast(nativeResult[i]); + } + } + else if constexpr (std::same_as) + { + std::array nativeResult{}; + glGetInteger64v(p_parameter, nativeResult.data()); - float GetFloat(uint32_t p_parameter) - { - GLfloat result; - glGetFloatv(p_parameter, &result); - return static_cast(result); + for (size_t i = 0; i < p_output.size() && i < nativeResult.size(); ++i) + { + p_output[i] = static_cast(nativeResult[i]); + } + } + else if constexpr (std::same_as) + { + glGetIntegerv(p_parameter, p_output.data()); + } + else if constexpr (std::same_as) + { + glGetFloatv(p_parameter, p_output.data()); + } + else if constexpr (std::same_as) + { + glGetDoublev(p_parameter, p_output.data()); + } } - float GetFloat(uint32_t p_parameter, uint32_t p_index) + /** + * Reads a single value for an OpenGL parameter. + * Use BufferSize to size the read buffer for parameters that return more than one value. + * @param p_parameter The OpenGL parameter to query. + */ + template + T GetValue(uint32_t p_parameter) { - GLfloat result; - glGetFloati_v(p_parameter, p_index, &result); - return static_cast(result); + std::array result{}; + GetValue(p_parameter, std::span(result)); + return result[0]; } - double GetDouble(uint32_t p_parameter) + /** + * Reads one or more values for an indexed OpenGL parameter into a caller-provided buffer. + * @param p_parameter The OpenGL parameter to query. + * @param p_output The buffer the values are written into. + * @param p_index The index of the element to query. + */ + template + void GetValueIndexed(uint32_t p_parameter, std::span p_output, uint32_t p_index) { - GLdouble result; - glGetDoublev(p_parameter, &result); - return static_cast(result); - } + if constexpr (std::same_as) + { + std::array nativeResult{}; + glGetBooleani_v(p_parameter, p_index, nativeResult.data()); - double GetDouble(uint32_t p_parameter, uint32_t p_index) - { - GLdouble result; - glGetDoublei_v(p_parameter, p_index, &result); - return static_cast(result); - } + for (size_t i = 0; i < p_output.size() && i < nativeResult.size(); ++i) + { + p_output[i] = static_cast(nativeResult[i]); + } + } + else if constexpr (std::same_as) + { + std::array nativeResult{}; + glGetInteger64i_v(p_parameter, p_index, nativeResult.data()); - int64_t GetInt64(uint32_t p_parameter) - { - GLint64 result; - glGetInteger64v(p_parameter, &result); - return static_cast(result); + for (size_t i = 0; i < p_output.size() && i < nativeResult.size(); ++i) + { + p_output[i] = static_cast(nativeResult[i]); + } + } + else if constexpr (std::same_as) + { + glGetIntegeri_v(p_parameter, p_index, p_output.data()); + } + else if constexpr (std::same_as) + { + glGetFloati_v(p_parameter, p_index, p_output.data()); + } + else if constexpr (std::same_as) + { + glGetDoublei_v(p_parameter, p_index, p_output.data()); + } } - int64_t GetInt64(uint32_t p_parameter, uint32_t p_index) + /** + * Reads a single value for an indexed OpenGL parameter. + * Use BufferSize to size the read buffer for parameters that return more than one value. + * @param p_parameter The OpenGL parameter to query. + * @param p_index The index of the element to query. + */ + template + T GetValueIndexed(uint32_t p_parameter, uint32_t p_index) { - GLint64 result; - glGetInteger64i_v(p_parameter, p_index, &result); - return static_cast(result); + std::array result{}; + GetValueIndexed(p_parameter, std::span(result), p_index); + return result[0]; } std::string GetString(uint32_t p_parameter) @@ -166,50 +230,50 @@ namespace OvRendering::Data::PipelineState pso; // Rasterization - pso.rasterizationMode = static_cast(GetInt(GL_POLYGON_MODE)); - pso.lineWidthPow2 = OvRendering::Utils::Conversions::FloatToPow2(GetFloat(GL_LINE_WIDTH)); + pso.rasterizationMode = static_cast(GetValue(GL_POLYGON_MODE)); + pso.lineWidthPow2 = OvRendering::Utils::Conversions::FloatToPow2(GetValue(GL_LINE_WIDTH)); // Color write mask - GLboolean colorWriteMask[4]; - glGetBooleanv(GL_COLOR_WRITEMASK, colorWriteMask); + std::array colorWriteMask{}; + GetValue(GL_COLOR_WRITEMASK, colorWriteMask); pso.colorWriting.r = colorWriteMask[0]; pso.colorWriting.g = colorWriteMask[1]; pso.colorWriting.b = colorWriteMask[2]; pso.colorWriting.a = colorWriteMask[3]; // Capability - pso.depthWriting = GetBool(GL_DEPTH_WRITEMASK); - pso.blending = GetBool(GL_BLEND); - pso.culling = GetBool(GL_CULL_FACE); - pso.dither = GetBool(GL_DITHER); - pso.polygonOffsetFill = GetBool(GL_POLYGON_OFFSET_FILL); - pso.sampleAlphaToCoverage = GetBool(GL_SAMPLE_ALPHA_TO_COVERAGE); - pso.depthTest = GetBool(GL_DEPTH_TEST); - pso.scissorTest = GetBool(GL_SCISSOR_TEST); - pso.stencilTest = GetBool(GL_STENCIL_TEST); - pso.multisample = GetBool(GL_MULTISAMPLE); + pso.depthWriting = GetValue(GL_DEPTH_WRITEMASK); + pso.blending = GetValue(GL_BLEND); + pso.culling = GetValue(GL_CULL_FACE); + pso.dither = GetValue(GL_DITHER); + pso.polygonOffsetFill = GetValue(GL_POLYGON_OFFSET_FILL); + pso.sampleAlphaToCoverage = GetValue(GL_SAMPLE_ALPHA_TO_COVERAGE); + pso.depthTest = GetValue(GL_DEPTH_TEST); + pso.scissorTest = GetValue(GL_SCISSOR_TEST); + pso.stencilTest = GetValue(GL_STENCIL_TEST); + pso.multisample = GetValue(GL_MULTISAMPLE); // Stencil - pso.stencilFuncOp = ValueToEnum(static_cast(GetInt(GL_STENCIL_FUNC))); - pso.stencilFuncRef = GetInt(GL_STENCIL_REF); - pso.stencilFuncMask = static_cast(GetInt(GL_STENCIL_VALUE_MASK)); + pso.stencilFuncOp = ValueToEnum(static_cast(GetValue(GL_STENCIL_FUNC))); + pso.stencilFuncRef = GetValue(GL_STENCIL_REF); + pso.stencilFuncMask = static_cast(GetValue(GL_STENCIL_VALUE_MASK)); - pso.stencilWriteMask = static_cast(GetInt(GL_STENCIL_WRITEMASK)); + pso.stencilWriteMask = static_cast(GetValue(GL_STENCIL_WRITEMASK)); - pso.stencilOpFail = ValueToEnum(static_cast(GetInt(GL_STENCIL_FAIL))); - pso.depthOpFail = ValueToEnum(static_cast(GetInt(GL_STENCIL_PASS_DEPTH_FAIL))); - pso.bothOpFail = ValueToEnum(static_cast(GetInt(GL_STENCIL_PASS_DEPTH_PASS))); + pso.stencilOpFail = ValueToEnum(static_cast(GetValue(GL_STENCIL_FAIL))); + pso.depthOpFail = ValueToEnum(static_cast(GetValue(GL_STENCIL_PASS_DEPTH_FAIL))); + pso.bothOpFail = ValueToEnum(static_cast(GetValue(GL_STENCIL_PASS_DEPTH_PASS))); // Depth - pso.depthFunc = ValueToEnum(static_cast(GetInt(GL_DEPTH_FUNC))); + pso.depthFunc = ValueToEnum(static_cast(GetValue(GL_DEPTH_FUNC))); // Culling - pso.cullFace = ValueToEnum(static_cast(GetInt(GL_CULL_FACE_MODE))); + pso.cullFace = ValueToEnum(static_cast(GetValue(GL_CULL_FACE_MODE))); // Blending - pso.blendingSrcFactor = ValueToEnum(static_cast(GetInt(GL_BLEND_SRC))); - pso.blendingDestFactor = ValueToEnum(static_cast(GetInt(GL_BLEND_DST))); - pso.blendingEquation = ValueToEnum(static_cast(GetInt(GL_BLEND_EQUATION))); + pso.blendingSrcFactor = ValueToEnum(static_cast(GetValue(GL_BLEND_SRC))); + pso.blendingDestFactor = ValueToEnum(static_cast(GetValue(GL_BLEND_DST))); + pso.blendingEquation = ValueToEnum(static_cast(GetValue(GL_BLEND_EQUATION))); return pso; }