The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
As a simple way to render multiple textures that are the same other than color I load a plain white circle in to an SDL_Texture then just call SDL_SetTextureColorMod() giving it the color I want to make the circle.

This all works fine if the textures are individual (Example 1) but if I am sharing the SDL_Texture so that multiple objects all reference it, it means that SDL_SetTextureColorMod() must be called every render frame before the object renders the texture since the color it gave last time may have been changed by another object (Example 2).

Is calling SDL_SetTextureColorMod() every render frame, for potentially quite a lot of objects sharing a texture, going to cause major performance issues?

The reason it is required is the system is designed using a shared texture functionality with basic reference counting (I understand that there are probably better ways to do this using smart pointers but that is not the topic for discussion here). Is it going to be better to just let each object have it's own copy of the SDL_Texture so it only has to set the color once (or whenever it needs to change) rather than every render frame?

Example 1:

Code:
SDL_Texture* tex1;
SDL_Texture* tex2;
SDL_Texture* tex3;
...
// All 3 instances have their own SDL_Texture
MyObject A(tex1);
MyObject B(tex2);
MyObject C(tex3);
...
// A call to set the color of the texture is only required once for each class


Example 2:

Code:
SDL_Texture* tex;
...
// All 3 instances share the SDL_Texture
MyObject A(tex);
MyObject B(tex);
MyObject C(tex);
...
// A call to set the color of the texture must be made before rendering
// each object to ensure that any other object has not set a different color.
// E.g if the draw order was A, B, C and the color was set to be different
// for each object then before rendering B, each frame it would need to set
// the color again otherwise it would have the color of A and the same
// for the others   


Edit: This would also extend to SDL_SetTextureAlphaMod() and SDL_SetTextureBlendMode() or other similar functions

For reference I'm using SDL2.
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Robotic-Brain
Guest

Looking at the code SDL_SetTextureColorMod() seems to alter the state of
the SDL_COPY_MODULATE_COLOR flag, which in turn might cause a texture
reallocation (if I understand the meaning of SDL_InvalidateMap() right)

so the worst case boils down to this code sequence:
SDL_SetTextureColorMod(tex, 255, 255, 255);
SDL_SetTextureColorMod(tex, anyR, anyG, anyB);
SDL_SetTextureColorMod(tex, 255, 255, 255);

so if you make sure never to call it with 100% white you should be fine
(I would do some benchmarks though)

the same seems to be true for those other functions just with other
value combinations
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Jonny D


Joined: 12 Sep 2009
Posts: 932
If SDL_gpu would work for you and you have actual performance needs, then I would recommend that.  It has GPU_CreateAliasImage() which you can use for shallow copies of textures (same texture data, different render settings - like color).  It also uses sprite batching to minimize the overhead of multiple GL calls.

Jonny D





On Sat, Jul 26, 2014 at 7:42 AM, Robotic-Brain wrote:
Quote:
Looking at the code SDL_SetTextureColorMod() seems to alter the state of the SDL_COPY_MODULATE_COLOR flag, which in turn might cause a texture reallocation (if I understand the meaning of SDL_InvalidateMap() right)

so the worst case boils down to this code sequence:
SDL_SetTextureColorMod(tex, 255, 255, 255);
SDL_SetTextureColorMod(tex, anyR, anyG, anyB);
SDL_SetTextureColorMod(tex, 255, 255, 255);

so if you make sure never to call it with 100% white you should be fine
(I would do some benchmarks though)

the same seems to be true for those other functions just with other value combinations
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
Quote:
which in turn might cause a texture
reallocation (if I understand the meaning of SDL_InvalidateMap() right)

so the worst case boils down to this code sequence:
SDL_SetTextureColorMod(tex, 255, 255, 255);
SDL_SetTextureColorMod(tex, anyR, anyG, anyB);
SDL_SetTextureColorMod(tex, 255, 255, 255);

so if you make sure never to call it with 100% white you should be fine
(I would do some benchmarks though)


