OpenGL renderer is feature complete!
authorSam Lantinga <slouken@libsdl.org>
Sat, 22 Jul 2006 23:04:41 +0000
changeset 1927 aeb8263d377a
parent 1926 307355678142
child 1928 861bc36f0ab3
OpenGL renderer is feature complete! Dynamically load GL functions in the OpenGL renderer.
src/video/SDL_glfuncs.h
src/video/SDL_renderer_gl.c
--- a/src/video/SDL_glfuncs.h	Sat Jul 22 21:58:17 2006 +0000
+++ b/src/video/SDL_glfuncs.h	Sat Jul 22 23:04:41 2006 +0000
@@ -16,9 +16,9 @@
 SDL_PROC(void, glBlendFunc, (GLenum, GLenum))
 SDL_PROC_UNUSED(void, glCallList, (GLuint))
 SDL_PROC_UNUSED(void, glCallLists, (GLsizei, GLenum, const GLvoid *))
-SDL_PROC_UNUSED(void, glClear, (GLbitfield))
+SDL_PROC(void, glClear, (GLbitfield))
 SDL_PROC_UNUSED(void, glClearAccum, (GLfloat, GLfloat, GLfloat, GLfloat))
-SDL_PROC_UNUSED(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
+SDL_PROC(void, glClearColor, (GLclampf, GLclampf, GLclampf, GLclampf))
 SDL_PROC_UNUSED(void, glClearDepth, (GLclampd))
 SDL_PROC_UNUSED(void, glClearIndex, (GLfloat))
 SDL_PROC_UNUSED(void, glClearStencil, (GLint))
@@ -33,7 +33,7 @@
 SDL_PROC_UNUSED(void, glColor3iv, (const GLint *))
 SDL_PROC_UNUSED(void, glColor3s, (GLshort, GLshort, GLshort))
 SDL_PROC_UNUSED(void, glColor3sv, (const GLshort *))
-SDL_PROC(void, glColor3ub, (GLubyte, GLubyte, GLubyte))
+SDL_PROC_UNUSED(void, glColor3ub, (GLubyte, GLubyte, GLubyte))
 SDL_PROC_UNUSED(void, glColor3ubv, (const GLubyte *))
 SDL_PROC_UNUSED(void, glColor3ui, (GLuint, GLuint, GLuint))
 SDL_PROC_UNUSED(void, glColor3uiv, (const GLuint *))
@@ -43,14 +43,14 @@
 SDL_PROC_UNUSED(void, glColor4bv, (const GLbyte *))
 SDL_PROC_UNUSED(void, glColor4d, (GLdouble, GLdouble, GLdouble, GLdouble))
 SDL_PROC_UNUSED(void, glColor4dv, (const GLdouble *))
-SDL_PROC(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
+SDL_PROC_UNUSED(void, glColor4f, (GLfloat, GLfloat, GLfloat, GLfloat))
 SDL_PROC_UNUSED(void, glColor4fv, (const GLfloat *))
 SDL_PROC_UNUSED(void, glColor4i, (GLint, GLint, GLint, GLint))
 SDL_PROC_UNUSED(void, glColor4iv, (const GLint *))
 SDL_PROC_UNUSED(void, glColor4s, (GLshort, GLshort, GLshort, GLshort))
 SDL_PROC_UNUSED(void, glColor4sv, (const GLshort *))
-SDL_PROC(void, glColor4ub,
-         (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
+SDL_PROC_UNUSED(void, glColor4ub,
+                (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha))
 SDL_PROC_UNUSED(void, glColor4ubv, (const GLubyte * v))
 SDL_PROC_UNUSED(void, glColor4ui,
                 (GLuint red, GLuint green, GLuint blue, GLuint alpha))
@@ -89,7 +89,7 @@
 SDL_PROC(void, glDisable, (GLenum cap))
 SDL_PROC_UNUSED(void, glDisableClientState, (GLenum array))
 SDL_PROC_UNUSED(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count))
-SDL_PROC(void, glDrawBuffer, (GLenum mode))
+SDL_PROC_UNUSED(void, glDrawBuffer, (GLenum mode))
 SDL_PROC_UNUSED(void, glDrawElements,
                 (GLenum mode, GLsizei count, GLenum type,
                  const GLvoid * indices))
@@ -119,8 +119,8 @@
 SDL_PROC_UNUSED(void, glEvalPoint2, (GLint i, GLint j))
 SDL_PROC_UNUSED(void, glFeedbackBuffer,
                 (GLsizei size, GLenum type, GLfloat * buffer))
-SDL_PROC(void, glFinish, (void))
-SDL_PROC(void, glFlush, (void))
+SDL_PROC_UNUSED(void, glFinish, (void))
+SDL_PROC_UNUSED(void, glFlush, (void))
 SDL_PROC_UNUSED(void, glFogf, (GLenum pname, GLfloat param))
 SDL_PROC_UNUSED(void, glFogfv, (GLenum pname, const GLfloat * params))
 SDL_PROC_UNUSED(void, glFogi, (GLenum pname, GLint param))
@@ -153,7 +153,7 @@
 SDL_PROC_UNUSED(void, glGetPixelMapusv, (GLenum map, GLushort * values))
 SDL_PROC_UNUSED(void, glGetPointerv, (GLenum pname, GLvoid * *params))
 SDL_PROC_UNUSED(void, glGetPolygonStipple, (GLubyte * mask))
-SDL_PROC(const GLubyte *, glGetString, (GLenum name))
+SDL_PROC_UNUSED(const GLubyte *, glGetString, (GLenum name))
 SDL_PROC_UNUSED(void, glGetTexEnvfv,
                 (GLenum target, GLenum pname, GLfloat * params))
 SDL_PROC_UNUSED(void, glGetTexEnviv,
@@ -276,16 +276,16 @@
 SDL_PROC_UNUSED(void, glPolygonMode, (GLenum face, GLenum mode))
 SDL_PROC_UNUSED(void, glPolygonOffset, (GLfloat factor, GLfloat units))
 SDL_PROC_UNUSED(void, glPolygonStipple, (const GLubyte * mask))
-SDL_PROC(void, glPopAttrib, (void))
-SDL_PROC(void, glPopClientAttrib, (void))
-SDL_PROC(void, glPopMatrix, (void))
+SDL_PROC_UNUSED(void, glPopAttrib, (void))
+SDL_PROC_UNUSED(void, glPopClientAttrib, (void))
+SDL_PROC_UNUSED(void, glPopMatrix, (void))
 SDL_PROC_UNUSED(void, glPopName, (void))
 SDL_PROC_UNUSED(void, glPrioritizeTextures,
                 (GLsizei n, const GLuint * textures,
                  const GLclampf * priorities))
-SDL_PROC(void, glPushAttrib, (GLbitfield mask))
-SDL_PROC(void, glPushClientAttrib, (GLbitfield mask))
-SDL_PROC(void, glPushMatrix, (void))
+SDL_PROC_UNUSED(void, glPushAttrib, (GLbitfield mask))
+SDL_PROC_UNUSED(void, glPushClientAttrib, (GLbitfield mask))
+SDL_PROC_UNUSED(void, glPushMatrix, (void))
 SDL_PROC_UNUSED(void, glPushName, (GLuint name))
 SDL_PROC_UNUSED(void, glRasterPos2d, (GLdouble x, GLdouble y))
 SDL_PROC_UNUSED(void, glRasterPos2dv, (const GLdouble * v))
@@ -315,9 +315,9 @@
                 (GLshort x, GLshort y, GLshort z, GLshort w))
 SDL_PROC_UNUSED(void, glRasterPos4sv, (const GLshort * v))
 SDL_PROC_UNUSED(void, glReadBuffer, (GLenum mode))
-SDL_PROC(void, glReadPixels,
-         (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
-          GLenum type, GLvoid * pixels))
+SDL_PROC_UNUSED(void, glReadPixels,
+                (GLint x, GLint y, GLsizei width, GLsizei height,
+                 GLenum format, GLenum type, GLvoid * pixels))
 SDL_PROC_UNUSED(void, glRectd,
                 (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2))
 SDL_PROC_UNUSED(void, glRectdv, (const GLdouble * v1, const GLdouble * v2))
@@ -418,7 +418,7 @@
          (GLenum target, GLint level, GLint xoffset, GLint yoffset,
           GLsizei width, GLsizei height, GLenum format, GLenum type,
           const GLvoid * pixels))
-SDL_PROC(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
+SDL_PROC_UNUSED(void, glTranslated, (GLdouble x, GLdouble y, GLdouble z))
 SDL_PROC_UNUSED(void, glTranslatef, (GLfloat x, GLfloat y, GLfloat z))
 SDL_PROC_UNUSED(void, glVertex2d, (GLdouble x, GLdouble y))
 SDL_PROC_UNUSED(void, glVertex2dv, (const GLdouble * v))
@@ -451,4 +451,5 @@
                 (GLint size, GLenum type, GLsizei stride,
                  const GLvoid * pointer))
 SDL_PROC(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height))
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_renderer_gl.c	Sat Jul 22 21:58:17 2006 +0000
+++ b/src/video/SDL_renderer_gl.c	Sat Jul 22 23:04:41 2006 +0000
@@ -98,6 +98,13 @@
 {
     SDL_GLContext context;
     SDL_bool GL_ARB_texture_rectangle_supported;
+    int blendMode;
+    int scaleMode;
+
+    /* OpenGL functions */
+#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
+#include "SDL_glfuncs.h"
+#undef SDL_PROC
 } GL_RenderData;
 
 typedef struct
@@ -151,6 +158,32 @@
     SDL_SetError("%s: %s", prefix, error);
 }
 
