Committing to mantis.
The problem was that we were not replacing the surfaceData object at the right
time. Previously, we would call setDisplayMode(), followed by
replaceSurfaceData(). However, there was no way to ensure that the right
stuff would happen in between these two calls to make sure that the new
surfaceData would have the right color model. Specifically, when we change
display modes, the dynamicColorModel of the GraphicsDevice must be recreated
in the new display mode. In order for this to happen, the old one must be
nulled-out by the time a request is made to the GraphicsDevice for a new
one. When the colorModel is null, we cause it to be recreated, which
forces us to examine the new color info for the new display mode.
What used to happen is that we would set display mode, not necessarily
null-out the obsolete dynamicColorModel in GraphicsDevice, then we would
create our new surfaceData object. This new surfaceData object would
request the dynamicColorModel, would get the reference to the obsolete
object, and would then create the surfaceData with the old (incorrect)
color data. At the native level, everything would be fine because
DirectDraw always creates surfaces in the current display mode. But
the decisions we make in our Java code hinge on the color data at the
Java level, not at the native level, so we would do things like assign
an incorrect scan stride, or an incorrect color value for pixels, etc.
The fix is to wait until the right time to replace the surfaceData.
We currently null-out the obsolete dynamicColorModel when we
receive the WM_DISPLAYCHANGE event (which we receive at some indeterminate
time after the display mode switch). So we should wait until after that
time to replace the surfaceData object.
The code change is simple; previously we would avoid propagating the
display switch event in some fullscreen situations, but really
we should only avoid recreating the primary. By simply moving the
end-bracket of the if() clause in the WM_DISPLAYCHANGE case, we
force surfaceData recreations to happen in all cases, which forces all
surfaceData objects to be recreated with the new, correct colorModel
At the same time, we should remove the old replaceSurfaceData() call;
the setDisplayMode() call will force a WM_DISPLAYCHANGE event in cases
where a replacement is necessary (when we have actually changed the
display mode and not just set it to the one that was already active)
and that, in turn, will force its own surfaceData replacement.