I've been trying to learn how to use the SDL library with C (not C++) and recently discovered that the reason for all the errors I was getting was that I was looking at an SDL1 tutorial, not an SDL2 tutorial. I've since discovered that SDL2 has implemented a number of layers of abstraction absent (as far as I know) from SDL1 which appear to be impossible to bypass.
Specifically, whereas in SDL1, drawing a set of pixels on the screen was accomplished by:
define surface - find rgb values for pixels - draw pixels on surface - draw surface on screen
in SDL2 it appears to instead by done by:
define window - create renderer for window - create surface - find rgb values for pixels - draw pixels to surface - convert surface to texture - send texture to renderer - redraw window
While I understand how textures can be a simpler way to do things if there are things other than raw pixel data involved, especially if there are multiple sources for the data, in the specific case I want to use it for (a single window program in which raw pixel data is the only thing that will ever be drawn) the distinction between the window, renderer and texture is just pointless abstraction. Additionally, it seems that in most cases data from images will be loaded to the SDL_Surface class which must then be converted to a texture, adding even more unnecessary abstraction.
Is there any way to circumvent this aside from reverting to an older version of SDL?
I shared exactly the same thought when I began to use SDL2.
First of all, it's maybe unclear because you didn't explored a lot SDL2, but even if you doesn't want to do OGL/DX, these additional layers are useful even with plain 2D and pixel processing.
For instance, SDL_RenderCopyEx
can render a surface while rotating and resizing it on the fly. In SDL1, you'd have needed to use a third party library or to code your own rotozoom algorithms to achieve the same thing.
Another useful ability is that you can easily render primitives. For instance, there is an optimized SDL_RenderDrawLine
method, where in SDL1 you'd have needed to build your own method which will create a surface, browse and blit pixel infomations, and blit the line back to your full surface.
There are a lot of other methods which I'm sure you will discover in given time, such as color modulation.
The next point is that you think SDL1 is more low-level and 'realistic' and that SDL2 add some additional layers. In fact, modern graphic cards are used to work as SDL2 does. Usually, you don't store a huge bitmap in memory (SDL_Surface
s are raw data), you don't blit some other surfaces to it and then send it to the graphic card. Graphic cards are thinking in terms of texturing.
Now if you still want to bypass these "additional layers", you still can, by isolating the texture rendering process. I think the cleanest way to achieve this is by creating a linked list of the surfaces you want to blit:
struct SurfaceElement {
SDL_Surface* s;
SDL_Rect clip;
SDL_Rect position;
struct SurfaceElement * next;
};
typedef struct SurfaceElement SurfaceElement;
void ProcessingLoop() {
SurfaceElement *surfacesList = (SurfaceElement *)malloc(sizeof(SurfaceElement));
// Create surfaces, work on surfaces
// When you're done with a surface, add it to the list:
surfacesList = AddToBlitList(yourSurface, yourClipPos, yourBlitPos, surfacesList);
// When everything is okay and you're ready to blit:
TextureBlittingProcess(surfacesList, renderer);
}
SurfaceElement* AddToBlitList(SDL_Surface *s, SDL_Rect clip, SDL_Rect position, SurfaceElement *head) {
SurfaceElement *current = (SurfaceElement*)malloc(sizeof(SurfaceElement));
current->s = s;
current->clip = clip;
current->position = position;
current->next = head;
return current;
}
void TextureBlittingProcess(SurfaceElement *surfacesList, SDL_Renderer *renderer) {
while (surfaceList) {
SDL_Texture *t = SDL_CreateTextureFromSurface(renderer, surfaceList->s)
SDL_RenderCopy(renderer, t, &(surfaceList->clip), &(surfaceList->position));
surfaceList = surfaceList->next;
}
}
Last, if you really don't see the point of using these textures, if you don't necessarily want to blit a texture but just to do operations on its pixels, maybe SDL is just not for you. You should read about Matlab or maybe Scripting languages such as Python or Caml.