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
Can the pointer to the window surface change?
xiver77


Joined: 03 Jun 2015
Posts: 5
So the `GetWindowSurface` function returns the pointer to the window surface, but is it safe to store the pointer in a variable and read from it instead of calling `GetWindowSurface` multiple times? For this I'd need the assumption that the pointer to the window surface does not change, but the documentation does not say about this.

I'm not changing the size of the window by the way.
DarioOO


Joined: 27 Dec 2014
Posts: 15
When it can change its implementation dependent that's why i suppose it is not documented. It is a good Software Engineering practice (from agile development book) to use the "getter functions" when you can instead of storing a variable with the value. On the long run it will cause less and less bugs.

Reason behind that:
- If the value can be cached to improve performance, chances are good the Getter itself can perform caching
- Makes code more readable (no variable, just the method, and you have one less line of code elsewhere: no variable declaration)
- No undefined behvaiour if there is no documentation about returned value changin depending on state of the object you get it from (sdl window in this case)
- Most times ends up to be more performant (inlining & variable storing is already performed by compiler and CPU).
- "but I need the value" => you need the method to get that value:

EDIT:
the code shows that:
Code:
SDL_Surface *
SDL_GetWindowSurface(SDL_Window * window)
{
    CHECK_WINDOW_MAGIC(window, NULL);

    if (!window->surface_valid) {
        if (window->surface) {
            window->surface->flags &= ~SDL_DONTFREE;
            SDL_FreeSurface(window->surface);
        }
        window->surface = SDL_CreateWindowFramebuffer(window);
        if (window->surface) {
            window->surface_valid = SDL_TRUE;
            window->surface->flags |= SDL_DONTFREE;
        }
    }
    return window->surface;
}


The function already perform caching, plus other non trivial checks. Trust me if you start storing that value elsewhere you'll incurr in some hard to debug bug
xiver77


Joined: 03 Jun 2015
Posts: 5
DarioOO wrote:
When it can change its implementation dependent that's why i suppose it is not documented. It is a good Software Engineering practice (from agile development book) to use the "getter functions" when you can instead of storing a variable with the value. On the long run it will cause less and less bugs.

Reason behind that:
- If the value can be cached to improve performance, chances are good the Getter itself can perform caching
- Makes code more readable (no variable, just the method, and you have one less line of code elsewhere: no variable declaration)
- No undefined behvaiour if there is no documentation about returned value changin depending on state of the object you get it from (sdl window in this case)
- Most times ends up to be more performant (inlining & variable storing is already performed by compiler and CPU).
- "but I need the value" => you need the method to get that value:

EDIT:
the code shows that:
Code:
SDL_Surface *
SDL_GetWindowSurface(SDL_Window * window)
{
    CHECK_WINDOW_MAGIC(window, NULL);

    if (!window->surface_valid) {
        if (window->surface) {
            window->surface->flags &= ~SDL_DONTFREE;
            SDL_FreeSurface(window->surface);
        }
        window->surface = SDL_CreateWindowFramebuffer(window);
        if (window->surface) {
            window->surface_valid = SDL_TRUE;
            window->surface->flags |= SDL_DONTFREE;
        }
    }
    return window->surface;
}


The function already perform caching, plus other non trivial checks. Trust me if you start storing that value elsewhere you'll incurr in some hard to debug bug


What I see from the code is that it's perfectly safe to assume the pointer to the window surface will not change if I do not invalidate the window surface by such as resizing. A short test with my game shows that calling `SDL_GetWindowSurface` whenever I access the window surface makes the frame rate drop to half compared to when I store the pointer in an external static variable, with `-O3` full optimization.

Accessing screen pixels directly in SDL2 should have better support at least as much as it had in SDL1.2 in my opinion.
DarioOO


Joined: 27 Dec 2014
Posts: 15
No it is not safe assuming that, just because you looked at implementation ^^. SDL2 api is still to be changed, refined, so you cannot make assumptions on undocumented features.

Also you'll never know if you develop some code that change screen resolution or that make the context loss or the surface to be dropped (maybe because there's a function that call FreeSurface without you notice it.)
. If you want safe code you cannot take that assumption. If you want performant code DO NOT USE frame rate for measuring time (meausure milliseconds/microseconds) and spend time/effort optimizing where needed (bottlenecks). Also it is obviouse that if you measure something that takes 8 CPu instructions versus something that takes 4 cpu instructions you measure half time Very Happy.( but 8 and 4 are very low numbers for something that is harder to call more than a bunch of times every frame) But unless you access that pointer thousand times each frame that will make not difference for final application performance. Early optimization is the root of all evil.

What you can assume is that you can do "some work" with the pointer (something short enough to last a frame) before it changes. If they wanted to make safe assuming that, they will probably had used a double pointer (a pointer to the location where is stored the pointer).

Then you can enforce the condition:
-by checking device is not lost
-by checking resolution is not changed

