Tag Archives: renderer

Window and Renderer

Last updated on November 20th, 2021

Every SDL2 program that shall show some graphic output has to have at least one SDL2 window and a SDL2 renderer. The window is the entity that is showing the graphic output and the renderer is the “machine” that is generating the output to be shown in the window. The code to set up a window and a renderer is as follows.

program SDL_WindowAndRenderer;

uses SDL2;

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;

begin

  //initilization of video subsystem
  if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt;

  // full set up
  sdlWindow1 := SDL_CreateWindow('Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN);
  if sdlWindow1 = nil then Halt;

  sdlRenderer := SDL_CreateRenderer(sdlWindow1, -1, 0);
  if sdlRenderer = nil then Halt;

  // quick set up
  {
  if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
    then Halt;
  }

  // render to window for 2 seconds
  SDL_RenderPresent(sdlRenderer);
  SDL_Delay(2000);

  // clear memory
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

  //closing SDL2
  SDL_Quit;

end.  

Let’s have closer look at the var clause.

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;

The SDL2 Window

In SDL 2.0 you can create as many windows as you like, and each window is adressed by its PSDL_Window variable. We just need one window for now, let’s call it “sdlWindow1”. It defines the window’s properties, e.g. size, appearance, border, title name and so on. And it holds the content it shows.

Creation of a Window

  // full set up
  sdlWindow1 := SDL_CreateWindow('Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN);
  if sdlWindow1 = nil then Halt;

The creation of a SDL2 window is simple as using the function SDL_CreateWindow(title, x, y, width, height, flags) or more specific:

SDL_CreateWindow(const title: PAnsiChar; x: SInt32; y: SInt32; w: SInt32; h: SInt32; flags: UInt32): PSDL_Window

In our example the window is titled “Window1”, it is located at position x = 50 and y = 50 pixels (relative to your screen). It has a width and height of 500 pixels respecitvly. And we have used the flag SDL_WINDOW_SHOWN. More about these flags later. First let’s get an understanding of the coordinate system in SDL2.

The Coordinate System in SDL 2.0

This rule applies:

The origin from where to count to place a window is always the left upper corner of your screen.

So if you choose (0/0) as coordinates the window’s left upper corner will be placed right at the left upper corner of your screen. The diagram below may help to understand this. You may try SDL_WINDOWPOS_CENTERED for each or both coordinates which will lead to a centered window with respect of the screen. If you choose SDL_WINDOWPOS_UNDEFINED you don’t care for the window’s position.

SDL2 window and coordinates diagram
Creative Commons License This image by https://www.freepascal-meets-sdl.net is licensed under a Creative Commons Attribution 4.0 International License.
The window is placed with respect to the left upper corner of the screen.

SDL 2.0 windows and their properties

Now let’s talk about the flags. They decide for the properties of the window. Look at the following table (source) of possible flags and you may get an idea what they do.

Flag
Description
SDL_WINDOW_FULLSCREENfullscreen window
SDL_WINDOW_FULLSCREEN_DESKTOPfullscreen window at the current desktop resolution
SDL_WINDOW_OPENGLwindow usable with OpenGL context
SDL_WINDOW_SHOWNwindow is visible
SDL_WINDOW_HIDDENwindow is not visible
SDL_WINDOW_BORDERLESSno window decoration
SDL_WINDOW_RESIZABLEwindow can be resized
SDL_WINDOW_MINIMIZEDwindow is minimized
SDL_WINDOW_MAXIMIZEDwindow is maximized
SDL_WINDOW_INPUT_GRABBEDwindow has grabbed input focus
SDL_WINDOW_INPUT_FOCUSwindow has input focus
SDL_WINDOW_MOUSE_FOCUSwindow has mouse focus
SDL_WINDOW_FOREIGNwindow not created by SDL
SDL_WINDOW_ALLOW_HIGHDPIwindow should be created in high-DPI mode if supported (available since SDL 2.0.1)

As you can see, these flags determine different properties of  the window. E.g. SDL_WINDOW_FULLSCREEN will create a fullscreen window and SDL_WINDOW_BORDERLESS will create a borderless window. You may combine several flags by OR (if appropriate). For our purpose SDL_WINDOW_SHOWN is a good choice because we just create a shown window without any further restrictions.

The SDL2 Renderer

In computer graphics rendering means the process of synthesizing the final image on your screen from the individual basic data structures. To draw some content to the window, we need therefore a renderer. The PSDL_Renderer (which we declared in the var clause) is responsible for synthesizing all the content in a window, be it some lines, a flat background, a texture, a 3d object, or whatever. We call our PSDL_Renderer “sdlRenderer”.

Creation of a Renderer

  sdlRenderer := SDL_CreateRenderer(sdlWindow1, -1, 0);
  if sdlRenderer = nil then Halt;

The creation of the renderer is as simple as one function call of SDL_CreateRenderer(window, index, flags) or

SDL_CreateRenderer(window: PSDL_Window; index: SInt32; flags: UInt32): PSDL_Renderer

First we need the renderer to know where to render the finished/rendered output. That will be “Window1” in our case. Next the shown function asks for a cryptic “index”. Well, each driver which is capable of rendering (e.g. OpenGL, Direct3d, Software,…) is indexed in SDL 2.0. In principle you could choose one specific driver here by choosing the corresponding index. Since we don’t know too much about the drivers at the moment the best choice is -1. -1 means that the first driver which is supporting the chosen flag(s) is chosen. Talking about flags, there are four flags you may choose:

  1. SDL_RENDERER_SOFTWARE
  2. SDL_RENDERER_ACCELERATED
  3. SDL_RENDERER_PRESENTVSYNC
  4. SDL_RENDERER_TARGETTEXTURE

You should always prefer SDL_RENDERER_ACCELERATED because this means the graphics board is responsible for rendering, SDL_RENDERER_SOFTWARE in contrast means, the CPU has to do the rendering. As discussed before for best performance the graphic board is the best choice for rendering/graphic related tasks. SDL_RENDERER_PRESENTVSYNC allows for so called vertical synchronization which means that the display of the rendered image is synchronized with the refresh rate of the monitor. SDL_RENDERER_TARGETTEXTURE allows for rendering to a texture. You may have noticed that none of these flags but 0 was used in the example code. This automatically gives priority to hardware accelerated renderers.

Quick Creation of a Window and a Renderer

 // quick set up
  {
  if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
    then Halt;
  }

Instead of creating the window and the renderer separately as demonstrated, you may use SDL_CreateWindowAndRenderer(width, height, window flags, window pointer pointer, renderer pointer pointer). This has the advantage that you just need one line to set up a window and a renderer, though setting a window title, a window position or specific renderer flags have to be done afterwards if necessary.

Just remove the curly brackets and enclose the “full set up” -part to try it.

SDL_CreateWindowAndRenderer(width: SInt32; height: SInt32; window_flags: UInt32; window: PPSDL_Window; renderer: PPSDL_Renderer): SInt32

This function returns 0 on success and -1 on failure.

Rendering a SDL2 Scene

The actual rendering is achieved by SDL_RenderPresent(renderer). As a sidenote for people coming from SDL 1.2, this is what formerly has been achieved by SDL_Flip().

SDL_RenderPresent(renderer: PSDL_Renderer)

Freezing (delaying) a running program in SDL 2.0

SDL_Delay(time in milliseconds) is a simple, yet powerful and important procedure to stop the program running for a certain time in milliseconds. 2000 milliseconds are two seconds. This is kind of a twin of Pascal’s Delay procedure.

Clean up the memory in SDL 2.0

Now the final lines of code are discussed. One of the most important rules for sophisticated programming is followed here:

Always clean up the memory on program finish.

For nearly any pointer type generated by SDL 2.0, there is a destroy procedure to remove it from memory. These procedures are comparable to Pascal’s dispose procedure to remove pointer types from memory. Make sure to destroy the objects in the opposite sequence of their generation. We first created a window, then a renderer. So now we go the opposite way, first destroy the renderer and then the window by the procedures SDL_DestroyRenderer(renderer) and SDL_DestroyWindow(window) respectively.

Here we go:

  // clear memory
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

Do not forget to quit SDL2 finally (which we don’t).

That’s it. And now things are going to get really interesting :-).

← previous Chapter | next Chapter →