If the OpenGL renderer is selected for a non-OpenGL window, recreate the window with OpenGL enabled.
authorSam Lantinga <slouken@libsdl.org>
Sat, 22 Jul 2006 21:02:57 +0000
changeset 1924 69217fdd2c0a
parent 1923 d4572b97b08f
child 1925 411bfb37082b
If the OpenGL renderer is selected for a non-OpenGL window, recreate the window with OpenGL enabled. Added OpenGL renderer error checking. Use fast-path texture formats in the OpenGL renderer.
src/SDL_compat.c
src/video/SDL_renderer_gl.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/win32/SDL_d3drender.c
src/video/win32/SDL_gdirender.c
test/common.c
--- a/src/SDL_compat.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/SDL_compat.c	Sat Jul 22 21:02:57 2006 +0000
@@ -469,7 +469,8 @@
                           height);
     if (!SDL_VideoTexture) {
         SDL_VideoTexture =
-            SDL_CreateTexture(0, SDL_TextureAccess_Local, width, height);
+            SDL_CreateTexture(SDL_PixelFormat_RGB888, SDL_TextureAccess_Local,
+                              width, height);
     }
     if (!SDL_VideoTexture) {
         return NULL;
--- a/src/video/SDL_renderer_gl.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/video/SDL_renderer_gl.c	Sat Jul 22 21:02:57 2006 +0000
@@ -72,7 +72,7 @@
       SDL_TextureBlendMode_Mod),
      (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast |
       SDL_TextureScaleMode_Slow),
-     18,
+     16,
      {
       SDL_PixelFormat_Index1LSB,
       SDL_PixelFormat_Index1MSB,
@@ -88,10 +88,8 @@
       SDL_PixelFormat_RGB888,
       SDL_PixelFormat_BGR888,
       SDL_PixelFormat_ARGB8888,
-      SDL_PixelFormat_RGBA8888,
       SDL_PixelFormat_ABGR8888,
-      SDL_PixelFormat_BGRA8888,
-      SDL_PixelFormat_ARGB2101010},     /* FIXME: YUV texture support */
+      SDL_PixelFormat_ARGB2101010},
      0,
      0}
 };
@@ -115,6 +113,43 @@
 } GL_TextureData;
 
 
