LCOV - code coverage report
Current view: top level - src - gl-wrappers.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 14.2 % 260 37
Test Date: 2025-06-27 11:12:05 Functions: 42.1 % 19 8

            Line data    Source code
       1              : // Copyright (c) 2025 Milton McDonald
       2              : // This source code is licensed under the MIT License. See LICENSE file in the
       3              : // project root for details.
       4              : 
       5              : #include "graphics-engine/gl-wrappers.h"
       6              : 
       7              : #include <cassert>
       8              : #include <iostream>
       9              : #include <unordered_map>
      10              : #include <utility>
      11              : 
      12              : #include "error.h"
      13              : #include "glad/glad.h"
      14              : #include "graphics-engine/gl-types.h"
      15              : #include "graphics-engine/types.h"
      16              : 
      17              : using enum graphics_engine::types::ErrorCode;
      18              : using enum graphics_engine::gl_types::GLBufferTarget;
      19              : using enum graphics_engine::gl_types::GLClearBit;
      20              : using enum graphics_engine::gl_types::GLDataType;
      21              : using enum graphics_engine::gl_types::GLDataUsagePattern;
      22              : using enum graphics_engine::gl_types::GLDrawMode;
      23              : using enum graphics_engine::gl_types::GLShaderObjectParameter;
      24              : using enum graphics_engine::gl_types::GLShaderType;
      25              : 
      26              : using graphics_engine::error::MakeErrorCode;
      27              : using graphics_engine::gl_clear_flags::IGLClearFlags;
      28              : using graphics_engine::gl_types::GLBufferTarget;
      29              : using graphics_engine::gl_types::GLDataType;
      30              : using graphics_engine::gl_types::GLDataUsagePattern;
      31              : using graphics_engine::gl_types::GLDrawMode;
      32              : using graphics_engine::gl_types::GLShaderObjectParameter;
      33              : using graphics_engine::gl_types::GLShaderType;
      34              : using graphics_engine::types::Expected;
      35              : 
      36              : using std::cerr;
      37              : using std::is_same_v;
      38              : using std::to_underlying;
      39              : using std::unexpected;
      40              : 
      41              : static_assert(is_same_v<GLbitfield, unsigned int>,
      42              :               "GLbitfield and unsigned int are not the same type!");
      43              : static_assert(is_same_v<GLboolean, unsigned char>,
      44              :               "GLboolean and unsigned char are not the same type!");
      45              : static_assert(is_same_v<GLchar, char>,
      46              :               "GLchar and char are not the same type!");
      47              : static_assert(is_same_v<GLint, int>, "GLint and int are not the same type!");
      48              : static_assert(is_same_v<GLsizei, int>,
      49              :               "GLsizei and int are not the same type!");
      50              : 
      51              : #ifdef _WIN64
      52              : static_assert(is_same_v<GLsizeiptr, long long int>,
      53              :               "GLsizeiptr and long long int are not the same type!");
      54              : #else
      55              : static_assert(is_same_v<GLsizeiptr, long int>,
      56              :               "GLsizeiptr and long long int are not the same type!");
      57              : #endif
      58              : static_assert(is_same_v<GLuint, unsigned int>,
      59              :               "GLuint and unsigned int are not the same type!");
      60              : static_assert(is_same_v<GLvoid, void>,
      61              :               "GLvoid and void are not the same type!");
      62              : 
      63              : namespace graphics_engine::gl_wrappers {
      64              : 
      65              : namespace {
      66              : 
      67            0 : auto ConvertGLBufferTarget(GLBufferTarget target) -> GLenum {
      68            0 :   switch (target) {
      69              :     default:
      70              :       assert(false);  // If we get here, add a new case to the switch.
      71              :       [[fallthrough]];
      72              :     case kArray:
      73              :       return GL_ARRAY_BUFFER;
      74              :     case kCopyRead:
      75              :       return GL_COPY_READ_BUFFER;
      76              :     case kCopyWrite:
      77              :       return GL_COPY_WRITE_BUFFER;
      78              :     case kElementArray:
      79              :       return GL_ELEMENT_ARRAY_BUFFER;
      80              :     case kPixelPack:
      81              :       return GL_PIXEL_PACK_BUFFER;
      82              :     case kPixelUnpack:
      83              :       return GL_PIXEL_UNPACK_BUFFER;
      84              :     case kTexture:
      85              :       return GL_TEXTURE;
      86              :     case kTransformFeedback:
      87              :       return GL_TRANSFORM_FEEDBACK_BUFFER;
      88              :     case kUniform:
      89              :       return GL_UNIFORM_BUFFER;
      90              :   }
      91              : }
      92              : 
      93            0 : auto ConvertGLDataType(GLDataType type) -> GLenum {
      94            0 :   switch (type) {
      95              :     default:
      96              :       assert(false);  // If we get here, add a new case to the switch.
      97              :       [[fallthrough]];
      98              :     case kByte:
      99              :       return GL_BYTE;
     100              :     case kUnsignedByte:
     101              :       return GL_UNSIGNED_BYTE;
     102              :     case kShort:
     103              :       return GL_SHORT;
     104              :     case kUnsignedShort:
     105              :       return GL_UNSIGNED_SHORT;
     106              :     case kInt:
     107              :       return GL_INT;
     108              :     case kUnsignedInt:
     109              :       return GL_UNSIGNED_INT;
     110              :     case kHalfFloat:
     111              :       return GL_HALF_FLOAT;
     112              :     case kFloat:
     113              :       return GL_FLOAT;
     114              :     case kDouble:
     115              :       return GL_DOUBLE;
     116              :     case kInt_2_10_10_10_Rev:
     117              :       return GL_INT_2_10_10_10_REV;
     118              :     case kUnsignedInt_2_10_10_10_Rev:
     119              :       return GL_UNSIGNED_INT_2_10_10_10_REV;
     120              :   }
     121              : }
     122              : 
     123            0 : auto ConvertGLDataUsagePattern(GLDataUsagePattern usage) -> GLenum {
     124            0 :   switch (usage) {
     125              :     default:
     126              :       assert(false);  // If we get here, add a new case to the switch.
     127              :       [[fallthrough]];
     128              :     case kStreamDraw:
     129              :       return GL_STREAM_DRAW;
     130              :     case kStreamRead:
     131              :       return GL_STREAM_READ;
     132              :     case kStreamCopy:
     133              :       return GL_STREAM_COPY;
     134              :     case kStaticDraw:
     135              :       return GL_STATIC_DRAW;
     136              :     case kStaticRead:
     137              :       return GL_STATIC_READ;
     138              :     case kStaticCopy:
     139              :       return GL_STATIC_COPY;
     140              :     case kDynamicDraw:
     141              :       return GL_DYNAMIC_DRAW;
     142              :     case kDynamicRead:
     143              :       return GL_DYNAMIC_READ;
     144              :     case kDynamicCopy:
     145              :       return GL_DYNAMIC_COPY;
     146              :   }
     147              : }
     148              : 
     149            0 : auto ConvertGLDrawMode(GLDrawMode mode) -> GLenum {
     150            0 :   switch (mode) {
     151              :     default:
     152              :       assert(false);  // If we get here, add a new case to the switch.
     153              :       [[fallthrough]];
     154              :     case kPoints:
     155              :       return GL_POINTS;
     156              :     case kLineStrip:
     157              :       return GL_LINE_STRIP;
     158              :     case kLineLoop:
     159              :       return GL_LINE_LOOP;
     160              :     case kLines:
     161              :       return GL_LINES;
     162              :     case kLineStripAdjacency:
     163              :       return GL_LINE_STRIP_ADJACENCY;
     164              :     case kLinesAdjacency:
     165              :       return GL_LINES_ADJACENCY;
     166              :     case kTriangleStrip:
     167              :       return GL_TRIANGLE_STRIP;
     168              :     case kTriangleFan:
     169              :       return GL_TRIANGLE_FAN;
     170              :     case kTriangles:
     171              :       return GL_TRIANGLES;
     172              :     case kTriangleStripAdjacency:
     173              :       return GL_TRIANGLE_STRIP_ADJACENCY;
     174              :     case kTrianglesAdjacency:
     175              :       return GL_TRIANGLES_ADJACENCY;
     176              :   }
     177              : }
     178              : 
     179            2 : auto ConvertGLShaderObjectParameter(GLShaderObjectParameter pname) -> GLenum {
     180            2 :   switch (pname) {
     181              :     default:
     182              :       assert(false);  // If we get here, add a new case to the switch.
     183              :       [[fallthrough]];
     184              :     case kShaderType:
     185              :       return GL_SHADER_TYPE;
     186              :     case kDeleteStatus:
     187              :       return GL_DELETE_STATUS;
     188              :     case kCompileStatus:
     189              :       return GL_COMPILE_STATUS;
     190              :     case kInfoLogLength:
     191              :       return GL_INFO_LOG_LENGTH;
     192              :     case kShaderSourceLength:
     193              :       return GL_SHADER_SOURCE_LENGTH;
     194              :   }
     195              : }
     196              : 
     197            2 : auto ConvertGLShaderType(GLShaderType shader_type) -> GLenum {
     198            2 :   switch (shader_type) {
     199            0 :     default:
     200            0 :       std::cerr << "ConvertGLShaderType failed with underlying value "
     201            0 :                 << static_cast<int>(shader_type) << '\n';
     202              :       assert(false);  // If we get here, add a new case to the switch.
     203              :       [[fallthrough]];
     204              :     case kFragment:
     205              :       return GL_FRAGMENT_SHADER;
     206              :     case kGeometry:
     207              :       return GL_GEOMETRY_SHADER;
     208            1 :     case kVertex:
     209            1 :       return GL_VERTEX_SHADER;
     210              :   }
     211              : }
     212              : 
     213              : }  // namespace
     214              : 
     215            2 : auto AttachShader(unsigned int program, unsigned int shader) -> Expected<void> {
     216            2 :   glAttachShader(program, shader);
     217            2 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     218            0 :     cerr << "glAttachShader failed with error code " << error << '\n';
     219            0 :     switch (error) {
     220            0 :       default:
     221            0 :         assert(false);  // If we get here, add a new case to the switch.
     222            0 :         [[fallthrough]];
     223            0 :       case GL_INVALID_VALUE:
     224            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     225            0 :       case GL_INVALID_OPERATION:
     226            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     227              :     }
     228              :   }
     229              : 
     230            2 :   return {};
     231              : }
     232              : 
     233            0 : auto BindBuffer(GLBufferTarget target, unsigned int buffer) -> Expected<void> {
     234            0 :   GLenum gl_target = ConvertGLBufferTarget(target);
     235            0 :   glBindBuffer(gl_target, buffer);
     236            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     237            0 :     cerr << "glBindBuffer failed with error code " << error << '\n';
     238            0 :     switch (error) {
     239            0 :       default:
     240            0 :         assert(false);  // If we get here, add a new case to the switch.
     241            0 :         [[fallthrough]];
     242            0 :       case GL_INVALID_ENUM:
     243            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     244            0 :       case GL_INVALID_OPERATION:
     245            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     246              :     }
     247              :   }
     248              : 
     249            0 :   return {};
     250              : }
     251              : 
     252            0 : auto BindVertexArray(unsigned int array) -> Expected<void> {
     253            0 :   glBindVertexArray(array);
     254            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     255            0 :     cerr << "glBindVertexArray failed with error code " << error << '\n';
     256            0 :     switch (error) {
     257            0 :       default:
     258            0 :         assert(false);  // If we get here, add a new case to the switch.
     259            0 :         [[fallthrough]];
     260            0 :       case GL_INVALID_OPERATION:
     261            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     262              :     }
     263              :   }
     264              : 
     265            0 :   return {};
     266              : }
     267              : 
     268            0 : auto BufferData(GLBufferTarget target, long long int size, const void* data,
     269              :                 GLDataUsagePattern usage) -> Expected<void> {
     270            0 :   GLenum gl_target = ConvertGLBufferTarget(target);
     271            0 :   GLenum gl_usage = ConvertGLDataUsagePattern(usage);
     272            0 :   glBufferData(gl_target, size, data, gl_usage);
     273            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     274            0 :     cerr << "glBufferData failed with error code " << error << '\n';
     275            0 :     switch (error) {
     276            0 :       default:
     277            0 :         assert(false);  // If we get here, add a new case to the switch.
     278            0 :         [[fallthrough]];
     279            0 :       case GL_INVALID_ENUM:
     280            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     281            0 :       case GL_INVALID_OPERATION:
     282            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     283            0 :       case GL_INVALID_VALUE:
     284            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     285            0 :       case GL_OUT_OF_MEMORY:
     286            0 :         return unexpected(MakeErrorCode(kGLErrorOutOfMemory));
     287              :     }
     288              :   }
     289              : 
     290            0 :   return {};
     291              : }
     292              : 
     293            0 : auto Clear(const IGLClearFlags& flags) -> types::Expected<void> {
     294            0 :   GLbitfield mask = 0;
     295            0 :   if (flags.Test(kColor)) {
     296            0 :     mask |= GL_COLOR_BUFFER_BIT;
     297              :   }
     298            0 :   if (flags.Test(kDepth)) {
     299            0 :     mask |= GL_DEPTH_BUFFER_BIT;
     300              :   }
     301            0 :   if (flags.Test(kStencil)) {
     302            0 :     mask |= GL_STENCIL_BUFFER_BIT;
     303              :   }
     304            0 :   glClear(mask);
     305            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     306            0 :     cerr << "glClear failed with error code " << error << '\n';
     307            0 :     switch (error) {
     308            0 :       default:
     309            0 :         assert(false);  // If we get here, add a new case to the switch.
     310            0 :         [[fallthrough]];
     311            0 :       case GL_INVALID_VALUE:
     312            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     313              :     }
     314              :   }
     315              : 
     316            0 :   return {};
     317              : }
     318              : 
     319            2 : auto CompileShader(unsigned int shader) -> Expected<void> {
     320            2 :   glCompileShader(shader);
     321            2 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     322            0 :     cerr << "glCompileShader failed with error code " << error << '\n';
     323            0 :     switch (error) {
     324            0 :       default:
     325            0 :         assert(false);  // If we get here, add a new case to the switch.
     326            0 :         [[fallthrough]];
     327            0 :       case GL_INVALID_OPERATION:
     328            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     329            0 :       case GL_INVALID_VALUE:
     330            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     331              :     }
     332              :   }
     333              : 
     334            2 :   return {};
     335              : }
     336              : 
     337            1 : auto CreateProgram() -> Expected<unsigned int> {
     338            1 :   GLuint program_id = glCreateProgram();
     339            1 :   if (program_id == 0) {
     340            0 :     cerr << "An error occurred creating the program object.";
     341            0 :     return unexpected(MakeErrorCode(kGLError));
     342              :   }
     343              : 
     344            1 :   return program_id;
     345              : }
     346              : 
     347            2 : auto CreateShader(GLShaderType shader_type) -> Expected<unsigned int> {
     348            2 :   GLenum gl_shader_type = ConvertGLShaderType(shader_type);
     349            2 :   GLuint shader = glCreateShader(gl_shader_type);
     350            2 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     351            0 :     cerr << "glCreateShader failed with error code " << error << '\n';
     352            0 :     switch (error) {
     353            0 :       default:
     354            0 :         assert(false);  // If we get here, add a new case to the switch.
     355            0 :         [[fallthrough]];
     356            0 :       case GL_INVALID_ENUM:
     357            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     358              :     }
     359              :   }
     360              : 
     361            2 :   assert(shader > 0U);
     362            2 :   return shader;
     363              : }
     364              : 
     365            0 : auto DrawArrays(GLDrawMode mode, int first, int count) -> Expected<void> {
     366            0 :   GLenum gl_mode = ConvertGLDrawMode(mode);
     367            0 :   glDrawArrays(gl_mode, first, count);
     368            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     369            0 :     cerr << "glDrawArrays failed with error code " << error << '\n';
     370            0 :     switch (error) {
     371            0 :       default:
     372            0 :         assert(false);  // If we get here, add a new case to the switch.
     373            0 :         [[fallthrough]];
     374            0 :       case GL_INVALID_ENUM:
     375            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     376            0 :       case GL_INVALID_OPERATION:
     377            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     378            0 :       case GL_INVALID_VALUE:
     379            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     380              :     }
     381              :   }
     382              : 
     383            0 :   return {};
     384              : }
     385              : 
     386            0 : auto EnableVertexAttribArray(unsigned int index) -> Expected<void> {
     387            0 :   glEnableVertexAttribArray(index);
     388            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     389            0 :     cerr << "glEnableVertexAttribArray failed with error code " << error
     390            0 :          << '\n';
     391            0 :     switch (error) {
     392            0 :       default:
     393            0 :         assert(false);  // If we get here, add a new case to the switch.
     394            0 :         [[fallthrough]];
     395            0 :       case GL_INVALID_OPERATION:
     396            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     397            0 :       case GL_INVALID_VALUE:
     398            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     399              :     }
     400              :   }
     401              : 
     402            0 :   return {};
     403              : }
     404              : 
     405            0 : auto GenBuffers(int n, unsigned int* buffers) -> Expected<void> {
     406            0 :   glGenBuffers(n, buffers);
     407            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     408            0 :     cerr << "glGenBuffers failed with error code " << error << '\n';
     409            0 :     switch (error) {
     410            0 :       default:
     411            0 :         assert(false);  // If we get here, add a new case to the switch.
     412            0 :         [[fallthrough]];
     413            0 :       case GL_INVALID_VALUE:
     414            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     415              :     }
     416              :   }
     417              : 
     418            0 :   return {};
     419              : }
     420              : 
     421            0 : auto GenVertexArrays(int n, unsigned int* arrays) -> Expected<void> {
     422            0 :   glGenVertexArrays(n, arrays);
     423            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     424            0 :     cerr << "glGenVertexArrays failed with error code " << error << '\n';
     425            0 :     switch (error) {
     426            0 :       default:
     427            0 :         assert(false);  // If we get here, add a new case to the switch.
     428            0 :         [[fallthrough]];
     429            0 :       case GL_INVALID_VALUE:
     430            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     431              :     }
     432              :   }
     433              : 
     434            0 :   return {};
     435              : }
     436              : 
     437            0 : DLLEXPORT [[nodiscard]] auto GetShaderInfoLog(unsigned int shader,
     438              :                                               int max_length, int* length,
     439              :                                               char* info_log)
     440              :     -> types::Expected<void> {
     441            0 :   glGetShaderInfoLog(shader, max_length, length, info_log);
     442            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     443            0 :     cerr << "glGetShaderInfoLog failed with error code " << error << '\n';
     444            0 :     switch (error) {
     445            0 :       default:
     446            0 :         assert(false);  // If we get here, add a new case to the switch.
     447            0 :         [[fallthrough]];
     448            0 :       case GL_INVALID_VALUE:
     449            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     450            0 :       case GL_INVALID_OPERATION:
     451            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     452              :     }
     453              :   }
     454              : 
     455            0 :   return {};
     456              : }
     457              : 
     458            2 : DLLEXPORT [[nodiscard]] auto GetShaderiv(
     459              :     unsigned int shader, gl_types::GLShaderObjectParameter pname, int* params)
     460              :     -> types::Expected<void> {
     461            2 :   GLenum gl_pname = ConvertGLShaderObjectParameter(pname);
     462            2 :   glGetShaderiv(shader, gl_pname, params);
     463            2 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     464            0 :     cerr << "glGetShaderiv failed with error code " << error << '\n';
     465            0 :     switch (error) {
     466            0 :       default:
     467            0 :         assert(false);  // If we get here, add a new case to the switch.
     468            0 :         [[fallthrough]];
     469            0 :       case GL_INVALID_ENUM:
     470            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     471            0 :       case GL_INVALID_OPERATION:
     472            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     473            0 :       case GL_INVALID_VALUE:
     474            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     475              :     }
     476              :   }
     477              : 
     478            2 :   return {};
     479              : }
     480              : 
     481            1 : auto LinkProgram(unsigned int program) -> types::Expected<void> {
     482            1 :   glLinkProgram(program);
     483            1 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     484            0 :     cerr << "glLinkProgram failed with error code " << error << '\n';
     485            0 :     switch (error) {
     486            0 :       default:
     487            0 :         assert(false);  // If we get here, add a new case to the switch.
     488            0 :         [[fallthrough]];
     489            0 :       case GL_INVALID_VALUE:
     490            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     491            0 :       case GL_INVALID_OPERATION:
     492            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     493              :     }
     494              :   }
     495              : 
     496            1 :   return {};
     497              : }
     498              : 
     499            2 : auto ShaderSource(unsigned int shader, int count, const char** string,
     500              :                   const int* length) -> Expected<void> {
     501            2 :   glShaderSource(shader, count, string, length);
     502            2 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     503            0 :     cerr << "glShaderSource failed with error code " << error << '\n';
     504            0 :     switch (error) {
     505            0 :       default:
     506            0 :         assert(false);  // If we get here, add a new case to the switch
     507            0 :         [[fallthrough]];
     508            0 :       case GL_INVALID_VALUE:
     509            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     510            0 :       case GL_INVALID_OPERATION:
     511            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     512              :     }
     513              :   }
     514              : 
     515            2 :   return {};
     516              : }
     517              : 
     518            0 : auto UseProgram(unsigned int program) -> Expected<void> {
     519            0 :   glUseProgram(program);
     520            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     521            0 :     cerr << "glUseProgram failed with error code " << error << '\n';
     522            0 :     switch (error) {
     523            0 :       default:
     524            0 :         assert(false);  // If we get here, add a new case to the switch.
     525            0 :         [[fallthrough]];
     526            0 :       case GL_INVALID_OPERATION:
     527            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     528            0 :       case GL_INVALID_VALUE:
     529            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     530              :     }
     531              :   }
     532              : 
     533            0 :   return {};
     534              : }
     535              : 
     536            0 : auto VertexAttribPointer(unsigned int index, int size, GLDataType type,
     537              :                          unsigned char normalized, int stride,
     538              :                          const void* pointer) -> Expected<void> {
     539            0 :   GLenum gl_type = ConvertGLDataType(type);
     540            0 :   glVertexAttribPointer(index, size, gl_type, normalized, stride, pointer);
     541            0 :   if (GLenum error = glGetError(); error != GL_NO_ERROR) {
     542            0 :     cerr << "glVertexAttribPointer failed with error code " << error << '\n';
     543            0 :     switch (error) {
     544            0 :       default:
     545            0 :         assert(false);  // If we get here, add a new case to the switch.
     546            0 :         [[fallthrough]];
     547            0 :       case GL_INVALID_ENUM:
     548            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidEnum));
     549            0 :       case GL_INVALID_OPERATION:
     550            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidOperation));
     551            0 :       case GL_INVALID_VALUE:
     552            0 :         return unexpected(MakeErrorCode(kGLErrorInvalidValue));
     553              :     }
     554              :   }
     555              : 
     556            0 :   return {};
     557              : }
     558              : 
     559              : }  // namespace graphics_engine::gl_wrappers
        

Generated by: LCOV version 2.0-1