/*
 * $Id: $ 
 */

/*
 * Mesa 3-D graphics library
 * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * $Log:  $
 */

/*
 * TODO:
 * Dynamic allocate the vectorbuffer for polydrawing. (memory improvment)
 * implement shared list.
 * fix resizing bug.
 * some native asm rutine
 * fast asm line drawin in db mode
 * fast asm clear       in db mode
 * read buffer rutines  in db-mode
 * 
 * IDEAS:
 */

#include <stdlib.h>
#include <stdio.h>
#include <gl/gl.h>
#include "context.h"
#include "dd.h"
#include "xform.h"
#include "macros.h"
#include "types.h"
#include "vb.h"

#include <AOS/amigamesa.h>

static void cybStandardResize(GLcontext *ctx, GLuint * width, GLuint * height);
static void cybStandardResizeDB(GLcontext *ctx, GLuint * width, GLuint * height);

/**********************************************************************/
/*****                  amiga/Mesa private misc procedures        *****/
/**********************************************************************/

static void MyWritePixelArray(void *a, int b, int c, int d, struct RastPort *e, int f, int g, int h, int i, int j)
{
  WritePixelArray(a, b, c, d, e, f, g, h, i, j);
}

static void MyWriteRGBPixel(void *a, int b, int c, int d, struct RastPort *e, int f, int g, int h, int i, int j)
{
  WritePixelArray(a, b, c, d, e, f, g, h, i, j);
}

static void MyReadPixelArray(void *a, ULONG b, ULONG c, ULONG d, struct RastPort *e, ULONG f, ULONG g, ULONG h, ULONG i, ULONG j)
{
  ReadPixelArray(a, b, c, d, e, f, g, h, i, j);
}

/**********************************************************************/
/*****                Miscellaneous device driver funcs           *****/
/**********************************************************************/

static const char *cybRendererString(void)
{
  return "CyberGraphX standard\n";
}

static const char *cybRendererStringDB(void)
{
  return "CyberGraphX fast\n";
}

static void cybClearIndex(GLcontext *ctx, GLuint index)
{
  /*
   * implement glClearIndex 
   * usually just save the value in the context struct 
   */
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybClearIndex(%d)\n", index);

  amesa->clearpixel = amesa->penconv[index];
}

static void cybClearColor(GLcontext *ctx,
			  GLubyte r, GLubyte g, GLubyte b, GLubyte a)
{
  /*
   * implement glClearColor 
   * color components are floats in [0,1] 
   * usually just save the value in the context struct 
   */
  /*
   * @@@ TODO FREE COLOR IF NOT USED 
   */
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybClearColor(%d, %d, %d, %d)\n", r, g, b, a);

  if (amesa->depth > 8)
    amesa->clearpixel = TC_RGBA(r, g, b);
  else
    amesa->clearpixel = PL_RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b);
}

static GLbitfield cybClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
			   GLint x, GLint y, GLint width, GLint height)
{
  /*
   * Clear the specified region of the color buffer using the clear color
   * or index as specified by one of the two functions above.
   * If all==GL_TRUE, clear whole buffer
   */
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybClear(%d, %d, %d, %d, %d)\n", all, x, y, width, height);

  if (all) {
    struct gl_viewport_attrib *vport = &ctx->Viewport;

    DEBUGOUT(2, " FillPixelArray(%d,%d,%d,%d);\n",
	     FIXx(vport->X),
	     FIXy(vport->Y) - vport->Height,
	     FIXx(vport->X) + vport->Width - 1,
	     FIXy(vport->Y) - 1);

    FillPixelArray(amesa->rp,
		   FIXx(vport->X),
		   FIXy(vport->Y) - vport->Height,
		   vport->Width,
		   vport->Height,
		   amesa->clearpixel >> 8);
  }
  else {
    if (amesa->rp != 0) {
      DEBUGOUT(2, " FillPixelArray(%d,%d,%d,%d);\n",
	       FIXx(x),
	       FIXy(y) - height,
	       FIXx(x) + width - 1,
	       FIXy(y) - 1);

      FillPixelArray(amesa->rp, FIXx(x),
				FIXy(y) - height,
				width,
				height,
				amesa->clearpixel >> 8);
    }
    else
      printf("Serius error amesa->rp=0 detected in cybClear() in file cybmesa.c\n");
  }

  return mask & (~GL_COLOR_BUFFER_BIT);
}

static GLbitfield cybClearDB(GLcontext *ctx, GLbitfield mask, GLboolean all,
			     GLint x, GLint y, GLint width, GLint height)
{
  /*
   * Clear the specified region of the color buffer using the clear color
   * or index as specified by one of the two functions above.
   * If all==GL_TRUE, clear whole buffer
   */
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  register ULONG *db;
  register ULONG col = amesa->clearpixel;

  DEBUGOUT(1, "cybClearDB(%d, %d, %d, %d, %d)\n", all, x, y, width, height);

  if (all) {
    int size = (amesa->RealWidth * amesa->RealHeight) - 1;

    db = ((ULONG *)amesa->BackArray);
    while(size-- >= 0) {
      *db++ = col;
    }
  }
  else {
    int x1, y1, x2, y2, last;

    x = FIXx(x);
    y2 = FIXy(y);
    x2 = x + width;
    last = amesa->RealWidth - (x2 - x);
    y = y2 - height;
    db = ((ULONG *)amesa->BackArray) + (y * amesa->RealWidth) + x;

    for (y1 = y; y1 < y2; y1++) {
      for (x1 = x; x1 < x2; x1++) {
	*db++ = col;
      }
      db += last;
    }
  }

  return mask & (~GL_COLOR_BUFFER_BIT);
}

static void cybSetIndex(GLcontext *ctx, GLuint index)
{
  /*
   * Set the amesa color index. 
   */
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybSetIndex(%d)\n", index);

  amesa->pixel = amesa->penconv[(unsigned char)index];
}

static void cybSetColor(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a)
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybSetColor(%d, %d, %d, %d)\n", r, g, b, a);

  /*
   * Set the current RGBA color. 
   * r is in 0..255.RedScale 
   * g is in 0..255.GreenScale 
   * b is in 0..255.BlueScale 
   * a is in 0..255.AlphaScale 
   */
  if (amesa->depth > 8)
    amesa->pixel = TC_RGBA(r, g, b);
  else
    amesa->pixel = PL_RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b);
}

