We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3680 - Pixelformat discrepancy between textures when created or when updated
Summary: Pixelformat discrepancy between textures when created or when updated
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: HG 2.1
Hardware: x86_64 Windows 8
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-06-23 14:02 UTC by axel mattauch
Modified: 2017-06-27 12:34 UTC (History)
2 users (show)

See Also:


Attachments
Test program with pertinent test sequences (5.13 KB, text/x-csrc)
2017-06-23 14:02 UTC, axel mattauch
Details
This test program is relevant (11.31 KB, text/x-csrc)
2017-06-23 14:13 UTC, axel mattauch
Details
screen copy (4.13 KB, image/png)
2017-06-23 14:14 UTC, axel mattauch
Details
How create a texture with a pixelformat supported by the driver? (13.30 KB, text/x-csrc)
2017-06-26 09:12 UTC, axel mattauch
Details
Log associated to the june 26th version of the code (2.13 KB, text/plain)
2017-06-26 09:18 UTC, axel mattauch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description axel mattauch 2017-06-23 14:02:15 UTC
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.
Comment 1 axel mattauch 2017-06-23 14:13:17 UTC
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.
Comment 2 axel mattauch 2017-06-23 14:14:44 UTC
Created attachment 2771 [details]
screen copy
Comment 3 axel mattauch 2017-06-23 14:22:45 UTC
This report supersedes #3648
Comment 4 Simon Hug 2017-06-24 08:26:21 UTC
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.
Comment 5 axel mattauch 2017-06-25 15:22:37 UTC
(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/
Comment 6 axel mattauch 2017-06-25 15:44:38 UTC
(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!
Comment 7 axel mattauch 2017-06-26 09:08:53 UTC
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.
Comment 8 axel mattauch 2017-06-26 09:12:38 UTC
Created attachment 2776 [details]
How create a texture with a pixelformat supported by the driver?

Pertinent code segment is between lines 89 to 133
Comment 9 axel mattauch 2017-06-26 09:18:07 UTC
Created attachment 2777 [details]
Log associated to the june 26th version of the code

"SDL_Log" outputs.
Comment 10 Simon Hug 2017-06-26 10:20:53 UTC
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.
Comment 11 axel mattauch 2017-06-27 12:22:02 UTC
(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)
Comment 12 axel mattauch 2017-06-27 12:34:47 UTC
(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.