From afc295cf9366959d85b7e38b9c69d1cc2bbdbf48 Mon Sep 17 00:00:00 2001 From: assiduous Date: Wed, 19 Feb 2020 18:20:32 -0800 Subject: Reworked GL type conversions and added tests --- .../include/GLTypeConversions.hpp | 264 ++++++++++++-------- .../GraphicsEngineOpenGL/src/GLTypeConversions.cpp | 127 ---------- .../src/GL/GLTypeConversionsTest.cpp | 272 +++++++++++++++++++++ 3 files changed, 438 insertions(+), 225 deletions(-) create mode 100644 Tests/DiligentCoreAPITest/src/GL/GLTypeConversionsTest.cpp diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp index fa8e8daa..332fc304 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp @@ -30,75 +30,43 @@ namespace Diligent { -// clang-format off -static const GLenum PrimTopologyToGLTopologyMap[] = -{ - 0, //PRIMITIVE_TOPOLOGY_UNDEFINED = 0 - GL_TRIANGLES, //PRIMITIVE_TOPOLOGY_TRIANGLE_LIST - GL_TRIANGLE_STRIP, //PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, - GL_POINTS, //PRIMITIVE_TOPOLOGY_POINT_LIST - GL_LINES, //PRIMITIVE_TOPOLOGY_LINE_LIST - GL_LINE_STRIP //PRIMITIVE_TOPOLOGY_LINE_STRIP -}; -// clang-format on - inline GLenum PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY PrimTopology) { - VERIFY_EXPR(PrimTopology < _countof(PrimTopologyToGLTopologyMap)); - auto GLTopology = PrimTopologyToGLTopologyMap[PrimTopology]; -#ifdef _DEBUG - switch (PrimTopology) + // clang-format off + static constexpr GLenum PrimTopologyToGLTopologyMap[] = { - // clang-format off - case PRIMITIVE_TOPOLOGY_UNDEFINED: VERIFY_EXPR(GLTopology == 0); break; - case PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: VERIFY_EXPR(GLTopology == GL_TRIANGLES); break; - case PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: VERIFY_EXPR(GLTopology == GL_TRIANGLE_STRIP); break; - case PRIMITIVE_TOPOLOGY_POINT_LIST: VERIFY_EXPR(GLTopology == GL_POINTS); break; - case PRIMITIVE_TOPOLOGY_LINE_LIST: VERIFY_EXPR(GLTopology == GL_LINES); break; - case PRIMITIVE_TOPOLOGY_LINE_STRIP: VERIFY_EXPR(GLTopology == GL_LINE_STRIP); break; - default: UNEXPECTED("Unexpected primitive topology"); - // clang-format on - } -#endif - return GLTopology; -} + 0, // PRIMITIVE_TOPOLOGY_UNDEFINED = 0 + GL_TRIANGLES, // PRIMITIVE_TOPOLOGY_TRIANGLE_LIST + GL_TRIANGLE_STRIP, // PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, + GL_POINTS, // PRIMITIVE_TOPOLOGY_POINT_LIST + GL_LINES, // PRIMITIVE_TOPOLOGY_LINE_LIST + GL_LINE_STRIP // PRIMITIVE_TOPOLOGY_LINE_STRIP + }; + // clang-format on -// clang-format off -static const GLenum TypeToGLTypeMap[] = -{ - 0, //VT_UNDEFINED = 0 - GL_BYTE, //VT_INT8 - GL_SHORT, //VT_INT16 - GL_INT, //VT_INT32 - GL_UNSIGNED_BYTE, //VT_UINT8 - GL_UNSIGNED_SHORT, //VT_UINT16 - GL_UNSIGNED_INT, //VT_UINT32 - GL_HALF_FLOAT, //VT_FLOAT16 - GL_FLOAT //VT_FLOAT32 -}; -// clang-format on + VERIFY_EXPR(PrimTopology < _countof(PrimTopologyToGLTopologyMap)); + return PrimTopologyToGLTopologyMap[PrimTopology]; +} inline GLenum TypeToGLType(VALUE_TYPE Value) { - VERIFY_EXPR(Value < _countof(TypeToGLTypeMap)); - auto GLType = TypeToGLTypeMap[Value]; -#ifdef _DEBUG - switch (Value) + // clang-format off + static constexpr GLenum TypeToGLTypeMap[] = { - // clang-format off - case VT_INT8: VERIFY_EXPR(GLType == GL_BYTE); break; - case VT_INT16: VERIFY_EXPR(GLType == GL_SHORT); break; - case VT_INT32: VERIFY_EXPR(GLType == GL_INT); break; - case VT_UINT8: VERIFY_EXPR(GLType == GL_UNSIGNED_BYTE); break; - case VT_UINT16: VERIFY_EXPR(GLType == GL_UNSIGNED_SHORT); break; - case VT_UINT32: VERIFY_EXPR(GLType == GL_UNSIGNED_INT); break; - case VT_FLOAT16: VERIFY_EXPR(GLType == GL_HALF_FLOAT); break; - case VT_FLOAT32: VERIFY_EXPR(GLType == GL_FLOAT); break; - default: UNEXPECTED("Unexpected value type"); - // clang-format on - } -#endif - return GLType; + 0, // VT_UNDEFINED = 0 + GL_BYTE, // VT_INT8 + GL_SHORT, // VT_INT16 + GL_INT, // VT_INT32 + GL_UNSIGNED_BYTE, // VT_UINT8 + GL_UNSIGNED_SHORT, // VT_UINT16 + GL_UNSIGNED_INT, // VT_UINT32 + GL_HALF_FLOAT, // VT_FLOAT16 + GL_FLOAT // VT_FLOAT32 + }; + // clang-format on + + VERIFY_EXPR(Value < _countof(TypeToGLTypeMap)); + return TypeToGLTypeMap[Value]; } inline GLenum UsageToGLUsage(const BufferDesc& Desc) @@ -182,48 +150,63 @@ inline void FilterTypeToGLFilterType(FILTER_TYPE Filter, GLenum& GLFilter, Bool& } } -GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags = 0); -TEXTURE_FORMAT GLInternalTexFormatToTexFormat(GLenum GlFormat); -GLenum CorrectGLTexFormat(GLenum GLTexFormat, Uint32 BindFlags); +inline GLenum CorrectGLTexFormat(GLenum GLTexFormat, Uint32 BindFlags) +{ + if (BindFlags & BIND_DEPTH_STENCIL) + { + if (GLTexFormat == GL_R32F) + GLTexFormat = GL_DEPTH_COMPONENT32F; + if (GLTexFormat == GL_R16) + GLTexFormat = GL_DEPTH_COMPONENT16; + } + return GLTexFormat; +} + inline GLenum TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_MODE Mode) { - switch (Mode) + // clang-format off + static constexpr GLenum TexAddressModeToGLAddressModeMap[] = { - // clang-format off - case TEXTURE_ADDRESS_UNKNOWN: UNEXPECTED( "Texture address mode is not specified" ); return GL_CLAMP_TO_EDGE; - case TEXTURE_ADDRESS_WRAP: return GL_REPEAT; - case TEXTURE_ADDRESS_MIRROR: return GL_MIRRORED_REPEAT; - case TEXTURE_ADDRESS_CLAMP: return GL_CLAMP_TO_EDGE; - case TEXTURE_ADDRESS_BORDER: return GL_CLAMP_TO_BORDER; - case TEXTURE_ADDRESS_MIRROR_ONCE: return GL_MIRROR_CLAMP_TO_EDGE; // only available with OpenGL 4.4 - // This mode seems to be different from D3D11_TEXTURE_ADDRESS_MIRROR_ONCE - // The texture coord is clamped to the [-1, 1] range, but mirrors the - // negative direction with the positive. Basically, it acts as - // GL_CLAMP_TO_EDGE except that it takes the absolute value of the texture - // coordinates before clamping. - default: UNEXPECTED( "Unknown texture address mode" ); return GL_CLAMP_TO_EDGE; - // clang-format on - } + 0, // TEXTURE_ADDRESS_UNKNOWN = 0 + GL_REPEAT, // TEXTURE_ADDRESS_WRAP + GL_MIRRORED_REPEAT, // TEXTURE_ADDRESS_MIRROR + GL_CLAMP_TO_EDGE, // TEXTURE_ADDRESS_CLAMP + GL_CLAMP_TO_BORDER, // TEXTURE_ADDRESS_BORDER + + // Only available in OpenGL 4.4+ + // This mode seems to be different from D3D11_TEXTURE_ADDRESS_MIRROR_ONCE + // The texture coord is clamped to the [-1, 1] range, but mirrors the + // negative direction with the positive. Basically, it acts as + // GL_CLAMP_TO_EDGE except that it takes the absolute value of the texture + // coordinates before clamping. + GL_MIRROR_CLAMP_TO_EDGE // TEXTURE_ADDRESS_MIRROR_ONCE + }; + // clang-format on + + VERIFY_EXPR(Mode < _countof(TexAddressModeToGLAddressModeMap)); + return TexAddressModeToGLAddressModeMap[Mode]; } inline GLenum CompareFuncToGLCompareFunc(COMPARISON_FUNCTION Func) { - switch (Func) + // clang-format off + static constexpr GLenum CompareFuncToGLCompareFuncMap[] = { - // clang-format off - case COMPARISON_FUNC_UNKNOWN: UNEXPECTED( "Comparison function is not specified" ); return GL_ALWAYS; - case COMPARISON_FUNC_NEVER: return GL_NEVER; - case COMPARISON_FUNC_LESS: return GL_LESS; - case COMPARISON_FUNC_EQUAL: return GL_EQUAL; - case COMPARISON_FUNC_LESS_EQUAL: return GL_LEQUAL; - case COMPARISON_FUNC_GREATER: return GL_GREATER; - case COMPARISON_FUNC_NOT_EQUAL: return GL_NOTEQUAL; - case COMPARISON_FUNC_GREATER_EQUAL: return GL_GEQUAL; - case COMPARISON_FUNC_ALWAYS: return GL_ALWAYS; - default: UNEXPECTED( "Unknown comparison func" ); return GL_ALWAYS; - // clang-format on - } + 0, // COMPARISON_FUNC_UNKNOWN = 0 + GL_NEVER, // COMPARISON_FUNC_NEVER + GL_LESS, // COMPARISON_FUNC_LESS + GL_EQUAL, // COMPARISON_FUNC_EQUAL + GL_LEQUAL, // COMPARISON_FUNC_LESS_EQUAL + GL_GREATER, // COMPARISON_FUNC_GREATER + GL_NOTEQUAL, // COMPARISON_FUNC_NOT_EQUAL + GL_GEQUAL, // COMPARISON_FUNC_GREATER_EQUAL + GL_ALWAYS // COMPARISON_FUNC_ALWAYS + }; + // clang-format on + + VERIFY_EXPR(Func < _countof(CompareFuncToGLCompareFuncMap)); + return CompareFuncToGLCompareFuncMap[Func]; } struct NativePixelAttribs @@ -301,11 +284,96 @@ inline Uint32 GetPixelTypeSize(GLenum Type) } } +inline GLenum AccessFlags2GLAccess(UAV_ACCESS_FLAG UAVAccessFlags) +{ + // clang-format off + static constexpr GLenum AccessFlags2GLAccessMap[] = + { + 0, // UAV_ACCESS_UNSPECIFIED == 0 + GL_READ_ONLY, // UAV_ACCESS_FLAG_READ + GL_WRITE_ONLY, // UAV_ACCESS_FLAG_WRITE + GL_READ_WRITE // UAV_ACCESS_FLAG_READ_WRITE + }; + // clang-format on + + VERIFY_EXPR(UAVAccessFlags < _countof(AccessFlags2GLAccessMap)); + return AccessFlags2GLAccessMap[UAVAccessFlags]; +} + +inline GLenum StencilOp2GlStencilOp(STENCIL_OP StencilOp) +{ + // clang-format off + static constexpr GLenum StencilOp2GlStencilOpMap[] = + { + 0, // STENCIL_OP_UNDEFINED == 0 + GL_KEEP, // STENCIL_OP_KEEP + GL_ZERO, // STENCIL_OP_ZERO + GL_REPLACE, // STENCIL_OP_REPLACE + GL_INCR, // STENCIL_OP_INCR_SAT + GL_DECR, // STENCIL_OP_DECR_SAT + GL_INVERT, // STENCIL_OP_INVERT + GL_INCR_WRAP, // STENCIL_OP_INCR_WRAP + GL_DECR_WRAP, // STENCIL_OP_DECR_WRAP + }; + // clang-format on + + VERIFY_EXPR(StencilOp < _countof(StencilOp2GlStencilOpMap)); + return StencilOp2GlStencilOpMap[StencilOp]; +} + +inline GLenum BlendFactor2GLBlend(BLEND_FACTOR bf) +{ + // clang-format off + static constexpr GLenum BlendFactor2GLBlendMap[] = + { + 0, // BLEND_FACTOR_UNDEFINED == 0 + GL_ZERO, // BLEND_FACTOR_ZERO + GL_ONE, // BLEND_FACTOR_ONE + GL_SRC_COLOR, // BLEND_FACTOR_SRC_COLOR + GL_ONE_MINUS_SRC_COLOR, // BLEND_FACTOR_INV_SRC_COLOR + GL_SRC_ALPHA, // BLEND_FACTOR_SRC_ALPHA + GL_ONE_MINUS_SRC_ALPHA, // BLEND_FACTOR_INV_SRC_ALPHA + GL_DST_ALPHA, // BLEND_FACTOR_DEST_ALPHA + GL_ONE_MINUS_DST_ALPHA, // BLEND_FACTOR_INV_DEST_ALPHA + GL_DST_COLOR, // BLEND_FACTOR_DEST_COLOR + GL_ONE_MINUS_DST_COLOR, // BLEND_FACTOR_INV_DEST_COLOR + GL_SRC_ALPHA_SATURATE, // BLEND_FACTOR_SRC_ALPHA_SAT + GL_CONSTANT_COLOR, // BLEND_FACTOR_BLEND_FACTOR + GL_ONE_MINUS_CONSTANT_COLOR, // BLEND_FACTOR_INV_BLEND_FACTOR + GL_SRC1_COLOR, // BLEND_FACTOR_SRC1_COLOR + GL_ONE_MINUS_SRC1_COLOR, // BLEND_FACTOR_INV_SRC1_COLOR + GL_SRC1_ALPHA, // BLEND_FACTOR_SRC1_ALPHA + GL_ONE_MINUS_SRC1_ALPHA // BLEND_FACTOR_INV_SRC1_ALPHA + }; + // clang-format on + + VERIFY_EXPR(bf < _countof(BlendFactor2GLBlendMap)); + return BlendFactor2GLBlendMap[bf]; +} + +inline GLenum BlendOperation2GLBlendOp(BLEND_OPERATION BlendOp) +{ + // clang-format off + static constexpr GLenum BlendOperation2GLBlendOpMap[] = + { + 0, // BLEND_OPERATION_UNDEFINED + GL_FUNC_ADD, // BLEND_OPERATION_ADD + GL_FUNC_SUBTRACT, // BLEND_OPERATION_SUBTRACT + GL_FUNC_REVERSE_SUBTRACT, // BLEND_OPERATION_REV_SUBTRACT + GL_MIN, // BLEND_OPERATION_MIN + GL_MAX // BLEND_OPERATION_MAX + }; + // clang-format on + + VERIFY_EXPR(BlendOp < _countof(BlendOperation2GLBlendOpMap)); + return BlendOperation2GLBlendOpMap[BlendOp]; +} + + +GLenum TexFormatToGLInternalTexFormat(TEXTURE_FORMAT TexFormat, Uint32 BindFlags = 0); +TEXTURE_FORMAT GLInternalTexFormatToTexFormat(GLenum GlFormat); + NativePixelAttribs GetNativePixelTransferAttribs(TEXTURE_FORMAT TexFormat); -GLenum AccessFlags2GLAccess(Uint32 UAVAccessFlags); GLenum TypeToGLTexFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized); -GLenum StencilOp2GlStencilOp(STENCIL_OP StencilOp); -GLenum BlendFactor2GLBlend(BLEND_FACTOR bf); -GLenum BlendOperation2GLBlendOp(BLEND_OPERATION BlendOp); } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp index dde10533..27893ed8 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp @@ -244,18 +244,6 @@ TEXTURE_FORMAT GLInternalTexFormatToTexFormat(GLenum GlFormat) return FormatMap[GlFormat]; } -GLenum CorrectGLTexFormat(GLenum GLTexFormat, Uint32 BindFlags) -{ - if (BindFlags & BIND_DEPTH_STENCIL) - { - if (GLTexFormat == GL_R32F) - GLTexFormat = GL_DEPTH_COMPONENT32F; - if (GLTexFormat == GL_R16) - GLTexFormat = GL_DEPTH_COMPONENT16; - } - return GLTexFormat; -} - NativePixelAttribs GetNativePixelTransferAttribs(TEXTURE_FORMAT TexFormat) { // http://www.opengl.org/wiki/Pixel_Transfer @@ -403,23 +391,6 @@ NativePixelAttribs GetNativePixelTransferAttribs(TEXTURE_FORMAT TexFormat) } } -GLenum AccessFlags2GLAccess(Uint32 UAVAccessFlags) -{ - static GLenum AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ_WRITE + 1] = {}; - static bool bIsInit = false; - if (!bIsInit) - { - AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ] = GL_READ_ONLY; - AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_WRITE] = GL_WRITE_ONLY; - AccessFlags2GLAccessMap[UAV_ACCESS_FLAG_READ_WRITE] = GL_READ_WRITE; - bIsInit = true; - } - - auto GLAccess = AccessFlags2GLAccessMap[UAVAccessFlags & UAV_ACCESS_FLAG_READ_WRITE]; - return GLAccess; -} - - GLenum TypeToGLTexFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNormalized) { switch (ValType) @@ -575,102 +546,4 @@ GLenum TypeToGLTexFormat(VALUE_TYPE ValType, Uint32 NumComponents, Bool bIsNorma } } -GLenum StencilOp2GlStencilOp(STENCIL_OP StencilOp) -{ - static bool bIsInit = false; - static GLenum GLStencilOps[STENCIL_OP_NUM_OPS] = {}; - if (!bIsInit) - { - GLStencilOps[STENCIL_OP_KEEP] = GL_KEEP; - GLStencilOps[STENCIL_OP_ZERO] = GL_ZERO; - GLStencilOps[STENCIL_OP_REPLACE] = GL_REPLACE; - GLStencilOps[STENCIL_OP_INCR_SAT] = GL_INCR; - GLStencilOps[STENCIL_OP_DECR_SAT] = GL_DECR; - GLStencilOps[STENCIL_OP_INVERT] = GL_INVERT; - GLStencilOps[STENCIL_OP_INCR_WRAP] = GL_INCR_WRAP; - GLStencilOps[STENCIL_OP_DECR_WRAP] = GL_DECR_WRAP; - bIsInit = true; - } - - if (StencilOp > STENCIL_OP_UNDEFINED && StencilOp < STENCIL_OP_NUM_OPS) - { - auto GlStencilOp = GLStencilOps[StencilOp]; - VERIFY(GlStencilOp != 0 || GlStencilOp == 0 && StencilOp == STENCIL_OP_ZERO, "Unexpected stencil op"); - return GlStencilOp; - } - else - { - UNEXPECTED("Stencil operation (", StencilOp, ") is out of allowed range [1, ", STENCIL_OP_NUM_OPS - 1, "]"); - return 0; - } -} - - -GLenum BlendFactor2GLBlend(BLEND_FACTOR bf) -{ - static bool bIsInit = false; - static GLenum GLBlend[BLEND_FACTOR_NUM_FACTORS] = {}; - if (!bIsInit) - { - GLBlend[BLEND_FACTOR_ZERO] = GL_ZERO; - GLBlend[BLEND_FACTOR_ONE] = GL_ONE; - GLBlend[BLEND_FACTOR_SRC_COLOR] = GL_SRC_COLOR; - GLBlend[BLEND_FACTOR_INV_SRC_COLOR] = GL_ONE_MINUS_SRC_COLOR; - GLBlend[BLEND_FACTOR_SRC_ALPHA] = GL_SRC_ALPHA; - GLBlend[BLEND_FACTOR_INV_SRC_ALPHA] = GL_ONE_MINUS_SRC_ALPHA; - GLBlend[BLEND_FACTOR_DEST_ALPHA] = GL_DST_ALPHA; - GLBlend[BLEND_FACTOR_INV_DEST_ALPHA] = GL_ONE_MINUS_DST_ALPHA; - GLBlend[BLEND_FACTOR_DEST_COLOR] = GL_DST_COLOR; - GLBlend[BLEND_FACTOR_INV_DEST_COLOR] = GL_ONE_MINUS_DST_COLOR; - GLBlend[BLEND_FACTOR_SRC_ALPHA_SAT] = GL_SRC_ALPHA_SATURATE; - GLBlend[BLEND_FACTOR_BLEND_FACTOR] = GL_CONSTANT_COLOR; - GLBlend[BLEND_FACTOR_INV_BLEND_FACTOR] = GL_ONE_MINUS_CONSTANT_COLOR; - GLBlend[BLEND_FACTOR_SRC1_COLOR] = GL_SRC1_COLOR; - GLBlend[BLEND_FACTOR_INV_SRC1_COLOR] = GL_ONE_MINUS_SRC1_COLOR; - GLBlend[BLEND_FACTOR_SRC1_ALPHA] = GL_SRC1_ALPHA; - GLBlend[BLEND_FACTOR_INV_SRC1_ALPHA] = GL_ONE_MINUS_SRC1_ALPHA; - - bIsInit = true; - } - if (bf > BLEND_FACTOR_UNDEFINED && bf < BLEND_FACTOR_NUM_FACTORS) - { - auto glbf = GLBlend[bf]; - VERIFY(glbf != 0 || glbf == 0 && bf == BLEND_FACTOR_ZERO, "Incorrect blend factor"); - return glbf; - } - else - { - UNEXPECTED("Incorrect blend factor (", bf, ")"); - return 0; - } -} - -GLenum BlendOperation2GLBlendOp(BLEND_OPERATION BlendOp) -{ - static bool bIsInit = false; - static GLenum GLBlendOp[BLEND_OPERATION_NUM_OPERATIONS] = {}; - if (!bIsInit) - { - GLBlendOp[BLEND_OPERATION_ADD] = GL_FUNC_ADD; - GLBlendOp[BLEND_OPERATION_SUBTRACT] = GL_FUNC_SUBTRACT; - GLBlendOp[BLEND_OPERATION_REV_SUBTRACT] = GL_FUNC_REVERSE_SUBTRACT; - GLBlendOp[BLEND_OPERATION_MIN] = GL_MIN; - GLBlendOp[BLEND_OPERATION_MAX] = GL_MAX; - - bIsInit = true; - } - - if (BlendOp > BLEND_OPERATION_UNDEFINED && BlendOp < BLEND_OPERATION_NUM_OPERATIONS) - { - auto glbop = GLBlendOp[BlendOp]; - VERIFY(glbop != 0, "Incorrect blend operation"); - return glbop; - } - else - { - UNEXPECTED("Incorrect blend operation (", BlendOp, ")"); - return 0; - } -} - } // namespace Diligent diff --git a/Tests/DiligentCoreAPITest/src/GL/GLTypeConversionsTest.cpp b/Tests/DiligentCoreAPITest/src/GL/GLTypeConversionsTest.cpp new file mode 100644 index 00000000..84510632 --- /dev/null +++ b/Tests/DiligentCoreAPITest/src/GL/GLTypeConversionsTest.cpp @@ -0,0 +1,272 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "../../include/GL/TestingEnvironmentGL.hpp" +#include "../include/GLTypeConversions.hpp" + +#include "gtest/gtest.h" + +using namespace Diligent; + +namespace +{ + +TEST(GLTypeConversionsTest, PrimitiveTopologyToGLTopology) +{ +#define CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "PrimitiveTopologyToGLTopology function assumes that " #EnumElement " equals " #ExpectedValue ": fix PrimTopologyToGLTopologyMap array and update this assertion.") + // clang-format off + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_UNDEFINED, 0); + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1); + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 2); + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_POINT_LIST, 3); + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_LINE_LIST, 4); + CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE(PRIMITIVE_TOPOLOGY_LINE_STRIP, 5); + static_assert(PRIMITIVE_TOPOLOGY_LINE_STRIP + 1 == PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST, + "Did you add a new PRIMITIVE_TOPOLOGY enum value that is not patch? Please update PrimitiveTopologyToGLTopology function."); + // clang-format on +#undef CHECK_PRIMITIVE_TOPOLOGY_ENUM_VALUE + + // clang-format off + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_UNDEFINED), GLenum{0}); + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST), GLenum{GL_TRIANGLES}); + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP), GLenum{GL_TRIANGLE_STRIP}); + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_POINT_LIST), GLenum{GL_POINTS}); + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_LINE_LIST), GLenum{GL_LINES}); + EXPECT_EQ(PrimitiveTopologyToGLTopology(PRIMITIVE_TOPOLOGY_LINE_STRIP), GLenum{GL_LINE_STRIP}); + // clang-format on +} + +TEST(GLTypeConversionsTest, TypeToGLType) +{ +#define CHECK_VALUE_TYPE_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "TypeToGLType function assumes that " #EnumElement " equals " #ExpectedValue ": fix TypeToGLTypeMap array and update this assertion.") + // clang-format off + CHECK_VALUE_TYPE_ENUM_VALUE(VT_UNDEFINED, 0); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_INT8, 1); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_INT16, 2); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_INT32, 3); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_UINT8, 4); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_UINT16, 5); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_UINT32, 6); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_FLOAT16, 7); + CHECK_VALUE_TYPE_ENUM_VALUE(VT_FLOAT32, 8); + // clang-format on + static_assert(VT_NUM_TYPES == 9, "Did you add a new VALUE_TYPE enum value? Please update TypeToGLType function."); +#undef CHECK_VALUE_TYPE_ENUM_VALUE + + // clang-format off + EXPECT_EQ(TypeToGLType(VT_UNDEFINED), GLenum{0}); + EXPECT_EQ(TypeToGLType(VT_INT8), GLenum{GL_BYTE}); + EXPECT_EQ(TypeToGLType(VT_INT16), GLenum{GL_SHORT}); + EXPECT_EQ(TypeToGLType(VT_INT32), GLenum{GL_INT}); + EXPECT_EQ(TypeToGLType(VT_UINT8), GLenum{GL_UNSIGNED_BYTE}); + EXPECT_EQ(TypeToGLType(VT_UINT16), GLenum{GL_UNSIGNED_SHORT}); + EXPECT_EQ(TypeToGLType(VT_UINT32), GLenum{GL_UNSIGNED_INT}); + EXPECT_EQ(TypeToGLType(VT_FLOAT16), GLenum{GL_HALF_FLOAT}); + EXPECT_EQ(TypeToGLType(VT_FLOAT32), GLenum{GL_FLOAT}); + // clang-format on +} + +TEST(GLTypeConversionsTest, TexAddressModeToGLAddressMode) +{ +#define CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "TexAddressModeToGLAddressMode function assumes that " #EnumElement " equals " #ExpectedValue ": fix TexAddressModeToGLAddressModeMap array and update this assertion.") + // clang-format off + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_UNKNOWN, 0); + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_WRAP, 1); + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_MIRROR, 2); + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_CLAMP, 3); + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_BORDER, 4); + CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE(TEXTURE_ADDRESS_MIRROR_ONCE, 5); + // clang-format on + static_assert(TEXTURE_ADDRESS_NUM_MODES == 6, + "Did you add a new TEXTURE_ADDRESS_MODE enum value? Please update TexAddressModeToGLAddressMode function."); +#undef CHECK_TEXTURE_ADDRESS_MODE_ENUM_VALUE + + // clang-format off + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_UNKNOWN), GLenum{0}); + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_WRAP), GLenum{GL_REPEAT}); + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_MIRROR), GLenum{GL_MIRRORED_REPEAT}); + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_CLAMP), GLenum{GL_CLAMP_TO_EDGE}); + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_BORDER), GLenum{GL_CLAMP_TO_BORDER}); + EXPECT_EQ(TexAddressModeToGLAddressMode(TEXTURE_ADDRESS_MIRROR_ONCE), GLenum{GL_MIRROR_CLAMP_TO_EDGE}); + // clang-format on +} + +TEST(GLTypeConversionsTest, CompareFuncToGLCompareFunc) +{ +#define CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "CompareFuncToGLCompareFunc function assumes that " #EnumElement " equals " #ExpectedValue ": fix CompareFuncToGLCompareFuncMap array and update this assertion.") + // clang-format off + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_UNKNOWN, 0); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_NEVER, 1); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_LESS, 2); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_EQUAL, 3); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_LESS_EQUAL, 4); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_GREATER, 5); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_NOT_EQUAL, 6); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_GREATER_EQUAL, 7); + CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE(COMPARISON_FUNC_ALWAYS, 8); + // clang-format on + static_assert(COMPARISON_FUNC_NUM_FUNCTIONS == 9, + "Did you add a new COMPARISON_FUNCTION enum value? Please update CompareFuncToGLCompareFunc function."); +#undef CHECK_COMPARISON_FUNC_MODE_ENUM_VALUE + + // clang-format off + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_UNKNOWN), GLenum{0}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_NEVER), GLenum{GL_NEVER}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_LESS), GLenum{GL_LESS}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_EQUAL), GLenum{GL_EQUAL}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_LESS_EQUAL), GLenum{GL_LEQUAL}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_GREATER), GLenum{GL_GREATER}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_NOT_EQUAL), GLenum{GL_NOTEQUAL}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_GREATER_EQUAL), GLenum{GL_GEQUAL}); + EXPECT_EQ(CompareFuncToGLCompareFunc(COMPARISON_FUNC_ALWAYS), GLenum{GL_ALWAYS}); + // clang-format on +} + + +TEST(GLTypeConversionsTest, AccessFlags2GLAccess) +{ +#define CHECK_UAV_ACCESS_FLAG_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "AccessFlags2GLAccess function assumes that " #EnumElement " equals " #ExpectedValue ": fix AccessFlags2GLAccessMap array and update this assertion.") + // clang-format off + CHECK_UAV_ACCESS_FLAG_ENUM_VALUE(UAV_ACCESS_UNSPECIFIED, 0); + CHECK_UAV_ACCESS_FLAG_ENUM_VALUE(UAV_ACCESS_FLAG_READ, 1); + CHECK_UAV_ACCESS_FLAG_ENUM_VALUE(UAV_ACCESS_FLAG_WRITE, 2); + CHECK_UAV_ACCESS_FLAG_ENUM_VALUE(UAV_ACCESS_FLAG_READ_WRITE, 3); + // clang-format on +#undef CHECK_UAV_ACCESS_FLAG_ENUM_VALUE + + // clang-format off + EXPECT_EQ(AccessFlags2GLAccess(UAV_ACCESS_UNSPECIFIED), GLenum{0}); + EXPECT_EQ(AccessFlags2GLAccess(UAV_ACCESS_FLAG_READ), GLenum{GL_READ_ONLY}); + EXPECT_EQ(AccessFlags2GLAccess(UAV_ACCESS_FLAG_WRITE), GLenum{GL_WRITE_ONLY}); + EXPECT_EQ(AccessFlags2GLAccess(UAV_ACCESS_FLAG_READ_WRITE), GLenum{GL_READ_WRITE}); + // clang-format on +} + +TEST(GLTypeConversionsTest, StencilOp2GlStencilOp) +{ +#define CHECK_STENCIL_OP_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "StencilOp2GlStencilOp function assumes that " #EnumElement " equals " #ExpectedValue ": fix StencilOp2GlStencilOpMap array and update this assertion.") + // clang-format off + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_UNDEFINED, 0); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_KEEP, 1); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_ZERO, 2); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_REPLACE, 3); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_INCR_SAT, 4); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_DECR_SAT, 5); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_INVERT, 6); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_INCR_WRAP, 7); + CHECK_STENCIL_OP_ENUM_VALUE(STENCIL_OP_DECR_WRAP, 8); + // clang-format on + static_assert(STENCIL_OP_NUM_OPS == 9, "Did you add a new STENCIL_OP enum value? Please update StencilOp2GlStencilOp function."); +#undef CHECK_STENCIL_OP_ENUM_VALUE + + // clang-format off + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_UNDEFINED), GLenum{0}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_KEEP), GLenum{GL_KEEP}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_ZERO), GLenum{GL_ZERO}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_REPLACE), GLenum{GL_REPLACE}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_INCR_SAT), GLenum{GL_INCR}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_DECR_SAT), GLenum{GL_DECR}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_INVERT), GLenum{GL_INVERT}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_INCR_WRAP), GLenum{GL_INCR_WRAP}); + EXPECT_EQ(StencilOp2GlStencilOp(STENCIL_OP_DECR_WRAP), GLenum{GL_DECR_WRAP}); + // clang-format on +} + +TEST(GLTypeConversionsTest, BlendFactor2GLBlend) +{ +#define CHECK_BLEND_FACTOR_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "BlendFactor2GLBlend function assumes that " #EnumElement " equals " #ExpectedValue ": fix BlendFactor2GLBlendMap array and update this assertion.") + // clang-format off + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_UNDEFINED, 0); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_ZERO, 1); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_ONE, 2); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_SRC_COLOR, 3); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_SRC_COLOR, 4); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_SRC_ALPHA, 5); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_SRC_ALPHA, 6); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_DEST_ALPHA, 7); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_DEST_ALPHA, 8); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_DEST_COLOR, 9); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_DEST_COLOR, 10); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_SRC_ALPHA_SAT, 11); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_BLEND_FACTOR, 12); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_BLEND_FACTOR, 13); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_SRC1_COLOR, 14); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_SRC1_COLOR, 15); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_SRC1_ALPHA, 16); + CHECK_BLEND_FACTOR_ENUM_VALUE(BLEND_FACTOR_INV_SRC1_ALPHA, 17); + // clang-format on + static_assert(BLEND_FACTOR_NUM_FACTORS == 18, "Did you add a new BLEND_FACTOR enum value? Please update BlendFactor2GLBlend function."); +#undef CHECK_BLEND_FACTOR_ENUM_VALUE + + // clang-format off + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_UNDEFINED), GLenum{0}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_ONE), GLenum{GL_ONE}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_SRC_COLOR), GLenum{GL_SRC_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_SRC_COLOR), GLenum{GL_ONE_MINUS_SRC_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_SRC_ALPHA), GLenum{GL_SRC_ALPHA}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_SRC_ALPHA), GLenum{GL_ONE_MINUS_SRC_ALPHA}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_DEST_ALPHA), GLenum{GL_DST_ALPHA}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_DEST_ALPHA), GLenum{GL_ONE_MINUS_DST_ALPHA}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_DEST_COLOR), GLenum{GL_DST_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_DEST_COLOR), GLenum{GL_ONE_MINUS_DST_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_SRC_ALPHA_SAT), GLenum{GL_SRC_ALPHA_SATURATE}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_BLEND_FACTOR), GLenum{GL_CONSTANT_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_BLEND_FACTOR), GLenum{GL_ONE_MINUS_CONSTANT_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_SRC1_COLOR), GLenum{GL_SRC1_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_SRC1_COLOR), GLenum{GL_ONE_MINUS_SRC1_COLOR}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_SRC1_ALPHA), GLenum{GL_SRC1_ALPHA}); + EXPECT_EQ(BlendFactor2GLBlend(BLEND_FACTOR_INV_SRC1_ALPHA), GLenum{GL_ONE_MINUS_SRC1_ALPHA}); + // clang-format on +} + +TEST(GLTypeConversionsTest, BlendOperation2GLBlendOp) +{ + +#define CHECK_BLEND_OPERATION_ENUM_VALUE(EnumElement, ExpectedValue) static_assert(EnumElement == ExpectedValue, "BlendOperation2GLBlendOp function assumes that " #EnumElement " equals " #ExpectedValue ": fix BlendOperation2GLBlendOpMap array and update this assertion.") + // clang-format off + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_UNDEFINED, 0); + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_ADD, 1); + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_SUBTRACT, 2); + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_REV_SUBTRACT, 3); + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_MIN, 4); + CHECK_BLEND_OPERATION_ENUM_VALUE(BLEND_OPERATION_MAX, 5); + // clang-format on + static_assert(BLEND_OPERATION_NUM_OPERATIONS == 6, + "Did you add a new BLEND_OPERATION enum value? Please update BlendOperation2GLBlendOp function."); +#undef CHECK_BLEND_OPERATION_ENUM_VALUE + + // clang-format off + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_UNDEFINED), GLenum{0}); + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_ADD), GLenum{GL_FUNC_ADD}); + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_SUBTRACT), GLenum{GL_FUNC_SUBTRACT}); + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_REV_SUBTRACT), GLenum{GL_FUNC_REVERSE_SUBTRACT}); + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_MIN), GLenum{GL_MIN}); + EXPECT_EQ(BlendOperation2GLBlendOp(BLEND_OPERATION_MAX), GLenum{GL_MAX}); + // clang-format on +} + +} // namespace -- cgit v1.2.3