static GLboolean cybIndexMask(GLcontext *ctx, GLuint mask)
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  DEBUGOUT(1, "cybIndexMask(0x%x)\n", mask);

  /*
   * implement glIndexMask if possible, else return GL_FALSE 
   */
  amesa->rp->Mask = (unsigned char) mask;

  return (GL_TRUE);
}

static GLboolean cybColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
			      GLboolean bmask, GLboolean amask)
{
  /*
   * implement glColorMask if possible, else return GL_FALSE 
   */
  return (GL_FALSE);
}

/**********************************************************************/
/*****            Accelerated point, line, polygon rendering      *****/
/**********************************************************************/

/*
 *  Render a number of points by some hardware/OS accerated method
 */

static void cybFastPointsFunction(GLcontext *ctx, GLuint first, GLuint last)
{

  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  struct vertex_buffer *VB = ctx->VB;
  int i;
  register struct RastPort *rp = amesa->rp;

  DEBUGOUT(1, "cybFastPointsFunction: ");

  if (VB->MonoColor) {
    /*
     * draw all points using the current color (setColor) 
     */
    DEBUGOUT(1, "VB->MonoColor\n");
    for (i = first; i <= last; i++) {
      if (!VB->ClipMask[i]) {
	/*
	 * compute window coordinate 
	 */
	int x, y;

	x = FIXx((GLint) (VB->Win[i][0]));
	y = FIXy((GLint) (VB->Win[i][1]));
	WriteRGBPixel(rp, x, y, amesa->pixel >> 8);
	DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
  else {
    /*
     * each point is a different color 
     */
    DEBUGOUT(1, "!VB.MonoColor\n");
    for (i = first; i <= last; i++) {
      if (!VB->ClipMask[i]) {
	int x, y;

	x = FIXx((GLint) (VB->Win[i][0]));
	y = FIXy((GLint) (VB->Win[i][1]));
	WriteRGBPixel(rp, x, y, (*VB->Color[i]) >> 8);
	DEBUGOUT(3, " WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
}

static points_func cybChoosePointsFunction(GLcontext *ctx)
{
  DEBUGOUT(1, "cybChoosePointsFunction\n");
  /*
   * Examine the current rendering state and return a pointer to a 
   * fast point-rendering function if possible. 
   */
  if (ctx->Point.Size == 1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask == 0
      && !ctx->Texture.Enabled					/*
								 * &&  ETC, ETC 
								 */ ) {
    return cybFastPointsFunction;
  }
  else {
    return NULL;
  }
}

static points_func cybChoosePointsFunctionDB(GLcontext *ctx)
{
  return NULL;
}

 /*
  *  Render a line by some hardware/OS accerated method 
  */

static line_func cybChooseLineFunction(GLcontext *ctx)
{
  DEBUGOUT(1, "cybChooseLineFunction\n");
  /*
   * Examine the current rendering state and return a pointer to a 
   * fast line-rendering function if possible. 
   */

  return NULL;
}

static line_func cybChooseLineFunctionDB(GLcontext *ctx)
{
  return NULL;
}

/**********************************************************************/
/*****                  Optimized polygon rendering               *****/
/**********************************************************************/

/*
 * Draw a filled polygon of a single color. If there is hardware/OS support
 * for polygon drawing use that here.   Otherwise, call a function in
 * polygon.c to do the drawing.
 */

static triangle_func cybChooseTriangleFunction(GLcontext *ctx)
{
  DEBUGOUT(1, "cybChooseTriangleFunction\n");
  /*
   * Examine the current rendering state and return a pointer to a 
   * fast polygon-rendering function if possible. 
   */
  return NULL;
}

static triangle_func cybChooseTriangleFunctionDB(GLcontext *ctx)
{
  return NULL;
}

/**********************************************************************/
/*****        write spans of RGBA pixels                          *****/
/**********************************************************************/

/* Write RGBA pixels to an RGBA (or permuted) buffer. */
static void cybWriteRGBASpan(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			     CONST GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  ULONG *dp;
  struct RastPort *rp = amesa->rp;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybWriteRGBASpan(%d, %d, %d): ", n, x, y);

  if (!mask) {
    DEBUGOUT(1, "nomask\n");
    MyWritePixelArray(rgba, 0, 0, 4 * n, rp, x, y, n, 1, RECTFMT_RGBA);
    DEBUGOUT(2, " WritePixelArray(%d, %d, %d)\n", n, x, y);
  }
  else if ((dp = (ULONG *) amesa->imageline)) {			/* if imageline allocated then use fastversion */
    int i, ant;

    DEBUGOUT(1, "mask FAST\n");

    ant = 0;
    for (i = 0; i < n; i++) {					/* draw pixel (x[i],y[i]) */
      if (*mask++) {
	ant++;
	*dp++ = *((ULONG *) & rgba[i][0]);
      }
      else {
	if (ant) {
	  MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
	  DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
	  dp = (ULONG *) amesa->imageline;
	  x += ant;
	  ant = 0;
	}
	else
	  x++;
      }
    }

    if (ant) {
      MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
      DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
    }
  }
  else {							/* Slower version */
    int i;

    DEBUGOUT(1, "mask SLOW\n");

    /* draw some pixels */
    for (i = 0; i < n; i++, x++) {
      if (*mask++) {
	/* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */
	WriteRGBPixel(rp, x, y, (*((ULONG *)&rgba[i][0]) >> 8));
	DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
}

/* Write RGB pixels to an RGBA (or permuted) buffer. */
static void cybWriteRGBSpan(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			    CONST GLubyte rgb[][3], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  ULONG *dp;
  struct RastPort *rp = amesa->rp;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybWriteRGBSpan(%d, %d, %d): ", n, x, y);

  if (!mask) {
    DEBUGOUT(1, "nomask\n");
    MyWritePixelArray(rgb, 0, 0, 3 * n, rp, x, y, n, 1, RECTFMT_RGB);
    DEBUGOUT(2, " WritePixelArray(%d, %d, %d)\n", n, x, y);
  }
  else if ((dp = (ULONG *) amesa->imageline)) {			/* if imageline allocated then use fastversion */
    int i, ant;

    DEBUGOUT(1, "mask FAST\n");

    ant = 0;
    for (i = 0; i < n; i++) {					/* draw pixel (x[i],y[i]) */
      if (*mask++) {
	ant++;
	*dp++ = *((ULONG *) & rgb[i][0]) & 0xFFFFFF00;
      }
      else {
	if (ant) {
	  MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
	  DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
	  dp = (ULONG *) amesa->imageline;
	  x += ant;
	  ant = 0;
	}
	else
	  x++;
      }
    }

    if (ant) {
      MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
      DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
    }
  }
  else {							/* Slower version */
    int i;

    DEBUGOUT(1, "mask SLOW\n");

    /* draw some pixels */
    for (i = 0; i < n; i++, x++) {
      if (*mask++) {
	/* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */
	WriteRGBPixel(rp, x, y, (*((ULONG *) & rgb[i][0]) >> 8));
	DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
}

static void cybWriteCI32Span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			     const GLuint index[],
			     const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i, ant;
  ULONG *dp;
  unsigned long *penconv = amesa->penconv;
  register struct RastPort *rp = amesa->rp;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybWriteCI32Span(%d, %d, %d)\n", n, x, y);

#if 0
  if (!mask) {
    WriteLUTArray
  } else
#endif
  if ((dp = (ULONG *) amesa->imageline)) {
    /*
     * if imageline have been
     * allocated then use fastversion 
     */
    ant = 0;
    for (i = 0; i < n; i++) {
      /* draw pixel (x[i],y[i]) using index[i] */
      if (*mask++) {
	ant++;
	*dp++ = penconv[(unsigned char)index[i]];
	DEBUGOUT(4, "   index[%d] = 0x%lx\n", i, index[i]);
      }
      else {
	if (ant) {
	  MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
	  DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
	  dp = (ULONG *) amesa->imageline;
	  x += ant;
	  ant = 0;
	}
	else
	  x++;
      }
    }

    if (ant) {
      MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
      DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
    }
  }
  else {
    /* Slower */
    for (i = 0; i < n; i++, x++) {
      if (*mask++) {
	/* draw pixel (x[i],y[i]) using index[i] */
	WriteRGBPixel(rp, x, y, penconv[(unsigned char)index[i]] >> 8);
	DEBUGOUT(4, "   index[%d] = 0x%lx\n", i, index[i]);
	DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
}

static void cybWriteCI8Span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			    const GLubyte index[],
			    const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i, ant;
  ULONG *dp;
  unsigned long *penconv = amesa->penconv;
  register struct RastPort *rp = amesa->rp;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybWriteCI8Span(%d, %d, %d)\n", n, x, y);

#if 0
  if (!mask) {
    WriteLUTArray
  } else
#endif
  if ((dp = (ULONG *) amesa->imageline)) {
    /*
     * if imageline have been
     * allocated then use fastversion 
     */
    ant = 0;
    for (i = 0; i < n; i++) {
      /* draw pixel (x[i],y[i]) using index[i] */
      if (*mask++) {
	ant++;
	*dp++ = penconv[(unsigned char)index[i]];
      }
      else {
	if (ant) {
	  MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
	  DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
	  dp = (ULONG *) amesa->imageline;
	  x += ant;
	  ant = 0;
	}
	else
	  x++;
      }
    }
    if (ant) {
      MyWritePixelArray(amesa->imageline, 0, 0, 4 * ant, rp, x, y, ant, 1, RECTFMT_RGBA);
      DEBUGOUT(3, "  WritePixelArray(%d, %d, %d)\n", ant, x, y);
    }
  }
  else {
    /* Slower */
    for (i = 0; i < n; i++, x++) {
      if (*mask++) {
	/* draw pixel (x[i],y[i]) using index[i] */
	WriteRGBPixel(rp, x, y, penconv[(unsigned char)index[i]] >> 8);
	DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", x, y);
      }
    }
  }
}

static void cybWriteMonoCISpan(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i, j;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybWriteMonoCISpan(%d, %d, %d)\n", n, x, y);

  i = 0;

  while (i < n) {
    while (!*mask++ && i < n) {
      i++;
      x++;
    }

    if (i < n) {
      j = 0;
      while (*mask++ && i < n) {
	i++;
	j++;
      }
      FillPixelArray(amesa->rp, x, y, j, 1, amesa->pixel >> 8);
      DEBUGOUT(3, "  FillPixelArray(%d, %d, %d)\n", j, x, y);
    }
  }
}

/**********************************************************************/
/*****        write spans of RGBA pixels doublebuffered           *****/
/**********************************************************************/

static void cybWriteRGBASpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			       CONST GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;

  DEBUGOUT(1, "cybWriteRGBASpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = &((ULONG *) amesa->BackArray)[FIXxy(x, y)];

  /* Slower */
  if (mask) {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = 0; i < n; i++) {
      if (*mask++) {
	*db = *((ULONG *)&rgba[i][0]);
      }
      db++;
    }
  }
  else {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = n - 1; i >= 0; i--)
      *db++ = *((ULONG *)rgba)++;
  }
}

static void cybWriteRGBSpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			      CONST GLubyte rgb[][3], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;

  DEBUGOUT(1, "cybWriteRGBSpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = &((ULONG *) amesa->BackArray)[FIXxy(x, y)];

  /* Slower */
  if (mask) {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = 0; i < n; i++) {
      if (*mask++) {
	*db = *((ULONG *) & rgb[i][0]) & 0xFFFFFF00;
      }
      db++;
    }
  }
  else {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = 0; i < n; i++) {
      *db++ = *((ULONG *)&rgb[i][0]) & 0xFFFFFF00;
    }
  }
}

static void cybWriteCI32SpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			       const GLuint index[],
			       const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;
  register unsigned long *penconv = amesa->penconv;

  DEBUGOUT(1, "cybWriteCI32SpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = &((ULONG *) amesa->BackArray)[FIXxy(x, y)];

  /* Slower */
  if (mask) {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = 0; i < n; i++) {
      if (*mask++) {
	*db = penconv[(unsigned char)index[i]];
	DEBUGOUT(4, "   index[%d] = 0x%lx\n", i, index[i]);
      }
      db++;
    }
  }
  else {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = n - 1; i >= 0; i--) {
      DEBUGOUT(4, "   index[%d] = 0x%lx\n", n - i + 1, *index);
      *db++ = penconv[(unsigned char)*index++];
    }
  }
}

static void cybWriteCI8SpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			      const GLubyte index[],
			      const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;
  register unsigned long *penconv = amesa->penconv;

  DEBUGOUT(1, "cybWriteCI8SpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = &((ULONG *) amesa->BackArray)[FIXxy(x, y)];

  /* Slower */
  if (mask) {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = 0; i < n; i++) {
      if (*mask++) {
	*db = penconv[(unsigned char)index[i]];
      }
      db++;
    }
  }
  else {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = n - 1; i >= 0; i--) {
      *db++ = penconv[(unsigned char)*index++];
    }
  }
}

static void cybWriteMonoCISpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;

  DEBUGOUT(1, "cybWriteMonoCISpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = &((ULONG *)amesa->BackArray)[FIXxy(x, y)];

  /* Slower */
  if (mask) {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = n - 1; i >= 0; i--) {
      if (*mask++) {
	*db = amesa->pixel;
      }
      db++;
    }
  }
  else {
    /* draw pixel (x[i],y[i]) using index[i] */
    for (i = n - 1; i >= 0; i--)
      *db++ = amesa->pixel;
  }
}

/**********************************************************************/
/*****        read spans of RGBA pixels                           *****/
/**********************************************************************/
/* Here we should check if the size of the colortable is <256 */

static void cybReadRGBASpan(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			    GLubyte rgba[][4])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybReadRGBASpan(%d, %d, %d)\n", n, x, y);

  MyReadPixelArray(rgba, 0, 0, n * 4, amesa->rp, x, y, n, 1, RECTFMT_RGBA);
  DEBUGOUT(2, " ReadPixelArray(%d, %d, %d)\n", n, x, y);
}

static void cybReadCI32Span(const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint index[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  register ULONG *db;

  y = FIXy(y);
  x = FIXx(x);
  DEBUGOUT(1, "cybReadCI32Span(%d, %d, %d)\n", n, x, y);

  /*  Currently this is wrong RGBA-values are NO indexes !!! */
  if ((db = (ULONG *)amesa->imageline)) {
    int i;

    MyReadPixelArray(db, 0, 0, 4 * n, amesa->rp, x, y, n, 1, RECTFMT_RGBA);
    DEBUGOUT(3, "  ReadPixelArray(%d, %d, %d)\n", n, x, y);
    for (i = n - 1; i >= 0; i--) {
      ULONG col = *db++;
      *index++ = PL_RGBA((unsigned char)(col >> 24),
			 (unsigned char)(col >> 16),
			 (unsigned char)(col >>  8));
    }
  }
  else {
    int i;

    for (i = n - 1; i >= 0; i--) {
      ULONG col = ReadRGBPixel(amesa->rp, x++, y);
      DEBUGOUT(3, "  ReadRGBPixel(%d, %d)\n", x - 1, y);
      *index++ = PL_RGBA((unsigned char)(col >> 24),
			 (unsigned char)(col >> 16),
			 (unsigned char)(col >>  8));
    }
  }
}

/**********************************************************************/
/*****        read spans of RGBA pixels doublebuffered            *****/
/**********************************************************************/

static void cybReadRGBASpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y,
			        GLubyte rgba[][4])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;

  DEBUGOUT(1, "cybReadRGBASpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = ((ULONG *)amesa->BackArray) + FIXxy(x, y);
  for (i = n - 1; i >= 0; i--)
    *((ULONG *)rgba)++ = *db++;
}

static void cybReadCI32SpanDB(const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint index[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register ULONG *db;
  ULONG col;

  DEBUGOUT(1, "cybReadCI32SpanDB(%d, %d, %d)\n", n, FIXx(x), FIXy(y));

  db = ((ULONG *)amesa->BackArray) + FIXxy(x, y);

  for (i = n - 1; i >= 0; i--) {
    col = *db++;
    *index++ = PL_RGBA((unsigned char)(col >> 24),
		       (unsigned char)(col >> 16),
		       (unsigned char)(col >>  8));
  }
}

/**********************************************************************/
/*****        write arrays of RGBA pixels                         *****/
/**********************************************************************/

static void cybWriteRGBAPixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			       CONST GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register struct RastPort *rp = amesa->rp;

  DEBUGOUT(1, "cybWriteRGBAPixels(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      /*
       * write pixel x[i], y[i] using red[i],green[i],blue[i],alpha[i] 
       */
      WriteRGBPixel(rp, FIXx(x[i]), FIXy(y[i]), (*((ULONG *)&rgba[i][0]) >> 8));
      DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", FIXx(x[i]), FIXy(y[i]));
    }
  }
}

static void cybWriteCI32Pixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			       const GLuint index[], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  register unsigned long *penconv = amesa->penconv;
  int i;
  register struct RastPort *rp = amesa->rp;

  DEBUGOUT(1, "cybWriteCI32Pixels(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      WriteRGBPixel(rp, FIXx(x[i]), FIXy(y[i]), penconv[(unsigned char)index[i]] >> 8);
      DEBUGOUT(4, "   index[%d] = 0x%lx\n", i, index[i]);
      DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", FIXx(x[i]), FIXy(y[i]));
    }
  }
}

static void cybWriteMonoCIPixels(const GLcontext *ctx, GLuint n,
				 const GLint x[], const GLint y[],
				 const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register struct RastPort *rp = amesa->rp;

  DEBUGOUT(1, "cybWriteMonoCIPixels(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      /* write pixel x[i], y[i] using current index */
      WriteRGBPixel(rp, FIXx(x[i]), FIXy(y[i]), amesa->pixel >> 8);
      DEBUGOUT(3, "  WriteRGBPixel(%d, %d)\n", FIXx(x[i]), FIXy(y[i]));
    }
  }
}

