DPI with SDL_Renderer
The example uses SDL_Surface
. Does DPI scaling work differently with SDL_Renderer
or SDL_Texture
?
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.
Pixel Density and High-DPI Displays
Learn how to create SDL applications that look great on modern displays across different platforms