Resize window SDL2

Hi, I could use some help on this.

Some background first: Java was developed by Sun to compete on the
desktop with Windows. In particular Java was "write once run anywhere"
and it came with a GUI. Neither Java nor the GUI were very good, but
the appeal of a platform independent GUI was one of the main reasons
for Java’s success.

I am developing a “write once run anywhere” system too, but it is uses
a different technology. Instead of a VM and bytecode compiler, my
system generates C++ source which is then compiled down to
machine binary by your system C++ compiler. This should be faster,
and in particular, better for game development :slight_smile:

Because I generate C++, bindings to C libraries are particularly
easy to create and usually involve mapping types but little or no
executable code (unlike, say, bindings in Python). Here’s an
example of a library of bindings … for SDL of course:

http://felix-lang.org/$/usr/local/lib/felix/felix-latest/share/lib/sdl

Before developing games I need some tools. In particular
a GUI would be useful. And of course it has to be platform
independent! So of course I’m trying to use SDL because
the aim of SDL is to provide a platform independent game
development environment.

http://felix-lang.org/$/usr/local/lib/felix/felix-latest/share/lib/gui

It’s a bit crude at the moment, but the methodology seems to
work up to a point:

http://felix-lang.org/$/usr/local/lib/felix/felix-latest/share/src/web/tutopt//sdlgui

But I have a problem. Tests gui_04_* on do event handling. When I resize a
window the program seems to work, unless the bounding rect of the stuff
I’m drawing is entirely outsize the window rect. That seems to crash my
program every time.

This is a clear indication of a bug in SDL because none of my code
knows anything about clipping etc… Indeed, examining some of the SDL
code and docs, it is not specified clearly what happens intersecting
non-intersecting rects and it is not clear that every drawing routine
in the whole of SDL correctly handles negative width or height.
SDL_IntersectRect DOES product a negative dimension if there
is no intersection, and this is set to a SDL_Surface clipping rectangle.
A lot of SDL code does not do any special checks for this.
In some cases it works anyhow. It’s hard to be sure.

Unfortunately I cannot experiment because I’m running OSX 10.6.8 and
can no longer compile SDL from source.

However here’s the quandary. I have tried to make a C program
doing roughly the same drawing operations crash with a resize
and it doesn’t.

Which is a strong indication SDL works and the bug is in my code :slight_smile:
[And I’m sure I’m not the only SDL user about … :]

So now I have a contradiction.

Using gdb I find more than one of my programs crashes with
exactly the same single symbol on the stack, unfortunately
it has nothing to do with the problem. It’s not even a function.
The indication is corruption.

Using Valgrind, my program crashes, Valgrind crashes, the
iTerm terminal emulator crashes and my computer hangs.
A hardware reset is required.

The crash also occurs on Linux, so it isn’t OSX specific.
[Not surprising, since I’m using software rendering].

I am not asking for debugging help but thinking help!
Logically, the bug is in SDL because my code is entirely
independent of the context creating the crash, and the SDL C handling
this is very suspicious, but my C code designed to demonstrate
this fails to crash, indicating a corruption caused by my system
or my test code, bindings, or compiler. But the bindings and
test code work without resizing and the compiler compiles a
lot of other code and is fairly robust after 20+ years of development.–
john skaller
@john_skaller
http://felix-lang.org

Hi, I could use some help on this.

Ok, I have managed to get Valgrind to tell where the error is:

