We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2535

Summary: the viewport clips render coordinates rather than scaling them
Product: SDL Reporter: Adam M. <adam>
Component: videoAssignee: Sam Lantinga <slouken>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: major    
Priority: P2    
Version: HG 2.1   
Hardware: x86_64   
OS: Windows 7   

Description Adam M. 2014-05-10 22:59:42 UTC
Publications like this (http://lazyfoo.net/tutorials/SDL/09_the_viewport/index.php) say that the viewport causes rendering to occur to a portion of the window while still having the same coordinate system (particularly, size) as the window.

Maybe it works with the texture they're using as an example (and I haven't confirmed that it does), but it does not work when filling rectangles, say.

For example, without a viewport, I draw this: http://i58.tinypic.com/28ibuw3.png
Then I set a viewport 2/3rds of the window and draw the same thing.
I expect to see the same image scaled down to 2/3rds of the window, as in the article above. Instead, I see this: http://i61.tinypic.com/35lx2f8.png  It is clipped, not scaled. In fact, setting the clip rect gives me the same output. Because it would be pointless to have two rectangles with the same behavior, I assume that is a bug.

Here is a sample program to reproduce the behavior on my system:

#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <stdio.h>

void FillRect(SDL_Renderer *pRenderer, int x, int y, int width, int height, Uint8 r, Uint8 g, Uint8 b)
{
  SDL_Rect rect;
  rect.x = x, rect.y = y, rect.w = width, rect.h = height;
  SDL_SetRenderDrawColor(pRenderer, r, g, b, 255);
  SDL_RenderFillRect(pRenderer, &rect);
}

int main()
{
  const int Width = 400, Height = 300;
  SDL_Init(SDL_INIT_EVENTS|SDL_INIT_VIDEO);
  SDL_Window *pWindow = SDL_CreateWindow("Window", 100, 100, Width, Height, 0);
  SDL_Renderer *pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_SOFTWARE);

  SDL_Rect rect;
  rect.x = 0, rect.y = 0, rect.w = Width*2/3, rect.h = Height*2/3;
  SDL_RenderSetViewport(pRenderer, &rect);

  while(true)
  {
    SDL_Event e;
    SDL_WaitEvent(&e);
    if(e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_EXPOSED)
    {
      FillRect(pRenderer, 0, 0, Width/2, Height/2, 255, 255, 255);
      FillRect(pRenderer, Width/2, 0, Width/2, Height/2, 255, 0, 0);
      FillRect(pRenderer, 0, Height/2, Width/2, Height/2, 0, 255, 0);
      FillRect(pRenderer, Width/2, Height/2, Width/2, Height/2, 0, 0, 255);
      SDL_RenderPresent(pRenderer);
    }
    else if(e.type == SDL_QUIT) break;
  }

  SDL_DestroyRenderer(pRenderer);
  SDL_DestroyWindow(pWindow);
  SDL_Quit();
  return 0;
}

It also reproduces without SDL_RENDERER_SOFTWARE for me.
Comment 1 Adam M. 2014-05-10 23:15:17 UTC
There's a possibility that it's related to using NULL for the rectangle vs. not. In fact, if I use a hollow rectangle it's also clipped, except when I pass NULL for the rectangle, in which case it's properly scaled to the viewport.
Comment 2 Adam M. 2014-05-10 23:57:07 UTC
I confirmed that this happens for points, lines, rectangles, and filled rectangles. None of those functions scale to the viewport (except the rectangle-based ones when NULL is passed for the rectangle).

Is the viewport just completely broken?
Comment 3 Sam Lantinga 2017-08-14 13:48:08 UTC
The SDL viewport doesn't work like a 3D viewport - it's just a view into the current framebuffer, and you can use the clip rectangle to clip within that. There is a separate scale that you can set to scale drawing into the viewport, and SDL_SetLogicalScale() uses these in combination to achieve what you're looking for.

I agree this is confusing and I'm marking it for review with SDL 2.1.
Comment 4 Adam M. 2017-08-15 06:24:39 UTC
This isn't fresh in my mind anymore, but when you do the review you may want to consider the behavior when using NULL for the rectangle versus passing in a rectangle. I don't know if that's an inconsistency or whether the documentation just needs updating.

I do wonder about the differences between the clip rect and the viewport if they do pretty much the same thing.
Comment 5 Sam Lantinga 2017-08-15 07:22:25 UTC
Yep, definitely. I'm seriously considering removing all the viewport/logical scale craziness and always using a target texture for that case.