Weird flickering


#1

Hello,

I try to use texture locking to draw single pixels and I get a strange flickering, as if there were 2 “buffers” linked to the window or the texture. In order to improve performance, I would like to only copy the modified pixel when updating the window. Is it possible ?

#include <SDL2/SDL.h>
#include

using namespace std;

int main( int argc, char **argv )
{
SDL_Init( SDL_INIT_EVERYTHING );
atexit( SDL_Quit );

const unsigned int width = 607;
const unsigned int height = 600;

SDL_Window *window = SDL_CreateWindow( “title”, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );

SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

SDL_RendererInfo info;
SDL_GetRendererInfo( renderer, &info );
cout << "Renderer name: " << info.name << endl;
cout << "Texture formats: " << endl;
for ( Uint32 i = 0; i < info.num_texture_formats; i++ )
cout << SDL_GetPixelFormatName( info.texture_formats[ i ] ) << endl;

// SDL_PIXELFORMAT_ARGB8888 is the first format listed by the above code
SDL_Texture *texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height );

// initial clear

unsigned char lockedPixels = nullptr;
int pitch;
SDL_LockTexture( texture, NULL, (void
*)&lockedPixels, &pitch );
memset( lockedPixels, 0, height * pitch );
SDL_UnlockTexture( texture );
SDL_RenderCopy( renderer, texture, NULL, NULL );
SDL_RenderPresent( renderer );

// event loop

SDL_Event event;
bool running = true;
int x = 0, y = 0;
while ( running )
{
while ( SDL_PollEvent( &event ) )
if ( (SDL_QUIT == event.type) || (SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode) )
{
running = false;
break;
}

  // move pixel
  x = (x + 1) % width;
  y = (y + 1) % height;

  unsigned char *lockedPixels = nullptr;
  int pitch;

  SDL_LockTexture( texture, NULL, (void**)&lockedPixels, &pitch );

  // draw pixel

  int ind = y * pitch + x * 4;
  lockedPixels[ ind ] = 255;

  SDL_UnlockTexture( texture );

  // update window

  SDL_Rect rect = { x, y, 1, 1 };
  SDL_RenderCopy( renderer, texture, &rect, &rect );

  SDL_RenderPresent( renderer );

}

SDL_DestroyTexture( texture );
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
}


#2

Hi, from the doc:
https://wiki.libsdl.org/SDL_RenderPresent

“The backbuffer should be considered invalidated after each present; do not assume that previous contents will exist between frames. You are strongly encouraged to call SDL_RenderClear() to initialize the backbuffer before starting each new frame’s drawing, even if you plan to overwrite every pixel.”

I think this is your problem.


#3

Thank you for your answer.
My intent was not to clear and redraw all frame, for performance reasons as only one pixel changes from one frame to the next.
So I wonder : what is the point of the rect in SDL_RenderCopy if all frame has to be cleared ? There something I don’t get :slight_smile:
I know that surfaces live in system RAM and texture in GPU memory. Is there a documentation on what operations do (transfers, …), what one can expect (valid/invalid state), … ?
Thanks !


#4

rects are very important in many uses. The typical one being sprite rendering: you have a texture with your sprites, and you want to display one of then on your scene. The src rect is used for selecting the sprite, and the dest rect is used to tell where to put it in the scene.

In your case, you could define a 1x1 texture (your pixel) and RenderCopy it on your main screen.
But this is an extreme example. I suppose that in this case SDL_RenderDrawPoint would be more efficient.

Once your background texture is on the GPU side, it’s very fast to render it, and can (should) be done at each frame. What is “slow” is to transfer new data from the CPU to the GPU.


#5

the doc (wiki) contains several remarks on this issue. But I don’t know other references… except reading the source.


#6

Thank you for the answers, I’ll try the 1x1 texture and SDL_RenderDrawPoint.