I have a weird problem with a race condition in the SDL Renderer. This leads to content not being drawn under certain circumstances. The weird thing about it:
It seems that the data is correctly copied to uiBuffer. It I force repaint by externally setting blitUI it will be painted to the screen without having to run the copy-loop from main thread again. Does anyone have an idea what might be wrong here?
Full application is at http://previous.sourceforge.net. Relevant code is in trunk/src/fast_screen.c.
This is my code (simplified):
SDL_Surface* sdlscrn;
SDL_Renderer* sdlRenderer;
static void* uiBuffer;
static void* uiBufferTmp;
static SDL_atomic_t blitUI;
static SDL_SpinLock uiBufferLock;
static uint32_t mask;
static SDL_Rect screenRect;
Thread 0 (main):
SDL_LockSurface(sdlscrn);
int count = sdlscrn->w * sdlscrn->h;
uint32_t* dst = (uint32_t*)uiBuffer;
uint32_t* src = (uint32_t*)sdlscrn->pixels;
SDL_AtomicLock(&uiBufferLock);
for(int i = count; --i >= 0; src++)
*dst++ = *src == mask ? 0 : *src;
SDL_AtomicSet(&blitUI, 1);
SDL_AtomicUnlock(&uiBufferLock);
SDL_UnlockSurface(sdlscrn);
Thread 1 (draw):
SDL_Texture* uiTexture;
uint32_t r, g, b, a;
uint32_t format;
int d;
SDL_RenderSetLogicalSize(sdlRenderer, width, height);
uiTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
SDL_SetTextureBlendMode(uiTexture, SDL_BLENDMODE_BLEND);
fbTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STREAMING, width, height);
SDL_SetTextureBlendMode(fbTexture, SDL_BLENDMODE_NONE);
SDL_QueryTexture(uiTexture, &format, &d, &d, &d);
SDL_PixelFormatEnumToMasks(format, &d, &r, &g, &b, &a);
mask = g | a;
sdlscrn = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, r, g, b, a);
uiBuffer = malloc(sdlscrn->h * sdlscrn->pitch);
uiBufferTmp = malloc(sdlscrn->h * sdlscrn->pitch);
SDL_FillRect(sdlscrn, NULL, mask);
while (doRepaint) {
bool updateUI = false;
SDL_AtomicLock(&uiBufferLock);
if (SDL_AtomicSet(&blitUI, 0)) {
memcpy(uiBufferTmp, uiBuffer, sdlscrn->h * sdlscrn->pitch);
updateUI = true;
}
SDL_AtomicUnlock(&uiBufferLock);
if (updateUI) {
SDL_UpdateTexture(uiTexture, NULL, uiBufferTmp, sdlscrn->pitch);
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, uiTexture, NULL, &screenRect);
SDL_RenderPresent(sdlRenderer);
} else {
SDL_Delay(10);
}
}