effectively adding more complexity than needed to your code and by losing any performance you gained ^^. Don't do that. If you have any performance problem users here will be happy to help you fix that (I doubt the performance problem would be caused by that function)
xiver77


Joined: 03 Jun 2015
Posts: 5
DarioOO wrote:
No it is not safe assuming that, just because you looked at implementation ^^. SDL2 api is still to be changed, refined, so you cannot make assumptions on undocumented features.

Also you'll never know if you develop some code that change screen resolution or that make the context loss or the surface to be dropped (maybe because there's a function that call FreeSurface without you notice it.)
. If you want safe code you cannot take that assumption. If you want performant code DO NOT USE frame rate for measuring time (meausure milliseconds/microseconds) and spend time/effort optimizing where needed (bottlenecks). Also it is obviouse that if you measure something that takes 8 CPu instructions versus something that takes 4 cpu instructions you measure half time Very Happy.( but 8 and 4 are very low numbers for something that is harder to call more than a bunch of times every frame) But unless you access that pointer thousand times each frame that will make not difference for final application performance. Early optimization is the root of all evil.

What you can assume is that you can do "some work" with the pointer (something short enough to last a frame) before it changes. If they wanted to make safe assuming that, they will probably had used a double pointer (a pointer to the location where is stored the pointer).

Then you can enforce the condition:
-by checking device is not lost
-by checking resolution is not changed

effectively adding more complexity than needed to your code and by losing any performance you gained ^^. Don't do that. If you have any performance problem users here will be happy to help you fix that (I doubt the performance problem would be caused by that function)


I know what you mean. It just makes me think to go back to SDL1.2's `SDL_SetVideoMode`.
DarioOO


Joined: 27 Dec 2014
Posts: 15
why? for a function that has 3/4 assembly extra instructions? things that disappoint me are things like discontinued Cmake build script, not a changin or different API. You can do:

Code:

void doSomework( SDL_window * w){
    SDL_Surface * s = SDL_GetWindowSurface(w);
    //do some work
   
    //s no longer referenced when works end
}


but certainly you can't do


Code:

SDL_Surface * s = NULL;

void doSomework( SDL_window * w){
    s = SDL_GetWindowSurface(w);
   //do some work
   
   //ouch! s still referenced
}
xiver77


Joined: 03 Jun 2015
Posts: 5
DarioOO wrote:
why? for a function that has 3/4 assembly extra instructions? things that disappoint me are things like discontinued Cmake build script, not a changin or different API. You can do:

Code:

void doSomework( SDL_window * w){
    SDL_Surface * s = SDL_GetWindowSurface(w);
    //do some work
   
    //s no longer referenced when works end
}


but certainly you can't do


Code:

SDL_Surface * s = NULL;

void doSomework( SDL_window * w){
    s = SDL_GetWindowSurface(w);
   //do some work
   
   //ouch! s still referenced
}


With `SDL_SetVideoMode` I can access the screen pixels directly anytime by just,

Code:
SDL_Surface *window;

/* during initialization */
window = SDL_SetVideoMode(...);

/* access pixels */
window->pixels


But with `SDL_CreateWindow` and `SDL_GetWindowSurface`,

Code:
SDL_Window *window;

/* during initialization */
window = SDL_CreateWindow(...);

/* access pixels */
SDL_GetWindowSurface(window)->pixels


At least in my game the second approach IS slower, even with full compiler optimization. The speed gets similar only when I do as,

Code:
SDL_Surface *window_surface;

/* during initialization */
window_surface = SDL_GetWindowSurface(window);

/* access pixels */
window_surface->pixels


I do see the problem when I do this. But I'd rather go back using SDL1.2 than make my game slow by calling the getter everywhere. Calling `SDL_GetWindowSurface` at the beginning of a function did not make a big speed difference with just calling it everywhere.
DarioOO


Joined: 27 Dec 2014
Posts: 15
oh a pity. Personally I don't mind because I use OpenGL directly to access pixels when saving screenshots, but if in your game you manipulate pixels directly to do graphics than that's a real and bad bottleneck Sad
xiver77


Joined: 03 Jun 2015
Posts: 5
DarioOO wrote:
oh a pity. Personally I don't mind because I use OpenGL directly to access pixels when saving screenshots, but if in your game you manipulate pixels directly to do graphics than that's a real and bad bottleneck Sad


I get 400 FPS in my laptop, and over 100 FPS in a virtual machine running in my laptop. The CPU is i3 something. I do whole screen alpha-blending in software and only one CPU core is used for the entire game, but still fast enough.
Can the pointer to the window surface change?
Ryan C. Gordon
Guest

Quote:
why? for a function that has 3/4 assembly extra instructions? things that disappoint me are things like discontinued Cmake build script, not a changin or different API.

To be clear, the cmake scripts aren't discontinued.

--ryan.


_______________________________________________
SDL mailing list

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