On Tue, Oct 31, 2000 at 01:59:37PM -0800, Jon M. Taylor wrote:
> On Mon, 30 Oct 2000, beef wrote:
>
> > On Sat, 28 Oct 2000, Jon M. Taylor wrote:
> > It kindof works, but flickers horribly on the fbdev.
>
> > what/where _could_ this doublebuffer problem be?
>
> So, I did a QuickHack(tm) to work around the problem - I pointed
> both buffers to the ggi_visual |->. This let me render to either the
> front or back buffer, mapped to either hardware or software
> front/backbuffers, with or without hardware acceleration for both drawing
> triangles and the page flips. As you have seen it also causes horrible
> flickering. But it "worked" and at the time that was all I was interested
> in. The hack was never meant to be more than a stopgap until I figured
> out how to do it all properly. Unfortunately, there wasn't much in the
> way of buffer management API cut-ins in Mesa at the time, so it turned out
> to be more work than I had anticipated, and a few weeks later my Savage4
> driver project got canned and I stopped working on GGIMesa except for the
> occasional build fixes to keep up with the changing Mesa internals.
At that time I found that using a main loop looking like this does sort of
proper double-buffering using GGIMesa. Note that the SetMode call sets the
virtual width to twice the physical width.
int main(int argc, char *argv[])
{
int wid=800, hei=600;
ggi_visual_t vis;
if(ggiInit()) {
fprintf(stderr, "Can't initialize ggi.\n");
return EXIT_FAILURE;
}
vis = ggiOpen(NULL);
ggiSetFlags(vis, GGIFLAG_ASYNC);
if(!vis) {
fprintf(stderr, "Can't open default ggi target.\n");
ggiExit();
return EXIT_FAILURE;
}
if(ggiSetGraphMode(vis, wid, hei, 2*wid, hei, 0) < 0) {
fprintf(stderr, "Can't set mode on ggi visual.\n");
ggiClose(vis);
ggiExit();
return EXIT_FAILURE;
}
GGIMesaContext ctx = GGIMesaCreateContext();
GGIMesaSetVisual(ctx, vis, true, false);
GGIMesaMakeCurrent(ctx);
Initialize();
for(;;) {
draw();
static bool first=true;
glFlush();
glFinish();
ggiFlush(vis);
ggiSetOrigin(vis, first ? 0 : wid,0);
reshape(first ? wid : 0,0,wid,hei);
glClear(GL_DEPTH_BUFFER_BIT);
ggiDrawBox(vis, first ? wid : 0,0,wid,hei);
first=!first;
}
return EXIT_SUCCESS;
}
The reshape call takes four parameters (x,y,width,height), and sets the GL viewport
to draw in that area only. It can look like this:
static void reshape(int x, int y, int width, int height)
{
GLfloat h = (GLfloat) height / (GLfloat) width;
glViewport((GLint) x, (GLint) y, (GLint) width, (GLint) height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
glTranslatef(0.0, 0.0, -7.0);
glMatrixMode(GL_MODELVIEW);
}
This can still flicker a bit as the ggiSetOrigin() call isn't synchronized with the
physical display rate. This synchronization needs support for the (fb|KGI)con driver.
(It wasn't synchronized at the time I made this, maybe it is now?)
I think something like this should me added to GGIMesa. Let the application set up
the display (using GGI) and tell GGIMesa to draw into an area of a frame. Let GGI
deal with double-buffering. All GGIMesa needs to do is allow changing of what frame
to draw into, and what area of it.
--
Niklas