Hello, thank you for responding. If it is only changing the value of the SDL_COPY_MODULATE_COLOR flag (through bitwise operations) why would there be a texture reallocation? I'm also not quite sure what you mean regarding the worst case code sequence especially why I shouldn't set to 100% white?

Code:

   SDL_render.c

   596 int
   597 SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
   598 {
   599     SDL_Renderer *renderer;
   600
   601     CHECK_TEXTURE_MAGIC(texture, -1);
   602
   603     renderer = texture->renderer;
   604     if (r < 255 || g < 255 || b < 255) {
   605         texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
   606     } else {
   607         texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
   608     }
   609     texture->r = r;
   610     texture->g = g;
   611     texture->b = b;
   612     if (texture->native) {
   613         return SDL_SetTextureColorMod(texture->native, r, g, b);
   614     } else if (renderer->SetTextureColorMod) {
   615         return renderer->SetTextureColorMod(renderer, texture);
   616     } else {
   617         return 0;
   618     }
   619 }
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Robotic-Brain
Guest

Am 26.07.2014 14:45, schrieb Zammalad:
Quote:

Code:

SDL_render.c

596 int
597 SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g,
Uint8 b)
598 {
599 SDL_Renderer *renderer;
600
601 CHECK_TEXTURE_MAGIC(texture, -1);
602
603 renderer = texture->renderer;
604 if (r < 255 || g < 255 || b < 255) {
605 texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
606 } else {
607 texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
608 }
609 texture->r = r;
610 texture->g = g;
611 texture->b = b;
612 if (texture->native) {
613 return SDL_SetTextureColorMod(texture->native, r, g, b);
614 } else if (renderer->SetTextureColorMod) {
615 return renderer->SetTextureColorMod(renderer, texture);
616 } else {
617 return 0;
618 }
619 }


as you can see in line 615 it just forwards the call to some renderer
defined function
As far as I could see directFB is the only implementation, which
actually maps this to a no-op
therefore all other renderers seem to use the implementation from
SW_SetTextureColorMod which redirects to SDL_SetSurfaceColorMod

the 100% white restriction comes from the if statements in line 324 and
line 329

http://hg.libsdl.org/SDL/file/6d059ed9b6ca/src/video/SDL_surface.c#l310

Code:

310 int
311 SDL_SetSurfaceColorMod(SDL_Surface * surface, Uint8 r, Uint8 g,
Uint8 b)
312 {
313 int flags;
314
315 if (!surface) {
316 return -1;
317 }
318
319 surface->map->info.r = r;
320 surface->map->info.g = g;
321 surface->map->info.b = b;
322
323 flags = surface->map->info.flags;
324 if (r != 0xFF || g != 0xFF || b != 0xFF) {
325 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
326 } else {
327 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
328 }
329 if (surface->map->info.flags != flags) {
330 SDL_InvalidateMap(surface->map);
331 }
332 return 0;
333 }
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Sik


Joined: 26 Nov 2011
Posts: 905
I had to look up to make sure.

Neither the OpenGL nor the Direct3D renderers seem to define a texture
color modulation function... WTF? This is a really simple function for
the GPU (even for immediate mode OpenGL, jeez), why isn't this
supported directly by those renderers in the first place? Or am I
misunderstanding the code?
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Alex Szpakowski
Guest

The color modulation happens at draw time (inside GL_RenderCopy etc.), via GL_SetColor in the OpenGL backend of SDL_Render.
It is very cheap.

On Jul 26, 2014, at 3:44 PM, Sik the hedgehog wrote:

Quote:
I had to look up to make sure.

Neither the OpenGL nor the Direct3D renderers seem to define a texture
color modulation function... WTF? This is a really simple function for
the GPU (even for immediate mode OpenGL, jeez), why isn't this
supported directly by those renderers in the first place? Or am I
misunderstanding the code?
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Sik


Joined: 26 Nov 2011
Posts: 905
OK that makes a lot more of sense I suppose.

2014-07-26 15:46 GMT-03:00, Alex Szpakowski:
Quote:
The color modulation happens at draw time (inside GL_RenderCopy etc.), via
GL_SetColor in the OpenGL backend of SDL_Render.
It is very cheap.

