Sign in to follow this  
The GMan

[SDL] Distorted Surface Image

Recommended Posts

I am in desparate need of help. I will be visiting the Game Developers Conference at the beginning of next week and have just found a problem in my game that I cannot seem to fix. I am creating a hardware surface using SDL_CreateRGBSurface(). I then load a background image and blit it to this surface tiling it until it fills the whole surface. This makes up the background for my level. This works flawlessly on any pentium III and IV processor I have tested it on. Recently I tested it on an AMD 64 processor and an Intel Pentium M processor and I get some serious graphical problems. The background shows up upside down, mirrored, sometimes it shows up filled with random colors from previous backgrounds on other levels. I have narrowed the problem down to the fact that I am creating a surface as a SDL_HWSURFACE. If I simply change the flag to SDL_SWSURFACE it works flawlessly (however the frame rate is seriously affected). If anyone has any suggestions as to what could be causing this please feel free to make any comments, suggestions, etc. I appreciate any and all help in advance. Here is some code:
// Create surfaces large enough to fit the map
background = SDL_CreateRGBSurface(NULL, width * TILE_SIZE, height * TILE_SIZE, COLOR_DEPTH, NULL, NULL, NULL, NULL);
originalBackground = SDL_CreateRGBSurface(NULL, width * TILE_SIZE, height * TILE_SIZE, COLOR_DEPTH, NULL, NULL, NULL, NULL);

SDL_FillRect(background, NULL, 0);
SDL_FillRect(originalBackground, NULL, 0);

// Converting any created surfaces to the same format as the screen supposedly speeds up blitting
SDL_Surface *temp = SDL_ConvertSurface(background, screen->format, SDL_HWSURFACE);
SDL_FreeSurface(background);
background = temp;
	
temp = SDL_ConvertSurface(originalBackground, screen->format, SDL_HWSURFACE);

SDL_FreeSurface(originalBackground);
originalBackground = temp;
	
temp = SDL_ConvertSurface(tiles, screen->format, SDL_HWSURFACE | SDL_SRCCOLORKEY | SDL_RLEACCEL);
SDL_FreeSurface(tiles);
tiles = temp;

// Set transparency for the tile layer
if( SDL_SetColorKey(tiles, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(tiles->format, 255, 0, 255)) < 0)
{
	ErrorHandler("Could not set ColorKey + RLE for the background: %s\n", SDL_GetError());
}

if(!background || !originalBackground) ErrorHandler("Could not create background surface.");

// The following code allows for a ("any width" x 352) background to be repeated for the entire 
// length of the map's width. If the map's width is not evenly divisible by the width
// of the background, the remaining piece of the background is added.
{
	directory = BACKGROUND_DIRECTORY;
	file = directory + backgroundFilename;
			
	SDL_Surface *tempBackground = SDL_LoadBMP(file.c_str());
	temp = SDL_ConvertSurface(tempBackground, screen->format, SDL_HWSURFACE);
	SDL_FreeSurface(tempBackground);
	tempBackground = temp;

	int i = 0;
	for(i = 0; i < (width * TILE_SIZE) / tempBackground->w; i++)
	{
		Blit(background, tempBackground, i * tempBackground->w, 0, 0, 0, tempBackground->w, tempBackground->h);
		Blit(originalBackground, tempBackground, i * tempBackground->w, 0, 0, 0, tempBackground->w, tempBackground->h);
	}
	
	int remainingPixels = (width * TILE_SIZE) % tempBackground->w;
	if(remainingPixels != 0)
	{
		Blit(background, tempBackground, i * tempBackground->w, 0, 0, 0, remainingPixels, tempBackground->h);
		Blit(originalBackground, tempBackground, i * tempBackground->w, 0, 0, 0, remainingPixels, tempBackground->h);
	}

	SDL_FreeSurface(tempBackground);
}


[Edited by - The GMan on March 15, 2006 3:00:47 AM]

Share this post


Link to post
Share on other sites
Just for clarity, fill out all of the parameters from SDL_CreateRGBSurface:


SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int bitsPerPixel,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 rmask = 0xff000000;
Uint32 gmask = 0x00ff0000;
Uint32 bmask = 0x0000ff00;
Uint32 amask = 0x000000ff;
#else
Uint32 rmask = 0x000000ff;
Uint32 gmask = 0x0000ff00;
Uint32 bmask = 0x00ff0000;
Uint32 amask = 0xff000000;
#endif

/*
Don't Use NULL for the first parameter, its conceptually wrong as the
first parameter isn't a pointer.
*/

background = SDL_CreateRGBSurface(SDL_SWSURFACE, width * TILE_SIZE, height * TILE_SIZE, COLOR_DEPTH, rmask, gmask , bmask amask );




I have a feeling its something to do with the fact that you pass in zero for rmask....amask, it probably resorts to doing something that works at 32bits, but fails at 64.

Share this post


Link to post
Share on other sites
rip-off,

Thanks for your reply. I did forget to mention that I tried using that #if, #else block to set the mask values and the problem persisted. Next, I explicitly set the BIG_ENDIAN values and then the other values. They all failed. Also, the framerate dropped to around 3 FPS with the #if, #else block in place so I left it out. Any ideas on why that may be?

-[EDIT]-
You are also very correct in saying not to pass NULL for values that are not pointers. I have replaced the line with the mask values and will test it tomorrow on my housemate's computer. It seems to be working fine on my machine (I'm not really sure why it didn't work the first time I tried it) but, as I have seen, that doesn't matter too much. I will post back tomorrow with the results.

Share this post


Link to post
Share on other sites
I have tried everything and I am still getting the same result. There is only one thing that seems to work but it is will not do for a final result. If I create both RGB surfaces as SDL_SWSURFACEs then convert them via SDL_DisplayFormat() it shows up fine. However, when I try to blit from another surface to the background surface I get a frame rate of about 4 FPS.

Any suggestions, I am at a loss and the conference is comming up very quickly.

And another thing, on the Celeron M laptop I am testing it on, windowed mode does not work the window appears but no graphics are displayed. Any other window that passes over the canvas of my window will leave a trail. However, on the AMD 64 processor and the Pentium 4 and Pentium 3 processors I have tested this on it works flawlessly.

I am so confused.

[Edited by - The GMan on March 15, 2006 8:11:09 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this