OGLplus (0.45.0) a C++ wrapper for OpenGL

error.hpp
Go to the documentation of this file.
1 
12 #pragma once
13 #ifndef OGLPLUS_ERROR_1107121317_HPP
14 #define OGLPLUS_ERROR_1107121317_HPP
15 
16 #include <oglplus/auxiliary/obj_desc.hpp>
17 #include <oglplus/config.hpp>
18 #include <stdexcept>
19 #include <cassert>
20 #include <list>
21 #include <map>
22 
23 #if OGLPLUS_CUSTOM_ERROR_HANDLING
24 #include <functional>
25 #endif
26 
27 #define OGLPLUS_ERROR_INFO_CONTEXT(CONTEXT, CLASS) \
28  static const char* _errinf_ctxt(void) \
29  { \
30  return #CONTEXT; \
31  } \
32  static const char* _errinf_cls(void) \
33  { \
34  return #CLASS; \
35  }
36 
37 #define OGLPLUS_ERROR_INFO_REUSE_CONTEXT(SOURCE) \
38  using SOURCE::_errinf_ctxt; \
39  using SOURCE::_errinf_cls;
40 
41 
42 // Define a macro that initializes the _glsym member of ErrorInfo
43 #if OGLPLUS_ERROR_INFO_NO_GL_SYMBOL
44 #define OGLPLUS_ERROR_INFO_INIT_GLSYM(SYMBOL)
45 #else
46 #define OGLPLUS_ERROR_INFO_INIT_GLSYM(SYMBOL) , SYMBOL
47 #endif
48 
49 // Define a macro that initializes the _file member of ErrorInfo
50 #if OGLPLUS_ERROR_INFO_NO_FILE
51 #define OGLPLUS_ERROR_INFO_INIT_FILE(FILEPATH)
52 #else
53 #define OGLPLUS_ERROR_INFO_INIT_FILE(FILEPATH) , FILEPATH
54 #endif
55 
56 // Define a macro that initializes the _func member of ErrorInfo
57 #if OGLPLUS_ERROR_INFO_NO_FUNC
58 #define OGLPLUS_ERROR_INFO_INIT_FUNC(FUNC)
59 #else
60 #define OGLPLUS_ERROR_INFO_INIT_FUNC(FUNC) , FUNC
61 #endif
62 
63 // Define a macro that initializes the _line member of ErrorInfo
64 #if OGLPLUS_ERROR_INFO_NO_LINE
65 #define OGLPLUS_ERROR_INFO_INIT_LINE(LINE)
66 #else
67 #define OGLPLUS_ERROR_INFO_INIT_LINE(LINE) , LINE
68 #endif
69 
70 // Define a macro that initializes the _cls_name member of ErrorInfo
71 #if OGLPLUS_ERROR_INFO_NO_CLASS_NAME
72 #define OGLPLUS_ERROR_INFO_INIT_CLS_NAME(NAME)
73 #else
74 #define OGLPLUS_ERROR_INFO_INIT_CLS_NAME(NAME) , NAME
75 #endif
76 
77 // Define a macro that initializes the _bind_tgt member of ErrorInfo
78 #if OGLPLUS_ERROR_INFO_NO_BIND_TARGET
79 #define OGLPLUS_ERROR_INFO_INIT_BIND_TGT(NAME)
80 #else
81 #define OGLPLUS_ERROR_INFO_INIT_BIND_TGT(NAME) , NAME
82 #endif
83 
84 // Define a macro that initializes the description-related members of ErrorInfo
85 #if OGLPLUS_ERROR_INFO_NO_OBJECT_DESC
86 #define OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(GET, PURGE, NAME)
87 #else
88 #define OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(GET, PURGE, NAME) \
89  , GET, PURGE, GLuint(NAME)
90 #endif
91 
92 
93 #define OGLPLUS_ERROR_INFO(CONTEXT) \
94 oglplus::ErrorInfo(\
95  sizeof(decltype(&gl ## CONTEXT)) \
96  OGLPLUS_ERROR_INFO_INIT_GLSYM(#CONTEXT) \
97  OGLPLUS_ERROR_INFO_INIT_FILE(__FILE__) \
98  OGLPLUS_ERROR_INFO_INIT_FUNC(__FUNCTION__) \
99  OGLPLUS_ERROR_INFO_INIT_LINE(__LINE__) \
100  OGLPLUS_ERROR_INFO_INIT_CLS_NAME("") \
101  OGLPLUS_ERROR_INFO_INIT_BIND_TGT(StrLit()) \
102  OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(nullptr, nullptr, 0) \
103 )
104 
105 #define OGLPLUS_LIMIT_ERROR_INFO(CONTEXT) \
106 oglplus::ErrorInfo(\
107  sizeof(decltype(GL_ ## CONTEXT)) \
108  OGLPLUS_ERROR_INFO_INIT_GLSYM(#CONTEXT) \
109  OGLPLUS_ERROR_INFO_INIT_FILE(__FILE__) \
110  OGLPLUS_ERROR_INFO_INIT_FUNC(__FUNCTION__) \
111  OGLPLUS_ERROR_INFO_INIT_LINE(__LINE__) \
112  OGLPLUS_ERROR_INFO_INIT_CLS_NAME("") \
113  OGLPLUS_ERROR_INFO_INIT_BIND_TGT(StrLit()) \
114  OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(nullptr, nullptr, 0) \
115 )
116 
117 #define OGLPLUS_ERROR_INFO_AUTO_CTXT() \
118 oglplus::ErrorInfo(\
119  0 \
120  OGLPLUS_ERROR_INFO_INIT_GLSYM(_errinf_ctxt()) \
121  OGLPLUS_ERROR_INFO_INIT_FILE(__FILE__) \
122  OGLPLUS_ERROR_INFO_INIT_FUNC(__FUNCTION__) \
123  OGLPLUS_ERROR_INFO_INIT_LINE(__LINE__) \
124  OGLPLUS_ERROR_INFO_INIT_CLS_NAME(_errinf_cls()) \
125  OGLPLUS_ERROR_INFO_INIT_BIND_TGT(StrLit()) \
126  OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(nullptr, nullptr, 0) \
127 )
128 
129 #define OGLPLUS_ERROR_INFO_STR(CONTEXT_STR) \
130 oglplus::ErrorInfo(\
131  0 \
132  OGLPLUS_ERROR_INFO_INIT_GLSYM(CONTEXT_STR) \
133  OGLPLUS_ERROR_INFO_INIT_FILE(__FILE__) \
134  OGLPLUS_ERROR_INFO_INIT_FUNC(__FUNCTION__) \
135  OGLPLUS_ERROR_INFO_INIT_LINE(__LINE__) \
136  OGLPLUS_ERROR_INFO_INIT_CLS_NAME("") \
137  OGLPLUS_ERROR_INFO_INIT_BIND_TGT(StrLit()) \
138  OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS(nullptr, nullptr, 0) \
139 )
140 
141 #define OGLPLUS_OBJECT_ERROR_INFO(CONTEXT, CLASS, TARGET_NAME, NAME) \
142 oglplus::ErrorInfo(\
143  sizeof(decltype(&gl ## CONTEXT)) \
144  OGLPLUS_ERROR_INFO_INIT_GLSYM(#CONTEXT) \
145  OGLPLUS_ERROR_INFO_INIT_FILE(__FILE__) \
146  OGLPLUS_ERROR_INFO_INIT_FUNC(__FUNCTION__) \
147  OGLPLUS_ERROR_INFO_INIT_LINE(__LINE__) \
148  OGLPLUS_ERROR_INFO_INIT_CLS_NAME(#CLASS) \
149  OGLPLUS_ERROR_INFO_INIT_BIND_TGT(TARGET_NAME) \
150  OGLPLUS_ERROR_INFO_INIT_OBJ_DECS_FUNCS( \
151  &oglplus::aux::ObjectDescRegistry<CLASS##Ops>::_get_desc, \
152  &oglplus::aux::ObjectDescRegistry<CLASS##Ops>::_purge_archive,\
153  NAME \
154  ) \
155 )
156 
157 namespace oglplus {
158 
166 
176 struct ErrorInfo
177 {
178  // the data members of this structure are internal
179  // implementation details which are subject to change
180  // without any prior notice. Do not use directly.
181 
182  const size_t _dummy;
183 
184 #if !OGLPLUS_ERROR_INFO_NO_GL_SYMBOL
185  const char* _glsym;
186 #endif
187 
188 #if !OGLPLUS_ERROR_INFO_NO_FILE
189  const char* _file;
190 #endif
191 
192 #if !OGLPLUS_ERROR_INFO_NO_FUNC
193  const char* _func;
194 #endif
195 
196 #if !OGLPLUS_ERROR_INFO_NO_LINE
197  const unsigned _line;
198 #endif
199 
200 #if !OGLPLUS_ERROR_INFO_NO_CLASS_NAME
201  const char* _cls_name;
202 #endif
203 
204 #if !OGLPLUS_ERROR_INFO_NO_BIND_TARGET
205  const StrLit _bind_tgt;
206 #endif
207 
208 #if !OGLPLUS_ERROR_INFO_NO_OBJECT_DESC
209  const String& (*_get_obj_desc)(GLuint);
210  void (*_purge_archive)(void);
211  GLuint _obj_name;
212 #endif
213 
214  inline ErrorInfo(
215  const size_t dummy
217  , const char* glsym
218 #endif
219 
221  , const char* file
222 #endif
223 
225  , const char* func
226 #endif
227 
229  , const unsigned line
230 #endif
231 
233  , const char* cls_name
234 #endif
235 
237  , const StrLit& bind_tgt
238 #endif
239 
241  , const String& (*get_obj_desc)(GLuint)
242  , void (*purge_archive)(void)
243  , GLuint obj_name
244 #endif
245  ): _dummy(dummy)
246 
247 #if !OGLPLUS_ERROR_INFO_NO_GL_SYMBOL
248  , _glsym(glsym)
249 #endif
250 
251 #if !OGLPLUS_ERROR_INFO_NO_FILE
252  , _file(file)
253 #endif
254 
255 #if !OGLPLUS_ERROR_INFO_NO_FUNC
256  , _func(func)
257 #endif
258 
259 #if !OGLPLUS_ERROR_INFO_NO_LINE
260  , _line(line)
261 #endif
262 
263 #if !OGLPLUS_ERROR_INFO_NO_CLASS_NAME
264  , _cls_name(cls_name)
265 #endif
266 
267 #if !OGLPLUS_ERROR_INFO_NO_BIND_TARGET
268  , _bind_tgt(bind_tgt)
269 #endif
270 
271 #if !OGLPLUS_ERROR_INFO_NO_OBJECT_DESC
272  , _get_obj_desc(get_obj_desc)
273  , _purge_archive(purge_archive)
274  , _obj_name(obj_name)
275 #endif
276  { }
277 };
278 
280 
300 const char* ErrorGLSymbol(const ErrorInfo& info);
301 
303 
319 const char* ErrorFile(const ErrorInfo& info);
320 
322 
338 const char* ErrorFunc(const ErrorInfo& info);
339 
341 
357 unsigned ErrorLine(const ErrorInfo& info);
358 
360 
376 const char* ErrorClassName(const ErrorInfo& info);
377 
379 
395 const char* ErrorBindTarget(const ErrorInfo& info);
396 
398 
414 const String& ErrorObjectDescription(const ErrorInfo& info);
415 
417 
426 class Error
427  : public std::runtime_error
428 {
429 public:
431  typedef std::map<String, String> PropertyMap;
432 
433 #if !OGLPLUS_ERROR_NO_PROPERTIES
434  typedef PropertyMap PropertyMapInit;
435 #else
436  struct PropertyMapInit { };
437 #endif
438 
440  typedef std::list<ErrorInfo> PropagationInfoList;
441 private:
442  GLenum _code;
443  ErrorInfo _info;
444 #if !OGLPLUS_ERROR_NO_PROPERTIES
445  PropertyMap _properties;
446 #endif
447 
448 #if !OGLPLUS_ERROR_NO_PROPAGATION_INFO
449  PropagationInfoList _propagation;
450 #endif
451  bool _assertion;
452 public:
453  Error(
454  GLenum code,
455  const char* desc,
456  const ErrorInfo& info,
457  bool assertion = false
458  );
459 
460  Error(
461  GLenum code,
462  const char* desc,
463  const ErrorInfo& info,
464  PropertyMapInit&& properties
465  );
466 
467  inline ~Error(void) throw()
468  { }
469 
471 
481  GLenum Code(void) const
482  {
483  return _code;
484  }
485 
487 
496  const ErrorInfo& ThrowInfo(void) const
497  {
498  return _info;
499  }
500 
502 
515  const char* GLSymbol(void) const
516  {
518  }
519 
521 
530  const char* File(void) const
531  {
533  }
534 
536 
545  const char* Func(void) const
546  {
548  }
549 
551 
560  unsigned Line(void) const
561  {
563  }
564 
566  const char* ClassName(void) const
567  {
569  }
570 
572  const char* BindTarget(void) const
573  {
575  }
576 
578  const String& ObjectDescription(void) const
579  {
581  }
582 
583 #if OGLPLUS_DOCUMENTATION_ONLY || OGLPLUS_ERROR_NO_PROPERTIES
584 
589  {
590  return PropertyMap();
591  }
592 #else
593  const PropertyMap& Properties(void) const
594  {
595  return _properties;
596  }
597 #endif
598 
599 #if OGLPLUS_DOCUMENTATION_ONLY || !OGLPLUS_ERROR_NO_PROPERTIES
600  template <typename Key, typename Value>
602  static void AddPropertyValue(
603  PropertyMapInit& properties,
604  Key&& key,
605  Value&& value
606  )
607  {
608  properties[key] = value;
609  }
610 #else
611  template <typename Key, typename Value>
612  static void AddPropertyValue(PropertyMapInit&, Key&&, Value&&) { }
613 #endif
614 
616  void SetPropertyValue(const String& key, const String& value);
617 
618 #if OGLPLUS_DOCUMENTATION_ONLY || OGLPLUS_ERROR_NO_PROPAGATION_INFO
619 
624  {
625  return PropagationInfoList();
626  }
627 #else
628  const PropagationInfoList& PropagationInfo(void) const
629  {
630  return _propagation;
631  }
632 #endif
633 
634  void Trace(const ErrorInfo& info);
635 
636  void Cleanup(void) const;
637 };
638 
640 
646  : public Error
647 {
648 public:
649  OutOfMemory(GLenum code, const char* desc, const ErrorInfo& info)
650  : Error(code, desc, info, true)
651  { }
652 };
653 
654 #if OGLPLUS_DOCUMENTATION_ONLY
655 
673  : public Error
674 { };
675 #else
676 class MissingFunction
677  : public Error
678 {
679 public:
680  MissingFunction(GLenum code, const char* msg, const ErrorInfo& info)
681  : Error(code, msg, info, true)
682  { }
683 };
684 #endif
685 
687 
696  : public Error
697 {
698 private:
699  GLuint _value;
700  GLuint _limit;
701 public:
702  LimitError(
703  GLuint value,
704  GLuint limit,
705  const GLchar* msg,
706  const ErrorInfo& info
707  ): Error(GL_INVALID_VALUE, msg, info)
708  , _value(value)
709  , _limit(limit)
710  { }
711 
713  GLuint Value(void) const
714  {
715  return _value;
716  }
717 
719  GLuint Limit(void) const
720  {
721  return _limit;
722  }
723 };
724 
726 
733  : public Error
734 {
735 private:
736  GLint _location;
737 public:
739  GLenum code,
740  GLint location,
741  const GLchar* msg,
742  const ErrorInfo& info,
743  Error::PropertyMapInit&& properties
744  ): Error(code, msg, info, std::move(properties))
745  , _location(location)
746  { }
747 
749 
752  GLint Location(void) const
753  {
754  return _location;
755  }
756 };
757 
758 #if OGLPLUS_DOCUMENTATION_ONLY || OGLPLUS_CUSTOM_ERROR_HANDLING
759 
761 
767 struct ErrorData
768 {
769 private:
770  GLenum _error_code;
771  GLuint _value;
772  GLuint _limit;
773  const char* _message;
774  ErrorInfo _info;
775  Error::PropertyMap _properties;
776  bool _assertion;
777  bool _fatal_error;
778  bool _build_error;
779  bool _limit_error;
780 public:
782  inline GLenum ErrorCode(void) const
783  {
784  return _error_code;
785  }
786 
788  inline GLuint Value(void) const
789  {
790  return _value;
791  }
792 
794  inline GLuint Limit(void) const
795  {
796  return _limit;
797  }
798 
800 
803  inline const char* Message(void) const
804  {
805  return _message;
806  }
807 
809  inline const ErrorInfo& Info(void) const
810  {
811  return _info;
812  }
813 
815  inline const Error::PropertyMap& Properties(void) const
816  {
817  return _properties;
818  }
819 
821  inline bool Assertion(void) const
822  {
823  return _assertion;
824  }
825 
827  inline bool FatalError(void) const
828  {
829  return _fatal_error;
830  }
831 
833  inline bool BuildError(void) const
834  {
835  return _build_error;
836  }
837 
839  inline bool LimitError(void) const
840  {
841  return _limit_error;
842  }
843 
844  inline ErrorData(
845  GLenum error_code,
846  GLuint value,
847  GLuint limit,
848  const char* message,
849  const ErrorInfo& info,
850  Error::PropertyMapInit&& properties,
851  bool assertion,
852  bool fatal_error,
853  bool build_error,
854  bool limit_error
855  ): _error_code(error_code)
856  , _value(value)
857  , _limit(limit)
858  , _message(message)
859  , _info(info)
860  , _properties(std::move(properties))
861  , _assertion(assertion)
862  , _fatal_error(fatal_error)
863  , _build_error(build_error)
864  , _limit_error(limit_error)
865  { }
866 };
867 
869 
875 typedef std::function<bool (const ErrorData&)> ErrorHandlerFunc;
876 
877 namespace aux {
878 
879 bool _has_error_handler(void);
880 ErrorHandlerFunc& _get_error_handler(void);
881 
882 } // namespace aux
883 
885 
894 {
895 private:
896  size_t _installed;
897 
899 public:
902 
904  ~LocalErrorHandler(void);
905 };
906 
907 #endif // OGLPLUS_CUSTOM_ERROR_HANDLING
908 
909 template <class Exception>
910 inline void HandleBuildError(const String& msg, const ErrorInfo& info)
911 {
912 #if OGLPLUS_CUSTOM_ERROR_HANDLING
913  if(aux::_has_error_handler() && aux::_get_error_handler()(
914  ErrorData(
915  GL_INVALID_OPERATION,
916  0u, 0u,
917  msg.c_str(),
918  info,
919  Error::PropertyMapInit(),
920  false,
921  false,
922  true,
923  false
924  )
925  )) return;
926 #endif // OGLPLUS_CUSTOM_ERROR_HANDLING
927  throw Exception(msg, info);
928 }
929 
930 template <class Exception, typename FBStatus>
931 inline void HandleIncompleteFramebuffer(
932  FBStatus status,
933  const ErrorInfo& info
934 )
935 {
936  const GLchar* msg = "Framebuffer is incomplete";
937 #if OGLPLUS_CUSTOM_ERROR_HANDLING
938  if(aux::_has_error_handler() && aux::_get_error_handler()(
939  ErrorData(
940  GL_INVALID_FRAMEBUFFER_OPERATION,
941  0u, 0u,
942  msg,
943  info,
944  Error::PropertyMapInit(),
945  false,
946  false,
947  false,
948  true
949  )
950  )) return;
951 #endif // OGLPLUS_CUSTOM_ERROR_HANDLING
952  throw Exception(status, msg, info);
953 }
954 
955 void HandleShaderVariableError(
956  GLenum code,
957  GLint location,
958  const GLchar* msg,
959  const ErrorInfo& info,
960  Error::PropertyMapInit&& properties
961 );
962 
963 void HandleLimitError(GLuint value, GLuint limit, const ErrorInfo& info);
964 
965 #if !OGLPLUS_NO_VARIADIC_TEMPLATES && !OGLPLUS_NO_GLFUNC_CHECKS
966 void HandleMissingFunction(const ErrorInfo& info);
967 #endif // OGLPLUS_NO_VARIADIC_TEMPLATES || OGLPLUS_NO_GLFUNC_CHECKS
968 
969 void HandleError(
970  GLenum code,
971  const GLchar* msg,
972  const ErrorInfo& info,
973  Error::PropertyMapInit&& properties
974 );
975 
976 void HandleError(GLenum code, const ErrorInfo& info, bool assertion);
977 
978 #if OGLPLUS_DOCUMENTATION_ONLY
979 
985 #define OGLPLUS_IS_ERROR(EXPRESSION)
986 #endif
987 
988 #ifndef OGLPLUS_IS_ERROR
989 #define OGLPLUS_IS_ERROR(EXPRESSION) (EXPRESSION)
990 #endif
991 
992 #if OGLPLUS_DOCUMENTATION_ONLY
993 
997 #define OGLPLUS_CHECK(PARAM)
998 #endif
999 
1000 #ifndef OGLPLUS_CHECK
1001 #define OGLPLUS_CHECK(PARAM) { \
1002  GLenum error_code = ::glGetError(); \
1003  if(error_code != GL_NO_ERROR) HandleError(error_code, PARAM, false); \
1004 }
1005 #endif
1006 
1007 #if OGLPLUS_DOCUMENTATION_ONLY
1008 
1013 #define OGLPLUS_VERIFY(PARAM)
1014 #endif
1015 
1016 #ifndef OGLPLUS_VERIFY
1017 #if !OGPLUS_LOW_PROFILE
1018 #define OGLPLUS_VERIFY(PARAM) { \
1019  GLenum error_code = ::glGetError(); \
1020  if(error_code != GL_NO_ERROR) HandleError(error_code, PARAM, true); \
1021 }
1022 #else
1023 #define OGLPLUS_VERIFY(PARAM)
1024 #endif
1025 #endif
1026 
1027 #define OGLPLUS_IGNORE(PARAM) ::glGetError();
1028 
1029 } // namespace oglplus
1030 
1031 #if !OGLPLUS_LINK_LIBRARY || defined(OGLPLUS_IMPLEMENTING_LIBRARY)
1032 #include <oglplus/error.ipp>
1033 #endif
1034 
1035 #endif // include guard

Copyright © 2010-2014 Matúš Chochlík, University of Žilina, Žilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Wed Apr 30 2014 by Doxygen (version 1.8.4).