summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-02-20 02:20:32 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-02-20 02:20:32 +0000
commitafc295cf9366959d85b7e38b9c69d1cc2bbdbf48 (patch)
tree1b0336caa000a72754f9cf765f323ded488860c4
parentAdded GL_HALF_FLOAT type (diff)
downloadDiligentCore-afc295cf9366959d85b7e38b9c69d1cc2bbdbf48.tar.gz
DiligentCore-afc295cf9366959d85b7e38b9c69d1cc2bbdbf48.zip
Reworked GL type conversions and added tests
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp264
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLTypeConversions.cpp127
-rw-r--r--Tests/DiligentCoreAPITest/src/GL/GLTypeConversionsTest.cpp272
3 files changed, 438 insertions, 225 deletions
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