Skip to content

Instantly share code, notes, and snippets.

@mmj-the-fighter
Last active January 28, 2025 03:46
Show Gist options
  • Save mmj-the-fighter/c13933412d89b6208da94a4aaf4f4f50 to your computer and use it in GitHub Desktop.
Save mmj-the-fighter/c13933412d89b6208da94a4aaf4f4f50 to your computer and use it in GitHub Desktop.
useful for software rendering techniques.
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/
//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