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 723904dda95ba22c
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
     1.1 --- a/include/SDL_render.h	Mon May 27 21:44:16 2013 -0700
     1.2 +++ b/include/SDL_render.h	Wed May 29 03:07:55 2013 -0700
     1.3 @@ -212,6 +212,12 @@
     1.4                                                  SDL_RendererInfo * info);
     1.5  
     1.6  /**
     1.7 + *  \brief Get the output size of a rendering context.
     1.8 + */
     1.9 +extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer * renderer,
    1.10 +                                                      int *w, int *h);
    1.11 +
    1.12 +/**
    1.13   *  \brief Create a texture for a rendering context.
    1.14   *
    1.15   *  \param renderer The renderer.
     2.1 --- a/src/render/SDL_render.c	Mon May 27 21:44:16 2013 -0700
     2.2 +++ b/src/render/SDL_render.c	Wed May 29 03:07:55 2013 -0700
     2.3 @@ -337,6 +337,25 @@
     2.4      return 0;
     2.5  }
     2.6  
     2.7 +int
     2.8 +SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
     2.9 +{
    2.10 +    CHECK_RENDERER_MAGIC(renderer, -1);
    2.11 +
    2.12 +    if (renderer->target) {
    2.13 +        return SDL_QueryTexture(renderer->target, NULL, NULL, w, h);
    2.14 +    } else if (renderer->window) {
    2.15 +        SDL_GetWindowSize(renderer->window, w, h);
    2.16 +        return 0;
    2.17 +    } else if (renderer->GetOutputSize) {
    2.18 +        return renderer->GetOutputSize(renderer, w, h);
    2.19 +    } else {
    2.20 +        /* This should never happen */
    2.21 +        SDL_SetError("Renderer doesn't support querying output size");
    2.22 +        return -1;
    2.23 +    }
    2.24 +}
    2.25 +
    2.26  static SDL_bool
    2.27  IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
    2.28  {
    2.29 @@ -985,13 +1004,8 @@
    2.30      float scale;
    2.31      SDL_Rect viewport;
    2.32  
    2.33 -    if (renderer->target) {
    2.34 -        SDL_QueryTexture(renderer->target, NULL, NULL, &w, &h);
    2.35 -    } else if (renderer->window) {
    2.36 -        SDL_GetWindowSize(renderer->window, &w, &h);
    2.37 -    } else {
    2.38 -        /* FIXME */
    2.39 -        return SDL_SetError("Internal error: No way to get output resolution");
    2.40 +    if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
    2.41 +        return -1;
    2.42      }
    2.43  
    2.44      want_aspect = (float)renderer->logical_w / renderer->logical_h;
    2.45 @@ -1074,16 +1088,8 @@
    2.46      } else {
    2.47          renderer->viewport.x = 0;
    2.48          renderer->viewport.y = 0;
    2.49 -        if (renderer->target) {
    2.50 -            SDL_QueryTexture(renderer->target, NULL, NULL,
    2.51 -                              &renderer->viewport.w, &renderer->viewport.h);
    2.52 -        } else if (renderer->window) {
    2.53 -            SDL_GetWindowSize(renderer->window,
    2.54 -                              &renderer->viewport.w, &renderer->viewport.h);
    2.55 -        } else {
    2.56 -            /* This will be filled in by UpdateViewport() */
    2.57 -            renderer->viewport.w = 0;
    2.58 -            renderer->viewport.h = 0;
    2.59 +        if (SDL_GetRendererOutputSize(renderer, &renderer->viewport.w, &renderer->viewport.h) < 0) {
    2.60 +            return -1;
    2.61          }
    2.62      }
    2.63      return renderer->UpdateViewport(renderer);
     3.1 --- a/src/render/SDL_sysrender.h	Mon May 27 21:44:16 2013 -0700
     3.2 +++ b/src/render/SDL_sysrender.h	Wed May 29 03:07:55 2013 -0700
     3.3 @@ -78,6 +78,7 @@
     3.4      const void *magic;
     3.5  
     3.6      void (*WindowEvent) (SDL_Renderer * renderer, const SDL_WindowEvent *event);
     3.7 +    int (*GetOutputSize) (SDL_Renderer * renderer, int *w, int *h);
     3.8      int (*CreateTexture) (SDL_Renderer * renderer, SDL_Texture * texture);
     3.9      int (*SetTextureColorMod) (SDL_Renderer * renderer,
    3.10                                 SDL_Texture * texture);
     4.1 --- a/src/render/direct3d/SDL_render_d3d.c	Mon May 27 21:44:16 2013 -0700
     4.2 +++ b/src/render/direct3d/SDL_render_d3d.c	Wed May 29 03:07:55 2013 -0700
     4.3 @@ -866,23 +866,25 @@
     4.4      IDirect3DDevice9_SetViewport(data->device, &viewport);
     4.5  
     4.6      /* Set an orthographic projection matrix */
     4.7 -    matrix.m[0][0] = 2.0f / renderer->viewport.w;
     4.8 -    matrix.m[0][1] = 0.0f;
     4.9 -    matrix.m[0][2] = 0.0f;
    4.10 -    matrix.m[0][3] = 0.0f;
    4.11 -    matrix.m[1][0] = 0.0f;
    4.12 -    matrix.m[1][1] = -2.0f / renderer->viewport.h;
    4.13 -    matrix.m[1][2] = 0.0f;
    4.14 -    matrix.m[1][3] = 0.0f;
    4.15 -    matrix.m[2][0] = 0.0f;
    4.16 -    matrix.m[2][1] = 0.0f;
    4.17 -    matrix.m[2][2] = 1.0f;
    4.18 -    matrix.m[2][3] = 0.0f;
    4.19 -    matrix.m[3][0] = -1.0f;
    4.20 -    matrix.m[3][1] = 1.0f;
    4.21 -    matrix.m[3][2] = 0.0f;
    4.22 -    matrix.m[3][3] = 1.0f;
    4.23 -    IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
    4.24 +    if (renderer->viewport.w && renderer->viewport.h) {
    4.25 +        matrix.m[0][0] = 2.0f / renderer->viewport.w;
    4.26 +        matrix.m[0][1] = 0.0f;
    4.27 +        matrix.m[0][2] = 0.0f;
    4.28 +        matrix.m[0][3] = 0.0f;
    4.29 +        matrix.m[1][0] = 0.0f;
    4.30 +        matrix.m[1][1] = -2.0f / renderer->viewport.h;
    4.31 +        matrix.m[1][2] = 0.0f;
    4.32 +        matrix.m[1][3] = 0.0f;
    4.33 +        matrix.m[2][0] = 0.0f;
    4.34 +        matrix.m[2][1] = 0.0f;
    4.35 +        matrix.m[2][2] = 1.0f;
    4.36 +        matrix.m[2][3] = 0.0f;
    4.37 +        matrix.m[3][0] = -1.0f;
    4.38 +        matrix.m[3][1] = 1.0f;
    4.39 +        matrix.m[3][2] = 0.0f;
    4.40 +        matrix.m[3][3] = 1.0f;
    4.41 +        IDirect3DDevice9_SetTransform(data->device, D3DTS_PROJECTION, &matrix);
    4.42 +    }
    4.43  
    4.44      return 0;
    4.45  }
     5.1 --- a/src/render/opengl/SDL_render_gl.c	Mon May 27 21:44:16 2013 -0700
     5.2 +++ b/src/render/opengl/SDL_render_gl.c	Wed May 29 03:07:55 2013 -0700
     5.3 @@ -849,28 +849,25 @@
     5.4          return 0;
     5.5      }
     5.6  
     5.7 -    if (!renderer->viewport.w || !renderer->viewport.h) {
     5.8 -        /* The viewport isn't set up yet, ignore it */
     5.9 -        return -1;
    5.10 -    }
    5.11 -
    5.12      data->glViewport(renderer->viewport.x, renderer->viewport.y,
    5.13                       renderer->viewport.w, renderer->viewport.h);
    5.14  
    5.15      data->glMatrixMode(GL_PROJECTION);
    5.16      data->glLoadIdentity();
    5.17 -    if (renderer->target) {
    5.18 -        data->glOrtho((GLdouble) 0,
    5.19 -                      (GLdouble) renderer->viewport.w,
    5.20 -                      (GLdouble) 0,
    5.21 -                      (GLdouble) renderer->viewport.h,
    5.22 -                       0.0, 1.0);
    5.23 -    } else {
    5.24 -        data->glOrtho((GLdouble) 0,
    5.25 -                      (GLdouble) renderer->viewport.w,
    5.26 -                      (GLdouble) renderer->viewport.h,
    5.27 -                      (GLdouble) 0,
    5.28 -                       0.0, 1.0);
    5.29 +    if (renderer->viewport.w && renderer->viewport.h) {
    5.30 +        if (renderer->target) {
    5.31 +            data->glOrtho((GLdouble) 0,
    5.32 +                          (GLdouble) renderer->viewport.w,
    5.33 +                          (GLdouble) 0,
    5.34 +                          (GLdouble) renderer->viewport.h,
    5.35 +                           0.0, 1.0);
    5.36 +        } else {
    5.37 +            data->glOrtho((GLdouble) 0,
    5.38 +                          (GLdouble) renderer->viewport.w,
    5.39 +                          (GLdouble) renderer->viewport.h,
    5.40 +                          (GLdouble) 0,
    5.41 +                           0.0, 1.0);
    5.42 +        }
    5.43      }
    5.44      return GL_CheckError("", renderer);
    5.45  }
     6.1 --- a/src/render/opengles/SDL_render_gles.c	Mon May 27 21:44:16 2013 -0700
     6.2 +++ b/src/render/opengles/SDL_render_gles.c	Wed May 29 03:07:55 2013 -0700
     6.3 @@ -623,12 +623,14 @@
     6.4      data->glViewport(renderer->viewport.x, renderer->viewport.y,
     6.5                 renderer->viewport.w, renderer->viewport.h);
     6.6  
     6.7 -    data->glMatrixMode(GL_PROJECTION);
     6.8 -    data->glLoadIdentity();
     6.9 -    data->glOrthof((GLfloat) 0,
    6.10 -             (GLfloat) renderer->viewport.w,
    6.11 -             (GLfloat) renderer->viewport.h,
    6.12 -             (GLfloat) 0, 0.0, 1.0);
    6.13 +    if (renderer->viewport.w && renderer->viewport.h) {
    6.14 +        data->glMatrixMode(GL_PROJECTION);
    6.15 +        data->glLoadIdentity();
    6.16 +        data->glOrthof((GLfloat) 0,
    6.17 +                 (GLfloat) renderer->viewport.w,
    6.18 +                 (GLfloat) renderer->viewport.h,
    6.19 +                 (GLfloat) 0, 0.0, 1.0);
    6.20 +    }
    6.21      return 0;
    6.22  }
    6.23  
     7.1 --- a/src/render/opengles2/SDL_render_gles2.c	Mon May 27 21:44:16 2013 -0700
     7.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Wed May 29 03:07:55 2013 -0700
     7.3 @@ -906,6 +906,10 @@
     7.4      GLfloat projection[4][4];
     7.5      GLuint locProjection;
     7.6  
     7.7 +    if (!renderer->viewport.w || !renderer->viewport.h) {
     7.8 +        return 0;
     7.9 +    }
    7.10 +
    7.11      /* Prepare an orthographic projection */
    7.12      projection[0][0] = 2.0f / renderer->viewport.w;
    7.13      projection[0][1] = 0.0f;
     8.1 --- a/src/render/software/SDL_render_sw.c	Mon May 27 21:44:16 2013 -0700
     8.2 +++ b/src/render/software/SDL_render_sw.c	Wed May 29 03:07:55 2013 -0700
     8.3 @@ -39,6 +39,7 @@
     8.4  static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
     8.5  static void SW_WindowEvent(SDL_Renderer * renderer,
     8.6                             const SDL_WindowEvent *event);
     8.7 +static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
     8.8  static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
     8.9  static int SW_SetTextureColorMod(SDL_Renderer * renderer,
    8.10                                   SDL_Texture * texture);
    8.11 @@ -110,9 +111,14 @@
    8.12          data->surface = data->window;
    8.13      }
    8.14      if (!data->surface) {
    8.15 -        data->surface = data->window = SDL_GetWindowSurface(renderer->window);
    8.16 +        SDL_Surface *surface = SDL_GetWindowSurface(renderer->window);
    8.17 +        if (surface) {
    8.18 +            data->surface = data->window = surface;
    8.19 +            renderer->viewport.w = surface->w;
    8.20 +            renderer->viewport.h = surface->h;
    8.21  
    8.22 -        SW_UpdateViewport(renderer);
    8.23 +            SW_UpdateViewport(renderer);
    8.24 +        }
    8.25      }
    8.26      return data->surface;
    8.27  }
    8.28 @@ -143,6 +149,7 @@
    8.29      data->surface = surface;
    8.30  
    8.31      renderer->WindowEvent = SW_WindowEvent;
    8.32 +    renderer->GetOutputSize = SW_GetOutputSize;
    8.33      renderer->CreateTexture = SW_CreateTexture;
    8.34      renderer->SetTextureColorMod = SW_SetTextureColorMod;
    8.35      renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
    8.36 @@ -195,6 +202,25 @@
    8.37  }
    8.38  
    8.39  static int
    8.40 +SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
    8.41 +{
    8.42 +    SDL_Surface *surface = SW_ActivateRenderer(renderer);
    8.43 +
    8.44 +    if (surface) {
    8.45 +        if (w) {
    8.46 +            *w = surface->w;
    8.47 +        }
    8.48 +        if (h) {
    8.49 +            *h = surface->h;
    8.50 +        }
    8.51 +        return 0;
    8.52 +    } else {
    8.53 +        SDL_SetError("Software renderer doesn't have an output surface");
    8.54 +        return -1;
    8.55 +    }
    8.56 +}
    8.57 +
    8.58 +static int
    8.59  SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
    8.60  {
    8.61      int bpp;
    8.62 @@ -313,11 +339,6 @@
    8.63          return 0;
    8.64      }
    8.65  
    8.66 -    if (!renderer->viewport.w && !renderer->viewport.h) {
    8.67 -        /* There may be no window, so update the viewport directly */
    8.68 -        renderer->viewport.w = surface->w;
    8.69 -        renderer->viewport.h = surface->h;
    8.70 -    }
    8.71      SDL_SetClipRect(data->surface, &renderer->viewport);
    8.72      return 0;
    8.73  }