I’m moving today (was hoping that I was making a common or obvious mistake
and so there might just be a solution waiting when I moved… hoping being
the operative), will slice my code up for posting once settled at new
address - shouldn’t be too long.
I’ve found some time now.
And, thanks to Sean Ridenour, I found out what is going on. For whatever
reason, SDL is unable to create a hardware surface for my ‘FrameBuffer’
(w.r.t. the code below), so the 78% must be the cost of trying to throw
about 47mb (in the 24bpp mode my card defaults to) across the bus every
second.
Specifically, I find that the flags member of my front surface does not have
the SDL_HWSURFACE flag set, even though SetVideoMode succeeds with the
SDL_HWSURFACE flag. Which I hadn’t thought to check.
The significant parts of my SDL code follow below. As I say, on my Celeron
533, UpdateRect is given as taking 78% of processing time. Trying the same
thing here on a Celeron 1.4 with pretty much the same graphics card gives
pretty much the same results. DXDiag claims that the graphics card on the
1.4Ghz system has 32mb “Approx. Total Memory”, and it is running in 1024x768
24bit. I therefore have no idea why I cannot get a video buffer. The card in
my 533Mhz is in the same mode but apparently only has 4mb “Approx. Total
Memory”.
I have, in the short term, removed my DirectX code entirely from the project
having had nothing but excellent reports on the Linux related SDL port of my
project. I will endeavour dearchive it and post it in the near future.
Code:
CDisplay::CDisplay()
{
DispFlags = SDL_FULLSCREEN | SDL_ANYFORMAT;
ToggleFullScreen();
}
void CDisplay::ToggleFullScreen()
{
do
{
DispFlags ^= SDL_FULLSCREEN;
if(DispFlags&SDL_FULLSCREEN)
{
FrameBuffer = SDL_SetVideoMode(800, 600, 8, DispFlags | SDL_HWPALETTE |
SDL_HWSURFACE);
if(!FrameBuffer) FrameBuffer = SDL_SetVideoMode(800, 600, 8, DispFlags |
SDL_HWPALETTE);
if(!FrameBuffer) FrameBuffer = SDL_SetVideoMode(800, 600, 8, DispFlags);
SDL_ShowCursor(SDL_DISABLE);
}
else
{
/* NB: this first DispFlags | SDL_HWSURFACE succeeds on my hardware */
FrameBuffer = SDL_SetVideoMode(640, 512, 0, DispFlags | SDL_HWSURFACE);
if(!FrameBuffer) = SDL_SetVideoMode(640, 512, 0, DispFlags);
SDL_ShowCursor(SDL_ENABLE);
/* This does happen! */
if(!(FrameBuffer->flags & SDL_HWSURFACE))
fprintf(stderr,“Warning: can’t get hardware surface\n”);
}
}
while(!FrameBuffer);
if(FrameBuffer->format->BytesPerPixel == 1)
{
SDL_Color Pal[16];
int c = 8;
while(c–)
{
Pal[c^7].r = (c&4) ? 0xff : 0;
Pal[c^7].g = (c&2) ? 0xff : 0;
Pal[c^7].b = (c&1) ? 0xff : 0;
}
SDL_SetColors(FrameBuffer, Pal, 0, 16);
}
}
void CDisplay::DrawDisplay()
{
if(!SDL_LockSurface(FrameBuffer))
{
/* draw some pixels here */
SDL_UnlockSurface(FrameBuffer);
SDL_UpdateRect(FrameBuffer, XOffset, YOffset, XOffset+640, YOffset+512);
}
}
void Go()
{
SDL_Init(SDL_INIT_EVERYTHING);
CDisplay *Disp = new CDisplay();
Uint32 FrameStart = SDL_GetTicks();
bool Quit = false;
while(!Quit)
{
/* (paired down) event management */
SDL_Event ev;
while(SDL_PollEvent(&ev))
{
switch(ev.type)
{
case SDL_QUIT : Quit = true; break;
}
}
/* there is actually processing between these in the real program, but the
point is that two frames are expected in 40ms */
Disp->DrawDisplay();
Disp->DrawDisplay();
/* timing */
Uint32 Difference = SDL_GetTicks();
Difference -= FrameStart;
Difference -= 40;
FrameStart += 40;
if(Difference < 40)
SDL_Delay(Difference);
else
if(Difference > 460)
FrameStart = SDL_GetTicks();
}
}
-Thomas