In many cases, doing all your rendering in software and then moving it
to an SDL_Texture will get it to the screen faster than using
SDL_UpdateWindowSurface(), too.
Then why doesn’t SDL_UpdateWindowSurface() do that internally? Oh,
wait, it does.
Did I make you angry? I’m trying to understand the aggression in your reply.
SDL_UpdateWindowSurface() calls the target’s UpdateWindowFramebuffer
implementation eventually…
https://hg.libsdl.org/SDL/file/c3ec7c3e6c24/src/video/SDL_video.c#l1972
…which, on X11, calls either XPutImage (slow!) or XShmPutImage (less
slow).
…on Windows, this calls BitBlt (a function from Win16!)
https://hg.libsdl.org/SDL/file/c3ec7c3e6c24/src/video/windows/SDL_windowsframebuffer.c#l95
On the other hand, if you use an SDL_Texture, you’re likely using either
OpenGL or Direct3D to get it to texture memory for the draw, and these
tend to be faster paths on modern systems.
On systems that only offer OpenGL(ES), UpdateWindowSurface() will put it
in a GL texture for you, as I said before, but you still can’t get
scaling or vsync out of the system unless you go through the Render API
or OpenGL/Direct3D directly.
SDL_RenderPresent calls SDL_UpdateWindowSurface(): at least as many
copy operations as when using SDL_UpdateWindowSurface() directly.
You’re describing SDL’s software renderer, which is not what you would
get in almost any circumstance. If you use an SDL_Texture to push an
otherwise software-rendered game to the screen, it’ll use Direct3D or
OpenGL to get the final rendering to the screen by default.
(What you’re describing is true for this case, though: if you get the
software renderer, you might have been better off just using
SDL_UpdateWindowSurface() to avoid a blit, but you’ve probably got
deeper problems if you ended up here, and it’ll still work without any
changes to your program.)
The first copy operation can theoretically be elided by using
SDL_LockTexture, but you lose read access (necessary for blending
operations), you lose the ability to only change a few individual pixels
(Bug 1586), and there’s no guarantee that SDL_UnlockTexture won’t
perform a copy anyway.
Treat textures as unidirectional: always be pushing data to them, don’t
read data back. Render to a buffer of memory (or an SDL_Surface, if you
prefer) and push that to the texture once a frame. If you need to read
back from what you’ve rendered, you read from your memory buffer.
–ryan.