• Advertisement

Archived

This topic is now archived and is closed to further replies.

Yet an other SDL thread

This topic is 5065 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Heya! Some of you may remember my previous thread on setting up a transluscent background for my custom windows in my game (Silver). Followed by me reporting 10 FPS max. Again, followed by me realizing that there are 1000 MS in a second, not 100. I'm planning on doing some optimization. I have a working scripting engine which automates my prelude/demo thingie, and figure I might pause developpement a bit and do some optimizing. Simple optimizing, like, the obvious stuff. The REALLY obvious stuff. Such as converting surfaces and all that. I get a nice 50-60 FPS (even with my crappy PC) when running the game. However, when I start displaying a window, I get about half of that (20-25). Ow. They seem to update somewhat slowly when I have two, such as with a character's name and their speech. I figure it wouldn't hurt to convert them to the display surface's format, so off I go. The SDL docs on SDL_DisplayFormatAlpha() state that "If you want to take advantage of hardware colorkey or alpha blit acceleration, you should set the colorkey and alpha value before calling this function." So I do just that for my background.  SDL_Temp = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCCOLORKEY, W << 4, H << 4, 32, 0xFF, 0xFF00, 0xFF0000, 0x00);  SDL_SetColorKey(SDL_Temp, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0xFF00FF);  SDL_SetAlpha (SDL_Temp, SDL_SRCALPHA, 128);  SDL_WPanel = SDL_DisplayFormatAlpha(SDL_Temp);  SDL_FreeSurface(SDL_Temp); And... my color key and translucency don't work. They work fine if I set them after calling SDL_DisplayFormatAlpha() though. So, what gives? And any basic pointers on making SDL-driven graphics display faster? (The profiler says pretty much 80-85% of the workload goes into blitting...) I don't want to do microoptimization or any unecessary preliminary optimization. My code works, I just don't want it to run unacceptably slow (which it almost does, considering what little it displays...) edit: formatting issues... [edited by - RuneLancer on April 12, 2004 10:41:59 PM]

Share this post


Link to post
Share on other sites
Advertisement
Well, it *appears* to work:

There are two supplementary functions first to better draw pixels and surfaces, then the main code:


Here is a pixel-putting function to color the surface:

// draws a pixel of specified RGB value onto a surface

void DrawPixel(SDL_Surface *s, int x, int y, Uint8 R, Uint8 G, Uint8 B, Uint8 A=0) {

// OOB

if ( x < 0 || y < 0 || x > s->w-1 || y > s->h-1 ) { return; }

Uint32 color;
if (A) { color = SDL_MapRGBA(s->format, R, G, B, A); }
else { color = SDL_MapRGB(s->format, R, G, B); }

switch (s->format->BytesPerPixel) {
case 1: {// Assuming 8-bpp

Uint8 *bufp;
bufp = (Uint8 *)s->pixels + y*s->pitch + x;
*bufp = color;
break;
}
case 2: {// Probably 15-bpp or 16-bpp

Uint16 *bufp;
bufp = (Uint16 *)s->pixels + y*s->pitch/2 + x;
*bufp = color;
break;
}
case 3: {// Slow 24-bpp mode, usually not used

Uint8 *bufp;
bufp = (Uint8 *)s->pixels + y*s->pitch + x * 3;
if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
bufp[0] = color;
bufp[1] = color >> 8;
bufp[2] = color >> 16;
}
else {
bufp[2] = color;
bufp[1] = color >> 8;
bufp[0] = color >> 16;
}
break;
}
case 4: {// Probably 32-bpp

Uint32 *bufp;
bufp = (Uint32 *)s->pixels + y*s->pitch/4 + x;
*bufp = color;
break;
}
}
}




a simple draw image function:

void DrawImage(SDL_Surface *img, int x, int y)
{
SDL_Rect dest;
dest.x = x;
dest.y = y;
SDL_BlitSurface(img, NULL, screen, &dest);
}



and then the regular make-it-work code:



// make a grey surface so we can tell if the blending and keying is working:

// (obviously replace "screen" with your main SDL screen surface)

SDL_FillRect ( screen , NULL , SDL_MapRGB ( screen->format, 128 , 128 , 128 ) ) ;

// create a new surface 100x100

SDL_Surface* temp = SDL_CreateRGBSurface(SDL_SWSURFACE, 100, 100, 32, 0, 0, 0, 0);
SDL_SetAlpha (temp, SDL_SRCALPHA, 128);
// uncomment to test color keying:

//SDL_SetColorKey(temp, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0);




// Draw some perty colors: ------\/-----------------

for (int x=0; x < temp->w; x++) {
for (int y=0; y < temp->h; y++) {
if (
x > temp->w/3*1 &&
x < temp->w/3*2 &&
y > temp->h/3*1 &&
y < temp->h/3*2
)
{
DrawPixel( temp, x, y, 100, 100, 200 );
}
else {
// uncomment to test more alpha-blending:

//DrawPixel( temp, x, y, 200, 200, 100 );

// otherwise make black:

DrawPixel( temp, x, y, 0, 0, 0 );
}
}
}
// Draw some perty colors: ------/\-----------------



// convert temp surface:

SDL_Surface* panel = SDL_DisplayFormatAlpha(temp);
SDL_FreeSurface(temp);

// blit the sucka

DrawImage( panel, 100, 100 );

