| Summary: | Pixelformat discrepancy between textures when created or when updated | ||
|---|---|---|---|
| Product: | SDL | Reporter: | axel mattauch <axel.mattauch> |
| Component: | render | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | axel.mattauch, chli.hug |
| Version: | HG 2.1 | ||
| Hardware: | x86_64 | ||
| OS: | Windows 8 | ||
| Attachments: |
Test program with pertinent test sequences
This test program is relevant screen copy How create a texture with a pixelformat supported by the driver? Log associated to the june 26th version of the code |
||
Created attachment 2770 [details]
This test program is relevant
This testprogram displays 5 rows of 8 squares
Row 1, 2 are as expected
Row 3 show a discrepancy
Row 4 & 5 are as expected, but after RGBA to ARGB for surface update.
Created attachment 2771 [details]
screen copy
This report supersedes #3648 The render drivers only support certain pixel formats. The SDL_Texture will have one of those formats. If you create an SDL_Texture form an SDL_Surface, it will automatically convert the data to the right format. Check what pixel formats are available for a render driver with SDL_GetRenderDriverInfo or an active renderer with SDL_GetRendererInfo. You can query the pixel format of the SDL_Texture with SDL_QueryTexture. The documentation doesn't state this, but SDL_UpdateTexture requires the data to be in the pixel format of the SDL_Texture. Your SDL_Surface format doesn't match the SDL_Texture format. (In reply to Simon Hug from comment #4) > The render drivers only support certain pixel formats. The SDL_Texture will > have one of those formats. If you create an SDL_Texture form an SDL_Surface, > it will automatically convert the data to the right format. > > Check what pixel formats are available for a render driver with > SDL_GetRenderDriverInfo or an active renderer with SDL_GetRendererInfo. > > You can query the pixel format of the SDL_Texture with SDL_QueryTexture. > > The documentation doesn't state this, but SDL_UpdateTexture requires the > data to be in the pixel format of the SDL_Texture. Your SDL_Surface format > doesn't match the SDL_Texture format. Thank you for the hints. I implemented all the queries and they shows effectively that RGBA are never available for the texture (at least for my computer): INFO: Pixel format for window : SDL_PIXELFORMAT_RGB888 INFO: 4 render drivers available INFO: 1 pixel formats available for render driver nr 0: INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: 1 pixel formats available for render driver nr 1: INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: 4 pixel formats available for render driver nr 2: INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: -> 1 SDL_PIXELFORMAT_ABGR8888 INFO: -> 2 SDL_PIXELFORMAT_RGB888 INFO: -> 3 SDL_PIXELFORMAT_BGR888 INFO: 8 pixel formats available for render driver nr 3: INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: -> 1 SDL_PIXELFORMAT_ABGR8888 INFO: -> 2 SDL_PIXELFORMAT_RGBA8888 INFO: -> 3 SDL_PIXELFORMAT_BGRA8888 INFO: -> 4 SDL_PIXELFORMAT_RGB888 INFO: -> 5 SDL_PIXELFORMAT_BGR888 INFO: -> 6 SDL_PIXELFORMAT_RGB565 INFO: -> 7 SDL_PIXELFORMAT_RGB555 INFO: 3 pixel formats available for the created renderer INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: -> 1 SDL_PIXELFORMAT_YV12 INFO: -> 2 SDL_PIXELFORMAT_IYUV INFO: Pixel format for surface : SDL_PIXELFORMAT_RGBA8888 INFO: Pixel format for texture : SDL_PIXELFORMAT_ARGB8888 Thus, I understand that format conversion is made by SDL_CreateTextureFromSurface, not by SDL_UpdateTexture (the same rule seems applied for blend mode). This lead me to some questions: 1/ (continuation) I have some questions: 1/ As the set of formats are different for the various render drivers: how can I choose the most convenient (for my application) driver when I create a render? And: do I have to choose a given driver? For example, render driver n°3 has 8 formats available; the 3rd (n°2) has the SDL_PIXELFORMAT_RGBA8888 wich I prefer to use. 2/ More precisely: I believe that the best (to make robust coding) would be to a) analyse the capability of the HW/SW , i.e. the window capabilities and the render driver capabilities b) to decide at the first steps of the runtime to choose the best strategy (for example some parameter) c) to implement routines using this parameter Can you give me some hints for that? 3/ For the target, can I set the (available) pixel format through SDL_SetRenderTarget? Thank You for the help PS: as written in https://discourse.libsdl.org/t/wiki-write-access/21963 I'm willing to make contributions to improve documentation...but under control! Hi! A made a step further. Because my configuration implements 4 render drivers, and the 4th supports SDL_PIXELFORMAT_RGBA8888, I made following change in my code: The renderer is created by prenderer = SDL_CreateRenderer(pwindow, 3, 0); instead of prenderer = SDL_CreateRenderer(pwindow, -1, 0); This respond to my own question 1. The log is now (extract): INFO: 8 pixel formats available for the created renderer INFO: -> 0 SDL_PIXELFORMAT_ARGB8888 INFO: -> 1 SDL_PIXELFORMAT_ABGR8888 INFO: -> 2 SDL_PIXELFORMAT_RGBA8888 INFO: -> 3 SDL_PIXELFORMAT_BGRA8888 INFO: -> 4 SDL_PIXELFORMAT_RGB888 INFO: -> 5 SDL_PIXELFORMAT_BGR888 INFO: -> 6 SDL_PIXELFORMAT_RGB565 INFO: -> 7 SDL_PIXELFORMAT_RGB555 INFO: Pixel format for surface : SDL_PIXELFORMAT_RGBA8888 INFO: Pixel format for texture : SDL_PIXELFORMAT_ARGB8888 This show that the render driver can be selected. But at this stage, while the renderer support (among others) the SDL_PIXELFORMAT_RGBA8888 the surface format is activated as SDL_PIXELFORMAT_RGBA8888 SDL_CreateTextureFromSurface(prenderer, psurface); will not create a texture with this format, but allways as SDL_PIXELFORMAT_ARGB8888 (the first format supported by this driver). --> Is there a way to impose to the texture the nth format supported by the driver? I attach the last version of the test program. Created attachment 2776 [details]
How create a texture with a pixelformat supported by the driver?
Pertinent code segment is between lines 89 to 133
Created attachment 2777 [details]
Log associated to the june 26th version of the code
"SDL_Log" outputs.
1. It depends on what the requirements of your applications are. The render backends all have their own quirks and the SDL render API can't expose all of those to the user or it would get complicated fast. Sometimes this means to just support one RGBA layout as it is the most common one. It may be necessary to rethink your approach if your data can really only be in the RGBA8888 format and conversion during runtime via SDL_ConvertSurface is too expensive. You're not required to choose a driver, but you always have to check what the created renderer supports. SDL tries to pick the backend that is best supported on the platform. Usually Direct3D on Windows and an OpenGL variant on other platforms. 2. You are correct, these steps are necessary for a robust application. It's probably safe to assume that the SDL_PIXELFORMAT_ARGB8888 format will be around for a long time and if you implement your routines for it, the application will work on all platforms. NOTE: What SDL reports as the last render driver (index 3 for you) is the software renderer. Only use it if you don't need hardware acceleration. This driver is going to be really slow on low-end systems. 3. You can only choose one of the supported formats for textures. I haven't checked yet, but this may be even more restrictive for target textures. 4. SDL_CreateTextureFromSurface has its own logic to find the supported pixel format. Create the texture with SDL_CreateTexture to get full control over that. For example on line 131, change this: ptexture = SDL_CreateTextureFromSurface(prenderer, psurface); to this (error checking not included): ptexture = SDL_CreateTexture(prenderer, pixelFormat, SDL_TEXTUREACCESS_STATIC, psurface->w, psurface->h); SDL_UpdateTexture(ptexture, NULL, psurface->pixels, psurface->pitch); If this issue is resolved, it may be better to move the conversation over to https://discourse.libsdl.org if you have additional questions. You even get a higher chance of other people joining in. (In reply to Simon Hug from comment #10) > 1. It depends on what the requirements of your applications are. The render > backends all have their own quirks and the SDL render API can't expose all > of those to the user or it would get complicated fast. Sometimes this means > to just support one RGBA layout as it is the most common one. > > It may be necessary to rethink your approach if your data can really only be > in the RGBA8888 format and conversion during runtime via SDL_ConvertSurface > is too expensive. > > You're not required to choose a driver, but you always have to check what > the created renderer supports. SDL tries to pick the backend that is best > supported on the platform. Usually Direct3D on Windows and an OpenGL variant > on other platforms. > > 2. You are correct, these steps are necessary for a robust application. It's > probably safe to assume that the SDL_PIXELFORMAT_ARGB8888 format will be > around for a long time and if you implement your routines for it, the > application will work on all platforms. > > NOTE: What SDL reports as the last render driver (index 3 for you) is the > software renderer. Only use it if you don't need hardware acceleration. This > driver is going to be really slow on low-end systems. > > 3. You can only choose one of the supported formats for textures. I haven't > checked yet, but this may be even more restrictive for target textures. > > 4. SDL_CreateTextureFromSurface has its own logic to find the supported > pixel format. Create the texture with SDL_CreateTexture to get full control > over that. > > For example on line 131, change this: > > ptexture = SDL_CreateTextureFromSurface(prenderer, psurface); > > to this (error checking not included): > > ptexture = SDL_CreateTexture(prenderer, pixelFormat, > SDL_TEXTUREACCESS_STATIC, psurface->w, psurface->h); > SDL_UpdateTexture(ptexture, NULL, psurface->pixels, psurface->pitch); > > > If this issue is resolved, it may be better to move the conversation over to > https://discourse.libsdl.org if you have additional questions. You even get > a higher chance of other people joining in. Yes, the issue is fully resolved, and I thank You for the huge help. From your last reply, I learned also: a) (continuation; I believe some character [Tab? Ctrl?] I typed closed the text input?) a) To check the SDL_RendererInfo flags b) To make use of SDL_CreateTexture + SDL_SetTextureBlendMode + SDL_UpdateTexture call instead of the simpler SDL_CreateTextureFromSurface Thank you for the support. I put the status to resolved. |
Created attachment 2769 [details] Test program with pertinent test sequences Context: I wish to use textures as "calculated sprites", where color and alpha channel will be coded in a longint (32 bits) format, preferably RGBA. The sprites (with constant size) will be updated from time to time. I believe it is preferable to create the texture once, and then to update them. But the following problem arises: When I create a texture, through SDL_CreateTextureFromSurface, colors and alpha are displayed as expected for RGBA coding. But using then SDL_UpdateTexture, the colors are not as expected. I have made a deep investigation in order to understand what occurs. It seems (see attachments) that for SDL_CreateTextureFromSurface, the RGBA format used in the surface is well blitted into the texture, but in order to refresh the texture through SDL_UpdateTexture, I have to code the surface in ARGB format. I think I have carefully read the wiki, but I've nothing encoutered in relation with this topic.