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 2373 - Fullscreen offset by a few pixels. Most strange workaround
Summary: Fullscreen offset by a few pixels. Most strange workaround
Status: RESOLVED ABANDONED
Alias: None
Product: SDL
Classification: Unclassified
Component: *don't know* (show other bugs)
Version: 2.0.2
Hardware: x86 Linux
: P2 minor
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-01-29 01:00 UTC by Loup Vaillant
Modified: 2018-08-06 21:20 UTC (History)
4 users (show)

See Also:


Attachments
Compile and run this file to reproduce the bug. Checks removed for brevity. (1.10 KB, text/x-csrc)
2014-01-29 01:00 UTC, Loup Vaillant
Details
Screenshot of the pixel offset issue (5.32 KB, image/png)
2014-11-20 19:09 UTC, Ben Swick
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Loup Vaillant 2014-01-29 01:00:26 UTC
Created attachment 1544 [details]
Compile and run this file to reproduce the bug. Checks removed for brevity.

SDL version
-----------
2.0.1 (package from Debian Linux, X86, using the XMonad window manager, v0.11)

Steps to reproduce
------------------
- Initialize SDL and the video subsystem.
- Create a window (fullscreen), a renderer, and a texture
- Fill the texture
- Draw the texture (RenderClear, RenderCopy, RenderPresent)

See the attached code for more detailed.  It's a single file, to be compiled in the obvious way.  I personally have used the command:

gcc -I/usr/include/SDL2 -D_REENTRANT -L/usr/lib/i386-linux-gnu -lSDL2 -o fdf src/main.c

(I have also tried various combinations of debug mode and optimization options.  The end result is the same.)

Expected result
---------------
The texture should be stretched across the entire screen.

Actual result
-------------
The 5-7 top rows stay black, and the right The texture seems to have been shifted downwards.

Workaround
----------
Insert a single call to SDL_PollEvent() anywhere between SDL_CreateRenderer() and SDL_RenderCopy();

This is most strange.  I fear the kind of non-local interactions that are needed to make this workaround work at all.

Additional notes
----------------
This bug cannot possibly affect interactive games in a meaningful way. At most, it may affect splash screens at the very start of the game: the only frames that are rendered before we need to poll events.

