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
21#cmakedefine VTK_REPORT_OPENGL_ERRORS
22
23// Description:
24// The following functions can be used to detect and report, and/or
25// silently clear OpenGL error flags. These are not intended to be
26// used driectly, instead use the following macros.
27//
28// vtkOpenGLClearErrorMacro() -- Silently clear OpenGL error flags.
29//
30// vtkOpenGLCheckErrorMacro(message) -- Check and clear OpenGL's error
31// flags. Report errors detected via vtkErrorMacro.
32//
33// vtkOpenGLStaticCheckErrorMacro(message) -- Check and clear OpenGL's
34// error flags. Report errors detected via vtkGenericWarningMacro.
35// This may be used in static methods and outside of vtkObjects.
36//
37// The intended usage pattern is to 1) call vtkOpenGLClearErrorMacro
38// at the top of, and 2) vtkOpenGLCheckErrorMacro at the bottom of
39// methods that make OpenGL calls.
40//
41// By calling vtkOpenGLClearErrorMacro at the top of a method that
42// makes OpenGL calls, you isolate the code and prevent it from
43// detecting any preceding errors. By calling vtkOpenGLCheckErrorMacro
44// at the bottom of the method you clear the error flags and report
45// any errors that have occured in the method where they occured.
46//
47// The macros maybe completely disabled via the CMakeLists variable
48// VTK_REPORT_OPENGL_ERRORS. Note that in that case error flags are
49// never cleared so that if an error occurs the flags will remain dirty
50// making it impossible for anyone else to use them reliably. Please
51// don't disable them with out a good reason.
52
53
54
55// Description:
56// Convert an OpenGL error code into a descriptive
57// string.
58inline
59const char *vtkOpenGLStrError(unsigned int code)
60{
61  switch(static_cast<GLenum>(code))
62    {
63    case GL_NO_ERROR:
64      return "No error";
65    case GL_INVALID_ENUM:
66      return "Invalid enum";
67    case GL_INVALID_VALUE:
68      return "Invalid value";
69    case GL_INVALID_OPERATION:
70      return "Invalid operation";
71    case GL_OUT_OF_MEMORY:
72      return "Out of memory";
73#if GL_ES_VERSION_2_0 != 1
74    case GL_STACK_OVERFLOW:
75      return "Stack overflow";
76    case GL_STACK_UNDERFLOW:
77      return "Stack underflow";
78    case GL_TABLE_TOO_LARGE:
79      return "Table too large";
80    case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
81      return "Invalid framebuffer operation";
82#endif
83    }
84  return "Unknown error";
85}
86
87// Description:
88// Check for OpenGL errors. Error status is querried until
89// OpenGL reports no errors. The list of errors and their
90// descriptions are returned in the user supplied arrays.
91// User passes the size of the arrays as the first argument.
92// Error flags will still be cleared if the user arays are
93// less than the number of errors.
94#if defined(VTK_REPORT_OPENGL_ERRORS)
95inline
96int vtkGetOpenGLErrors(
97      int maxNum,
98      unsigned int *errCode,
99      const char **errDesc)
100{
101  int i = 0;
102  GLenum code = glGetError();
103  if (i < maxNum)
104    {
105    errCode[i] = static_cast<unsigned int>(code);
106    errDesc[i] = vtkOpenGLStrError(code);
107    }
108  while (code != GL_NO_ERROR && i < maxNum)
109    {
110    i++;
111    code = glGetError();
112    if (i < maxNum)
113      {
114      errCode[i] = static_cast<unsigned int>(code);
115      errDesc[i] = vtkOpenGLStrError(code);
116      }
117    }
118  return i;
119}
120#else
121inline
122int vtkGetOpenGLErrors(
123      int maxNum,
124      unsigned int *errCode,
125      const char **errDesc)
126{
127  (void)maxNum;
128  (void)errCode;
129  (void)errDesc;
130  return 0;
131}
132#endif
133
134// Description:
135// Send a set of errors collected by GetOpenGLErrors
136// to the give stream. The number of errors is obtained
137// in the return value of GetOpenGLErrors, while the max
138// errors gives the size of the error arrays.
139#if defined(VTK_REPORT_OPENGL_ERRORS)
140inline
141void vtkPrintOpenGLErrors(
142      ostream &os,
143      int maxErrors,
144      int numErrors,
145      unsigned int *errCode,
146      const char **errDesc)
147{
148  os << numErrors << " OpenGL errors detected" << endl;
149  for (int i=0; (i<numErrors)&&(i<maxErrors); ++i)
150    {
151    os << "  " <<  i << " : (" << errCode[i] << ") " << errDesc[i] << endl;
152    }
153  if (numErrors>maxErrors)
154    {
155    os
156      << "More than " << maxErrors
157      << " detected! The remainder are not reported"
158      << endl;
159    }
160}
161#else
162inline
163void vtkPrintOpenGLErrors(
164      ostream &os,
165      int maxErrors,
166      int numErrors,
167      unsigned int *errCode,
168      const char **errDesc)
169{
170  (void)os;
171  (void)maxErrors;
172  (void)numErrors;
173  (void)errCode;
174  (void)errDesc;
175}
176#endif
177
178// Description:
179// Clear OpenGL's error flags.
180#if defined(VTK_REPORT_OPENGL_ERRORS)
181inline
182void vtkClearOpenGLErrors(const unsigned int maxErrors = 16)
183{
184  GLenum glError;
185  unsigned int i = 0;
186  do
187    {
188    glError = glGetError();
189    ++i;
190    }
191  while(i < maxErrors && glError != GL_NO_ERROR);
192}
193#else
194inline
195void vtkClearOpenGLErrors(const unsigned int maxErrors = 16)
196{
197  (void) maxErrors;
198}
199#endif
200
201#if !defined(VTK_REPORT_OPENGL_ERRORS)
202# define vtkOpenGLClearErrorMacro()
203# define vtkOpenGLCheckErrorMacro(message)
204# define vtkOpenGLStaticCheckErrorMacro(message)
205#else
206# define vtkOpenGLClearErrorMacro() vtkClearOpenGLErrors(16);
207# include <sstream> // for error macro
208# define vtkOpenGLCheckErrorMacroImpl(ostr, message) \
209{                                                    \
210  const int maxErrors = 16;                          \
211  unsigned int errCode[maxErrors] = {0};             \
212  const char *errDesc[maxErrors] = {NULL};           \
213                                                     \
214  int numErrors                                      \
215    = vtkGetOpenGLErrors(                            \
216        maxErrors,                                   \
217        errCode,                                     \
218        errDesc);                                    \
219                                                     \
220  if (numErrors)                                     \
221    {                                                \
222    std::ostringstream oss;                          \
223    vtkPrintOpenGLErrors(                            \
224          oss,                                       \
225          maxErrors,                                 \
226          numErrors,                                 \
227          errCode,                                   \
228          errDesc);                                  \
229                                                     \
230    ostr(<< message << " " << oss.str().c_str());    \
231    }                                                \
232}
233# define vtkOpenGLCheckErrorMacro(message) \
234  vtkOpenGLCheckErrorMacroImpl(vtkErrorMacro, message)
235# define vtkOpenGLStaticCheckErrorMacro(message) \
236  vtkOpenGLCheckErrorMacroImpl(vtkGenericWarningMacro, message)
237#endif
238
239// Use this macro for fine grained error checking during
240// debugging. It is removed for Release builds.
241#ifdef NDEBUG
242# define vtkOpenGLDebugClearErrorMacro()
243# define vtkOpenGLDebugCheckErrorMacro(message)
244#else
245# define vtkOpenGLDebugClearErrorMacro() \
246  vtkOpenGLClearErrorMacro()
247# define vtkOpenGLDebugCheckErrorMacro(message) \
248  vtkOpenGLStaticCheckErrorMacro(message)
249#endif
250
251#endif
252// VTK-HeaderTest-Exclude: vtkOpenGLError.h
253