Is my computer just slow?

Hi folks,

I’ve been playing around with SDL for a few days now (on a
PII 400 with a Matrox Millennium G200 video card and a
standard redhat 7.1 setup). I’ve just been trying to set
the value of each pixel to try and find the maximum
framerate I can get by writing each pixel for each frame.

I haven’t had any trouble getting it to work, but it just
seems really slow. At 640x480x32 I can only get about 8
fps. I tried writing directly to the hardware buffer as
well as writing to a buffer in system memory and then
blitting it, but the results were about the same.

Here’s what I’m doing to plot a screenful of pixels:

for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = SDL_MapRGB(sw_surface->format,R,G,B);
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

where pscreen is a pointer to the pixel data and sw_surface
is a pointer to an SDL_Surface.

Any suggestions?

Rafe

for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = SDL_MapRGB(sw_surface->format,R,G,B);
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

where pscreen is a pointer to the pixel data and sw_surface
is a pointer to an SDL_Surface.

Any suggestions?

first: always double-check that all surfaces have the same format,
and SDL_MapRGB() is not really designed to be used in realtime
you are calling a function in a dynamic library, the function itself is
pretty generic…
just build the color outside the loop:

Uint32 color;
color = SDL_MapRGB(sw_surface->format,R,G,B);
for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = color;
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

Gautier

Gautier Portet wrote:

for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = SDL_MapRGB(sw_surface->format,R,G,B);
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

where pscreen is a pointer to the pixel data and sw_surface
is a pointer to an SDL_Surface.

Any suggestions?

first: always double-check that all surfaces have the same format,
and SDL_MapRGB() is not really designed to be used in realtime
you are calling a function in a dynamic library, the function itself is
pretty generic…
just build the color outside the loop:

Uint32 color;
color = SDL_MapRGB(sw_surface->format,R,G,B);
for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = color;
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

you could also replace

pscreen+=sw_buffer->pitch / 4 - x;
with
pscreen+=(sw_buffer->pitch>>2) - x;

since bit shifting is much faster than division/multiplication.

/Magnus

Es schrieb Magnus:

you could also replace

pscreen+=sw_buffer->pitch / 4 - x;
with
pscreen+=(sw_buffer->pitch>>2) - x;

since bit shifting is much faster than division/multiplication.

modern compilers will see divide-by-numeric-literal and replace it.
The gcc will do this even on -O0 (optimize level 0). To have this in
C source code is a myth, only assembler programmers might benefit
from replacing these things.

DON’T DO THIS.

it just makes source code harder to read.

cheers, guido

Magnus wrote:

pscreen+=sw_buffer->pitch / 4 - x;
with
pscreen+=(sw_buffer->pitch>>2) - x;

since bit shifting is much faster than division/multiplication.

no

Yes it is, but it’s the compiler’s job to optimize this.On Saturday 8. December 2001 13:46, Mattias Engdeg?rd wrote:

Magnus wrote:

pscreen+=sw_buffer->pitch / 4 - x;
with
pscreen+=(sw_buffer->pitch>>2) - x;

since bit shifting is much faster than division/multiplication.

no


Trick


Linux User #229006 * http://counter.li.org

“There is no magic.” - Nakor, magic user.

Mattias Engdeg?rd wrote:

Magnus <@mange> wrote:

pscreen+=sw_buffer->pitch / 4 - x;
with
pscreen+=(sw_buffer->pitch>>2) - x;

since bit shifting is much faster than division/multiplication.

no

timings for the pentium, in clock cycles:

DIV 17-41
IDIV 22-46
MUL 9-11

SHR SHL SAR SAL 1-3

I would actually consider this much faster, although the compiler may
optimze /4 to >> 2.

/Magnus

Magnus wrote:

I would actually consider this much faster, although the compiler may
optimze /4 to >> 2.

I don’t think a dozen cycles per scan line is “much faster”, no.

first: always double-check that all surfaces have the same format,
and SDL_MapRGB() is not really designed to be used in realtime
you are calling a function in a dynamic library, the function itself is
pretty generic…
just build the color outside the loop:

Uint32 color;
color = SDL_MapRGB(sw_surface->format,R,G,B);
for(y=0;y<HEIGHT;y++)
{
for(x=0;x<WIDTH;x++)
{
*pscreen = color;
pscreen++;
}
pscreen+=sw_buffer->pitch / 4 - x;
}

Gautier

Thanks everybody for your help. Gautier’s suggestion ended
up more than doubling the frame rate. THe problem is, what
if I wanted to write pixel values as a function of x,y, and
time? Then I still have to call SDL_MapRGB in the inner
loop there or else build a huge 3D lookup table which
doesn’t sound very appealing. If I check the pixel format
beforehand, I suppose I could write my own My_MapRGB to
build up a color value depending on bpp and endianness of
the target machine. Does that sound like the best way to do
it?

Thanks again,

Rafe

Rafe Thayer wrote:

If I check the pixel format
beforehand, I suppose I could write my own My_MapRGB to
build up a color value depending on bpp and endianness of
the target machine.

That’s how it’s usually done; you write code by hand for the most
important cases (your own hardware, and other formats in common use)
and provide a generic fallback solution for the rest. MapRGB/GetRGB are
mostly convenience functions; they aren’t really meant to be used in
an inner loop