Fixed bug 1622 - SDL_RenderSetViewport with empty SDL_Rect raises wrong error for OpenGL rendering backend
authorSam Lantinga <slouken@libsdl.org>
Wed, 29 May 2013 03:07:55 -0700
changeset 7239 04dda95ba22c
parent 7238 daff4d9cedc6
child 7240 39eb4958950a
Fixed bug 1622 - SDL_RenderSetViewport with empty SDL_Rect raises wrong error for OpenGL rendering backend It's now legal to set an empty viewport rect - it will prevent any rendering. Also added an API to query the output size: SDL_GetRendererOutputSize()
include/SDL_render.h
src/render/SDL_render.c
src/render/SDL_sysrender.h
src/render/direct3d/SDL_render_d3d.c
src/render/opengl/SDL_render_gl.c
src/render/opengles/SDL_render_gles.c
src/render/opengles2/SDL_render_gles2.c
src/render/software/SDL_render_sw.c
--- a/include/SDL_render.h	Mon May 27 21:44:16 2013 -0700
+++ b/include/SDL_render.h	Wed May 29 03:07:55 2013 -0700
@@ -212,6 +212,12 @@
                                                 SDL_RendererInfo * info);
 
 /**
+ *  \brief Get the output size of a rendering context.
+ */
+extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer * renderer,
+                                                      int *w, int *h);
+
+/**
  *  \brief Create a texture for a rendering context.
  *
  *  \param renderer The renderer.
--- a/src/render/SDL_render.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/SDL_render.c	Wed May 29 03:07:55 2013 -0700
@@ -337,6 +337,25 @@
     return 0;
 }
 
+int
+SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
+{
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    if (renderer->target) {
+        return SDL_QueryTexture(renderer->target, NULL, NULL, w, h);
+    } else if (renderer->window) {
+        SDL_GetWindowSize(renderer->window, w, h);
+        return 0;
+    } else if (renderer->GetOutputSize) {
+        return renderer->GetOutputSize(renderer, w, h);
+    } else {
+        /* This should never happen */
+        SDL_SetError("Renderer doesn't support querying output size");
+        return -1;
+    }
+}
+
 static SDL_bool
 IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
 {
@@ -985,13 +1004,8 @@
     float scale;
     SDL_Rect viewport;
 
-    if (renderer->target) {
-        SDL_QueryTexture(renderer->target, NULL, NULL, &w, &h);
-    } else if (renderer->window) {
-        SDL_GetWindowSize(renderer->window, &w, &h);
-    } else {
-        /* FIXME */
-        return SDL_SetError("Internal error: No way to get output resolution");
+    if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
+        return -1;
     }
 
     want_aspect = (float)renderer->logical_w / renderer->logical_h;
@@ -1074,16 +1088,8 @@
     } else {
         renderer->viewport.x = 0;
         renderer->viewport.y = 0;
-        if (renderer->target) {
-            SDL_QueryTexture(renderer->target, NULL, NULL,
-                              &renderer->viewport.w, &renderer->viewport.h);
-        } else if (renderer->window) {
-            SDL_GetWindowSize(renderer->window,
-                              &renderer->viewport.w, &renderer->viewport.h);
-        } else {
-            /* This will be filled in by UpdateViewport() */
-            renderer->viewport.w = 0;
-            renderer->viewport.h = 0;
+        if (SDL_GetRendererOutputSize(renderer, &renderer->viewport.w, &renderer->viewport.h) < 0) {
+            return -1;
         }
     }
     return renderer->UpdateViewport(renderer);
--- a/src/render/SDL_sysrender.h	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/SDL_sysrender.h	Wed May 29 03:07:55 2013 -0700
@@ -78,6 +78,7 @@
     const void *magic;
 
     void (*WindowEvent) (SDL_Renderer * renderer, const SDL_WindowEvent *event);
+    int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
     int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
     int (*SetTextureColorMod) (SDL_Renderer * renderer,
                                SDL_Texture * texture);
--- a/src/render/direct3d/SDL_render_d3d.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/direct3d/SDL_render_d3d.c	Wed May 29 03:07:55 2013 -0700
@@ -866,23 +866,25 @@
     IDirect3DDevice9_SetViewport(data->device, &viewport);
 
     /* Set an orthographic projection matrix */
-    matrix.m[0][0] = 2.0f / renderer->viewport.w;
-    matrix.m[0][1] = 0.0f;
-    matrix.m[0][2] = 0.0f;
-    matrix.m[0][3] = 0.0f;
-    matrix.m[1][0] = 0.0f;
-    matrix.m[1][1] = -2.0f / renderer->viewport.h;
-    matrix.m[1][2] = 0.0f;
-    matrix.m[1][3] = 0.0f;
-    matrix.m[2][0] = 0.0f;
-    matrix.m[2][1] = 0.0f;
-    matrix.m[2][2] = 1.0f;
-    matrix.m[2][3] = 0.0f;
-    matrix.m[3][0] = -1.0f;
-    matrix.m[3][1] = 1.0f;
-    matrix.m[3][2] = 0.0f;
-    matrix.m[3][3] = 1.0f;
-    IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
+    if (renderer->viewport.w && renderer->viewport.h) {
+        matrix.m[0][0] = 2.0f / renderer->viewport.w;
+        matrix.m[0][1] = 0.0f;
+        matrix.m[0][2] = 0.0f;
+        matrix.m[0][3] = 0.0f;
+        matrix.m[1][0] = 0.0f;
+        matrix.m[1][1] = -2.0f / renderer->viewport.h;
+        matrix.m[1][2] = 0.0f;
+        matrix.m[1][3] = 0.0f;
+        matrix.m[2][0] = 0.0f;
+        matrix.m[2][1] = 0.0f;
+        matrix.m[2][2] = 1.0f;
+        matrix.m[2][3] = 0.0f;
+        matrix.m[3][0] = -1.0f;
+        matrix.m[3][1] = 1.0f;
+        matrix.m[3][2] = 0.0f;
+        matrix.m[3][3] = 1.0f;
+        IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
+    }
 
     return 0;
 }