==1417== Invalid write of size 8
==1417== at 0x1002A11E0: ??? (in /Library/Frameworks/SDL2.framework/Versions/A/SDL2)
==1417== by 0x100009FB0: flxusr::gui_04_wm_01::init::resume() (gui_04_wm_01.cpp:602)
==1417== by 0x100067243: flx::rtl::fthread_t::run() (flx_rtl.cpp:80)
==1417== by 0x1000694E8: flx::run::sync_sched::frun() (flx_sync.cpp:209)
==1417== by 0x1000640D7: flx::run::async_sched::prun(flx::run::async_sched::block_flag_t) (flx_async_world.cpp:132)
==1417== by 0x10006AE09: flx::run::flx_world::run_until_complete() (flx_world.cpp:327)
==1417== by 0x10000384A: felix_run(int, char**) (flx_run.include:330)
==1417== by 0x100003961: main (flx_run_main.cxx:4)
==1417== Address 0x11b2a90f0 is not stack’d, malloc’d or (recently) free’d
==1417==
==1417==
==1417== Process terminating with default action of signal 11 (SIGSEGV)
==1417== Access not within mapped region at address 0x11B2A90F8

  surf = (SDL_Surface*) ::SDL_GetWindowSurface(w_uncurry); //assign simple
  pixelformat = (*surf).format; //assign simple
  bgpixels = (_a5115t_55683) ::SDL_MapRGB(pixelformat, c.r, c.g, c.b); //assign simple
  _genout_urv55214  = (int) ::SDL_SetClipRect(surf, (SDL_Rect*)&r); //init
  _genout_urv55144  = _genout_urv55214; //init
  _genout_urv55131  = _genout_urv55144; //init
  (void)_genout_urv55131;
  _genout_urv55215  = SDL_FillRect (surf, NULL, bgpixels); //init

The last line there is line 602.

now, the docs say “NULL to fill the entire surface”.

Certainly this is wrong. The actual code in the Mercurial repository says:

/* If 'rect' == NULL, then fill the whole surface */
if (rect) {
    /* Perform clipping */
    if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
        return 0;
    }
    rect = &clipped;
} else {
    rect = &dst->clip_rect;
}

which clearly fills the clip rect of the surface NOT the whole surface.

The cliprect is set by SDL_SetClipRect, which sets the actual
cliprect to the intersection of the supplied cliprect and the window
bounding rect, which has non-positive width or height.

Then there’s a bit of a nasty selection of an optimal fill routine.
Includes special code for SSE etc … I would not be surprised if
these routine cannot handle negative width/height values,
they’re pretty complicated.

So it is again looking like a bug in SDL.
The reason my C code doesn’t crash is it calls SDL_FillRect with
an actual rectangle. The generated C++ sets the clip rect then
calls SDL_FillRect with NULL.On 22/02/2015, at 11:16 AM, john skaller wrote:


john skaller
@john_skaller
http://felix-lang.org

Hi, I could use some help on this.

Ok, it is DEFINITELY a bug in SDL. Perhaps someone can try this test code.
It crashes immediately on OSX 10.6.8, Macbook Pro.

#include “SDL2/SDL.h”

void draw(SDL_Window *w, int x, int y)
{
SDL_Rect r;
r.x=x; r.y=y; r.w=100; r.h=100;
SDL_Surface *s = SDL_GetWindowSurface (w);
SDL_SetClipRect (s,&r);
SDL_PixelFormat *f = s->format;
uint32_t bgpixels = SDL_MapRGB(f, 200,200,200);
SDL_FillRect(s,NULL,bgpixels);
SDL_UpdateWindowSurface (w);
}

void fred()
{
int x = 190;
int y = 170;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *w = SDL_CreateWindow (“title”,20,20,100,100,SDL_WINDOW_RESIZABLE);
draw (w,x,y);
SDL_PumpEvents();
SDL_Event e;
SDL_WaitEvent(&e);
while (e.type != SDL_QUIT)
{
fprintf (stderr, “Event …\n”);
draw(w, x,y);
SDL_WaitEvent(&e);
}
}
int main() { fred(); return 0; }On 23/02/2015, at 12:43 AM, john skaller wrote:

On 22/02/2015, at 11:16 AM, john skaller wrote:


john skaller
@john_skaller
http://felix-lang.org

Ok, it is DEFINITELY a bug in SDL. Perhaps someone can try this test code.
It crashes immediately on OSX 10.6.8, Macbook Pro.

Confirmed, crashes on Linux too:

Program received signal SIGSEGV, Segmentation fault. SDL_FillRect4SSE (h=, w=, color=13158600, pitch=400, pixels=0x7ffff7fff148 <error: Cannot access memory at address 0x7ffff7fff148>) at /home/fletch/project/SDL2-2.0.3/src/video/SDL_fillrect.c:130 130 DEFINE_SSE_FILLRECT(4, Uint32)

