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

Reply via email to