+static int
+GL_LoadFunctions(GL_RenderData * data)
+{
+#if defined(__QNXNTO__) && (_NTO_VERSION < 630)
+#define __SDL_NOGETPROCADDR__
+#elif defined(__MINT__)
+#define __SDL_NOGETPROCADDR__
+#endif
+#ifdef __SDL_NOGETPROCADDR__
+#define SDL_PROC(ret,func,params) data->func=func;
+#else
+#define SDL_PROC(ret,func,params) \
+    do { \
+        data->func = SDL_GL_GetProcAddress(#func); \
+        if ( ! data->func ) { \
+            SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
+            return -1; \
+        } \
+    } while ( 0 );
+#endif /* __SDL_NOGETPROCADDR__ */
+
+#include "SDL_glfuncs.h"
+#undef SDL_PROC
+    return 0;
+}
+
 void
 GL_AddRenderDriver(_THIS)
 {
@@ -205,6 +238,11 @@
     renderer->info.flags =
         (SDL_Renderer_PresentDiscard | SDL_Renderer_Accelerated);
 
+    if (GL_LoadFunctions(data) < 0) {
+        GL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
     data->context = SDL_GL_CreateContext(window->id);
     if (!data->context) {
         GL_DestroyRenderer(renderer);
@@ -224,8 +262,10 @@
         renderer->info.flags |= SDL_Renderer_PresentVSync;
     }
 
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &renderer->info.max_texture_width);
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &renderer->info.max_texture_height);
+    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE,
+                        &renderer->info.max_texture_width);
+    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE,
+                        &renderer->info.max_texture_height);
 
     if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
         || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
