title: SDL2 Rendering to texture
body: <p>My application has multiple views which utilize their own <code>SDL_Window</code> and <code>SDL_Renderer</code>, using the renderer to draw all of my tile layers into the main view (the main view contains a composited result of rendering several layers of tiles, and the other views are meant to show each individual layer in a photoshop-style 'layer panel'). The problem here is trying to take a texture (or surface, renderer, etc) and rendering it to another self-contained view. If I use <code>SetRenderTarget</code> and <code>SDL_RenderCopy</code>, it fails because the target texture belongs to a different renderer...</p>
  
  <p>I've also tried locking the pixels of each view's texture, in an attempt to manually copy over the pixels, but locking the pixels fails unless the texture was created as a streaming texture... Also, the views are of different sizes, so the target texture would need to be stretched down to fit, causing more work than should be necessary.</p>
  
  <p>This led me to the use of <code>SDL_SoftStretch</code>... Which works, but of course is <em>painfully</em> slow since it can't be used with hardware accelerated textures.</p>
  
  <p>Is there any plausible, reasonably efficient way of taking the rendered output of one <code>SDL_Window</code>, and rendering a scaled-down version version of it into another?<br/><br/><hr/></p>
  
  <p><strong>EDIT</strong>:<br/>
  Besides the cramped use of <code>SDL_SoftStretch</code>, this is the closest I came to getting things to work out...
  It fails because I hit another brick wall when looking for a way to grab the pixel data from the renderer:<br/><br/></p>
  
  <h2>SDLView.cpp</h2>
  
  <pre><code>//...
  BOOL SDLView::Init()
  {    
      m_sdlWindow = SDL_CreateWindowFrom( (PVOID)m_hWndParent );
      if(m_sdlWindow == NULL)
          return false;
  
      m_sdlRenderer = SDL_CreateRenderer(m_sdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
      if(m_sdlRenderer == NULL)
          return false;
  
      memset(&amp;m_rect, 0, sizeof(SDL_Rect));
      SDL_GetRendererOutputSize(m_sdlRenderer, &amp;m_rect.w, &amp;m_rect.h);
      m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow);
      m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, m_pixelFormat, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);
  
      SDL_SetRenderDrawColor(m_sdlRenderer, 0x64, 0x95, 0xED, 0xFF);
  
      return true;
  }
  
  BOOL SDLView::Clear()
  {
      memset(&amp;m_rect, 0, sizeof(SDL_Rect));
      SDL_GetRendererOutputSize(m_sdlRenderer, &amp;m_rect.w, &amp;m_rect.h);
      return SDL_RenderClear(m_sdlRenderer) == 0;
  }
  
  VOID SDLView::Present()
  {
      // Doesn't work because we still have no way of grabbing the rendered output!!
      SDL_RenderPresent(m_sdlRenderer);
      int result = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, NULL);
      if(result != 0) {
          std::string err(SDL_GetError());
          DebugBreak();
      }
  }
  </code></pre>
  
  <p><br/></p>
  
  <h2>LayerListItem.cpp</h2>
  
  <pre><code>void CLayerListItem::OnPaint()
  {
      CWnd::OnPaint();
      CRect rc;
      GetClientRect(&amp;rc);
  
      if(m_destView != nullptr)
      {
          m_destView-&gt;Clear();
          if(m_srcView != nullptr)
          {
              int srcPitch = 0, destPitch = 0;
              void *srcPixels = nullptr, *destPixels = nullptr;
  
              // Lock the source pixels
              int ret = SDL_LockTexture(m_srcView-&gt;GetTexture(), &amp;m_srcView-&gt;GetRect(), &amp;srcPixels, &amp;srcPitch);
              if(ret != 0) {
                  std::string err(SDL_GetError());
                  DebugBreak();
              }
              // Lock the destination pixels
              ret = SDL_LockTexture(m_destView-&gt;GetTexture(), &amp;m_destView-&gt;GetRect(), &amp;destPixels, &amp;destPitch);
              if(ret != 0) {
                  std::string err(SDL_GetError());
                  DebugBreak();
              }
  
              // Unlock all pixels
              SDL_UnlockTexture(m_destView-&gt;GetTexture());
              SDL_UnlockTexture(m_srcView-&gt;GetTexture());
  
              // Update our destinaition texture
              // (I have tried every possible combination for this line, still no dice!)
              int result = SDL_UpdateTexture(
                  m_destView-&gt;GetTexture(),
                  &amp;m_destView-&gt;GetRect(),
                  srcPixels, srcPitch
              );
              if(ret != 0) {
                  std::string err(SDL_GetError());
                  DebugBreak();
              }
              SDL_RenderCopy(m_destView-&gt;GetRenderer(), m_destView-&gt;GetTexture(), NULL, NULL);
  
              OutputDebugStringA("[RENDERED!]...\n");
          }
          m_destView-&gt;Present();
      }
  }
  </code></pre>
  
  <p><br/><br/>
  An OnPaint event is sent to fire off every few seconds, which in turn attempts to grab the rendered output and store it in <code>m_destView</code> (which, like <code>m_srcView</code>, is an SDLView). At best, this appears to result in a properly rendered main view (the 'source view'), but a pitch black destination view. I feel like I've tried everything at this point, unless there's something beyond what I've already attempted... any ideas?</p>