Fixed bug 1837 - Use error extension instead of glGetError()
authorSam Lantinga <slouken@libsdl.org>
Sun, 19 May 2013 22:28:10 -0700
changeset 7194987fb567bba9
parent 7193 c37d853c2f5e
child 7195 d206c3a59b2e
Fixed bug 1837 - Use error extension instead of glGetError()

Implemented support for GL_ARB_debug_output, but was unable to test it on Mac OS X.
include/SDL_test_common.h
src/render/opengl/SDL_glfuncs.h
src/render/opengl/SDL_render_gl.c
src/test/SDL_test_common.c
test/testgl2.c
     1.1 --- a/include/SDL_test_common.h	Sat May 18 23:32:53 2013 -0700
     1.2 +++ b/include/SDL_test_common.h	Sun May 19 22:28:10 2013 -0700
     1.3 @@ -104,6 +104,7 @@
     1.4      int gl_accelerated;
     1.5      int gl_major_version;
     1.6      int gl_minor_version;
     1.7 +    int gl_debug;
     1.8  } SDLTest_CommonState;
     1.9  
    1.10  #include "begin_code.h"
     2.1 --- a/src/render/opengl/SDL_glfuncs.h	Sat May 18 23:32:53 2013 -0700
     2.2 +++ b/src/render/opengl/SDL_glfuncs.h	Sun May 19 22:28:10 2013 -0700
     2.3 @@ -152,7 +152,7 @@
     2.4  SDL_PROC_UNUSED(void, glGetPixelMapfv, (GLenum map, GLfloat * values))
     2.5  SDL_PROC_UNUSED(void, glGetPixelMapuiv, (GLenum map, GLuint * values))
     2.6  SDL_PROC_UNUSED(void, glGetPixelMapusv, (GLenum map, GLushort * values))
     2.7 -SDL_PROC_UNUSED(void, glGetPointerv, (GLenum pname, GLvoid * *params))
     2.8 +SDL_PROC(void, glGetPointerv, (GLenum pname, GLvoid * *params))
     2.9  SDL_PROC_UNUSED(void, glGetPolygonStipple, (GLubyte * mask))
    2.10  SDL_PROC(const GLubyte *, glGetString, (GLenum name))
    2.11  SDL_PROC_UNUSED(void, glGetTexEnvfv,
     3.1 --- a/src/render/opengl/SDL_render_gl.c	Sat May 18 23:32:53 2013 -0700
     3.2 +++ b/src/render/opengl/SDL_render_gl.c	Sun May 19 22:28:10 2013 -0700
     3.3 @@ -100,6 +100,13 @@
     3.4  typedef struct
     3.5  {
     3.6      SDL_GLContext context;
     3.7 +
     3.8 +    SDL_bool GL_ARB_debug_output_supported;
     3.9 +    int errors;
    3.10 +    char **error_messages;
    3.11 +    GLDEBUGPROCARB next_error_callback;
    3.12 +    GLvoid *next_error_userparam;
    3.13 +
    3.14      SDL_bool GL_ARB_texture_rectangle_supported;
    3.15      struct {
    3.16          GL_Shader shader;
    3.17 @@ -151,7 +158,7 @@
    3.18      GL_FBOList *fbo;
    3.19  } GL_TextureData;
    3.20  
    3.21 -static __inline__ const char*
    3.22 +SDL_FORCE_INLINE const char*
    3.23  GL_TranslateError (GLenum error)
    3.24  {
    3.25  #define GL_ERROR_TRANSLATE(e) case e: return #e;
    3.26 @@ -170,22 +177,57 @@
    3.27  #undef GL_ERROR_TRANSLATE
    3.28  }
    3.29  
    3.30 -static __inline__ int
    3.31 -GL_CheckAllErrors (const char *prefix, SDL_Renderer * renderer, const char *file, int line, const char *function)
    3.32 +SDL_FORCE_INLINE void
    3.33 +GL_ClearErrors(SDL_Renderer *renderer)
    3.34 +{
    3.35 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    3.36 +
    3.37 +    if (data->GL_ARB_debug_output_supported) {
    3.38 +        if (data->errors) {
    3.39 +            int i;
    3.40 +            for (i = 0; i < data->errors; ++i) {
    3.41 +                SDL_free(data->error_messages[i]);
    3.42 +            }
    3.43 +            SDL_free(data->error_messages);
    3.44 +
    3.45 +            data->errors = 0;
    3.46 +            data->error_messages = NULL;
    3.47 +        }
    3.48 +    } else {
    3.49 +        while (data->glGetError() != GL_NO_ERROR) {
    3.50 +            continue;
    3.51 +        }
    3.52 +    }
    3.53 +}
    3.54 +
    3.55 +SDL_FORCE_INLINE int
    3.56 +GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
    3.57  {
    3.58      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    3.59      int ret = 0;
    3.60 -    /* check gl errors (can return multiple errors) */
    3.61 -    for (;;) {
    3.62 -        GLenum error = data->glGetError();
    3.63 -        if (error != GL_NO_ERROR) {
    3.64 -            if (prefix == NULL || prefix[0] == '\0') {
    3.65 -                prefix = "generic";
    3.66 +
    3.67 +    if (data->GL_ARB_debug_output_supported) {
    3.68 +        if (data->errors) {
    3.69 +            int i;
    3.70 +            for (i = 0; i < data->errors; ++i) {
    3.71 +                SDL_SetError("%s: %s (%d): %s %s", prefix, file, line, function, data->error_messages[i]);
    3.72 +                ret = -1;
    3.73              }
    3.74 -            SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
    3.75 -            ret++;
    3.76 -        } else {
    3.77 -            break;
    3.78 +            GL_ClearErrors(renderer);
    3.79 +        }
    3.80 +    } else {
    3.81 +        /* check gl errors (can return multiple errors) */
    3.82 +        for (;;) {
    3.83 +            GLenum error = data->glGetError();
    3.84 +            if (error != GL_NO_ERROR) {
    3.85 +                if (prefix == NULL || prefix[0] == '\0') {
    3.86 +                    prefix = "generic";
    3.87 +                }
    3.88 +                SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
    3.89 +                ret = -1;
    3.90 +            } else {
    3.91 +                break;
    3.92 +            }
    3.93          }
    3.94      }
    3.95      return ret;
    3.96 @@ -226,6 +268,7 @@
    3.97  {
    3.98      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    3.99  
   3.100 +    GL_ClearErrors(renderer);
   3.101      if (SDL_CurrentContext != data->context) {
   3.102          if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
   3.103              return -1;
   3.104 @@ -264,8 +307,35 @@
   3.105      GL_CheckError("", renderer);
   3.106  }
   3.107  
   3.108 +static void
   3.109 +GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, void *userParam)
   3.110 +{
   3.111 +    SDL_Renderer *renderer = (SDL_Renderer *) userParam;
   3.112 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   3.113  
   3.114 -GL_FBOList *
   3.115 +    if (type == GL_DEBUG_TYPE_ERROR_ARB) {
   3.116 +        /* Record this error */
   3.117 +        ++data->errors;
   3.118 +        data->error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages));
   3.119 +        if (data->error_messages) {
   3.120 +            data->error_messages[data->errors-1] = SDL_strdup(message);
   3.121 +        }
   3.122 +    }
   3.123 +    printf("%s\n", message);
   3.124 +
   3.125 +    /* If there's another error callback, pass it along, otherwise log it */
   3.126 +    if (data->next_error_callback) {
   3.127 +        data->next_error_callback(source, type, id, severity, length, message, data->next_error_userparam);
   3.128 +    } else {
   3.129 +        if (type == GL_DEBUG_TYPE_ERROR_ARB) {
   3.130 +            SDL_LogError(SDL_LOG_CATEGORY_RENDER, "%s", message);
   3.131 +        } else {
   3.132 +            SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "%s", message);
   3.133 +        }
   3.134 +    }
   3.135 +}
   3.136 +
   3.137 +static GL_FBOList *
   3.138  GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
   3.139  {
   3.140      GL_FBOList *result = data->framebuffers;
   3.141 @@ -374,6 +444,16 @@
   3.142          renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   3.143      }
   3.144  
   3.145 +    /* Check for debug output support */
   3.146 +    if (SDL_GL_ExtensionSupported("GL_ARB_debug_output")) {
   3.147 +        PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
   3.148 +
   3.149 +        data->GL_ARB_debug_output_supported = SDL_TRUE;
   3.150 +        data->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION_ARB, (GLvoid **)&data->next_error_callback);
   3.151 +        data->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM_ARB, &data->next_error_userparam);
   3.152 +        glDebugMessageCallbackARBFunc(GL_HandleDebugMessage, renderer);
   3.153 +    }
   3.154 +
   3.155      if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
   3.156          || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
   3.157          data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
   3.158 @@ -442,7 +522,7 @@
   3.159      }
   3.160  }
   3.161  
   3.162 -static __inline__ int
   3.163 +SDL_FORCE_INLINE int
   3.164  power_of_2(int input)
   3.165  {
   3.166      int value = 1;
   3.167 @@ -453,7 +533,7 @@
   3.168      return value;
   3.169  }
   3.170  
   3.171 -static __inline__ SDL_bool
   3.172 +SDL_FORCE_INLINE SDL_bool
   3.173  convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
   3.174                 GLint* internalFormat, GLenum* format, GLenum* type)
   3.175  {
   3.176 @@ -602,7 +682,7 @@
   3.177                                   texture_h, 0, format, type, NULL);
   3.178      }
   3.179      renderdata->glDisable(data->type);
   3.180 -    if (GL_CheckError("glTexImage2D()", renderer) > 0) {
   3.181 +    if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   3.182          return -1;
   3.183      }
   3.184  
   3.185 @@ -641,8 +721,7 @@
   3.186          renderdata->glDisable(data->type);
   3.187      }
   3.188  
   3.189 -    GL_CheckError("", renderer);
   3.190 -    return 0;
   3.191 +    return GL_CheckError("", renderer);
   3.192  }
   3.193  
   3.194  static int
   3.195 @@ -654,7 +733,6 @@
   3.196  
   3.197      GL_ActivateRenderer(renderer);
   3.198  
   3.199 -    GL_CheckError("", renderer);
   3.200      renderdata->glEnable(data->type);
   3.201      renderdata->glBindTexture(data->type, data->texture);
   3.202      renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   3.203 @@ -689,10 +767,7 @@
   3.204                                      data->format, data->formattype, pixels);
   3.205      }
   3.206      renderdata->glDisable(data->type);
   3.207 -    if (GL_CheckError("glTexSubImage2D()", renderer) > 0) {
   3.208 -        return -1;
   3.209 -    }
   3.210 -    return 0;
   3.211 +    return GL_CheckError("glTexSubImage2D()", renderer);
   3.212  }
   3.213  
   3.214  static int
   3.215 @@ -782,8 +857,7 @@
   3.216                        (GLdouble) 0,
   3.217                         0.0, 1.0);
   3.218      }
   3.219 -    GL_CheckError("", renderer);
   3.220 -    return 0;
   3.221 +    return GL_CheckError("", renderer);
   3.222  }
   3.223  
   3.224  static int
   3.225 @@ -965,9 +1039,7 @@
   3.226  #endif
   3.227          data->glEnd();
   3.228      }
   3.229 -    GL_CheckError("", renderer);
   3.230 -
   3.231 -    return 0;
   3.232 +    return GL_CheckError("", renderer);
   3.233  }
   3.234  
   3.235  static int
   3.236 @@ -983,9 +1055,7 @@
   3.237  
   3.238          data->glRectf(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
   3.239      }
   3.240 -    GL_CheckError("", renderer);
   3.241 -
   3.242 -    return 0;
   3.243 +    return GL_CheckError("", renderer);
   3.244  }
   3.245  
   3.246  static int
   3.247 @@ -1052,9 +1122,7 @@
   3.248  
   3.249      data->glDisable(texturedata->type);
   3.250  
   3.251 -    GL_CheckError("", renderer);
   3.252 -
   3.253 -    return 0;
   3.254 +    return GL_CheckError("", renderer);
   3.255  }
   3.256  
   3.257  static int
   3.258 @@ -1067,6 +1135,7 @@
   3.259      GLfloat minx, miny, maxx, maxy;
   3.260      GLfloat centerx, centery;
   3.261      GLfloat minu, maxu, minv, maxv;
   3.262 +
   3.263      GL_ActivateRenderer(renderer);
   3.264  
   3.265      data->glEnable(texturedata->type);
   3.266 @@ -1144,9 +1213,7 @@
   3.267  
   3.268      data->glDisable(texturedata->type);
   3.269  
   3.270 -    GL_CheckError("", renderer);
   3.271 -
   3.272 -    return 0;
   3.273 +    return GL_CheckError("", renderer);
   3.274  }
   3.275  
   3.276  static int
   3.277 @@ -1247,6 +1314,14 @@
   3.278      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   3.279  
   3.280      if (data) {
   3.281 +        GL_ClearErrors(renderer);
   3.282 +        if (data->GL_ARB_debug_output_supported) {
   3.283 +            PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARBFunc = (PFNGLDEBUGMESSAGECALLBACKARBPROC) SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
   3.284 +
   3.285 +            /* Uh oh, we don't have a safe way of removing ourselves from the callback chain, if it changed after we set our callback. */
   3.286 +            /* For now, just always replace the callback with the original one */
   3.287 +            glDebugMessageCallbackARBFunc(data->next_error_callback, data->next_error_userparam);
   3.288 +        }
   3.289          if (data->shaders) {
   3.290              GL_DestroyShaderContext(data->shaders);
   3.291          }
   3.292 @@ -1266,7 +1341,9 @@
   3.293      SDL_free(renderer);
   3.294  }
   3.295  
   3.296 -static int GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) {
   3.297 +static int
   3.298 +GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
   3.299 +{
   3.300      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   3.301      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   3.302      GL_ActivateRenderer(renderer);
   3.303 @@ -1289,7 +1366,9 @@
   3.304      return 0;
   3.305  }
   3.306  
   3.307 -static int GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) {
   3.308 +static int
   3.309 +GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
   3.310 +{
   3.311      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   3.312      GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
   3.313      GL_ActivateRenderer(renderer);
     4.1 --- a/src/test/SDL_test_common.c	Sat May 18 23:32:53 2013 -0700
     4.2 +++ b/src/test/SDL_test_common.c	Sun May 19 22:28:10 2013 -0700
     4.3 @@ -27,7 +27,7 @@
     4.4  #include <stdio.h>
     4.5  
     4.6  #define VIDEO_USAGE \
     4.7 -"[--video driver] [--renderer driver] [--info all|video|modes|render|event] [--log all|error|system|audio|video|render|input] [--display N] [--fullscreen | --fullscreen-desktop | --windows N] [--title title] [--icon icon.bmp] [--center | --position X,Y] [--geometry WxH] [--min-geometry WxH] [--max-geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
     4.8 +"[--video driver] [--renderer driver] [--gldebug] [--info all|video|modes|render|event] [--log all|error|system|audio|video|render|input] [--display N] [--fullscreen | --fullscreen-desktop | --windows N] [--title title] [--icon icon.bmp] [--center | --position X,Y] [--geometry WxH] [--min-geometry WxH] [--max-geometry WxH] [--depth N] [--refresh R] [--vsync] [--noframe] [--resize] [--minimize] [--maximize] [--grab]"
     4.9  
    4.10  #define AUDIO_USAGE \
    4.11  "[--rate N] [--format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE] [--channels N] [--samples N]"
    4.12 @@ -74,6 +74,7 @@
    4.13      state->gl_multisamplesamples = 0;
    4.14      state->gl_retained_backing = 1;
    4.15      state->gl_accelerated = -1;
    4.16 +    state->gl_debug = 0;
    4.17  
    4.18      return state;
    4.19  }
    4.20 @@ -99,6 +100,10 @@
    4.21          state->renderdriver = argv[index];
    4.22          return 2;
    4.23      }
    4.24 +    if (SDL_strcasecmp(argv[index], "--gldebug") == 0) {
    4.25 +        state->gl_debug = 1;
    4.26 +        return 1;
    4.27 +    }
    4.28      if (SDL_strcasecmp(argv[index], "--info") == 0) {
    4.29          ++index;
    4.30          if (!argv[index]) {
    4.31 @@ -656,6 +661,9 @@
    4.32              SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, state->gl_major_version);
    4.33              SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, state->gl_minor_version);
    4.34          }
    4.35 +        if (state->gl_debug) {
    4.36 +            SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
    4.37 +        }
    4.38  
    4.39          if (state->verbose & VERBOSE_MODES) {
    4.40              SDL_Rect bounds;
     5.1 --- a/test/testgl2.c	Sat May 18 23:32:53 2013 -0700
     5.2 +++ b/test/testgl2.c	Sun May 19 22:28:10 2013 -0700
     5.3 @@ -255,6 +255,7 @@
     5.4      printf("Vendor        : %s\n", glGetString(GL_VENDOR));
     5.5      printf("Renderer      : %s\n", glGetString(GL_RENDERER));
     5.6      printf("Version       : %s\n", glGetString(GL_VERSION));
     5.7 +    printf("Extensions    : %s\n", glGetString(GL_EXTENSIONS));
     5.8      printf("\n");
     5.9  
    5.10      status = SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);