On Jul 26, 2014, at 3:44 PM, Sik the hedgehog
wrote:

Quote:
I had to look up to make sure.

Neither the OpenGL nor the Direct3D renderers seem to define a texture
color modulation function... WTF? This is a really simple function for
the GPU (even for immediate mode OpenGL, jeez), why isn't this
supported directly by those renderers in the first place? Or am I
misunderstanding the code?
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Jonny D


Joined: 12 Sep 2009
Posts: 932
It is cheap unless you are rendering thousands of sprites...  then you need to batch them to avoid the glColor calls which certainly add up.

Jonny D


On Saturday, July 26, 2014, Sik the hedgehog wrote:
Quote:
OK that makes a lot more of sense I suppose.

2014-07-26 15:46 GMT-03:00, Alex Szpakowski <[url=javascript:;][/url]>:
Quote:
The color modulation happens at draw time (inside GL_RenderCopy etc.), via
GL_SetColor in the OpenGL backend of SDL_Render.
It is very cheap.

On Jul 26, 2014, at 3:44 PM, Sik the hedgehog <[url=javascript:;][/url]>
wrote:

Quote:
I had to look up to make sure.

Neither the OpenGL nor the Direct3D renderers seem to define a texture
color modulation function... WTF? This is a really simple function for
the GPU (even for immediate mode OpenGL, jeez), why isn't this
supported directly by those renderers in the first place? Or am I
misunderstanding the code?
_______________________________________________
SDL mailing list
[url=javascript:;][/url]
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list
[url=javascript:;][/url]
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list
[url=javascript:;][/url]
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Alex Szpakowski
Guest

The actual draw calls will be the bottleneck in that case, not the glColor calls (again, they’re very cheap, plus they don’t cause the draw calls to do much more state validation.)

On Jul 26, 2014, at 4:37 PM, Jonathan Dearborn wrote:

Quote:
It is cheap unless you are rendering thousands of sprites... then you need to batch them to avoid the glColor calls which certainly add up.

Jonny D
_____
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
So... overall what would be the answer to my question - Can I safely call SDL_SetTextureColorMod and similar functions potentially many many times a render frame? Think for example if I was using particles all sharing the same texture but being drawn different colors?

The only alternative I can see is to have individual instances of the texture which would surely be a large overhead itself.
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Robotic-Brain
Guest

For something like particles - which, I assume, are rarely 100% white -
it is totally save.
If you often have to alternate between 100% white and any other color,
only a benchmark test can give you an answer

Pseudo code:

loop:
SDL_SetTextureColorMod(tex, 255, 255, 255);
Render
SDL_SetTextureColorMod(tex, 0, 125, 255);
Render
end loop

you could also look into what Jonathan Dearborn suggested If you need
more speed

Am 26.07.2014 23:26, schrieb Zammalad:
Quote:
So... overall what would be the answer to my question - Can I safely
call SDL_SetTextureColorMod and similar functions potentially many
many times a render frame? Think for example if I was using particles
all sharing the same texture but being drawn different colors?

The only alternative I can see is to have individual instances of the
texture which would surely be a large overhead itself.

-------------------------

My Site [1]

Links:
------
[1] http://www.zamma.co.uk

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
Quote:
For something like particles - which, I assume, are rarely 100% white -
it is totally save.
If you often have to alternate between 100% white and any other color,
only a benchmark test can give you an answer

Pseudo code:

loop:
SDL_SetTextureColorMod(tex, 255, 255, 255);
Render
SDL_SetTextureColorMod(tex, 0, 125, 255);
Render
end loop


The thing I don't get about this though is why is it not safe to set to 100% white. Why would that be any different to setting it to a different color? I'm obviously missing something but I can't see what that is. I know you mentioned specific lines in the code, but why is that a limitation?
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Robotic-Brain
Guest

Look closely at the if statement I quoted [1]
here with some comments:

