I am trying to revive an old cross-platform graphics library that I wrote for my students over 20 years ago. After Apple pulled the plug on Carbon, I reimplemented the Mac side on top of SDL2, which was working about 10 years ago. This library is built around a persistent-screen model rather than a persistent-object model: pixels once drawn stay drawn until erased. Obviously, this model won’t work with double buffering. So I have rebuilt around this answer in order to get single buffering.
Standing alone, the code below works as intended, single-buffering, yielding this image:
Copied VERBATIM into my larger main file of my library in place of that file’s main(), it somehow executes in a double-buffering mode, with an obvious pattern of alternate lines being drawn into alternate buffers. And furthermore, showing evidence that SDL_RenderDrawLine is drawing into some sort of uninitialized memory and then being blitted piecemeal onto the main display texture. (Although I have included minimal headers here for brevity, this small example continues to work as intended even when I include EXACTLY the same headers (a much larger set) used in the full main file of the library.)
Obviously I can’t expect someone to debug my larger program, but does anyone know: where exactly is the “switch” in SDL2 that determines whether it will operate in single-buffer or double-buffer mode? Or have I perhaps exposed a bug? Something really delicate seems to be making the determination.
MacOS 14.2.1; SDL2 version 2.30.4
The code:
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <unistd.h>
SDL_Window* gWindow = NULL; //The window we'll be rendering to
SDL_Renderer* gRenderer = NULL; // Renders to an offscreen "texture" (frequent)
static SDL_Texture *target;
SDL_Event event;
void DrawNow();
int points[][2] = {
{50, 50},
{200, 100},
{50, 300},
{400, 400},
{300, 70},
{70, 450}
};
void AutoDraw() { // "User" graphics
filledCircleColor(gRenderer, 100, 100, 40, 0xff00ff00);
SDL_SetRenderDrawColor(gRenderer, 0xff, 0xaa, 0x00, 0xFF );
for (int i = 1; i < 6; i++) {
SDL_RenderDrawLine( gRenderer,
points[i - 1][0], points[i - 1][1],
points[i][0], points[i][1]);
DrawNow();
sleep(1);
}
}
void DrawNow() {
while (SDL_PollEvent(&event)) {
printf("Event: %dn", event.type);
}
fprintf(stderr, "step ");
SDL_SetRenderTarget(gRenderer, NULL);
SDL_RenderCopy(gRenderer, target, NULL, NULL);
SDL_RenderPresent(gRenderer);
SDL_SetRenderTarget(gRenderer, target);
}
int main() {
//Initialize SDL
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
printf( "SDL could not initialize! SDL Error: %sn", SDL_GetError() );
return 1;
}
gWindow = SDL_CreateWindow("Drawbox", 10, 10, 500, 500, 0);
if( gWindow == NULL ) {
printf( "Window could not be created! SDL Error: %sn", SDL_GetError() );
return -1;
}
//Create renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %sn", SDL_GetError() );
return -1;
}
/* Create texture for display buffering */
target = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 500, 500);
SDL_SetRenderTarget(gRenderer, target);
//Clear buffer
SDL_SetRenderDrawColor( gRenderer, 0, 0, 0, 0xff );
SDL_RenderClear( gRenderer );
// handle window creation events: A MUST!
SDL_Event event;
while (SDL_PollEvent(&event)) {
printf("Event: %dn", event.type);
}
circleColor(gRenderer, 100, 100, 50, 0x00ff00ff);
DrawNow();
AutoDraw();
sleep(15);
return 0;
}