+static void
+GL_SetError(const char *prefix, GLenum result)
+{
+    const char *error;
+
+    switch (result) {
+    case GL_NO_ERROR:
+        error = "GL_NO_ERROR";
+        break;
+    case GL_INVALID_ENUM:
+        error = "GL_INVALID_ENUM";
+        break;
+    case GL_INVALID_VALUE:
+        error = "GL_INVALID_VALUE";
+        break;
+    case GL_INVALID_OPERATION:
+        error = "GL_INVALID_OPERATION";
+        break;
+    case GL_STACK_OVERFLOW:
+        error = "GL_STACK_OVERFLOW";
+        break;
+    case GL_STACK_UNDERFLOW:
+        error = "GL_STACK_UNDERFLOW";
+        break;
+    case GL_OUT_OF_MEMORY:
+        error = "GL_OUT_OF_MEMORY";
+        break;
+    case GL_TABLE_TOO_LARGE:
+        error = "GL_TABLE_TOO_LARGE";
+        break;
+    default:
+        error = "UNKNOWN";
+        break;
+    }
+    SDL_SetError("%s: %s", prefix, error);
+}
+
 void
 GL_AddRenderDriver(_THIS)
 {
@@ -130,9 +165,10 @@
     GL_RenderData *data;
 
     if (!(window->flags & SDL_WINDOW_OPENGL)) {
-        SDL_SetError
-            ("The OpenGL renderer can only be used on OpenGL windows");
-        return NULL;
+        window->flags |= SDL_WINDOW_OPENGL;
+        if (SDL_RecreateWindow(window) < 0) {
+            return NULL;
+        }
     }
 
     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
@@ -239,6 +275,7 @@
     GLint internalFormat;
     GLenum format, type;
     int texture_w, texture_h;
+    GLenum result;
 
     switch (texture->format) {
     case SDL_PixelFormat_Index1LSB:
@@ -289,8 +326,8 @@
         break;
     case SDL_PixelFormat_RGB888:
         internalFormat = GL_RGB8;
-        format = GL_RGB;
-        type = GL_UNSIGNED_INT_8_8_8_8;
+        format = GL_BGRA;
+        type = GL_UNSIGNED_BYTE;
         break;
     case SDL_PixelFormat_BGR24:
         internalFormat = GL_RGB8;
@@ -299,28 +336,18 @@
         break;
     case SDL_PixelFormat_BGR888:
         internalFormat = GL_RGB8;
-        format = GL_BGR;
-        type = GL_UNSIGNED_INT_8_8_8_8;
+        format = GL_RGBA;
+        type = GL_UNSIGNED_BYTE;
         break;
     case SDL_PixelFormat_ARGB8888:
         internalFormat = GL_RGBA8;
         format = GL_BGRA;
-        type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case SDL_PixelFormat_RGBA8888:
-        internalFormat = GL_RGBA8;
-        format = GL_RGBA;
-        type = GL_UNSIGNED_INT_8_8_8_8;
+        type = GL_UNSIGNED_BYTE;
         break;
     case SDL_PixelFormat_ABGR8888:
         internalFormat = GL_RGBA8;
         format = GL_RGBA;
-        type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case SDL_PixelFormat_BGRA8888:
-        internalFormat = GL_RGBA8;
-        format = GL_BGRA;
-        type = GL_UNSIGNED_INT_8_8_8_8;
+        type = GL_UNSIGNED_BYTE;
         break;
     case SDL_PixelFormat_ARGB2101010:
         internalFormat = GL_RGB10_A2;
@@ -340,7 +367,7 @@
 
     texture->driverdata = data;
 
-    /* FIXME: Check for GL_ARB_texture_rectangle and GL_EXT_texture_rectangle */
+    glGetError();
     glGenTextures(1, &data->texture);
 #ifdef USE_GL_TEXTURE_RECTANGLE
     data->type = GL_TEXTURE_RECTANGLE_ARB;
@@ -360,7 +387,11 @@
     glBindTexture(data->type, data->texture);
     glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0,
                  format, type, NULL);
-
+    result = glGetError();
+    if (result != GL_NO_ERROR) {
+        GL_SetError("glTexImage2D()", result);
+        return -1;
+    }
     return 0;
 }
 
@@ -383,19 +414,36 @@
     return 0;
 }
 
+static void
+SetupTextureUpdate(SDL_Texture * texture, int pitch)
+{
+    if (texture->format == SDL_PixelFormat_Index1LSB) {
+        glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
+    } else if (texture->format == SDL_PixelFormat_Index1MSB) {
+        glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
+    }
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    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_TextureData *data = (GL_TextureData *) texture->driverdata;
+    GLenum result;
 
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);      /* FIXME, what to use for RGB 4 byte formats? */
-    glPixelStorei(GL_UNPACK_ROW_LENGTH,
-                  pitch / SDL_BYTESPERPIXEL(texture->format));
+    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);
-    /* FIXME: check for errors */
+    result = glGetError();
+    if (result != GL_NO_ERROR) {
+        GL_SetError("glTexSubImage2D()", result);
+        return -1;
+    }
     return 0;
 }
 
@@ -478,9 +526,7 @@
         int bpp = SDL_BYTESPERPIXEL(texture->format);
         int pitch = texturedata->pitch;
 
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  /* FIXME, what to use for RGB 4 byte formats? */
-        glPixelStorei(GL_UNPACK_ROW_LENGTH,
-                      pitch / SDL_BYTESPERPIXEL(texture->format));
+        SetupTextureUpdate(texture, pitch);
         glBindTexture(texturedata->type, texturedata->texture);
         for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
             SDL_Rect *rect = &dirty->rect;