/**********************************************************************/
/*****        write arrays of RGBA pixels doublebuffered          *****/
/**********************************************************************/

static void cybWriteRGBAPixelsDB(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
				 CONST GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;

  DEBUGOUT(1, "cybWriteRGBAPixelsDB(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      ((ULONG *)amesa->BackArray)[FIXxy(x[i], y[i])] = *((ULONG *)&rgba[i][0]);
    }
  }
}

static void cybWriteCI32PixelsDB(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
				 const GLuint index[], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  register unsigned long *penconv = amesa->penconv;
  int i;

  DEBUGOUT(1, "cybWriteCI32PixelsDB(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      ((ULONG *)amesa->BackArray)[FIXxy(x[i], y[i])] = penconv[(unsigned char)index[i]];
      DEBUGOUT(4, "   index[%d] = 0x%lx\n", i, index[i]);
    }
  }
}

static void cybWriteMonoCIPixelsDB(const GLcontext *ctx, GLuint n,
				   const GLint x[], const GLint y[],
				   const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;

  DEBUGOUT(1, "cybWriteMonoCIPixelsDB(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      ((ULONG *)amesa->BackArray)[FIXxy(x[i], y[i])] = amesa->pixel;
    }
  }
}

/**********************************************************************/
/*****        read arrays of RGBA pixels                          *****/
/**********************************************************************/
/* Read an array of color index pixels. */

