Last active
January 28, 2025 03:46
-
-
Save mmj-the-fighter/c13933412d89b6208da94a4aaf4f4f50 to your computer and use it in GitHub Desktop.
useful for software rendering techniques.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SDL3 Fast Pixel Manipulation Example | |
************************************ | |
This project demonstrates dynamic Texture Updates | |
************************************************* | |
Updates a streaming texture on every frame using either locked or lockless pixel manipulation techniques. | |
Performance Analysis | |
******************** | |
The program measures: | |
- Minimum frame time | |
- Maximum frame time | |
- Current frame time | |
These metrics are printed to the console upon exiting the application. | |
References | |
********** | |
Locked Approach: [SDL Streaming Texture Example] | |
https://github.com/libsdl-org/SDL/blob/main/examples/renderer/07-streaming-textures/streaming-textures.c | |
Lockless Approach: [Stack Overflow Discussion] | |
https://stackoverflow.com/questions/33304351/sdl2-fast-pixel-manipulation | |
License | |
******* | |
This project includes code based on external sources and is subject to their respective licenses. | |
How to run in Visual Studio: | |
*************************** | |
0) Make an empty project and copy the .c file and add it to project | |
1) Download and unzip the following in a folder of your convenience. | |
-------------------------------------------------------------------- | |
These are lib files, dll and and include files | |
https://github.com/libsdl-org/SDL/releases/download/release-3.2.0/SDL3-devel-3.2.0-VC.zip | |
2)Copy SDL3.DLL in your project folder. | |
3) Fix dependencies in project. | |
------------------------------- | |
Open your project in visual studio: | |
In project properties | |
C/C++ -> General: | |
additional include directories: | |
Type in path of your SDL3 library include folder e.g: D:\Libs\SDL3-devel-3.2.0-VC\SDL3-3.2.0\include | |
Linker -> General: | |
additional library directories: | |
Type in path of your SDL3 library lib folder e.g: D:\Libs\SDL3-devel-3.2.0-VC\SDL3-3.2.0\lib\x64 | |
Linker -> input: | |
Type in | |
SDL3.lib | |
Reference: https://www.libsdl.org/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Attribution1:(Locked Approach) https://github.com/libsdl-org/SDL/blob/main/examples/renderer/07-streaming-textures/streaming-textures.c | |
//Attribution2:(Lockless Aprroach) https://stackoverflow.com/questions/33304351/sdl2-fast-pixel-manipulation | |
//License | |
//This project includes code based on external sources and is subject to their respective licenses. | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <SDL3/SDL.h> | |
#define LOCKEDPIXELMANIPULATION | |
static SDL_Window* window = NULL; | |
static SDL_Renderer* renderer = NULL; | |
static SDL_Texture* texture = NULL; | |
#define WINDOW_WIDTH 640 | |
#define WINDOW_HEIGHT 480 | |
static unsigned char* pixels = NULL; | |
static int pitch; | |
static int blue; | |
static int green; | |
static int red; | |
int init() | |
{ | |
if (!SDL_Init(SDL_INIT_VIDEO)) | |
{ | |
printf("Couldn't initialize SDL: %s", SDL_GetError()); | |
return 1; | |
} | |
if (!SDL_CreateWindowAndRenderer( | |
"streaming-textures", | |
WINDOW_WIDTH, | |
WINDOW_HEIGHT, | |
0, | |
&window, | |
&renderer)) | |
{ | |
printf("Couldn't create window/renderer: %s", SDL_GetError()); | |
return 2; | |
} | |
texture = SDL_CreateTexture(renderer, | |
SDL_PIXELFORMAT_ARGB8888, | |
SDL_TEXTUREACCESS_STREAMING, | |
WINDOW_WIDTH, | |
WINDOW_HEIGHT); | |
if (!texture) | |
{ | |
printf("Couldn't create streaming texture: %s", SDL_GetError()); | |
return 3; | |
} | |
pitch = WINDOW_WIDTH * 4; | |
pixels = (unsigned char*)malloc(pitch * WINDOW_HEIGHT); | |
if (pixels == NULL) | |
{ | |
printf("Couldn't allocate pixels"); | |
return 4; | |
} | |
blue = rand() % 255; | |
green = rand() % 255; | |
red = rand() % 255; | |
return 0; | |
} | |
void destroy() | |
{ | |
if (pixels != NULL) { | |
free(pixels); | |
pixels = NULL; | |
} | |
SDL_DestroyTexture(texture); | |
/* SDL will clean up the window/renderer for us. */ | |
} | |
void draw() { | |
for (int y = 0; y < WINDOW_HEIGHT; ++y) | |
{ | |
for (int x = 0; x < WINDOW_WIDTH; ++x) | |
{ | |
unsigned char* loc = pixels + pitch * y + x * 4; | |
*loc = blue; | |
*(loc + 1) = green; | |
*(loc + 2) = red; | |
*(loc + 3) = 255; | |
} | |
} | |
++blue; | |
++green; | |
++red; | |
blue %= 255; | |
green %= 255; | |
red %= 255; | |
} | |
#ifdef LOCKEDPIXELMANIPULATION | |
int main(int argc, char* args[]) | |
{ | |
printf("locked sdl3 fast pixel manipulation\n"); | |
int rv = init(); | |
if (rv != 0) | |
{ | |
printf("Init failure"); | |
return rv; | |
} | |
int quit = 0; | |
SDL_Event e; | |
SDL_zero(e); | |
Uint32 frame_start_time, elapsed_time; | |
Uint32 minFrameTime = 1000000; | |
Uint32 maxFrameTime = 0; | |
while (0 == quit) | |
{ | |
frame_start_time = SDL_GetTicks(); | |
while (SDL_PollEvent(&e)) | |
{ | |
if (e.type == SDL_EVENT_QUIT) | |
{ | |
quit = 1; | |
destroy(); | |
printf("min=%d\tcur=%d\tmax=%d\n", minFrameTime, elapsed_time, maxFrameTime); | |
return 0; | |
} | |
} | |
draw(); | |
unsigned char* destPixels; | |
int destPitch; | |
if (SDL_LockTexture(texture, NULL, (void**)&destPixels, &destPitch)) | |
{ | |
for (int y = 0; y < WINDOW_HEIGHT; ++y) { | |
memcpy(destPixels + y * destPitch, pixels + y * pitch, pitch); | |
} | |
SDL_UnlockTexture(texture); | |
} | |
SDL_RenderTexture(renderer, texture, NULL, NULL); | |
SDL_RenderPresent(renderer); | |
elapsed_time = (SDL_GetTicks() - frame_start_time); | |
if (elapsed_time < minFrameTime){ | |
minFrameTime = elapsed_time; | |
} | |
else if (elapsed_time > maxFrameTime){ | |
maxFrameTime = elapsed_time; | |
} | |
//printf("%d\n", elapsed_time); | |
} | |
return 0; | |
} | |
#else | |
int main(int argc, char* args[]) | |
{ | |
printf("lockless sdl3 fast pixel manipulation\n"); | |
int rv = init(); | |
if (rv != 0) | |
{ | |
printf("Init failure"); | |
return rv; | |
} | |
int quit = 0; | |
SDL_Event e; | |
SDL_zero(e); | |
Uint32 frame_start_time, elapsed_time; | |
Uint32 minFrameTime = 1000000; | |
Uint32 maxFrameTime = 0; | |
while (0 == quit) | |
{ | |
frame_start_time = SDL_GetTicks(); | |
while (SDL_PollEvent(&e)) | |
{ | |
if (e.type == SDL_EVENT_QUIT) | |
{ | |
quit = 1; | |
destroy(); | |
printf("min=%d\tcur=%d\tmax=%d\n", minFrameTime, elapsed_time, maxFrameTime); | |
return; | |
} | |
} | |
draw(); | |
SDL_UpdateTexture(texture, NULL, pixels, pitch); | |
SDL_RenderTexture(renderer, texture, NULL, NULL); | |
SDL_RenderPresent(renderer); | |
elapsed_time = (SDL_GetTicks() - frame_start_time); | |
if (elapsed_time < minFrameTime){ | |
minFrameTime = elapsed_time; | |
} | |
else if (elapsed_time > maxFrameTime){ | |
maxFrameTime = elapsed_time; | |
} | |
//printf("%d\n", elapsed_time); | |
} | |
return 0; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment