| Summary: | Software renderer default render target does not get set correctly after using target texture | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Alex Robinson <aprobinsong> |
| Component: | render | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | sezeroz, sylvain.becker |
| Version: | 2.0.3 | ||
| Hardware: | x86_64 | ||
| OS: | Linux | ||
| Attachments: | SDL_render_sw.c patch file | ||
I think this is fixed, but it's hard to tell since your patch has no context. Can you try the latest SDL snapshot? http://www.libsdl.org/tmp/SDL-2.0.zip Thanks! I tried it and this is fixed from this commit: https://hg.libsdl.org/SDL/diff/f061a86fbb08/src/render/software/SDL_render_sw.c Thanks for confirming! |
Created attachment 2286 [details] SDL_render_sw.c patch file The software renderer uses the SW_RenderData struct, which has two fields: SDL_Surface* surface and SDL_Surface* window. From what I can see (based on the implementation of SW_SetRenderTarget at line 319 in SDL_render_sw.c), the surface field is treated as the current rendering target while the window field is treated as the default rendering target. To set the rendering target to a texture created with access method SDL_TEXTUREACCESS_TARGET, one would call SDL_SetRenderTarget with the texture of interest. To set the rendering target back to the default target, one would call SDL_SetRenderTarget will a NULL pointer. At line 326 in SDL_render_sw.c, the surface field gets set to the window field when a NULL pointer is passed in to the SW_SetRenderTarget method. After doing a quick search in SDL_render_sw.c I noticed that the window field never actually gets initialized anywhere (i.e. not in SW_ActivateRenderer or SW_CreateRendererForSurface). With the code in its current state I get the following error after running the following block of code: ' int bits_per_pixel; Uint32 rmask, gmask, bmask, amask; SDL_PixelFormatEnumToMask( SDL_PIXELFORMAT_ARGB888, &bits_per_pixel, &rmask, &gmask, &bmask, &amask ); SDL_Surface* surface = SDL_CreateRGBSurface( 0, 800, 600, bits_per_pixel, rmask, gmask, bmask, amask ); SDL_Renderer* sw_renderer = SDL_CreateSoftwareRenderer( surface ); SDL_Texture* texture = SDL_CreateTexture( sw_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 800, 600 ); SDL_SetRenderTarget( sw_renderer, texture ); SDL_SetRenderDrawColor( sw_renderer, 0xFF, 0, 0, 0xFF ); SDL_RenderClear( sw_renderer ); SDL_RenderPresent( sw_renderer ); SDL_SetRenderTarget( sw_renderer, NULL ); int return_value = SDL_RenderCopy( sw_renderer, texture, NULL, NULL ); if( return_value != 0 ) printf( "The texture could not be rendered! SDL_Error: %s\n", SDL_GetError() ); ` Output: "The texture could not be rendered! SDL error: Invalid window" Potential Fix: By initializing the window field of the SDL_RendererData object to the input surface in the SW_CreateRendererForSurface method the default target surface will be cached and subsequent calls to SW_SetRenderTarget with a NULL texture pointer will correctly restore the default surface target. See the attached patch file for SDL_render_sw.c