static void cybReadRGBAPixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			      GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register struct RastPort *rp = amesa->rp;

  DEBUGOUT(1, "cybReadRGBAPixels(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      *((ULONG *)&rgba[i][0]) = ReadRGBPixel(rp, FIXx(x[i]), FIXy(y[i])) << 8;
      DEBUGOUT(3, "  ReadRGBPixel(%d, %d)\n", FIXx(x[i]), FIXy(y[i]));
    }
  }
}

static void cybReadCI32Pixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			      GLuint index[], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  register struct RastPort *rp = amesa->rp;
  ULONG col;

  DEBUGOUT(1, "cybReadCI32Pixels(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      /* index[i] = read_pixel x[i], y[i] */
      col = ReadRGBPixel(rp, FIXx(x[i]), FIXy(y[i]));
      DEBUGOUT(3, "  ReadRGBPixel(%d, %d)\n", FIXx(x[i]), FIXy(y[i]));
      index[i] = PL_RGBA((unsigned char)(col >> 24),
			 (unsigned char)(col >> 16),
			 (unsigned char)(col >>  8));
    }
  }
}

/**********************************************************************/
/*****        read arrays of RGBA pixels doublebuffered           *****/
/**********************************************************************/

static void cybReadRGBAPixelsDB(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			        GLubyte rgba[][4], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;

  DEBUGOUT(1, "cybReadRGBAPixelsDB(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      *((ULONG *)&rgba[i][0]) = ((ULONG *)amesa->BackArray)[FIXxy(x[i], y[i])];
    }
  }
}

