SDL_BlitSurface() doesn't want to blit

Started by
4 comments, last by Fomas 16 years, 9 months ago
Hello boys and girls! :) The Subject says pretty much everything, after blitting one Surface onto another one the destination Surface remains black, though SDL_BlitSurface() says blitting was successful. ConstructTitle() loads title images and then blits them onto the empty Surface, which is then returned. ConstructWindow() assembles window elements such as title, border, buttons, canvas by bliting them onto the empty Surface, which is then returned. And finally the returned Window Surface is blited onto the destination Surface, which is a SetVideoMode Surface. The following code snippet is just an example and is more like a pseudocode, but it illustrates the problem very well.

Uint32 flags = SDL_SWSURFACE | SDL_SRCCOLORKEY | SDL_SRCALPHA,
       rMask = 0xff000000,
       gMask = 0x00ff0000,
       bMask = 0x0000ff00,
       aMask = 0x000000ff;

SDL_Surface *ConstructTitle()
{
    SDL_Surface *leftCorner = SDL_LoadBMP("lcorner.bmp"), // Assume loaded successully!
                *rightCorner = SDL_LoadBMP("rcorner.bmp"), // Assume loaded successully!
                *title = SDL_CreateRGBSurface(flags, 100, 100, 32,
                                              rMask, gMask, bMask, aMask);

    SDL_Rect r = {0, 0};
    SDL_BlitSurface(leftCorner, 0, title, &r);  // Works!

    r.x = leftCorner->w;
    SDL_BlitSurface(rightCorner, 0, title, &r); // Works!

    return title;
}

SDL_Surface *ConstructWindow()
{
    SDL_Surface *title = ConstructTitle();
    SDL_Surface *border = ConstructBorder();
    SDL_Surface *win = SDL_CreateRGBSurface(flags, 640, 480, 32,
                                            rMask, gMask, bMask, aMask);

    SDL_Rect r = {0, 0};
    SDL_BlitSurface(title, 0, win, &r); // Doesn't seem to work!

    r.y = title->h;
    SDL_BlitSurface(border, 0, win, &r); // Doesn't seem to work!

    return win;
}

int main()
{
    InitSDL();
    SDL_Surface *dest = SetVideoMode();

    SDL_Sufrace *win = ConstructWindow(); // Doesn't work!
    //SDL_Sufrace *win = ConstructTitle(); // Works!

    SDL_Rect r = {0, 0};
    SDL_BlitSurface(win, 0, dest, &r);
    SDL_Flip(dest);

    return 0;
}

Advertisement
Did you init SDL_video?
Game Development Tutorials, a few good game development tutorials located on my site.
Quote:Original post by Butterman
Did you init SDL_video?


Yes, I did...it's not an initialisation problem, as I've shown in the code that if I call ConstructTitle() directly then it's working but if I call ConstructWindow() then it's not. It seems like, even though I don't think it's true, the returned title, border etc. inside ConstructWindow() get destroyed...but if it did then SDL_BlitSurface() inside ConstructWindow() should have returned an error.
Ok I think I found a problem! ;) Apparently if the empty Surface is not fully filled/initialised or what ever you wanna call it, then SDL_BlitSurface() finds it hard to blit or doesn't blit at all but still doesn't give any errors, which is annoying.
I only added the SDL_FillRect() to fill the empty Surface with a color before blitting, and it seems it fixed the problem.
Here is a new code:
SDL_Surface *ConstructTitle(){    SDL_Surface *leftCorner = SDL_LoadBMP("lcorner.bmp"), // Assume loaded successully!                *rightCorner = SDL_LoadBMP("rcorner.bmp"), // Assume loaded successully!                *title = SDL_CreateRGBSurface(flags, 100, 100, 32,                                              rMask, gMask, bMask, aMask);    SDL_FillRect(title, 0, SDL_MapRGB(temp->format, 0, 0, 0)); // ADD to make it work!    SDL_Rect r = {0, 0};    SDL_BlitSurface(leftCorner, 0, title, &r);    r.x = leftCorner->w;    SDL_BlitSurface(rightCorner, 0, title, &r);    return title;}SDL_Surface *ConstructWindow(){    SDL_Surface *title = ConstructTitle();    SDL_Surface *border = ConstructBorder();    SDL_Surface *win = SDL_CreateRGBSurface(flags, 640, 480, 32,                                            rMask, gMask, bMask, aMask);    SDL_FillRect(win, 0, SDL_MapRGB(temp->format, 0, 0, 0)); // ADD to make it work!    SDL_Rect r = {0, 0};    SDL_BlitSurface(title, 0, win, &r);    r.y = title->h;    SDL_BlitSurface(border, 0, win, &r);    return win;}int main(){    InitSDL();    SDL_Surface *dest = SetVideoMode();    SDL_Sufrace *win = ConstructWindow();    //SDL_Sufrace *win = ConstructTitle();    SDL_Rect r = {0, 0};    SDL_BlitSurface(win, 0, dest, &r);    SDL_Flip(dest);    return 0;}

This issue has also bitten me more then a few time.

SDL_CreateRGBSurface() will create and fill a 32-bit surface with zeros then return it to you. That means all the alpha components are also zero. When you try to blit an image onto the surface, the alpha components remain untouched. So when you try to blit the surface to the screen you see nothing since the entire surface is still totally transparent.

So you can either disable per-pixel blits on the source surface or fill the destination surface(FillRect) so that the alpha components are all 255. It also helps that MapRGB() will automatically return a color whose alpha component is 255 for that format.

You can check out the various interactions/behaviors when blitting between surfaces(RGB and RGBA that set or don't SDL_SRCALPHA ) by reading these docs.
BlitSurface
SetAlpha
0xa0000000
Quote:Original post by Jack Sotac
This issue has also bitten me more then a few time.

SDL_CreateRGBSurface() will create and fill a 32-bit surface with zeros then return it to you. That means all the alpha components are also zero. When you try to blit an image onto the surface, the alpha components remain untouched. So when you try to blit the surface to the screen you see nothing since the entire surface is still totally transparent.

So you can either disable per-pixel blits on the source surface or fill the destination surface(FillRect) so that the alpha components are all 255. It also helps that MapRGB() will automatically return a color whose alpha component is 255 for that format.

BlitSurface
SetAlpha


Thanks a lot for clearing it out, Jack Sotac! Now it actually makes sense, cos I thought there was something wrong with blitting function.

This topic is closed to new replies.

Advertisement