// store the flag state
323 flags = surface->map->info.flags;
// 0xFF equals 255...
// if you invert every boolean expression and flip AND / OR
this becomes clearer:
// if red == 255 AND green == 255 AND blue == 255 jump to else
block
// -> aka "if 100% white reset flag, else set it (remember: if
and else are flipped)"
324 if (r != 0xFF || g != 0xFF || b != 0xFF) {
// this sets the flag
325 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
326 } else {
// this resets it
327 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
328 }
// compare new flag state to stored state...
329 if (surface->map->info.flags != flags) {
// ...if they differ InvalidateMap
330 SDL_InvalidateMap(surface->map);
331 }

now I don't exactly know what SDL_InvalidateMap() does...
But to me it looks like it stores the pixel data in a native and a user
defined version.
If the requested format changes, it deallocates the native version. (it
also seems to do some reference counting)

Now if you are deallocating stuff in there, it must be allocated
somewhere else to keep a balance. (or else you would release more than
you allocated)

So I assume the drawing functions check the texture and re-create it if
necessary.
As you should know any kind of heap alloc/dealloc is potentially
expensive. (unless SDL uses it's own optimized allocator, which I highly
doubt since this is highly application specific)

The overall structure seems to be the same for the other functions you
asked about, just the values are different

[1]
http://hg.libsdl.org/SDL/file/6d059ed9b6ca/src/video/SDL_surface.c#l310


Am 27.07.2014 01:13, schrieb Zammalad:
Quote:
The thing I don't get about this though is why is it not safe to set
to 100% white. Why would that be any different to setting it to a
different color? I'm obviously missing something but I can't see what
that is. I know you mentioned specific lines in the code, but why is
that a limitation?

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Sam Lantinga


Joined: 10 Sep 2009
Posts: 1765
Most of the time you'll be using a hardware renderer and changing colors will be very very cheap. If you're concerned about performance, try rendering with all the colors and then render with all of them white and see if you see any performance difference.

Cheers!



On Sat, Jul 26, 2014 at 6:06 PM, Robotic-Brain wrote:
Quote:
Look closely at the if statement I quoted [1]
here with some comments:

          // store the flag state
  323     flags = surface->map->info.flags;

          // 0xFF equals 255...
          // if you invert every boolean expression and flip AND / OR this becomes clearer:
          // if red == 255 AND green == 255 AND blue == 255 jump to else block
          // -> aka "if 100% white reset flag, else set it (remember: if and else are flipped)"
  324     if (r != 0xFF || g != 0xFF || b != 0xFF) {

              // this sets the flag
  325         surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
  326     } else {

              // this resets it
  327         surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
  328     }

          // compare new flag state to stored state...
  329     if (surface->map->info.flags != flags) {

              // ...if they differ InvalidateMap
  330         SDL_InvalidateMap(surface->map);
  331     }

now I don't exactly know what SDL_InvalidateMap() does...
But to me it looks like it stores the pixel data in a native and a user defined version.
If the requested format changes, it deallocates the native version. (it also seems to do some reference counting)

Now if you are deallocating stuff in there, it must be allocated somewhere else to keep a balance. (or else you would release more than you allocated)