static void cybReadCI32PixelsDB(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
			        GLuint index[], const GLubyte mask[])
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;
  int i;
  ULONG col;

  DEBUGOUT(1, "cybReadCI32PixelsDB(%d)\n", n);

  for (i = 0; i < n; i++) {
    if (*mask++) {
      /* index[i] = read_pixel x[i], y[i] */
      col = ((ULONG *)amesa->BackArray)[FIXxy(x[i], y[i])];
      index[i] = PL_RGBA((unsigned char)(col >> 24),
			 (unsigned char)(col >> 16),
			 (unsigned char)(col >>  8));
    }
  }
}

/**********************************************************************/
/**********************************************************************/

static GLboolean cybSetBuffer(GLcontext *ctx, GLenum mode)
{
  /*
   * set the current drawing/reading buffer, return GL_TRUE or GL_FALSE 
   * for success/failure 
   *
   * TODO implemed a set of buffers 
   */

  if (mode == GL_FRONT) {
    return (GL_TRUE);
  }
  else if (mode == GL_BACK) {
    return (GL_TRUE);
  }
  else {
    return (GL_FALSE);
  }
}

/**********************************************************************/
/*****                  amiga/Mesa private init/despose/resize       *****/
/**********************************************************************/

static void cybStandardResize(GLcontext *ctx, GLuint *width, GLuint *height)
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  *width = amesa->width;
  *height = amesa->height;
  DEBUGOUT(1, "cybStandardResize(%d, %d\n", *width, *height);

  if (!((amesa->width == (amesa->front_rp->Layer->bounds.MaxX - amesa->front_rp->Layer->bounds.MinX + 1 - amesa->left - amesa->right)) &&
	(amesa->height == (amesa->front_rp->Layer->bounds.MaxY - amesa->front_rp->Layer->bounds.MinY + 1 - amesa->bottom - amesa->top)))) {
    FreeOneLine(amesa);

    amesa->FixedWidth = amesa->RealWidth = amesa->front_rp->Layer->bounds.MaxX - amesa->front_rp->Layer->bounds.MinX + 1;
    amesa->FixedHeight = amesa->RealHeight = amesa->front_rp->Layer->bounds.MaxY - amesa->front_rp->Layer->bounds.MinY + 1;

    *width = amesa->width = amesa->RealWidth - amesa->left - amesa->right;
    *height = amesa->height = amesa->RealHeight - amesa->bottom - amesa->top;
    amesa->depth = GetCyberMapAttr(amesa->front_rp->BitMap, CYBRMATTR_DEPTH);
    DEBUGOUT(2, " Resize(%d, %d)\n", *width, *height);

    if (amesa->depth <= 8) {
      destroyTempRaster(amesa->rp);				/*  deallocate temp raster  */
      freeTempRPort(amesa);
    }

    if (amesa->visual->db_flag) {
      if (amesa->back_rp) {					/* Free double buffer */
	destroyRPort(amesa->back_rp);
      }
      if ((amesa->back_rp = makeRPort(amesa->RealWidth, amesa->RealHeight, amesa->depth, amesa->rp->BitMap)) == NULL) {
	amesa->rp = amesa->front_rp;
	printf("To little mem free. Couldn't allocate Dubblebuffer in this size.\n");
      }
      else {
	amesa->rp = amesa->back_rp;
      }
    }

    if (amesa->depth <= 8) {
      if (!makeTempRaster(amesa->rp))
        printf("Error allocating TmpRasterPort\n");
      allocTempRPort(amesa);
    }

    AllocOneLine(amesa);
  }
}

