This commit is contained in:
VegOwOtenks 2025-02-28 23:55:22 +01:00
commit 61f3235277
6 changed files with 198 additions and 0 deletions

7
.gitmodules vendored Normal file
View file

@ -0,0 +1,7 @@
[submodule "submodules/SDL_ttf"]
path = submodules/SDL_ttf
url = https://github.com/libsdl-org/SDL_ttf.git
[submodule "submodules/SDL"]
path = submodules/SDL
url = https://github.com/libsdl-org/SDL.git

5
CMakeLists.txt Normal file
View file

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.30)
project(SDL_FPSCounter C)
add_subdirectory(src/)

4
src/CMakeLists.txt Normal file
View file

@ -0,0 +1,4 @@
add_library(SDL_FPSCounter STATIC SDL_FPSCounter.c)
add_executable(fps-counter WIN32 main.c)
target_link_libraries(fps-counter SDL_FPSCounter SDL3 SDL3_ttf)

52
src/SDL_FPSCounter.c Normal file
View file

@ -0,0 +1,52 @@
#include "SDL_FPSCounter.h"
#include <stdlib.h>
#include <SDL3/SDL.h>
int SDL_CreateFPSCounter(SDL_FPSCounter* counter, uint32_t window_length)
{
counter->window = malloc(sizeof(uint64_t) * window_length);
if (counter->window == NULL) {
SDL_OutOfMemory();
return -1;
}
memset(counter->window, 0, window_length * sizeof(uint64_t));
counter->frequency = SDL_GetPerformanceFrequency();
counter->window_index = 0;
counter->window_length = window_length;
return EXIT_SUCCESS;
}
void SDL_DestroyFPSCounter(SDL_FPSCounter* counter)
{
free(counter->window);
memset(counter, 0, sizeof *counter);
}
int SDL_FPSCounterTick(SDL_FPSCounter* counter)
{
counter->window[counter->window_index] = SDL_GetPerformanceCounter();
counter->window_index++;
counter->window_index = counter->window_index % counter->window_length;
return EXIT_SUCCESS;
}
uint64_t SDL_FPSCounterFPS(SDL_FPSCounter* counter)
{
uint64_t last = counter->window[counter->window_index];
uint64_t current;
uint64_t acc_difference = 0;
for (uint32_t i = (counter->window_index + 1) % counter->window_length; i != counter->window_index; i = (i + 1) % counter->window_length) {
current = counter->window[i];
acc_difference += current - last;
last = current;
}
uint64_t average_difference = acc_difference / (counter->window_length - 1);
return counter->frequency / average_difference;
}

19
src/SDL_FPSCounter.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef SDL_FPSCOUNTER_H
#define SDL_FPSCOUNTER_H
#include <stdint.h>
typedef struct SDL_FPSCounter_s {
uint64_t frequency;
uint32_t window_index;
uint32_t window_length;
uint64_t* window;
} SDL_FPSCounter;
int SDL_CreateFPSCounter(SDL_FPSCounter* counter, uint32_t window_length);
void SDL_DestroyFPSCounter(SDL_FPSCounter* counter);
int SDL_FPSCounterTick(SDL_FPSCounter* counter);
uint64_t SDL_FPSCounterFPS(SDL_FPSCounter* counter);
#endif

111
src/main.c Normal file
View file

@ -0,0 +1,111 @@
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_properties.h>
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_surface.h>
#include <SDL3_ttf/SDL_ttf.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include "SDL_FPSCounter.h"
#define INITIAL_WINDOW_HEIGHT 600
#define INITIAL_WINDOW_WIDTH 600
void DrawNumber(SDL_Window* window, SDL_Renderer* renderer, SDL_Texture* digits[10], int number)
{
char number_string[snprintf(NULL, 0, "%i", number) + 1];
snprintf(number_string, sizeof(number_string), "%i", number);
int window_height, window_width;
SDL_GetWindowSize(window, &window_width, &window_height);
int current_x = 0;
char* digit_p = number_string;
for (; *digit_p; digit_p++) {
int index = (*digit_p) - '0';
SDL_Texture* digit_texture = digits[index];
SDL_FRect target_rect;
target_rect.x = current_x;
target_rect.y = 0;
SDL_GetTextureSize(digit_texture, &target_rect.w, &target_rect.h);
SDL_RenderTexture(renderer, digit_texture, NULL, &target_rect);
current_x += target_rect.w;
}
}
int main(int argc, char* argv[])
{
(void) argc;
(void) argv;
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS);
if (TTF_Init()) {
fprintf(stderr, "Initializing SDL2_ttf failed: %s\n", SDL_GetError());
}
SDL_Window* window = SDL_CreateWindow(
"FPS-Counter",
INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT,
0
);
if (window == NULL) {
fprintf(stderr, "Creating the window failed: %s\n", SDL_GetError());
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
if (renderer == NULL) {
fprintf(stderr, "Creating the window renderer failed: %s\n", SDL_GetError());
}
TTF_Font* number_font = TTF_OpenFont("/usr/share/fonts/urw-base35/NimbusMonoPS-Regular.otf", 300);
SDL_Texture* digits[10];
for (int i = 0; i < 10; i++) {
char string[3];
snprintf(string, 3, "%i", i);
SDL_Surface* digit_surface = TTF_RenderText_Solid(number_font, string, strlen(string),((SDL_Color) {0x2D, 0x2D, 0x2D, 0xFF}));
digits[i] = SDL_CreateTextureFromSurface(renderer, digit_surface);
SDL_DestroySurface(digit_surface);
}
TTF_CloseFont(number_font);
bool continue_ = true;
SDL_FPSCounter fpscounter;
if (SDL_CreateFPSCounter(&fpscounter, 1000)) {
fprintf(stderr, "Failed to create fps counter: %s\n", SDL_GetError());
return 1;
}
while (continue_) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_EVENT_QUIT:
continue_ = false;
break;
}
}
SDL_SetRenderDrawColor(renderer, 0xFF, 0xC2, 0xDE, 0xFF);
SDL_RenderClear(renderer);
SDL_FPSCounterTick(&fpscounter);
DrawNumber(window, renderer, digits, SDL_FPSCounterFPS(&fpscounter));
SDL_RenderPresent(renderer);
}
SDL_DestroyFPSCounter(&fpscounter);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}