@@ -233,19 +273,22 @@
     }
 
     /* Set up parameters for rendering */
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_CULL_FACE);
+    data->blendMode = -1;
+    data->scaleMode = -1;
+    data->glDisable(GL_DEPTH_TEST);
+    data->glDisable(GL_CULL_FACE);
     if (data->GL_ARB_texture_rectangle_supported) {
-        glEnable(GL_TEXTURE_RECTANGLE_ARB);
+        data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
     } else {
-        glEnable(GL_TEXTURE_2D);
+        data->glEnable(GL_TEXTURE_2D);
     }
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-    glViewport(0, 0, window->w, window->h);
-    glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0, 0.0, 1.0);
+    data->glMatrixMode(GL_PROJECTION);
+    data->glLoadIdentity();
+    data->glMatrixMode(GL_MODELVIEW);
+    data->glLoadIdentity();
+    data->glViewport(0, 0, window->w, window->h);
+    data->glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0, 0.0,
+                  1.0);
 
     return renderer;
 }
@@ -371,8 +414,8 @@
 
     texture->driverdata = data;
 
-    glGetError();
-    glGenTextures(1, &data->texture);
+    renderdata->glGetError();
+    renderdata->glGenTextures(1, &data->texture);
     if (renderdata->GL_ARB_texture_rectangle_supported) {
         data->type = GL_TEXTURE_RECTANGLE_ARB;
         texture_w = texture->w;
@@ -388,10 +431,10 @@
     }
     data->format = format;
     data->formattype = type;
