Pixel Density and High-DPI Displays

DPI with SDL_Renderer

The example uses SDL_Surface. Does DPI scaling work differently with SDL_Renderer or SDL_Texture?

Abstract art representing computer programming

Yes, DPI scaling works differently with SDL_Renderer and SDL_Texture, offering some advantages over surface-based rendering. Let's explore how to implement DPI-aware rendering with these tools.

Setting Up the Renderer

First, we need to create a renderer that's aware of our DPI settings:

#include <SDL.h>
#include <iostream>

float GetDPIScale(SDL_Window* Window) {/*...*/} int main() { SDL_SetHint( SDL_HINT_WINDOWS_DPI_SCALING, "1"); SDL_Init(SDL_INIT_VIDEO); SDL_Window* Window{SDL_CreateWindow( "Renderer DPI Demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_ALLOW_HIGHDPI )}; SDL_Renderer* Renderer{SDL_CreateRenderer( Window, -1, SDL_RENDERER_ACCELERATED )}; // Set logical size to match our design resolution float Scale{GetDPIScale(Window)}; int DesignWidth{800}; int DesignHeight{600}; SDL_RenderSetLogicalSize( Renderer, DesignWidth, DesignHeight ); // Main loop SDL_Event E; bool Running{true}; while (Running) { while (SDL_PollEvent(&E)) { if (E.type == SDL_QUIT) Running = false; } // Clear and render SDL_SetRenderDrawColor( Renderer, 50, 50, 50, 255); SDL_RenderClear(Renderer); // Draw a rectangle that will maintain its physical size SDL_SetRenderDrawColor( Renderer, 150, 50, 50, 255); SDL_Rect Rect{100, 100, 200, 100}; SDL_RenderFillRect(Renderer, &Rect); SDL_RenderPresent(Renderer); } SDL_DestroyRenderer(Renderer); SDL_DestroyWindow(Window); SDL_Quit(); return 0; }

Benefits of Renderer-Based Scaling

Using SDL_Renderer provides several advantages:

  • Hardware acceleration for scaling operations
  • Automatic DPI scaling through logical size
  • Better performance when rendering multiple objects
  • Simpler coordinate system management

Working with Textures

Textures also benefit from the renderer's DPI handling:

SDL_Texture* CreateTexture(
  SDL_Renderer* Renderer,
  int Width,
  int Height
) {
  return SDL_CreateTexture(
    Renderer,
    SDL_PIXELFORMAT_RGBA8888,
    SDL_TEXTUREACCESS_TARGET,
    Width, Height
  );
}

void RenderWithTexture(
  SDL_Renderer* Renderer) {
  // Create a texture at our design resolution
  SDL_Texture* Target{CreateTexture(
    Renderer, 800, 600)};

  // Set it as the render target
  SDL_SetRenderTarget(Renderer, Target);

  // Render to texture...
  SDL_SetRenderDrawColor(Renderer,
    150, 50, 50, 255);
  SDL_Rect Rect{100, 100, 200, 100};
  SDL_RenderFillRect(Renderer, &Rect);

  // Reset target and render the texture
  SDL_SetRenderTarget(Renderer, nullptr);
  SDL_RenderCopy(Renderer, Target, nullptr, nullptr);
}

The renderer's logical size setting automatically handles DPI scaling for all rendering operations, including texture rendering. This makes it easier to maintain consistent sizing across different display configurations.

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 71 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved