I was trying to use SDL_UpdateTexture
to create a texture from an allocated buffer of pixels, and I was surprised that it wasn't even rendering at 60fps (with the main culprit being SDL_UpdateTexture
):
#include <SDL2/SDL.h>
#include <sys/time.h>
static double time_in_ms(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
}
int main(void) {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *window = SDL_CreateWindow("Pixel formats" , 0, 0, 1920, 1080, 0);
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
double last_frame = time_in_ms();
while (1) {
int width, height;
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
return 0;
}
}
SDL_GetWindowSize(window, &width, &height);
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
Uint32 *pixels = malloc(width * height * sizeof(*pixels));
/* fill buffer with blue pixels */
for (int y = 0; y < height; y++) {
Uint32 *row = pixels + y * width;
for (int x = 0; x < width; x++) {
row[x] = 0x0000FFFF;
}
}
double update_begin = time_in_ms();
SDL_UpdateTexture(texture, NULL, pixels, width * sizeof(*pixels));
double update_end = time_in_ms();
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_DestroyTexture(texture);
free(pixels);
double this_frame = time_in_ms();
printf("frame took %fms\n", this_frame - last_frame);
printf(" - update texture: %fms\n", update_end - update_begin);
last_frame = this_frame;
}
}
But, if I just change SDL_PIXELFORMAT_RGBA8888
to SDL_PIXELFORMAT_ARGB8888
(and update 0x0000FFFF
to 0xFF0000FF
), all of a sudden, SDL_UpdateTexture
goes down from taking ~15ms per frame to ~1ms. This happens regardless of whether renderer
is an accelerated or software renderer. This seems very strange to me, since even if SDL_Texture
s are internally ARGB, it takes far less than 15ms to convert from RGBA to ARGB:
for (int y = 0; y < height; y++) {
Uint32 *row = pixels + y * width;
for (int x = 0; x < width; x++) {
Uint32 a = row[x] & 0xFF;
row[x] >>= 8;
row[x] |= a << 24;
}
}
Why might it be that SDL_UpdateTexture
is so much faster with ARGB than RGBA (and does this vary across platforms)?
(SDL_PIXELFORMAT_RGB888
is also quite fast (~2ms), but not as fast as ARGB)
User contributions licensed under CC BY-SA 3.0