-    glBindTexture(data->type, data->texture);
-    glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0,
-                 format, type, NULL);
-    result = glGetError();
+    renderdata->glBindTexture(data->type, data->texture);
+    renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
+                             texture_h, 0, format, type, NULL);
+    result = renderdata->glGetError();
     if (result != GL_NO_ERROR) {
         GL_SetError("glTexImage2D()", result);
         return -1;
@@ -419,31 +462,34 @@
 }
 
 static void
-SetupTextureUpdate(SDL_Texture * texture, int pitch)
+SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
+                   int pitch)
 {
     if (texture->format == SDL_PixelFormat_Index1LSB) {
-        glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
+        renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
     } else if (texture->format == SDL_PixelFormat_Index1MSB) {
-        glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
+        renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
     }
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glPixelStorei(GL_UNPACK_ROW_LENGTH,
-                  pitch / SDL_BYTESPERPIXEL(texture->format));
+    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
+                              pitch / SDL_BYTESPERPIXEL(texture->format));
 }
 
 static int
 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                  const SDL_Rect * rect, const void *pixels, int pitch)
 {
+    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
     GLenum result;
 
-    glGetError();
-    SetupTextureUpdate(texture, pitch);
-    glBindTexture(data->type, data->texture);
-    glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, rect->h,
-                    data->format, data->formattype, pixels);
-    result = glGetError();
+    renderdata->glGetError();
+    SetupTextureUpdate(renderdata, texture, pitch);
+    renderdata->glBindTexture(data->type, data->texture);
+    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
+                                rect->h, data->format, data->formattype,
+                                pixels);
+    result = renderdata->glGetError();
     if (result != GL_NO_ERROR) {
         GL_SetError("glTexSubImage2D()", result);
         return -1;
@@ -507,10 +553,10 @@
     g = ((GLclampf) ((color >> 8) & 0xFF)) / 255.0f;
     b = ((GLclampf) (color & 0xFF)) / 255.0f;
 
-    glClearColor(r, g, b, a);
-    glViewport(rect->x, window->h - rect->y, rect->w, rect->h);
-    glClear(GL_COLOR_BUFFER_BIT);
-    glViewport(0, 0, window->w, window->h);
+    data->glClearColor(r, g, b, a);
+    data->glViewport(rect->x, window->h - rect->y, rect->w, rect->h);
+    data->glClear(GL_COLOR_BUFFER_BIT);
+    data->glViewport(0, 0, window->w, window->h);
     return 0;
 }
 
@@ -530,16 +576,16 @@
         int bpp = SDL_BYTESPERPIXEL(texture->format);
         int pitch = texturedata->pitch;
 
-        SetupTextureUpdate(texture, pitch);
-        glBindTexture(texturedata->type, texturedata->texture);
+        SetupTextureUpdate(data, texture, pitch);
+        data->glBindTexture(texturedata->type, texturedata->texture);
         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
             SDL_Rect *rect = &dirty->rect;
             pixels =
                 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
                           rect->x * bpp);