// flip your screen here

SDL_Flip(screen);



i would also recommend that you NOT use the SDL_ prefix. that's for distinguishing libsdl from your own code.

For blitting graphics faster, the only real thing i can recommend is blitting less or not blitting at all. Sounds dumb, but it's the most surefire way to speed up your FPS. With my project, i'm working with multiple parallax scrolling background layers... at 1024x768. It's really bogging down even with an Athlon 2500 so i may just have to just reduce to 800x600 if i want all those extra bells n' whistles.

Also, RLE encoding is good if you have bands of identical horizontal pixels. (it works like a GIF image, in other words). It works by, instead of encoding each pixel, i.e. "pixel #1 = red, pixel #2 = red, pixel #3 = red", it just says "pixels 0-100 are all red" and saves a lot of space and time. This speeds up your blits so keep that in mind: horizontal bands! (very good for color keys since color keys are all the same color anyway. all color keyed pixels that are blitted with RLEACCEL on will be completely skipped. That's some good speed improvement).

[edited by - leiavoia on April 12, 2004 12:45:08 AM]

Share this post


Link to post
Share on other sites
The images I'm blitting are all highly RLE compressible, hence the flag. I'd be pretty stupid not to use it if one of my images is little more than a stylized black and pink (0xFF00FF; the colorkey ;P) box. So obviously, yes, I'd use SDL_RLEACCEL for my surface.

The res is 640x480; nice oldschool feel, which is exactly what I'm going for. The problem isn't that at all, though. As I've said in my post, I get a rather decent 50-60 FPS normally. When I start blitting a 50% translucent bitmap (roughly 256x64), my framerate drops quite a bit more than I'd expect it to. Especially considering I'm getting the 50-60 while blitting a full-screen bitmap. I figure the tradeoff would be pretty much the same: 640x480 bitmap vs. a 50% transluscent bitmap only roughly 5% the total area of the fullscreen bitmap.

Are you sure that that's how you're supposed to create a surface using the display's format and with transluscency/transparency? All's I get from my code is this...



Edit: Usually, I blit the (non-transluscent) border first (colorkeyed, obviously, with a hole where the transluscent bit'll go), then the transluscent, black bg (colorkeyed as well, as well as 50% transluscent). Unfortunatly, the bg is drawn over the border because color key is not in effect. Furthermore, seeing as these are two windows, the pink from the smaller one should show up through the bigger one if transluscency were enabled. It obviously isn't.

[edited by - RuneLancer on April 13, 2004 1:05:47 AM]

Share this post


Link to post
Share on other sites
Well, i tested the above code and i know it works. It's a grey background with 100x100 yellow square with a blue inset square. Transparancy works just fine, as does colorkeying.

EDIT: perhaps your key does not match? (try just plain ol' "0")

[edited by - leiavoia on April 13, 2004 1:26:56 AM]

Share this post


Link to post
Share on other sites
Nope, still doesn''t work. I read that...

"This function can be used to convert a colourkey to an alpha channel, if the SDL_SRCCOLORKEY flag is set on the surface. The generated surface will then be transparent (alpha=0) where the pixels match the colourkey, and opaque (alpha=255) elsewhere."

...but that doesn''t seem to be the case, as colorkeying doesn''t occure. I''ve also removed everything alpha-channel related (ie, the set alpha part and using SDL_DisplayFormat instead of SDL_DisplayFormatAlpha) and it works fine (just... without the alpha channel, of course).

This is pretty frustrating... It also works fine if I set the alpha channel AFTER converting, but I''d love to use the alpha blit acceleration it boasts...

Share this post


Link to post
Share on other sites
Huh, I just love this.

See, whenever I''m about to go to bed, it''s usually because I''m stuck on something and figure I''ll have better luck the next day. So whenever I''m about to throw in the towel, I end up fixing whatever problem is plaguing me.



Turns out... you have to set the alpha channel BEFORE the colorkey. Yep, it was that simple.

I get a very lovely 40-45 FPS when blitting these windows instead of the 20-25 I used to get. I''d say that''s a pretty worthwhile optimization.

Well, guess my other question would be when''s it ideal to create the surface in hardware and in software. I suppose I could probably get a dozen more FPS from careful use of that...

Share this post


Link to post
Share on other sites
hmmm... that would explain why my code worked then. I''ll have to remember that.

Share this post


Link to post
Share on other sites
I ran into an other unamusing snag this morning. There are a number of quirky things about SDL one must be careful of. This problem ended up locking up my program, in fact, and it's ridiculously simple.

I tried setting a 32bpp colorkey on a 4bpp image.

Obviously, you shouldn't do this. The only reason I did was because I copy-pasted code from my window class to a new class I was adding (to load background pictures) and didn't quite realize this until I ran the code. I tried commenting out parts of my code, then eventually found out that removing the SDL_SRCCOLORKEY flag made everything fine. That was quite a "WTF?!" moment for me until I used SDL_MapRGB (which I should've been using to begin with, actually, but since the display surface is 32bpp and I used to set the colorkey after converting; see previous posts , I figured I'd save time like that... eh...)

Bottom line: don't fuck up your pixel formats.

Edit: It works now. See?



[edited by - RuneLancer on April 13, 2004 11:59:14 AM]

Share this post


Link to post
Share on other sites

  • Advertisement