Delay of >6 mS needed for rendering without glitches

I am developping a program for UAV groundstation; it displays google earth tiles on screen and allows to scroll. The tiles are 640x 640 for a 1200 x 640 screen I did the first round of programming, and it is working, but: from time to time (every 20 - 30 renderings) there is a glitch, where the tiles are put on screen with an incorrect x offset (can be + 5 … +50 pixels or something similar). I traced (using cout the values passed for forming rectangle, and there are no programming errors, i.e. the rectange data is always correct, but in 2-4 % of rendings, the x is off… I suspected that it had to do with my management of graphic tiles in memory, so I switched to simply drawing rectangles (SDL_renderdrawrect), but the problem persisted…

When I put a delay (SDL_delay) after rendering, for values above 6 mS the intermittent offset diasppears…

I am pretty new to SDL, but I am at total loss where to look for problem…

I am running it on RPI Debian

// ---------------------------

int render_tile (char* file_nm, int srx, int sry, int srw, int srh, int dsx, int dsy, int dsw, int dsh)
{
int cur_mem_ndx;
char shortname[20];
char filename[128];

SDL_Rect SrcR;
SDL_Rect DestR;
SrcR.x = srx;
SrcR.y = sry;
SrcR.w = srw;
SrcR.h = srh;

dsy=0;
cout << dsx << " " << dsw << " \n";
dsh=640;
DestR.x = dsx;
DestR.y = dsy;
DestR.w = dsw;
DestR.h = dsh;

if (strcmp(file_nm,“EMPTY”)==0) { // if EMPTY, there is no image (on disk or in memory, so draw empty rectange
SDL_SetRenderDrawColor(renderer, 215, 125, 255, 123);
SDL_RenderDrawRect(renderer,&DestR);
return 1;
}

/*
cout << “Srcr.x:” << SrcR.x << “\n”;
cout << “Srcr.y:” << SrcR.y << “\n”;
cout << “Srcr.w:” << SrcR.w << “\n”;
cout << “Srcr.h:” << SrcR.h << “\n”;
cout << “Drcr.x:” << DestR.x << “\n”;
cout << “Drcr.y:” << DestR.y << “\n”;
cout << “Drcr.w:” << DestR.w << “\n”;
cout << “Drcr.h:” << DestR.h << “\n”;
cout << " ============= \n" ;*/

/*
cout << “Mem Tiles:\n”;
for (int i=0;i<mem_tiles_end;i++)
{cout << i << " kk " << mem_tiles_fname[i] << “\n”;}
cout << “mem_tiles_end:” << mem_tiles_end <<"\n";
*/

int ndx=0;
sprintf (shortname,"%s",file_nm);
while ((ndx<mem_tiles_end) and (!strcmp(mem_tiles_fname[ndx],shortname))==0) { ndx=ndx+1; }

if (ndx<mem_tiles_end) 
  { // we found the correct file name!! ndx points to array    

// cout << SrcR.x << " " << SrcR.w << " " << DestR.x << " " << DestR.w << “\n”;

   // SDL_RenderCopy(renderer, mem_tiles[ndx], &SrcR, &DestR);
    SDL_SetRenderDrawColor(renderer, 215, 225, 155, 123);
    DestR.x = dsx+2;
    DestR.y = dsy+2;
    DestR.w = dsw-2;
    DestR.h = dsh-2;
    SDL_RenderDrawRect(renderer,&DestR);
  }
else
  {  // the file was not found in memory, so should be fetched from disk:
       sprintf (filename,"/home/pi/Earth/%s",file_nm);  // obtain path to file           
       SDL_Surface * image = IMG_Load(filename); // load image from file
       if(!image) { 
               printf("IMG_Load: %s\n", IMG_GetError());  
               return 2; // this error really should not be happing, only if someone manually deleted
                 // files in the Earth folder
                 // I am not sure what should be done in this case
               }             
       mem_tiles[mem_tiles_end]=SDL_CreateTextureFromSurface(renderer, image);
       SDL_FreeSurface(image); 
       strcpy (mem_tiles_fname[mem_tiles_end],shortname);
  
       cur_mem_ndx=mem_tiles_end;
       if (mem_tiles_end<max_mem_tiles) {mem_tiles_end=mem_tiles_end+1;}
              else 
          { // overflow, delete first item to make room !!!
    
          }
    
   //   SDL_RenderCopy(renderer, mem_tiles[cur_mem_ndx], &SrcR, &DestR);
       SDL_SetRenderDrawColor(renderer, 115, 125, 155, 123);
       DestR.x = dsx+2;
       DestR.y = dsy+2;
       DestR.w = dsw-4;
       DestR.h = dsh-4;
       SDL_RenderDrawRect(renderer,&DestR);         
      }

SDL_RenderPresent(renderer); // copy to screen
SDL_Delay (6); // NOT SURE WHY, BUT WITHOUT IT, THERE IS AN OCCASIONAL GLITCH
return 0;
}

int show_Earth (double yfrom, double xfrom, int screen_zoom)
{

FILE *fp;
char filename[128];
char url[256];

int db_res;
char buf[512];
char *zErrMsg = 0;

double Lat;
// if (yfrom<0) {Lat=yfrom;} else {Lat=yto;} // We need Latitude closest to equater, because the scale is largest there
Lat=yfrom;

// cout << “STARTING…\n”;
int zoomlevel = screen_zoom;
double Meters_per_pixel=156543.03392cos(Lat0.017453293)/(1 << zoomlevel);
double Latitude_1_degree=111.13295-0.55982cos(2Lat0.017453293)+0.00117cos(4Lat0.017453293); // in km
double Longitude_1_degree=111.41288cos(Lat0.017453293)-0.0935cos(3Lat0.017453293)+0.00012cos(5Lat0.017453293); // in km
double Screen_width_degrees=((NAV_window_xMeters_per_pixel)/Longitude_1_degree)/1000;
double Screen_height_degrees=((NAV_window_y
Meters_per_pixel)/Latitude_1_degree)/1000;
double dx=Screen_width_degrees;
double dy=Screen_height_degrees;

double xto=xfrom+Screen_width_degrees;
double yto=yfrom+Screen_height_degrees;

double Tile_Size_X=(Meters_per_pixelGoogle_Tile_Size_X)/1000; // physical X dimension of a tile in km
double Tile_Size_Y=(Meters_per_pixel
Google_Tile_Size_Y)/1000; // physical X dimension of a tile in km

double Tile_Side_X=Tile_Size_X/Longitude_1_degree; // in degrees
double Tile_Side_Y=Tile_Size_Y/Latitude_1_degree; // in degrees

double Tile_Side_X_Half=Tile_Side_X/2;
double Tile_Side_Y_Half=Tile_Side_Y/2;

int Tile_Side_Destination_X=abs ((Tile_Side_X/dx))*NAV_window_x; // !!!
int Tile_Side_Destination_Y=Tile_Side_Destination_X; // abs (Tile_Side_X/dx)*1200;

int wx=0;
int wy=0;

// Check if any tile in offline corresponds to left-upper corner:

sprintf (buf,“SELECT * FROM TILES WHERE ZOOMLEVEL = %d AND X_FROM<= %2.6f AND X_TO>= %2.6f AND Y_FROM>= %2.6f AND Y_TO<= %2.6f;”,zoomlevel,xfrom,xfrom,yfrom,yfrom);
sqlite_ndx=0;
db_res = sqlite3_exec(db, buf,get_tile, 0, &zErrMsg); // tile(s) data are in the arrays _a
if( db_res != SQLITE_OK ) {
fprintf(stderr, “SQL error: %s\n”, zErrMsg);
sqlite3_free(zErrMsg);
}

if (sqlite_ndx==0) {return 0;}
// if NOT, repeat search for UPPER RIGHT CORNER, adjust values below !!!
// if NOT, repeat search for LOWER LEFT CORNER
// ELSE: increase group id and create a new set of tiles

// ERROR: there is vertical error in images; it seems that a few lines are cut out

int ndx=0;

// cout << “FILE:” << file_a[ndx] << “\n”;

int tsx = int((abs(xfrom_a[ndx]-xfrom))/abs(xfrom_a[ndx]-xto_a[ndx])*Google_Tile_Size_X);
// cout << xfrom_a[ndx]-xfrom << " - ";
int tsy = int((abs(yfrom_a[ndx]-yfrom))/abs(yfrom_a[ndx]-yto_a[ndx])*Google_Tile_Size_Y);
int tsw = Google_Tile_Size_X-tsx;
int tsh = Google_Tile_Size_Y-tsy;
int grp_id=grpid_a[ndx];
// cout << tsx << " hhhhhhh " << tsw << “\n”;
render_tile (file_a[ndx],tsx,tsy,tsw,tsh,0,0,tsw,tsh); // first tile
return 0;
int tsx_st=tsx; // source x
int tsy_st=tsy; // source y
int tsw_st=tsw; // source width
int tsh_st=tsh; // source height
double scr_x_remain=NAV_window_x-tsw;
int tile_x_need=ceil(scr_x_remain/Google_Tile_Size_X); // how many tiles are needed to complete screen
double scr_y_remain=NAV_window_y-tsh;
int tile_y_need=ceil(scr_y_remain/Google_Tile_Size_Y);

double xstep=abs(xfrom_a[ndx]-xto_a[ndx]); // in degrees
double ystep=abs(yfrom_a[ndx]-yto_a[ndx]);

double xcenter=xfrom_a[ndx]+xstep/2;
double ycenter=yfrom_a[ndx]-ystep/2;

int grpx=grpx_a[ndx];
int grpy=grpy_a[ndx];
int x_ndx=grpx+1;
int y_ndx=grpy;
// cout << temp-tsx << " v\n";temp=tsx;
while (y_ndx<= grpy+tile_y_need) {
while (x_ndx<=grpx+tile_x_need) {
sqlite_ndx=0;
sprintf (buf,“SELECT * FROM TILES WHERE ZOOMLEVEL = %d AND GROUP_ID=%d AND GROUP_X=%d AND GROUP_Y=%d;”,zoomlevel,grp_id,x_ndx,y_ndx);

   db_res = sqlite3_exec(db, buf,get_tile, 0, &zErrMsg); // tile(s) data are in the arrays _a
   int xoff=x_ndx-grpx;  // xoff,yoff = tile index ,1 tile = 1 
   int yoff=y_ndx-grpy;
   if (xoff==0) {tsx=tsx_st;tsw=tsw_st;wx=0;} else {tsx=0;tsw=Google_Tile_Size_X;wx=tsw_st+Google_Tile_Size_X*(xoff-1);}
   if (yoff==0) {tsy=tsy_st;tsh=tsh_st;wy=0;} else {tsy=0;tsh=Google_Tile_Size_Y;wy=tsh_st+Google_Tile_Size_Y*(yoff-1);}               

   if (sqlite_ndx>0)  { // there is a tile in memory!!!
           render_tile (file_a[ndx],tsx,tsy,tsw,tsh,wx,wy,tsw,tsh); 
           if ((y_ndx==grpy)  and (x_ndx==grpx)) {cout << temp-tsx << " v\n";temp=tsx; }
            }
     else
     { // no tile  in memory, must download!!}
       
       get_next_id ();
       get_google_tile (next_id, group_id, x_ndx,y_ndx,zoomlevel,Google_Tile_Size_X,Google_Tile_Size_Y,Meters_per_pixel,xcenter+xstep*xoff,ycenter-ystep*yoff,xstep,ystep);
       sqlite_ndx=0; 
       sprintf (buf,"SELECT * FROM TILES WHERE ZOOMLEVEL = %d AND GROUP_ID=%d AND GROUP_X=%d AND GROUP_Y=%d;",zoomlevel,grp_id,x_ndx,y_ndx); 
       db_res = sqlite3_exec(db, buf,get_tile, 0, &zErrMsg); // tile(s) data are in the arrays _a
       if (sqlite_ndx>0)  { // there is a tile in memory!!!
           render_tile (file_a[ndx],tsx,tsy,tsw,tsh,wx,wy,tsw,tsh); }
         else
          { sprintf (buf,"%s","EMPTY");
            render_tile (buf,tsx,tsy,tsw,tsh,wx,wy,tsw,tsh); }
     
     }
    
   x_ndx=x_ndx+1;
   
  }

  x_ndx=grpx;
  y_ndx=y_ndx+1;

}
return 0;

}
// --------------------------------------------------------------

I can’t speak to the specifics of what you’re doing, but when you say adding a delay changes behavior, I’m thinking your machine-as-a-whole is being taxed when you see that offset-error.

Try monitoring your computer’s resources as your program runs? Try profiling blocks of code? Is there are certain kind of argument or piece of data that causes it? Is there another process on your computer that operates at a similar interval as the error behavior?

I think you get the idea. Sorry I cannot provide anything more specific. Best of luck.