title: How to use SDL2 Texture as sort of updating canvas?
body: <p>I am trying to create a dynamic plotter in SDL2 for an embedded project. Currently, the code executes on both architectures, x86, and ARM. On x86 I get a smooth running plotter, however, on ARM it runs very slow at a fraction of the frames I get on x86. I am pretty sure this is because I rerender every pixel on the surface at this is a massive overheat on the embedded device.</p>
  
  <p>I tried rendering the new content to a texture, copy it to the renderer and then render, but this did not work at all.</p>
  
  <p>Due to the double-buffering, I have to clear every frame. Otherwise, I will "drop" changes. But I also need to render the old data points and only overwrite them when the plotter reaches them again.</p>
  
  <p>Is there a way in SDL2 to save these data points to some sort of canvas and only add (redraw) the newly added ones?</p>
  
  <p>Heres my source code:</p>
  
  <p><strong>Plotter.cpp</strong></p>
  
  <pre><code>#include &lt;SDL2/SDL.h&gt;
  #include &lt;stdio.h&gt;
  #include "PlotterHelper.h"
  
  /*Implementation*/
  int main(int arhc, char * argv[])
  {
      //Top and bottom viewport
      SDL_Rect topViewport;
      SDL_Rect bottomViewport;
      topViewport = CreateViewPort(0,0, SCREEN_WIDTH, (SCREEN_HEIGHT/2));
      bottomViewport = CreateViewPort(0,(SCREEN_HEIGHT/2), SCREEN_WIDTH, SCREEN_HEIGHT/2);
  
      float timeFrame = 4.0;
      int updateWidth = round(SCREEN_WIDTH/(60.0 * timeFrame));
  
  
      uint8_t backgroundColor = 0xff;
  
      int delayTime = 0;
      int sinusScale = 0;
      int rectWidth = RECT_WIDTH;
      bool rectEnd = false;
  
      SDL_Point points[SCREEN_WIDTH] = {0,0};
      int pointPosition = 0;
  
      if (!init())
      {
          printf("Init failed!\n");
      }
      else
      {
  
          SDL_ShowCursor(SDL_DISABLE);
          //Main lopp flag
          bool quit = false;
          //Event handler
          SDL_Event event;
  
          //While application is running
          while(!quit)
          {
              //Handle events on queue
              while (SDL_PollEvent( &amp;event) != 0)
              {
                  //User requests quit
                  if(event.type == SDL_QUIT)
                  {
                      quit = true;
                  }
                  else if(event.type == SDL_KEYDOWN)
                  {
                      switch(event.key.keysym.sym)
                      {
                      case SDLK_w:
                          delayTime += 50;
                          if(delayTime &gt; 5000)
                              delayTime = 5000;
                          break;
                      case SDLK_s:
                          delayTime -= 50;
                          if(delayTime &lt; 0)
                              delayTime = 0;
                          break;
                      case SDLK_d:
                          timeFrame -= 1;
                          if(timeFrame &lt; 1)
                              timeFrame = 1.0;
                          updateWidth = round(SCREEN_WIDTH/(60.0 * timeFrame));
                          printf("timeFrame = %lf\n", timeFrame);
                          break;
                      case SDLK_a:
                          timeFrame += 1;
                          if(timeFrame &gt; 44)
                              timeFrame = 44.0;
                          updateWidth = round(SCREEN_WIDTH/(60.0 * timeFrame));
                          printf("timeFrame = %lf\n", timeFrame);
                          break;
                      case SDLK_r:
                          if(backgroundColor == 0x3f)
                              break;
                          else
                          {
                              ++backgroundColor;
                              break;
                          }
                      case SDLK_f:
                          if(backgroundColor == 0x00)
                                  break;
                          else
                          {
                              --backgroundColor;
                              break;
                          }
                      }
                  }
              }
  
              //Reset Plotter when the end of the window was reached
              if(pointPosition &gt; SCREEN_WIDTH-1)
              {
                  pointPosition = 0;
                  sinusScale = (rand() % 100 + 1) - 50;
                  rectWidth = RECT_WIDTH;
                  rectEnd = false;
              }
  
              //Handler eraser when he reaches end of window
              if(((SCREEN_WIDTH-1) - pointPosition) &lt; RECT_WIDTH)
              {
                  rectWidth = (SCREEN_WIDTH -1) - pointPosition;
                  rectEnd = true;
  
              }
  
  
              //Clear screen
              SDL_SetRenderDrawColor(gRenderer, backgroundColor, backgroundColor, backgroundColor, 0xff);
              SDL_RenderClear(gRenderer);
  
  
              //Draw top viewport
              SDL_RenderSetViewport( gRenderer, &amp;topViewport );
  
              SDL_SetRenderDrawColor(gRenderer, 0x00, 0x66, 0x00, 0xff);
              for(int iterator = 0; iterator &lt;= SCREEN_WIDTH -1; ++iterator)
              {
                  SDL_RenderDrawLine(
                          gRenderer,
                          points[iterator].x,
                          0,
                          points[iterator].x,
                          SCREEN_HEIGHT/2);
              }
  
              PlotEraser(rectEnd, backgroundColor, rectWidth,points[pointPosition].x );
  
              //raw bottom viewport
              SDL_RenderSetViewport( gRenderer, &amp;bottomViewport );
  
              SDL_SetRenderDrawColor(gRenderer, 0x00, 0x66, 0x00, 0xff);
              for(int iterator = 0; iterator &lt;= SCREEN_WIDTH -1; ++iterator)
                  {
                      SDL_RenderDrawLine(
                              gRenderer,
                              points[iterator].x,
                              SCREEN_HEIGHT/2,
                              points[iterator].x,
                              points[iterator].y);
                  }
  
              PlotEraser(rectEnd, backgroundColor, rectWidth,points[pointPosition].x );
  
  
              for(int iterator = pointPosition; iterator &lt;= pointPosition + updateWidth; ++iterator)
              {
                  points[iterator].x = iterator;
                  points[iterator].y = round(((SCREEN_HEIGHT/4 )* sin(iterator/(100.0+sinusScale))) + SCREEN_HEIGHT/4);
              }
              pointPosition += updateWidth;
  
              //Update Screen
              SDL_RenderPresent(gRenderer);
  
              SDL_Delay(delayTime);
          }
  
      }
  
      //Free resources and close SDL
      close();
  
      return 0;
  }
  
  /*End of File*/
  
  </code></pre>
  
  <p><strong>PlotterHelper.cpp</strong></p>
  
  <pre><code>/*Includes*/
  
  #include "PlotterHelper.h"
  
  SDL_Window  * gWindow = NULL;
  SDL_Renderer * gRenderer = NULL;
  SDL_Renderer * intermediate = NULL;
  
  /*Implementation*/
  
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  bool init()
  {
      //Init  flag
      bool success = true;
  
      //Init SDL
      if(SDL_Init(SDL_INIT_VIDEO) &lt; 0)
      {
          printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
          success = false;
      }
      else
      {
          //Set texture filtering to linear
          if( !SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "1" ) )
          {
              printf( "Warning: Linear texture filtering not enabled!" );
          }
  
          //Set VSYNC
          if( !SDL_SetHint( SDL_HINT_RENDER_VSYNC, "1" ) )
          {
              printf( "Warning: VSYNC not enabled!" );
          }
  
          //Create window
          gWindow = SDL_CreateWindow(
                  "SDL Plotter",
                  SDL_WINDOWPOS_UNDEFINED,
                  SDL_WINDOWPOS_UNDEFINED,
                  SCREEN_WIDTH,
                  SCREEN_HEIGHT,
                  SDL_WINDOW_SHOWN );
          if (NULL == gWindow)
          {
              printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
              success = false;
          }
          else
          {
              //Create renderer for window
              gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED );
              if(NULL == gRenderer)
              {
                  printf("Renderer could not be created! SDLError: %s\n", SDL_GetError());
                  success = false;
              }
              else
              {
                  //Initialise renderer colour
                  SDL_SetRenderDrawColor(gRenderer, 0xff, 0xff, 0xff, 0xff);
              }
  
          }
      }
      return success;
  }
  
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  void close()
  {
      //Destroy window
      SDL_DestroyRenderer(gRenderer);
      SDL_DestroyWindow(gWindow);
      gRenderer = NULL;
      gWindow = NULL;
  
      //Quit SDL subsystems
      SDL_Quit();
  }
  
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  
  SDL_Rect CreateViewPort(int x, int y, int w, int h)
  {
      SDL_Rect Viewport;
      Viewport.x = x;
      Viewport.y = y;
      Viewport.w = w;
      Viewport.h = h;
  
      return Viewport;
  }
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  void PlotEraser(bool rectEnd, uint8_t backgroundColor, int rectWidth, int x)
  {
      SDL_Rect fillRectBot = {x, 0, rectWidth, SCREEN_HEIGHT/2};
  
      SDL_SetRenderDrawColor(gRenderer, backgroundColor, backgroundColor, backgroundColor, 0xff);
      SDL_RenderFillRect(gRenderer, &amp;fillRectBot);
  
      if(rectEnd)
      {
          int startRecWidth = RECT_WIDTH - rectWidth;
  
          SDL_Rect startRec = {0, 0, startRecWidth, SCREEN_HEIGHT/2};
          SDL_RenderFillRect(gRenderer, &amp;startRec);
      }
  }
  
  /*End of File*/
  
  </code></pre>
  
  <p><strong>PlotterHelper.h</strong></p>
  
  <pre><code>
  
  #ifndef PLOTTER_HELPER_H_
  #define PLOTTER_HELPER_H_
  
  #include &lt;SDL2/SDL.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;cmath&gt;
  #include &lt;string&gt;
  /*Globals*/
  
  //Screen  constants
  const int SCREEN_WIDTH = 1024;
  const int SCREEN_HEIGHT = 768;
  const int RECT_WIDTH = 10;
  
  //The window we'll be rendering to
  extern SDL_Window * gWindow;
  //The window renderer
  extern SDL_Renderer * gRenderer;
  extern SDL_Renderer * intermediate;
  
  
  /*Prototypes*/
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  //Starts up SDL and creates window
  bool init();
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  //Free media and shut down SDL
  void close();
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  //CreateVieport
  SDL_Rect CreateViewPort(int x, int y, int w, int h);
  /*********************************************************************
   *********************************************************************
   *********************************************************************
  */
  //Plot Eraser
  void PlotEraser(bool rectEnd, uint8_t backgroundColor, int rectWidth, int x);
  #endif /* PLOTTER_HELPER_H_ */
  /*End of File*/
  
  </code></pre>