On the attached bug-reproducing code I have, Valgrind catches a number of errors:
- 3 conditional jumps that depend on uninitialized values.
- A memory leak, even though I closed everything properly (or so I think).
I have no idea if these are related to this bug or not.
Comment 1 Loup Vaillant 2014-01-29 01:05:23 UTC
EDIT: (Don't know how to actually edit my bug report.)

Actual result
-------------
The 5-7 top rows, and the 1-3 rightmost collumns stay black.
The texture seems to have been shifted downwards and leftwards a few pixels.
Comment 2 Ben Swick 2014-11-19 17:33:12 UTC
I ran the attached code with the current (11/19/2014) code in HG and it appears correctly with 3 rows of 4 rectangles filling the screen.
Row one has 4 rectangles: red, green, blue, red
Row two has 4 rectangles: green, blue, red, green
Row three has 4 rectangles: blue, red, green, blue

I'm running Linux Mint 17 Cinnamon on x86_64 with a Radeon HD3850.
It ran correctly with -O0 and -O2.

It also ran correctly with 2.0.2 from the Ubuntu repository.
Comment 3 Loup Vaillant 2014-11-19 23:04:10 UTC
Since Debian updated to SDL 2.0.2, I have tried again.  Just to be sure, I have tried both -O2 and -O0.  I also tried to fiddle with the renderer, trying both SDL_RENDERER_SOFTWARE and SDL_RENDERER_ACCELERATED, in case something platform specific was happening.

The bug is still there in all cases.

So I have to ask: Ben Swick, are you *sure* your system displays no bug?  Just seeing the 12 rectangles is not enough.  They actually draw fine on my system too.  They're just off by a few pixels.

This is not an "in your face" bug that draws half of the screen wrong.  Just a few rows of black pixels at the border of the screen —less than 1% of the surface.  Very easy to miss, even when you squint your eyes.

Now how do I know that I am not imagining things?

- First, I look at the screen up close.  Like, with a magnifying glass.
- Second, I stick a sheet of paper on the border of my screen before I run the program.  That way, I can easily see if there is any offset at that border.
Comment 4 Ben Swick 2014-11-20 19:09:20 UTC
Created attachment 1941 [details]
Screenshot of the pixel offset issue

Screenshot showing the offset pixels.
Comment 5 Ben Swick 2014-11-20 19:13:37 UTC
I believe this is exposing a race condition with the X11 window manager during creation of the window.


I did some more testing and used Gimp to zoom in on screenshots.

On my machine if I use the software renderer with your code I actually get a completely transparent window (the Cinnamon transition animation shows a window opening but it is transparent).

If I use the accelerated renderer, I do see a somewhat similar pixel shift if zooming in on the right edge. I apologize for not looking more closely yesterday. The first 24 pixels along the right edge of each block have the color of the previous block (except black in the top block). Several of the other blocks have shifted pixels along the edges. I've attached a small PNG screenshot.

Uncommenting the SDL_PollEvent code does not change the results for me.



What does work is adding a short delay. I've found SDL_Delay(50) is pretty reliable on my machine and as low as 25 works occasionally. Putting it between SDL_CreateWindow() and SDL_CreateRenderer() makes the software renderer work perfectly. Putting it after SDL_CreateRenderer() makes the accelerated renderer work.



The part that indicates a window manager race condition is changing the width and height passed to SDL_CreateWindow() from zero to the actual display width and height. This causes the software rendererg to show the pixel shift effect. Again, adding the delay makes the rendering perfect.

After adding some timing checks, the transparency effect is due to the software renderer only taking a few milliseconds to create the renderer while the accelerated renderer takes almost 100 milliseconds. I think there's one race with creating the window and another when creating the accelerated renderer.
Comment 6 Ben Swick 2014-11-21 20:57:18 UTC
On my system, the X server sends two Expose events after the image has been drawn to the screen (PutImage with software, SwapBuffers with accelerated). One is 1px wide along the right side and one 24px high along the bottom (matches my taskbar).

Expose x=0 y=0 width=1280 height=1024 count=0x0000
PutImage / SwapBuffers
Expose x=1279 y=0 width=1 height=1000 count=0x0001
Expose x=0 y=1000 width=1280 height=24 count=0x0000

A sufficient delay before SDL_RenderPresent() gives enough time for the extra Expose events to happen before PutImage / SwapBuffers.


The X server Expose events indicate pixels in those areas need repainted. I suspect they are from the window manager getting rid of things like the taskbar (which is about 24 pixels on my system).


If the program either calls SDL_RenderPresent() periodically or in response to the SDL_WINDOWEVENT_EXPOSED event then it will look correct regardless of what the window manager does. I don't see any changes to SDL that would avoid those extra expose events or the invalid drawing that happens.

I'm guessing whatever initialization happens at the first call to SDL_PollEvent just happens to last long enough for any expose events to complete before SDL_RenderPresent() is reached.

How I check the X server conversation is by installing xtrace and running the command:  xtrace -s ./fdf | grep 'PutImage\|Expose\|SwapBuffers'



Incidentally, if I specify an x,y coordinate that is inside the virtual desktop but not actually on a monitor then I get even more fun events. SDL decides to use the size of the first monitor for the framebuffer, the window manager fullscreens the window on the second monitor, and I end up with a black bar and 40% of the window contents on the left half of my second monitor.

Again, the delay before SDL_RenderPresent() gives the window manager and SDL enough time to reach an understanding of the window size and placement and everything looks right.
Comment 7 Sylvain 2016-12-01 13:02:37 UTC
I just tried to reproduce the issue and this doesn't seem to occur ? Could it be fixed ?
Comment 8 Ben Swick 2016-12-12 21:15:24 UTC
I ran the test again with the current code from HG (00fe449fbefe from 12/11/2016) and the problem is still there on my system (using Cinnamon 2.8.8 as my window manager).

I don't think this is really a bug in SDL. I believe it is some kind of issue in the window manager (thus running a different one or newer version might fix the problem). However, the program is also flawed in that it calls SDL_RenderPresent() once and expects it to display properly forever. It already does not work with non-compositing window managers when other windows are moved across it.

On my system, adding SDL_WINDOW_BORDERLESS or SDL_WINDOW_MAXIMIZED to the SDL_CreateWindow() flags results in correct rendering. The borderless flag causes an extra request and sync with the X11 window manager that makes it work. The window manager probably just handles the maximized state better.
Comment 9 Alex Szpakowski 2016-12-13 13:09:00 UTC
(In reply to Ben Swick from comment #8)
> I don't think this is really a bug in SDL. I believe it is some kind of
> issue in the window manager (thus running a different one or newer version
> might fix the problem). However, the program is also flawed in that it calls
> SDL_RenderPresent() once and expects it to display properly forever. It
> already does not work with non-compositing window managers when other
> windows are moved across it.

The correct way to deal with the window's contents getting trashed is to redraw on SDL_WINDOWEVENT_EXPOSED window events (if you don't want to redraw every frame).
Comment 10 Ryan C. Gordon 2018-08-06 21:20:19 UTC
Hello, and sorry if you're getting dozens of copies of this message by email.

We are closing out bugs that appear to be abandoned in some form. This can happen for lots of reasons: we couldn't reproduce it, conversation faded out, the bug was noted as fixed in a comment but we forgot to mark it resolved, the report is good but the fix is impractical, we fixed it a long time ago without realizing there was an associated report, etc.

Individually, any of these bugs might have a better resolution (such as WONTFIX or WORKSFORME or INVALID) but we've added a new resolution of ABANDONED to make this easily searchable and make it clear that it's not necessarily unreasonable to revive a given bug report.

So if this bug is still a going concern and you feel it should still be open: please feel free to reopen it! But unless you respond, we'd like to consider these bugs closed, as many of them are several years old and overwhelming our ability to prioritize recent issues.

(please note that hundred of bug reports were sorted through here, so we apologize for any human error. Just reopen the bug in that case!)

Thanks,
--ryan.