--- a/src/render/opengl/SDL_render_gl.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/opengl/SDL_render_gl.c	Wed May 29 03:07:55 2013 -0700
@@ -849,28 +849,25 @@
         return 0;
     }
 
-    if (!renderer->viewport.w || !renderer->viewport.h) {
-        /* The viewport isn't set up yet, ignore it */
-        return -1;
-    }
-
     data->glViewport(renderer->viewport.x, renderer->viewport.y,
                      renderer->viewport.w, renderer->viewport.h);
 
     data->glMatrixMode(GL_PROJECTION);
     data->glLoadIdentity();
-    if (renderer->target) {
-        data->glOrtho((GLdouble) 0,
-                      (GLdouble) renderer->viewport.w,
-                      (GLdouble) 0,
-                      (GLdouble) renderer->viewport.h,
-                       0.0, 1.0);
-    } else {
-        data->glOrtho((GLdouble) 0,
-                      (GLdouble) renderer->viewport.w,
-                      (GLdouble) renderer->viewport.h,
-                      (GLdouble) 0,
-                       0.0, 1.0);
+    if (renderer->viewport.w && renderer->viewport.h) {
+        if (renderer->target) {
+            data->glOrtho((GLdouble) 0,
+                          (GLdouble) renderer->viewport.w,
+                          (GLdouble) 0,
+                          (GLdouble) renderer->viewport.h,
+                           0.0, 1.0);
+        } else {
+            data->glOrtho((GLdouble) 0,
+                          (GLdouble) renderer->viewport.w,
+                          (GLdouble) renderer->viewport.h,
+                          (GLdouble) 0,
+                           0.0, 1.0);
+        }
     }
     return GL_CheckError("", renderer);
 }
--- a/src/render/opengles/SDL_render_gles.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/opengles/SDL_render_gles.c	Wed May 29 03:07:55 2013 -0700
@@ -623,12 +623,14 @@
     data->glViewport(renderer->viewport.x, renderer->viewport.y,
                renderer->viewport.w, renderer->viewport.h);
 
-    data->glMatrixMode(GL_PROJECTION);
-    data->glLoadIdentity();
-    data->glOrthof((GLfloat) 0,
-             (GLfloat) renderer->viewport.w,
-             (GLfloat) renderer->viewport.h,
-             (GLfloat) 0, 0.0, 1.0);
+    if (renderer->viewport.w && renderer->viewport.h) {
+        data->glMatrixMode(GL_PROJECTION);
+        data->glLoadIdentity();
+        data->glOrthof((GLfloat) 0,
+                 (GLfloat) renderer->viewport.w,
+                 (GLfloat) renderer->viewport.h,
+                 (GLfloat) 0, 0.0, 1.0);
+    }
     return 0;
 }
 
--- a/src/render/opengles2/SDL_render_gles2.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/opengles2/SDL_render_gles2.c	Wed May 29 03:07:55 2013 -0700
@@ -906,6 +906,10 @@
     GLfloat projection[4][4];
     GLuint locProjection;
 
+    if (!renderer->viewport.w || !renderer->viewport.h) {
+        return 0;
+    }
+
     /* Prepare an orthographic projection */
     projection[0][0] = 2.0f / renderer->viewport.w;
     projection[0][1] = 0.0f;
--- a/src/render/software/SDL_render_sw.c	Mon May 27 21:44:16 2013 -0700
+++ b/src/render/software/SDL_render_sw.c	Wed May 29 03:07:55 2013 -0700
@@ -39,6 +39,7 @@
 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
 static void SW_WindowEvent(SDL_Renderer * renderer,
                            const SDL_WindowEvent *event);
+static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int SW_SetTextureColorMod(SDL_Renderer * renderer,
                                  SDL_Texture * texture);
@@ -110,9 +111,14 @@
         data->surface = data->window;
     }
     if (!data->surface) {
-        data->surface = data->window = SDL_GetWindowSurface(renderer->window);
+        SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
+        if (surface) {
+            data->surface = data->window = surface;
+            renderer->viewport.w = surface->w;
+            renderer->viewport.h = surface->h;
 
-        SW_UpdateViewport(renderer);
+            SW_UpdateViewport(renderer);
+        }
     }
     return data->surface;
 }
@@ -143,6 +149,7 @@
     data->surface = surface;
 
     renderer->WindowEvent = SW_WindowEvent;
+    renderer->GetOutputSize = SW_GetOutputSize;
     renderer->CreateTexture = SW_CreateTexture;
     renderer->SetTextureColorMod = SW_SetTextureColorMod;
     renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
@@ -195,6 +202,25 @@
 }
 
 static int
+SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
+{
+    SDL_Surface *surface = SW_ActivateRenderer(renderer);
+
+    if (surface) {
+        if (w) {
+            *w = surface->w;
+        }
+        if (h) {
+            *h = surface->h;
+        }
+        return 0;
+    } else {
+        SDL_SetError("Software renderer doesn't have an output surface");
+        return -1;
+    }
+}
+
+static int
 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     int bpp;
@@ -313,11 +339,6 @@
         return 0;
     }
 
-    if (!renderer->viewport.w && !renderer->viewport.h) {
-        /* There may be no window, so update the viewport directly */
-        renderer->viewport.w = surface->w;
-        renderer->viewport.h = surface->h;
-    }
     SDL_SetClipRect(data->surface, &renderer->viewport);
     return 0;
 }