static void cybStandardResizeDB(GLcontext *ctx, GLuint * width, GLuint * height)
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  *width = amesa->width;
  *height = amesa->height;
  DEBUGOUT(1, "cybStandardResizeDB(%d, %d\n", *width, *height);

  if (!((amesa->width == (amesa->rp->Layer->bounds.MaxX - amesa->rp->Layer->bounds.MinX + 1 - amesa->left - amesa->right)) &&
	(amesa->height == (amesa->rp->Layer->bounds.MaxY - amesa->rp->Layer->bounds.MinY + 1 - amesa->bottom - amesa->top)))) {
    amesa->RealWidth = amesa->rp->Layer->bounds.MaxX - amesa->rp->Layer->bounds.MinX + 1;
    amesa->RealHeight = amesa->rp->Layer->bounds.MaxY - amesa->rp->Layer->bounds.MinY + 1;
    amesa->FixedWidth = (amesa->RealWidth + 3) & 0xfffffffc;
    amesa->FixedHeight = amesa->RealHeight;

    *width = amesa->width = amesa->RealWidth - amesa->left - amesa->right;
    *height = amesa->height = amesa->RealHeight - amesa->bottom - amesa->top;
    amesa->depth = GetCyberMapAttr(amesa->rp->BitMap, CYBRMATTR_DEPTH);
    DEBUGOUT(2, " Resize(%d, %d)\n", *width, *height);

    if (amesa->visual->db_flag && amesa->BackArray) {
      destroyPenBackArray(amesa->BackArray);
      if (!(amesa->BackArray = allocPenBackArray(amesa->RealWidth, amesa->RealHeight, 4))) {
	printf("amigaMesa Error Can't allocate new PenArray in that size.\n");
	/*  amigaStandard_init(amesa); */
      }
    }

    if (amesa->depth <= 8)
      allocTempRPort(amesa);

    DEBUGOUT(1, " amesa->RealWidth =%d\n", amesa->RealWidth);
    DEBUGOUT(1, " amesa->RealHeight=%d\n", amesa->RealHeight);
    DEBUGOUT(1, " amesa->width =%d\n", amesa->width);
    DEBUGOUT(1, " amesa->height=%d\n", amesa->height);
    DEBUGOUT(1, " amesa->left  =%d\n", amesa->left);
    DEBUGOUT(1, " amesa->bottom=%d\n", amesa->bottom);
    DEBUGOUT(1, " amesa->right =%d\n", amesa->right);
    DEBUGOUT(1, " amesa->top   =%d\n", amesa->top);
    DEBUGOUT(1, " amesa->depth =%d\n", amesa->depth);
  }
}

static void cybStandardSwapBufferDB(struct amigamesa_context *amesa)
{
  struct gl_viewport_attrib *vport = &amesa->gl_ctx->Viewport;

  DEBUGOUT(1, "cybStandardSwapBufferDB\n");
  DEBUGOUT(2, " WritePixelArray(%d,%d,%d,%d);\n",
	   FIXx(vport->X),
	   FIXy(vport->Y) - vport->Height,
	   FIXx(vport->X) + vport->Width - 1,
	   FIXy(vport->Y) - 1);

  if (amesa->depth > 8) {
    MyWritePixelArray(amesa->BackArray,
		      vport->X,
		      amesa->RealHeight - vport->Height - vport->Y,
		      amesa->RealWidth * 4,
		      amesa->rp,
		      FIXx(vport->X),
		      FIXy(vport->Y) - vport->Height,
		      vport->Width,
		      vport->Height,
		      RECTFMT_RGBA);
  }
  else {
    MyWritePixelArray(amesa->BackArray,
		      vport->X,
		      amesa->RealHeight - vport->Height - vport->Y,
		      amesa->RealWidth,
		      amesa->rp,
		      FIXx(vport->X),
		      FIXy(vport->Y) - vport->Height,
		      vport->Width,
		      vport->Height,
		      RECTFMT_LUT8);
  }
}

static void cybFinish(void)
{
  /* implements glFinish if possible */
}

static void cybFlush(GLcontext *ctx)
{
  amigaMesaContext amesa = (amigaMesaContext) ctx->DriverCtx;

  /* implements glFlush if possible */
  /* cybStandardSwapBufferDB(ctx->DriverCtx); */
  (*amesa->SwapBuffer)(amesa);
}