This has the added advantage of identifying the specific sub-routine SDL_FillRect4SSE().

The culprit is in fact line 261 of SDL_FillRect.c in Mercurial repository which clearly
cannot handle negative height or width,

The solution is quite simple.

on Line 255 of SDL_FillRect.c in the repo, add this code:

if (SDL_NullRect (rect)) return SDL_True;

now go off an check that other routines make this test too, eg Blit,
line drawing, etc. I think these work however.On 23/02/2015, at 1:09 AM, john skaller wrote:

#include “SDL2/SDL.h”

void draw(SDL_Window *w, int x, int y)
{
SDL_Rect r;
r.x=x; r.y=y; r.w=100; r.h=100;
SDL_Surface *s = SDL_GetWindowSurface (w);
SDL_SetClipRect (s,&r);
SDL_PixelFormat *f = s->format;
uint32_t bgpixels = SDL_MapRGB(f, 200,200,200);
SDL_FillRect(s,NULL,bgpixels);
SDL_UpdateWindowSurface (w);
}

void fred()
{
int x = 190;
int y = 170;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *w = SDL_CreateWindow (“title”,20,20,100,100,SDL_WINDOW_RESIZABLE);
draw (w,x,y);
SDL_PumpEvents();
SDL_Event e;
SDL_WaitEvent(&e);
while (e.type != SDL_QUIT)
{
fprintf (stderr, “Event …\n”);
draw(w, x,y);
SDL_WaitEvent(&e);
}
}
int main() { fred(); return 0; }


john skaller
@john_skaller
http://felix-lang.org


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


john skaller
@john_skaller
http://felix-lang.org

Ok, it is DEFINITELY a bug in SDL. Perhaps someone can try this test code.
It crashes immediately on OSX 10.6.8, Macbook Pro.

Confirmed, crashes on Linux too:

Program received signal SIGSEGV, Segmentation fault. SDL_FillRect4SSE (h=, w=, color=13158600, pitch=400, pixels=0x7ffff7fff148 <error: Cannot access memory at address 0x7ffff7fff148>) at /home/fletch/project/SDL2-2.0.3/src/video/SDL_fillrect.c:130 130 DEFINE_SSE_FILLRECT(4, Uint32)

This has the added advantage of identifying the specific sub-routine SDL_FillRect4SSE().

The culprit is in fact line 261 of SDL_FillRect.c in Mercurial repository which clearly
cannot handle negative height or width,

The solution is quite simple.

on Line 255 of SDL_FillRect.c in the repo, add this code:

if (SDL_NullRect (rect)) return SDL_True;

Correction: SDL_RectEmpty.

I’m having a friend check this fixes the problem right now.
[I cannot compile SDL any more on OSX 10.6.8].On 23/02/2015, at 9:22 AM, john skaller wrote:

On 23/02/2015, at 1:09 AM, john skaller wrote:


john skaller
@john_skaller
http://felix-lang.org

This looks like a bug to me. I’m able to reproduce it on Win32, and on iOS with a few minor modifications. I’ve added some comments to the Bugzilla entry on it (at https://bugzilla.libsdl.org/show_bug.cgi?id=2868 ), along with a simplified test program, and John’s fix encoded as a patch (tested + working).

Sam, Ryan – if you like, and the patch looks good to you, I’d be happy to push the fix to hg.libsdl.org.

Cheers!
– David L.

Sam, Ryan – if you like, and the patch looks good to you, I’d be happy to push the fix to hg.libsdl.org.

Quick question: why return SDL_FALSE?

Wouldn’t one return that if the operation failed?
Writing completely off the surface (by doing nothing) is no
more a failure than a partial (i.e. clipped) write.

Is there a consistent convention here?

BTW: thanks for your work David!!On 23/02/2015, at 12:42 PM, DLudwig wrote:


john skaller
@john_skaller
http://felix-lang.org

john skaller wrote:

Quick question: why return SDL_FALSE?

SDL_FillRect() uses a convention whereby an int, rather than SDL_bool, is returned: 0 on success, and something else (usually -1) for failure.

Cheers!
– David L.