If I were to start writing a new renderer, the first thing I'd do is to hook it up to an external image viewer over some protocol. These days, I find myself liking TEV (https://github.com/Tom94/tev) a lot as a simple open-source image viewer that supports this and most other basic features that I'd want. See the links in the README for Python and Rust implementations of its protocol.
There are two PPM formats, both very simple: http://netpbm.sourceforge.net/doc/ppm.html
For example, the header
printf("P6\n%lu %lu\n255\n", width, height);
followed by width*height triplets of raw bytes representing the RGB values of each pixel.anecdotally, in my cpu based ray-tracers (i have one in c++ and python so far) , i have found that SDL based rendering causes noticeable slowdowns to become quite useless after the initial novelty wears off.
My CPU-based ray tracer uses the code I linked. SDL_LockTexture, go wide with threads writing into the locked buffer, SDL_UnlockTexture. If I skip the actual ray tracing, I get 1400 FPS uploading a 1024x1024 image.