-            glTexSubImage2D(texturedata->type, 0, rect->x, rect->y, rect->w,
-                            rect->h, texturedata->format,
-                            texturedata->formattype, pixels);
+            data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
+                                  rect->w, rect->h, texturedata->format,
+                                  texturedata->formattype, pixels);
         }
         SDL_ClearDirtyRects(&texturedata->dirty);
     }
@@ -558,54 +604,64 @@
     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
     maxv *= texturedata->texh;
 
-    glBindTexture(texturedata->type, texturedata->texture);
+    data->glBindTexture(texturedata->type, texturedata->texture);
 
-    switch (blendMode) {
-    case SDL_TextureBlendMode_None:
-        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-        glDisable(GL_BLEND);
-        break;
-    case SDL_TextureBlendMode_Mask:
-    case SDL_TextureBlendMode_Blend:
-        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        break;
-    case SDL_TextureBlendMode_Add:
-        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-        break;
-    case SDL_TextureBlendMode_Mod:
-        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
-        break;
+    if (blendMode != data->blendMode) {
+        switch (blendMode) {
+        case SDL_TextureBlendMode_None:
+            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+            data->glDisable(GL_BLEND);
+            break;
+        case SDL_TextureBlendMode_Mask:
+        case SDL_TextureBlendMode_Blend:
+            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            data->glEnable(GL_BLEND);
+            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            break;
+        case SDL_TextureBlendMode_Add:
+            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            data->glEnable(GL_BLEND);
+            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            break;
+        case SDL_TextureBlendMode_Mod:
+            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            data->glEnable(GL_BLEND);
+            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            break;
+        }
+        data->blendMode = blendMode;
     }
 
-    switch (scaleMode) {
-    case SDL_TextureScaleMode_None:
-    case SDL_TextureScaleMode_Fast:
-        glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        break;
-    case SDL_TextureScaleMode_Slow:
-    case SDL_TextureScaleMode_Best:
-        glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-        break;
+    if (scaleMode != data->scaleMode) {
+        switch (scaleMode) {
+        case SDL_TextureScaleMode_None:
+        case SDL_TextureScaleMode_Fast:
+            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
+                                  GL_NEAREST);
+            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
+                                  GL_NEAREST);
+            break;
+        case SDL_TextureScaleMode_Slow:
+        case SDL_TextureScaleMode_Best:
+            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
+                                  GL_LINEAR);
+            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
+                                  GL_LINEAR);
+            break;
+        }
+        data->scaleMode = scaleMode;
     }
 
-    glBegin(GL_TRIANGLE_STRIP);
-    glTexCoord2f(minu, minv);
-    glVertex2i(minx, miny);
-    glTexCoord2f(maxu, minv);
-    glVertex2i(maxx, miny);
-    glTexCoord2f(minu, maxv);
-    glVertex2i(minx, maxy);
-    glTexCoord2f(maxu, maxv);
-    glVertex2i(maxx, maxy);
-    glEnd();
+    data->glBegin(GL_TRIANGLE_STRIP);
+    data->glTexCoord2f(minu, minv);
+    data->glVertex2i(minx, miny);
+    data->glTexCoord2f(maxu, minv);
+    data->glVertex2i(maxx, miny);
+    data->glTexCoord2f(minu, maxv);
+    data->glVertex2i(minx, maxy);
+    data->glTexCoord2f(maxu, maxv);
+    data->glVertex2i(maxx, maxy);
+    data->glEnd();
 
     return 0;
 }
@@ -619,13 +675,14 @@
 static void
 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
+    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
     GL_TextureData *data = (GL_TextureData *) texture->driverdata;
 
     if (!data) {
         return;
     }
     if (data->texture) {
-        glDeleteTextures(1, &data->texture);
+        renderdata->glDeleteTextures(1, &data->texture);
     }
     if (data->pixels) {
         SDL_free(data->pixels);