So I assume the drawing functions check the texture and re-create it if necessary.
As you should know any kind of heap alloc/dealloc is potentially expensive. (unless SDL uses it's own optimized allocator, which I highly doubt since this is highly application specific)

The overall structure seems to be the same for the other functions you asked about, just the values are different

[1] http://hg.libsdl.org/SDL/file/6d059ed9b6ca/src/video/SDL_surface.c#l310


Am [url=tel:27.07.2014%2001]27.07.2014 01[/url]:13, schrieb Zammalad:
Quote:
 The thing I don't get about this though is why is it not safe to set
to 100% white. Why would that be any different to setting it to a
different color? I'm obviously missing something but I can't see what
that is. I know you mentioned specific lines in the code, but why is
that a limitation?


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Re: Safe/acceptable to call SDL_SetTextureColorMod a lot?
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
I can see what you are saying but unless I am mistaken (highly possible) surely the flag will change whatever color you set it to UNLESS you are setting it to the same color? So the 100% white limitation isn't actually an issue it is just used in that if statement for a different optimised way to set the flag. If the flag was white and you set it to pure blue then SDL_InvalidateMap would be called in the same way if you had set it from blue to pure white.

Robotic-Brain wrote:
Look closely at the if statement I quoted [1]
here with some comments:

// store the flag state
323 flags = surface->map->info.flags;
// 0xFF equals 255...
// if you invert every boolean expression and flip AND / OR
this becomes clearer:
// if red == 255 AND green == 255 AND blue == 255 jump to else
block
// -> aka "if 100% white reset flag, else set it (remember: if
and else are flipped)"
324 if (r != 0xFF || g != 0xFF || b != 0xFF) {
// this sets the flag
325 surface->map->info.flags |= SDL_COPY_MODULATE_COLOR;
326 } else {
// this resets it
327 surface->map->info.flags &= ~SDL_COPY_MODULATE_COLOR;
328 }
// compare new flag state to stored state...
329 if (surface->map->info.flags != flags) {
// ...if they differ InvalidateMap
330 SDL_InvalidateMap(surface->map);
331 }

now I don't exactly know what SDL_InvalidateMap() does...
But to me it looks like it stores the pixel data in a native and a user
defined version.
If the requested format changes, it deallocates the native version. (it
also seems to do some reference counting)

Now if you are deallocating stuff in there, it must be allocated
somewhere else to keep a balance. (or else you would release more than
you allocated)

So I assume the drawing functions check the texture and re-create it if
necessary.
As you should know any kind of heap alloc/dealloc is potentially
expensive. (unless SDL uses it's own optimized allocator, which I highly
doubt since this is highly application specific)

The overall structure seems to be the same for the other functions you
asked about, just the values are different

[1]
http://hg.libsdl.org/SDL/file/6d059ed9b6ca/src/video/SDL_surface.c#l310


Am 27.07.2014 01:13, schrieb Zammalad:
Quote:
The thing I don't get about this though is why is it not safe to set
to 100% white. Why would that be any different to setting it to a
different color? I'm obviously missing something but I can't see what
that is. I know you mentioned specific lines in the code, but why is
that a limitation?

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Safe/acceptable to call SDL_SetTextureColorMod a lot?
Robotic-Brain
Guest

I think you got it...
The issue is not setting it to white per se. The issue is changing it TO
or FROM white

But as I said only an actual benchmark can tell you if this is really
significant...

Am 27.07.2014 12:13, schrieb Zammalad:
Quote:
I can see what you are saying but unless I am mistaken (highly
possible) surely the flag will change whatever color you set it to
UNLESS you are setting it to the same color? So the 100% white
limitation isn't actually an issue it is just used in that if
statement for a different optimised way to set the flag. If the flag
was white and you set it to pure blue then SDL_InvalidateMap would be
called in the same way if you had set it from blue to pure white.

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Re: Safe/acceptable to call SDL_SetTextureColorMod a lot?
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
Ah right I think I understand now, thanks. From what Sam said though it should be safe to do but yes I will do some benchmarking when the codebase is in a position to.

Robotic-Brain wrote:
I think you got it...
The issue is not setting it to white per se. The issue is changing it TO
or FROM white

But as I said only an actual benchmark can tell you if this is really
significant...

Am 27.07.2014 12:13, schrieb Zammalad:
Quote:
I can see what you are saying but unless I am mistaken (highly
possible) surely the flag will change whatever color you set it to
UNLESS you are setting it to the same color? So the 100% white
limitation isn't actually an issue it is just used in that if
statement for a different optimised way to set the flag. If the flag
was white and you set it to pure blue then SDL_InvalidateMap would be
called in the same way if you had set it from blue to pure white.

_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Zammalad


Joined: 26 Mar 2013
Posts: 9
Location: North East, UK
I did some digging and also compiled SDL with debugging symbols so I could walk through the code. Seems that it is completely safe to do this as pretty much for most HW implementations (except directfb) renderer->SetTextureColorMod is NULL meaning the color and flag are set.