Tag Archives: renderer

Title Window SDL3

Window and Renderer in SDL3


Every SDL3 application with graphic output has to have at least one SDL3 window and a SDL3 renderer. The window is the entity that is showing the graphic output and the renderer is the “machine” that is generating the output. The code to set up a window and a renderer is as follows.

program SDL_WindowAndRenderer;

uses SDL3;

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;

begin

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

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

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

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

  // show window with rendered content for 2 seconds
  SDL_RenderPresent(sdlRenderer);
  SDL_Delay(2000);

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

  //closing SDL3
  SDL_Quit;

end.

Getting a Window with SDL3

With SDL3 you can create as many windows as you like, and each window is adressed by a variable of pointer type PSDL_Window. We just need one window we define in the var clause, 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 in SDL3

  sdlWindow1 := SDL_CreateWindow('Window1', 500, 500, 0);
  if sdlWindow1 = nil then Halt;

The actual creation of a window in SDL3 is as simple as using the function SDL_CreateWindow(title, width, height, flags). If it fails, sdlWindow1 will be nil afterwards. You should always check this.

In our example the window is titled “Window1”, it has a width and height of 500 pixels respectively. And we don’t want to set a specific flag. This will generate a common window as typical for your operating system at the screen’s center.

Hint for MacOS users: Window creation doesn’t work without an event loop in MacOS in SDL2. Please let me know, if this also applies for SDL3.

SDL3 Window Flags

The SDL3 window flags decide for the properties of the window. Look at the following list of possible flags and you may get an idea what they do. 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 the logical OR (if appropriate).

  • SDL_WINDOW_FULLSCREEN: fullscreen window at desktop resolution
  • SDL_WINDOW_OPENGL: window usable with an OpenGL context
  • SDL_WINDOW_OCCLUDED: window partially or completely obscured by another window
  • SDL_WINDOW_HIDDEN: window is not visible
  • SDL_WINDOW_BORDERLESS: no window decoration
  • SDL_WINDOW_RESIZABLE: window can be resized
  • SDL_WINDOW_MINIMIZED: window is minimized
  • SDL_WINDOW_MAXIMIZED: window is maximized
  • SDL_WINDOW_MOUSE_GRABBED: window has grabbed mouse focus
  • SDL_WINDOW_INPUT_FOCUS: window has input focus
  • SDL_WINDOW_MOUSE_FOCUS: window has mouse focus
  • SDL_WINDOW_EXTERNAL: window not created by SDL
  • SDL_WINDOW_MODAL: window is modal
  • SDL_WINDOW_HIGH_PIXEL_DENSITY: window uses high pixel density back buffer if possible
  • SDL_WINDOW_MOUSE_CAPTURE: window has mouse captured (unrelated to MOUSE_GRABBED)
  • SDL_WINDOW_ALWAYS_ON_TOP: window should always be above others
  • SDL_WINDOW_UTILITY: window should be treated as a utility window, not showing in the task bar and window list
  • SDL_WINDOW_TOOLTIP: window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window
  • SDL_WINDOW_POPUP_MENU: window should be treated as a popup menu, requires a parent window
  • SDL_WINDOW_KEYBOARD_GRABBED: window has grabbed keyboard input
  • SDL_WINDOW_VULKAN: window usable with a Vulkan instance
  • SDL_WINDOW_METAL: window usable with a Metal instance
  • SDL_WINDOW_TRANSPARENT: window with transparent buffer
  • SDL_WINDOW_NOT_FOCUSABLE: window should not be focusable

The Renderer

In computer graphics rendering means the process of synthesizing the final image on your screen from the individual basic data structures, be it some lines, a flat background, a texture, a 3d object, or whatever. Hence we need a renderer to draw some content to the window.

The PSDL_Renderer pointer (which we declared in the var clause) is responsible for this and we call our PSDL_Renderer handle “sdlRenderer”. You could have many different renderers in an application, but oftentimes you use just one.

Creation of a Renderer in SDL3

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

The creation of a renderer is as simple as one function call of SDL_CreateRenderer(window, name). If it fails, sdlRenderer is nil afterwards. The first argument is the window where the rendered output should be shown. That will be sdlWindow1 in our case.

The second argument should be nil which means SDL3 is choosing the best renderer for you. Otherwise you could specify a renderer by name, but that is not necessary for now.

Quick Creation of a Window and a Renderer

  if not SDL_CreateWindowAndRenderer(500, 500, 0, @sdlWindow1, @sdlRenderer)
    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. Since the window and renderer parameters are double pointers, you need to use the @ operator to make the window and renderer pointers available to the function.

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

The function returns a logical false on failure.

Rendering a SDL3 Scene

The actual rendering is achieved by SDL_RenderPresent(renderer).

Freezing (delaying) a running application in SDL3

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.

  // show window with rendered content for 2 seconds
  SDL_RenderPresent(sdlRenderer);
  SDL_Delay(2000);

Clean up the Memory in SDL3

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 SDL3, 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.

  // clear memory
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);
  
  //closing SDL3
  SDL_Quit;

Finally quit SDL3.

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

Previous Chapter | Next Chapter

Window and Renderer

Last updated on February 15th, 2025

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.

Creation of a Window on MacOS

If you use Linux or Windows, you may skip this paragraph.

It is important that the code shown above will not work on MacOS. For technical reasons you need to add an event loop to your code. Event loops are covered in a later chapter.

In short to make your code work:

  • add a variable “ExitLoop” of type “Boolean” to your var clause and preset it to False
  • add a variable “Event” of type “TSDL_Event” to your var clause
  • replace the call “SDL_Delay(2000);” with the following code snippet
  while not ExitLoop do
  begin
    while (SDL_PollEvent(@Event) <> 0) do
    begin
      if (Event.type_ = SDL_QUITEV) then
        ExitLoop := True;
    end;
  end;

Instead of a 2 second delay you need to quit your window (click on “X”) and the program will terminate.

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 →