tags:

views:

157

answers:

2

Below is some code to use SDL with Haskell to draw a diagonal line. I get a CYAN line when the RGB clearly should be white. This is on Ubuntu. Am I doing something wrong?

import qualified Graphics.UI.SDL as SDL
import qualified Graphics.UI.SDL.Primitives as SDLP

main = do
    SDL.init [SDL.InitEverything]
    SDL.setVideoMode 640 480 32 []
    SDL.setCaption "My Window" "My Test"
    surf0 <- SDL.getVideoSurface
    white <- SDL.mapRGB (SDL.surfaceGetPixelFormat surf0) 255 255 255
    SDLP.line surf0 0 0 640 480 white 
    SDL.flip surf0
    eventLoop
    SDL.quit
    print "done"
    where
    eventLoop = SDL.waitEventBlocking >>= checkEvent
    checkEvent (SDL.KeyUp _) = return ()
    checkEvent _ = eventLoop
A: 

I get the same issue on my system (for both lines and other primitives), and using the Pixel constructor directly instead of mapRGB seems to give the correct colors.

For example, if I import Graphics.UI.SDL.Color as SDLC and then let white' = SDLC.Pixel maxBound, I get a white line, as expected. With SDLC.Pixel 4278190335 (or 255 * 2^24 + 255, a sensible value for red), I get a red line.

This clearly isn't a real solution or answer, but it might suggest some starting points.

One other odd thing: if I print both your white and mine like so:

print =<< SDL.getRGBA white (SDL.surfaceGetPixelFormat surf0)
print =<< SDL.getRGBA white' (SDL.surfaceGetPixelFormat surf0)
print white
print white'

I get this:

(255,255,255,255)
(255,255,255,255)
Pixel 16777215
Pixel 4294967295

So they look the same via getRGBA, but the actual Pixel values are different.

Travis Brown
+1  A: 

I observe the same effect on Lucid with ATI HD2400 and radeon driver (if that matters). But there is a workaround.

This example draws a white line:

import qualified Graphics.UI.SDL as SDL
import qualified Graphics.UI.SDL.Primitives as SDLP

import Control.Applicative ((<$>))

main = do
    SDL.init [SDL.InitEverything]
    sbase <- SDL.setVideoMode 640 480 24 []  -- draw here
    -- an ugly hack to get pixel format from an RGB surface:
    rgbPF <- SDL.surfaceGetPixelFormat <$> SDL.createRGBSurfaceEndian [] 1 1 24
    white <- SDL.mapRGB rgbPF (-1) (-1) (-1)
    SDLP.line sbase 0 0 (640-1) (480-1) white
    SDL.flip sbase
    eventLoop
    SDL.quit
  where
    eventLoop = SDL.waitEventBlocking >>= checkEvent
    checkEvent (SDL.KeyDown _) = return ()
    checkEvent _ = eventLoop

I accept that this is an ugly hack, but it seems that default surface' pixel format is not RGB (?), and using a pixel format of a surface known to be RGB helps. I don't have experience with SDL, so I cannot tell what the right way to use it is.

jetxee