1/*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkOpenGLError.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14=========================================================================*/ 15#ifndef vtkOpenGLError_h 16#define vtkOpenGLError_h 17 18#include "vtkSetGet.h" 19#include "vtk_glew.h" 20#include <sstream> 21 22#ifndef NDEBUG 23// debug build. 24#cmakedefine VTK_REPORT_OPENGL_ERRORS 25#else // NDEBUG 26// release build 27#cmakedefine VTK_REPORT_OPENGL_ERRORS_IN_RELEASE_BUILDS 28#if defined(VTK_REPORT_OPENGL_ERRORS_IN_RELEASE_BUILDS) 29#cmakedefine VTK_REPORT_OPENGL_ERRORS 30#endif // defined(VTK_REPORT_OPENGL_ERRORS_IN_RELEASE_BUILDS) 31#endif // NDEBUG 32 33/** 34 * The following functions can be used to detect and report, and/or 35 * silently clear OpenGL error flags. These are not intended to be 36 * used directly, instead use the following macros. 37 * 38 * vtkOpenGLClearErrorMacro() -- Silently clear OpenGL error flags. 39 * 40 * vtkOpenGLCheckErrorMacro(message) -- Check and clear OpenGL's error 41 * flags. Report errors detected via vtkErrorMacro. 42 * 43 * vtkOpenGLStaticCheckErrorMacro(message) -- Check and clear OpenGL's 44 * error flags. Report errors detected via vtkGenericWarningMacro. 45 * This may be used in static methods and outside of vtkObjects. 46 * 47 * The intended usage pattern is to 1) call vtkOpenGLClearErrorMacro 48 * at the top of, and 2) vtkOpenGLCheckErrorMacro at the bottom of 49 * methods that make OpenGL calls. 50 * 51 * By calling vtkOpenGLClearErrorMacro at the top of a method that 52 * makes OpenGL calls, you isolate the code and prevent it from 53 * detecting any preceding errors. By calling vtkOpenGLCheckErrorMacro 54 * at the bottom of the method you clear the error flags and report 55 * any errors that have occurred in the method where they occurred. 56 * 57 * The macros maybe completely disabled via the CMakeLists variable 58 * VTK_REPORT_OPENGL_ERRORS. Note that in that case error flags are 59 * never cleared so that if an error occurs the flags will remain dirty 60 * making it impossible for anyone else to use them reliably. Please 61 * don't disable them with out a good reason. 62 */ 63 64/** 65 * Convert an OpenGL error code into a descriptive 66 * string. 67 */ 68inline 69const char *vtkOpenGLStrError(unsigned int code) 70{ 71 switch(static_cast<GLenum>(code)) 72 { 73 case GL_NO_ERROR: 74 return "No error"; 75 case GL_INVALID_ENUM: 76 return "Invalid enum"; 77 case GL_INVALID_VALUE: 78 return "Invalid value"; 79 case GL_INVALID_OPERATION: 80 return "Invalid operation"; 81 case GL_OUT_OF_MEMORY: 82 return "Out of memory"; 83#if GL_ES_VERSION_3_0 != 1 84 case GL_STACK_OVERFLOW: 85 return "Stack overflow"; 86 case GL_STACK_UNDERFLOW: 87 return "Stack underflow"; 88 case GL_TABLE_TOO_LARGE: 89 return "Table too large"; 90 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: 91 return "Invalid framebuffer operation"; 92#endif 93 } 94 return "Unknown error"; 95} 96 97/** 98 * Check for OpenGL errors. Error status is querried until 99 * OpenGL reports no errors. The list of errors and their 100 * descriptions are returned in the user supplied arrays. 101 * User passes the size of the arrays as the first argument. 102 * Error flags will still be cleared if the user arrays are 103 * less than the number of errors. 104 */ 105#if defined(VTK_REPORT_OPENGL_ERRORS) 106inline 107int vtkGetOpenGLErrors( 108 int maxNum, 109 unsigned int *errCode, 110 const char **errDesc) 111{ 112 int i = 0; 113 GLenum code = glGetError(); 114 if (i < maxNum) 115 { 116 errCode[i] = static_cast<unsigned int>(code); 117 errDesc[i] = vtkOpenGLStrError(code); 118 } 119 while (code != GL_NO_ERROR && i < maxNum) 120 { 121 i++; 122 code = glGetError(); 123 if (i < maxNum) 124 { 125 errCode[i] = static_cast<unsigned int>(code); 126 errDesc[i] = vtkOpenGLStrError(code); 127 } 128 } 129 return i; 130} 131#else 132inline 133int vtkGetOpenGLErrors( 134 int maxNum, 135 unsigned int *errCode, 136 const char **errDesc) 137{ 138 (void)maxNum; 139 (void)errCode; 140 (void)errDesc; 141 return 0; 142} 143#endif 144 145/** 146 * Send a set of errors collected by GetOpenGLErrors 147 * to the give stream. The number of errors is obtained 148 * in the return value of GetOpenGLErrors, while the max 149 * errors gives the size of the error arrays. 150 */ 151#if defined(VTK_REPORT_OPENGL_ERRORS) 152inline 153void vtkPrintOpenGLErrors( 154 ostream &os, 155 int maxErrors, 156 int numErrors, 157 unsigned int *errCode, 158 const char **errDesc) 159{ 160 os << numErrors << " OpenGL errors detected" << endl; 161 for (int i=0; (i<numErrors)&&(i<maxErrors); ++i) 162 { 163 os << " " << i << " : (" << errCode[i] << ") " << errDesc[i] << endl; 164 } 165 if (numErrors>maxErrors) 166 { 167 os 168 << "More than " << maxErrors 169 << " detected! The remainder are not reported" 170 << endl; 171 } 172} 173#else 174inline 175void vtkPrintOpenGLErrors( 176 ostream &os, 177 int maxErrors, 178 int numErrors, 179 unsigned int *errCode, 180 const char **errDesc) 181{ 182 (void)os; 183 (void)maxErrors; 184 (void)numErrors; 185 (void)errCode; 186 (void)errDesc; 187} 188#endif 189 190/** 191 * Errors are queried and reported via vtkGenericWarningMacro. An optional 192 * header message can be appended to the stream. Returns true if no errors 193 * were reported. 194 */ 195#if defined(VTK_REPORT_OPENGL_ERRORS) 196inline 197bool vtkOpenGLCheckErrors(const char* headerMessage = "") 198{ 199 const int maxNumErrors = 16; 200 unsigned int errCode[maxNumErrors] = {0}; 201 const char* errDesc[maxNumErrors] = {NULL}; 202 int numErrors = vtkGetOpenGLErrors(maxNumErrors, errCode, errDesc); 203 if (numErrors > 0) 204 { 205 std::ostringstream oss; 206 vtkPrintOpenGLErrors(oss, maxNumErrors, numErrors, errCode, errDesc); 207 vtkGenericWarningMacro(<< headerMessage << oss.str().c_str()); 208 return false; 209 } 210 return true; 211} 212#else 213inline 214bool vtkOpenGLCheckErrors(const char* errorMessage = "") 215{ 216 (void)errorMessage; 217 return true; 218} 219#endif 220 221/** 222 * Clear OpenGL's error flags. 223 */ 224#if defined(VTK_REPORT_OPENGL_ERRORS) 225inline 226void vtkClearOpenGLErrors(const unsigned int maxErrors = 16) 227{ 228 GLenum glError; 229 unsigned int i = 0; 230 do 231 { 232 glError = glGetError(); 233 ++i; 234 } 235 while(i < maxErrors && glError != GL_NO_ERROR); 236} 237#else 238inline 239void vtkClearOpenGLErrors(const unsigned int maxErrors = 16) 240{ 241 (void) maxErrors; 242} 243#endif 244 245#if !defined(VTK_REPORT_OPENGL_ERRORS) 246# define vtkOpenGLClearErrorMacro() 247# define vtkOpenGLCheckErrorMacro(message) 248# define vtkOpenGLStaticCheckErrorMacro(message) 249#else 250# define vtkOpenGLClearErrorMacro() vtkClearOpenGLErrors(16); 251# include <sstream> // for error macro 252# define vtkOpenGLCheckErrorMacroImpl(ostr, message) \ 253{ \ 254 const int maxErrors = 16; \ 255 unsigned int errCode[maxErrors] = {0}; \ 256 const char *errDesc[maxErrors] = {NULL}; \ 257 \ 258 int numErrors \ 259 = vtkGetOpenGLErrors( \ 260 maxErrors, \ 261 errCode, \ 262 errDesc); \ 263 \ 264 if (numErrors) \ 265 { \ 266 std::ostringstream oss; \ 267 vtkPrintOpenGLErrors( \ 268 oss, \ 269 maxErrors, \ 270 numErrors, \ 271 errCode, \ 272 errDesc); \ 273 \ 274 ostr(<< message << " " << oss.str().c_str()); \ 275 } \ 276} 277# define vtkOpenGLCheckErrorMacro(message) \ 278 vtkOpenGLCheckErrorMacroImpl(vtkErrorMacro, message) 279# define vtkOpenGLStaticCheckErrorMacro(message) \ 280 vtkOpenGLCheckErrorMacroImpl(vtkGenericWarningMacro, message) 281#endif 282 283// Use this macro for fine grained error checking during 284// debugging. It is removed for Release builds. 285#ifdef NDEBUG 286# define vtkOpenGLDebugClearErrorMacro() 287# define vtkOpenGLDebugCheckErrorMacro(message) 288#else 289# define vtkOpenGLDebugClearErrorMacro() \ 290 vtkOpenGLClearErrorMacro() 291# define vtkOpenGLDebugCheckErrorMacro(message) \ 292 vtkOpenGLStaticCheckErrorMacro(message) 293#endif 294 295#endif 296// VTK-HeaderTest-Exclude: vtkOpenGLError.h 297