--- a/src/video/SDL_sysvideo.h	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/video/SDL_sysvideo.h	Sat Jul 22 21:02:57 2006 +0000
@@ -397,6 +397,7 @@
 extern void SDL_AddRenderDriver(int displayIndex,
                                 const SDL_RenderDriver * driver);
 
+extern int SDL_RecreateWindow(SDL_Window * window);
 extern SDL_Window *SDL_GetWindowFromID(SDL_WindowID windowID);
 extern SDL_VideoDisplay *SDL_GetDisplayFromWindow(SDL_Window * window);
 
--- a/src/video/SDL_video.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/video/SDL_video.c	Sat Jul 22 21:02:57 2006 +0000
@@ -833,6 +833,20 @@
     return window.id;
 }
 
+int
+SDL_RecreateWindow(SDL_Window * window)
+{
+    if ((window->flags & SDL_WINDOW_OPENGL) && !_this->GL_CreateContext) {
+        window->flags &= ~SDL_WINDOW_OPENGL;
+        SDL_SetError("No OpenGL support in video driver");
+        return -1;
+    }
+    if (_this->DestroyWindow) {
+        _this->DestroyWindow(_this, window);
+    }
+    return _this->CreateWindow(_this, window);
+}
+
 SDL_Window *
 SDL_GetWindowFromID(SDL_WindowID windowID)
 {
@@ -1259,6 +1273,7 @@
             if (window->title) {
                 SDL_free(window->title);
             }
+            SDL_free(window);
             if (j != display->num_windows - 1) {
                 SDL_memcpy(&display->windows[i],
                            &display->windows[i + 1],
@@ -1421,6 +1436,9 @@
     texture->renderer = renderer;
 
     if (renderer->CreateTexture(renderer, texture) < 0) {
+        if (renderer->DestroyTexture) {
+            renderer->DestroyTexture(renderer, texture);
+        }
         SDL_free(texture);
         return 0;
     }
--- a/src/video/win32/SDL_d3drender.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/video/win32/SDL_d3drender.c	Sat Jul 22 21:02:57 2006 +0000
@@ -396,7 +396,6 @@
                                        PixelFormatToD3DFMT(texture->format),
                                        pool, &data->texture, NULL);
     if (FAILED(result)) {
-        SDL_free(data);
         D3D_SetError("CreateTexture()", result);
         return -1;
     }
--- a/src/video/win32/SDL_gdirender.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/src/video/win32/SDL_gdirender.c	Sat Jul 22 21:02:57 2006 +0000
@@ -249,7 +249,6 @@
     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
         data->yuv = SDL_SW_CreateYUVTexture(texture);
         if (!data->yuv) {
-            GDI_DestroyTexture(renderer, texture);
             return -1;
         }
         data->format = display->current_mode.format;
@@ -266,7 +265,6 @@
         bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
         bmi = (LPBITMAPINFO) SDL_calloc(1, bmi_size);
         if (!bmi) {
-            GDI_DestroyTexture(renderer, texture);
             SDL_OutOfMemory();
             return -1;
         }
@@ -291,7 +289,6 @@
                                           ncolors * sizeof(PALETTEENTRY));
             if (!palette) {
                 SDL_free(bmi);
-                GDI_DestroyTexture(renderer, texture);
                 SDL_OutOfMemory();
                 return -1;
             }
@@ -327,7 +324,6 @@
         data->pixels = NULL;
     }
     if (!data->hbm) {
-        GDI_DestroyTexture(renderer, texture);
         WIN_SetError("Couldn't create bitmap");
         return -1;
     }
--- a/test/common.c	Sat Jul 22 19:51:48 2006 +0000
+++ b/test/common.c	Sat Jul 22 21:02:57 2006 +0000
@@ -55,9 +55,6 @@
         if (!argv[index]) {
             return -1;
         }
-        if (SDL_strcasecmp(argv[index], "opengl") == 0) {
-            state->window_flags |= SDL_WINDOW_OPENGL;
-        }
         state->renderdriver = argv[index];
         return 2;
     }