BOOL
cybStandardInit(struct amigamesa_context *amesa, struct TagItem *tagList)
{
  DEBUGOUT(1, "cybStandardInit()\n");

  if (!(amesa->window = (struct Window *)GetTagData(AMA_Window, 0, tagList))) {
    if (!(amesa->rp = (struct RastPort *)GetTagData(AMA_RastPort, 0, tagList))) {
      LastError = AMESA_RASTPORT_TAG_MISSING;
      return (FALSE);
    }
    if (!(amesa->Screen = (struct Screen *)GetTagData(AMA_Screen, 0, tagList))) {
      LastError = AMESA_SCREEN_TAG_MISSING;
      return (FALSE);
    }
  }
  else {
    amesa->rp = amesa->window->RPort;
    amesa->Screen = amesa->window->WScreen;
  }

  if (CyberGfxBase != NULL && IsCyberModeID(GetVPModeID(&amesa->Screen->ViewPort)))
    amesa->depth = GetCyberMapAttr(amesa->rp->BitMap, CYBRMATTR_DEPTH);
  else
    amesa->depth = GetBitMapAttr(amesa->rp->BitMap, BMA_DEPTH);

  amesa->FixedWidth = amesa->RealWidth = amesa->rp->Layer->bounds.MaxX - amesa->rp->Layer->bounds.MinX + 1;
  amesa->FixedHeight = amesa->RealHeight = amesa->rp->Layer->bounds.MaxY - amesa->rp->Layer->bounds.MinY + 1;

  amesa->left = GetTagData(AMA_Left, 0, tagList);
  amesa->bottom = GetTagData(AMA_Bottom, 0, tagList);
  amesa->right = GetTagData(AMA_Right, 0, tagList);
  amesa->top = GetTagData(AMA_Top, 0, tagList);
  amesa->width = GetTagData(AMA_Width, amesa->RealWidth - amesa->left - amesa->right, tagList);
  amesa->height = GetTagData(AMA_Height, amesa->RealHeight - amesa->bottom - amesa->top, tagList);

  if (!amesa->right)
    amesa->right = amesa->RealWidth - amesa->left - amesa->width;
  if (!amesa->top)
    amesa->top = amesa->RealHeight - amesa->bottom - amesa->height;

  amesa->front_rp = amesa->rp;
  amesa->back_rp = NULL;
  /*  amesa->rp = amesa->front_rp; */

  /*  amesa->gl_ctx->BufferWidth = amesa->width; */
  /*  amesa->gl_ctx->BufferHeight = amesa->height; */
  amesa->pixel = 0;							/*  current drawing pen  */

  if (amesa->depth <= 8) {
    AllocCMap(amesa->Screen);
  }

  if (amesa->visual->db_flag == GL_TRUE) {
    DEBUGOUT(1, "doublebuffering inside amigastandard");
    if ((amesa->back_rp = makeRPort(amesa->RealWidth, amesa->RealHeight, amesa->depth, amesa->rp->BitMap)) != NULL) {
      amesa->gl_ctx->Color.DrawBuffer = GL_BACK;
      amesa->rp = amesa->back_rp;
    }
    else {
      printf("make_rastport failed\n");
      amesa->gl_ctx->Color.DrawBuffer = GL_FRONT;
    }
  }
  else {
    amesa->gl_ctx->Color.DrawBuffer = GL_FRONT;
  }
  AllocOneLine(amesa);						/*  A linebuffer for WritePixelLine  */

  /* this shall not be invoked att all if not cybergfx */
  if (amesa->depth <= 8) {
    if (!makeTempRaster(amesa->rp))
      printf("Error allocating TmpRastPort\n");
    allocTempRPort(amesa);
    allocArea(amesa->rp);
  }

  amesa->InitDD = amesa->depth <= 8 ? amigaStandardDDPointers : cybStandardDDPointers;	/*  standard drawing */
  amesa->Dispose = amigaStandardDispose;
  amesa->SwapBuffer = amigaStandardSwapBuffer;
  (*amesa->InitDD)(amesa->gl_ctx);

  DEBUGOUT(1, " amesa->RealWidth =%d\n", amesa->RealWidth);
  DEBUGOUT(1, " amesa->RealHeight=%d\n", amesa->RealHeight);
  DEBUGOUT(1, " amesa->width =%d\n", amesa->width);
  DEBUGOUT(1, " amesa->height=%d\n", amesa->height);
  DEBUGOUT(1, " amesa->left  =%d\n", amesa->left);
  DEBUGOUT(1, " amesa->bottom=%d\n", amesa->bottom);
  DEBUGOUT(1, " amesa->right =%d\n", amesa->right);
  DEBUGOUT(1, " amesa->top   =%d\n", amesa->top);
  DEBUGOUT(1, " amesa->depth =%d\n", amesa->depth);

  return (TRUE);
}

BOOL
cybStandardInitDB(struct amigamesa_context * amesa, struct TagItem * tagList)
{
  DEBUGOUT(1, "cybStandardInitDB()\n");

  if (!(amesa->window = (struct Window *)GetTagData(AMA_Window, 0, tagList))) {
    if (!(amesa->rp = (struct RastPort *)GetTagData(AMA_RastPort, 0, tagList))) {
      LastError = AMESA_RASTPORT_TAG_MISSING;
      return (FALSE);
    }
    if (!(amesa->Screen = (struct Screen *)GetTagData(AMA_Screen, 0, tagList))) {
      LastError = AMESA_SCREEN_TAG_MISSING;
      return (FALSE);
    }
  }
  else {
    amesa->rp = amesa->window->RPort;
    amesa->Screen = amesa->window->WScreen;
  }

  if (CyberGfxBase && IsCyberModeID(GetVPModeID(&amesa->Screen->ViewPort)))
    amesa->depth = GetCyberMapAttr(amesa->rp->BitMap, CYBRMATTR_DEPTH);
  else
    amesa->depth = GetBitMapAttr(amesa->rp->BitMap, BMA_DEPTH);

  amesa->RealWidth = amesa->rp->Layer->bounds.MaxX - amesa->rp->Layer->bounds.MinX + 1;
  amesa->RealHeight = amesa->rp->Layer->bounds.MaxY - amesa->rp->Layer->bounds.MinY + 1;

  if (amesa->depth <= 8)
    amesa->FixedWidth = ((amesa->RealWidth + 15) >> 4) << 4;
  else
    amesa->FixedWidth = (amesa->RealWidth + 3) & 0xfffffffc;
  amesa->FixedHeight = amesa->RealHeight;

  amesa->left = GetTagData(AMA_Left, 0, tagList);
  amesa->bottom = GetTagData(AMA_Bottom, 0, tagList);
  amesa->right = GetTagData(AMA_Right, 0, tagList);
  amesa->top = GetTagData(AMA_Top, 0, tagList);
  amesa->width = GetTagData(AMA_Width, amesa->RealWidth - amesa->left - amesa->right, tagList);
  amesa->height = GetTagData(AMA_Height, amesa->RealHeight - amesa->bottom - amesa->top, tagList);

  if (!amesa->right)
    amesa->right = amesa->RealWidth - amesa->left - amesa->width;
  if (!amesa->top)
    amesa->top = amesa->RealHeight - amesa->bottom - amesa->height;

  /*  amesa->gl_ctx->BufferWidth = amesa->width; */
  /*  amesa->gl_ctx->BufferHeight = amesa->height; */
  amesa->pixel = 0;						/* current drawing pen * */

  if (amesa->depth <= 8) {
    AllocCMap(amesa->Screen);					/*  colormap  */
    allocTempRPort(amesa);
  }

  if (amesa->visual->db_flag) {
    amesa->BackArray = allocPenBackArray(amesa->FixedWidth, amesa->FixedHeight, amesa->depth <= 8 ? 1 : 4);
    DEBUGOUT(1, "byte array at -------->0x%x ends at 0x%x size=0x%x (%d)\n", amesa->BackArray, amesa->BackArray + (((amesa->RealWidth + 15) >> 4) << 4) * (amesa->RealHeight + 1), (((amesa->RealWidth + 15) >> 4) << 4) * (amesa->RealHeight + 1), (((amesa->RealWidth + 15) >> 4) << 4) * (amesa->RealHeight + 1));
    amesa->gl_ctx->Color.DrawBuffer = GL_BACK;
  }
  else {
    amesa->gl_ctx->Color.DrawBuffer = GL_FRONT;
    return (FALSE);
  }

  amesa->InitDD = amesa->depth <= 8 ? amigaFasterDDPointers : cybFasterDDPointers;	/*  fast drawing */
  amesa->Dispose = amigaStandardDisposeDB;
  amesa->SwapBuffer = cybStandardSwapBufferDB;
  (*amesa->InitDD)(amesa->gl_ctx);

  DEBUGOUT(1, " amesa->RealWidth =%d\n", amesa->RealWidth);
  DEBUGOUT(1, " amesa->RealHeight=%d\n", amesa->RealHeight);
  DEBUGOUT(1, " amesa->width =%d\n", amesa->width);
  DEBUGOUT(1, " amesa->height=%d\n", amesa->height);
  DEBUGOUT(1, " amesa->left  =%d\n", amesa->left);
  DEBUGOUT(1, " amesa->bottom=%d\n", amesa->bottom);
  DEBUGOUT(1, " amesa->right =%d\n", amesa->right);
  DEBUGOUT(1, " amesa->top   =%d\n", amesa->top);
  DEBUGOUT(1, " amesa->depth =%d\n", amesa->depth);

  return (TRUE);
}

