Discussion:
[SDL] Weird behaviour on the Raspberry Pi
Andreas Falkenhahn
2016-09-28 15:07:32 UTC
Permalink
I've noticed some weird behaviour on the Raspberry Pi. Take a look at the
following little example code:

#include <SDL.h>

int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture1, *texture2, *texture3;
SDL_Event se;
int quit = 0, k;
int w = 295, reverse = 0;
char *pixbuf = malloc(640 * 480 * 4);
unsigned int *ptr;

SDL_Init(SDL_INIT_VIDEO);
SDL_VideoInit("RPI");

window = SDL_CreateWindow("Foo", 0, 0, 640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
texture1 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 480);
texture2 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 480);

memset(pixbuf, 0, 640 * 480 * 4);
SDL_UpdateTexture(texture1, NULL, pixbuf, 640 * 4);
SDL_RenderCopy(renderer, texture1, NULL, NULL);
SDL_RenderPresent(renderer);

ptr = (unsigned int *) pixbuf;
for(k = 0; k < 640 * 480; k++) *ptr++ = 0xffff0000;
SDL_UpdateTexture(texture2, NULL, pixbuf, 640 * 4);

SDL_ShowWindow(window);
SDL_RaiseWindow(window);

while(!quit) {

SDL_RenderCopy(renderer, texture1, NULL, NULL);

texture3 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, w);
SDL_SetRenderTarget(renderer, texture3);
SDL_SetTextureBlendMode(texture2, SDL_BLENDMODE_NONE);
SDL_RenderCopy(renderer, texture2, NULL, NULL);
SDL_SetTextureBlendMode(texture3, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopy(renderer, texture3, NULL, NULL);

SDL_RenderPresent(renderer);

while(SDL_PollEvent(&se)) {
if(se.type == SDL_MOUSEBUTTONDOWN) quit = 1;
}

SDL_DestroyTexture(texture3);

if(reverse) {
w -= 10;
} else {
w += 10;
}

if(w >= 640) {
w = 640;
reverse = 1;
} else if(w <= 2) {
w = 2;
reverse = 0;
}
}

SDL_DestroyTexture(texture1);
SDL_DestroyTexture(texture2);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

SDL_Quit();

free(pixbuf);

return 0;
}

On Windows, Linux & Mac this always fills the screen with red. On the Raspberry Pi,
however, the screen alternates between red and black. It is mostly red, but sometimes
it's also black, so it looks really weird.

Is that a bug in my code or in SDL's Pi backend?
--
Best regards,
Andreas Falkenhahn mailto:***@falkenhahn.com
rtrussell
2016-09-28 15:59:48 UTC
Permalink
Post by Andreas Falkenhahn
Is that a bug in my code or in SDL's Pi backend?
One thing I would question is that there's no SDL_RenderClear(). The docs say "You are strongly encouraged to call SDL_RenderClear() to initialize the backbuffer before starting each new frame's drawing". Does it make any difference if you change it as follows:


Code:
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture3, NULL, NULL);
SDL_RenderPresent(renderer);


Richard.
Andreas Falkenhahn
2016-09-28 16:40:11 UTC
Permalink
Post by rtrussell
One thing I would question is that there's no SDL_RenderClear().
The docs say "You are strongly encouraged to call SDL_RenderClear()
to initialize the backbuffer before starting each new frame's
No, doesn't make any difference. The screen still alternates between
red and black. Here is the updated code for reference:

#include <SDL.h>

int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture1, *texture2, *texture3;
SDL_Event se;
int quit = 0, k;
int w = 295, reverse = 0;
char *pixbuf = malloc(640 * 480 * 4);
unsigned int *ptr;

SDL_Init(SDL_INIT_VIDEO);
SDL_VideoInit("RPI");

window = SDL_CreateWindow("Foo", 0, 0, 640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
texture1 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 480);
texture2 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 480);

memset(pixbuf, 0, 640 * 480 * 4);
SDL_UpdateTexture(texture1, NULL, pixbuf, 640 * 4);
SDL_RenderCopy(renderer, texture1, NULL, NULL);
SDL_RenderPresent(renderer);

ptr = (unsigned int *) pixbuf;
for(k = 0; k < 640 * 480; k++) *ptr++ = 0xffff0000;
SDL_UpdateTexture(texture2, NULL, pixbuf, 640 * 4);

SDL_ShowWindow(window);
SDL_RaiseWindow(window);

while(!quit) {

texture3 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, w);

SDL_SetRenderTarget(renderer, texture3);
SDL_SetTextureBlendMode(texture2, SDL_BLENDMODE_NONE);
SDL_RenderCopy(renderer, texture2, NULL, NULL);
SDL_SetTextureBlendMode(texture3, SDL_BLENDMODE_BLEND);

SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture1, NULL, NULL);
SDL_RenderCopy(renderer, texture3, NULL, NULL);
SDL_RenderPresent(renderer);

while(SDL_PollEvent(&se)) {
if(se.type == SDL_MOUSEBUTTONDOWN) quit = 1;
}

SDL_DestroyTexture(texture3);

if(reverse) {
w -= 10;
} else {
w += 10;
}

if(w >= 640) {
w = 640;
reverse = 1;
} else if(w <= 2) {
w = 2;
reverse = 0;
}
}

SDL_DestroyTexture(texture1);
SDL_DestroyTexture(texture2);

SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);

SDL_Quit();

free(pixbuf);

return 0;
}
--
Best regards,
Andreas Falkenhahn mailto:***@falkenhahn.com
Jonathan Dearborn
2016-09-28 16:44:56 UTC
Permalink
Can you simplify this example with fewer textures and RTT calls and still
get this behavior?

Jonny D
Post by Andreas Falkenhahn
Post by rtrussell
One thing I would question is that there's no SDL_RenderClear().
The docs say "You are strongly encouraged to call SDL_RenderClear()
to initialize the backbuffer before starting each new frame's
No, doesn't make any difference. The screen still alternates between
#include <SDL.h>
int main(int argc, char *argv[])
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture1, *texture2, *texture3;
SDL_Event se;
int quit = 0, k;
int w = 295, reverse = 0;
char *pixbuf = malloc(640 * 480 * 4);
unsigned int *ptr;
SDL_Init(SDL_INIT_VIDEO);
SDL_VideoInit("RPI");
window = SDL_CreateWindow("Foo", 0, 0, 640, 480, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
texture1 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, 640, 480);
texture2 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, 640, 480);
memset(pixbuf, 0, 640 * 480 * 4);
SDL_UpdateTexture(texture1, NULL, pixbuf, 640 * 4);
SDL_RenderCopy(renderer, texture1, NULL, NULL);
SDL_RenderPresent(renderer);
ptr = (unsigned int *) pixbuf;
for(k = 0; k < 640 * 480; k++) *ptr++ = 0xffff0000;
SDL_UpdateTexture(texture2, NULL, pixbuf, 640 * 4);
SDL_ShowWindow(window);
SDL_RaiseWindow(window);
while(!quit) {
texture3 = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, w);
SDL_SetRenderTarget(renderer, texture3);
SDL_SetTextureBlendMode(texture2, SDL_BLENDMODE_NONE);
SDL_RenderCopy(renderer, texture2, NULL, NULL);
SDL_SetTextureBlendMode(texture3, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture1, NULL, NULL);
SDL_RenderCopy(renderer, texture3, NULL, NULL);
SDL_RenderPresent(renderer);
while(SDL_PollEvent(&se)) {
if(se.type == SDL_MOUSEBUTTONDOWN) quit = 1;
}
SDL_DestroyTexture(texture3);
if(reverse) {
w -= 10;
} else {
w += 10;
}
if(w >= 640) {
w = 640;
reverse = 1;
} else if(w <= 2) {
w = 2;
reverse = 0;
}
}
SDL_DestroyTexture(texture1);
SDL_DestroyTexture(texture2);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
free(pixbuf);
return 0;
}
--
Best regards,
_______________________________________________
SDL mailing list
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Andreas Falkenhahn
2016-09-29 15:16:54 UTC
Permalink
Can you simplify this example with fewer textures and RTT calls and still get this behavior?
It works correctly when disabling scaling, i.e. changing the following line

texture3 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, w);

into this line

texture3 = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 640, 480);

solves the problem and there is no alternation between red and black screens any
more. The problem only seems to appear when the dimensions of texture3 and texture2
don't match, i.e. when SDL_RenderCopy() needs to scale-copy texture2 to texture3
instead of just copying it without the involvement of scaling.
--
Best regards,
Andreas Falkenhahn mailto:***@falkenhahn.com
Andreas Falkenhahn
2016-10-14 21:30:34 UTC
Permalink
Filed this now as

https://bugzilla.libsdl.org/show_bug.cgi?id=3455

because it clearly seems to be a bug in the Raspi backend.
Post by Andreas Falkenhahn
Can you simplify this example with fewer textures and RTT calls and still get this behavior?
It works correctly when disabling scaling, i.e. changing the following line
texture3 = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, w);
into this line
texture3 = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 640, 480);
solves the problem and there is no alternation between red and black screens any
more. The problem only seems to appear when the dimensions of texture3 and texture2
don't match, i.e. when SDL_RenderCopy() needs to scale-copy texture2 to texture3
instead of just copying it without the involvement of scaling.
--
Best regards,
Andreas Falkenhahn mailto:***@falkenhahn.com
Loading...