/**********************************************************************/
/**********************************************************************/
/*
 * Initialize all the pointers in the DD struct.  Do this whenever   
 * a new context is made current or we change buffers via setBuffer! 
 */
void cybStandardDDPointers(GLcontext *ctx)
{
  /* amigaMesaContext amesa = ctx->DriverCtx; */
  DEBUGOUT(1, "cybStandardDDPointers()\n");

  ctx->Driver.RendererString = cybRendererString;

  ctx->Driver.UpdateState = cybStandardDDPointers;
  ctx->Driver.ClearIndex = cybClearIndex;
  ctx->Driver.ClearColor = cybClearColor;
  ctx->Driver.Clear = cybClear;

  ctx->Driver.Index = cybSetIndex;
  ctx->Driver.Color = cybSetColor;

  ctx->Driver.IndexMask = cybIndexMask;
  ctx->Driver.ColorMask = cybColorMask;

  ctx->Driver.SetBuffer = cybSetBuffer;
  ctx->Driver.GetBufferSize = cybStandardResize;

  ctx->Driver.PointsFunc = cybChoosePointsFunction(ctx);
  ctx->Driver.LineFunc = cybChooseLineFunction(ctx);
  ctx->Driver.TriangleFunc = cybChooseTriangleFunction(ctx);

  /*
   * Pixel/span writing functions: 
   */
  ctx->Driver.WriteRGBASpan = cybWriteRGBASpan;
  ctx->Driver.WriteRGBSpan = cybWriteRGBSpan;
  ctx->Driver.WriteCI32Span = cybWriteCI32Span;
  ctx->Driver.WriteCI8Span = cybWriteCI8Span;
  ctx->Driver.WriteMonoRGBASpan = cybWriteMonoCISpan;
  ctx->Driver.WriteMonoCISpan = cybWriteMonoCISpan;

  ctx->Driver.WriteRGBAPixels = cybWriteRGBAPixels;
  ctx->Driver.WriteCI32Pixels = cybWriteCI32Pixels;
  ctx->Driver.WriteMonoRGBAPixels = cybWriteMonoCIPixels;
  ctx->Driver.WriteMonoCIPixels = cybWriteMonoCIPixels;

  /*
   * Pixel/span reading functions: 
   */
  ctx->Driver.ReadRGBASpan = cybReadRGBASpan;
  ctx->Driver.ReadCI32Span = cybReadCI32Span;

  ctx->Driver.ReadRGBAPixels = cybReadRGBAPixels;
  ctx->Driver.ReadCI32Pixels = cybReadCI32Pixels;
}

void cybFasterDDPointers(GLcontext *ctx)
{
  /*  amigaMesaContext amesa = ctx->DriverCtx; */
  DEBUGOUT(1, "cybFasterDDPointers()\n");

  ctx->Driver.RendererString = cybRendererStringDB;

  ctx->Driver.UpdateState = cybFasterDDPointers;
  ctx->Driver.ClearIndex = cybClearIndex;
  ctx->Driver.ClearColor = cybClearColor;
  ctx->Driver.Clear = cybClearDB;

  ctx->Driver.Index = cybSetIndex;
  ctx->Driver.Color = cybSetColor;

  ctx->Driver.IndexMask = cybIndexMask;
  ctx->Driver.ColorMask = cybColorMask;

  ctx->Driver.SetBuffer = cybSetBuffer;
  ctx->Driver.GetBufferSize = cybStandardResizeDB;

  ctx->Driver.Flush = cybFlush;

  ctx->Driver.PointsFunc = cybChoosePointsFunctionDB(ctx);
  ctx->Driver.LineFunc = cybChooseLineFunctionDB(ctx);
  ctx->Driver.TriangleFunc = cybChooseTriangleFunctionDB(ctx);

  /*
   * Pixel/span writing functions: 
   */
  ctx->Driver.WriteRGBASpan = cybWriteRGBASpanDB;
  ctx->Driver.WriteRGBSpan = cybWriteRGBSpanDB;
  ctx->Driver.WriteCI32Span = cybWriteCI32SpanDB;
  ctx->Driver.WriteCI8Span = cybWriteCI8SpanDB;
  ctx->Driver.WriteMonoRGBASpan = cybWriteMonoCISpanDB;		/* same  */
  ctx->Driver.WriteMonoCISpan = cybWriteMonoCISpanDB;

  ctx->Driver.WriteRGBAPixels = cybWriteRGBAPixelsDB;
  ctx->Driver.WriteCI32Pixels = cybWriteCI32PixelsDB;
  ctx->Driver.WriteMonoRGBAPixels = cybWriteMonoCIPixelsDB;	/* same  */
  ctx->Driver.WriteMonoCIPixels = cybWriteMonoCIPixelsDB;

  /*
   * Pixel/span reading functions: 
   */
  ctx->Driver.ReadRGBASpan = cybReadRGBASpanDB;
  ctx->Driver.ReadCI32Span = cybReadCI32SpanDB;

  ctx->Driver.ReadRGBAPixels = cybReadRGBAPixelsDB;
  ctx->Driver.ReadCI32Pixels = cybReadCI32PixelsDB;
}

#undef DEBUGPRINT
