
#include <GL/gla.h>
#include "zgl.h"

static unsigned long *recup_cmap(int nc, unsigned long *cr);

typedef struct {
	GLContext *gl_context;
	int xsize,ysize;

	GLADrawable drawable;
	unsigned char *image;
	int bpp;
   
	//ave_pix_t *gc;

	// Ajouter la palette de couleur pour le rendu 8 bits (à utiliser avec rgb32).
	// unsigned long *cmap;


	/*
	// Intent
	int draw;

	// NGLX
  int pixtype; // pixel type in TinyGL

	// GLX
  Display *display;
  XVisualInfo visual_info;
  XImage *ximage;
  GC gc;
  Colormap cmap;
  int do_convert; // true if must do convertion to X11 format
  */
} TinyGLAContext;


/*
 * CreateContext
 */
GLAContext glACreateContext() //Display *dpy, XVisualInfo *vis, GLAContext shareList, BOOL direct )
{
  TinyGLAContext *ctx;

  ctx=gl_malloc(sizeof(TinyGLAContext));
	if (!ctx)
      return NULL;
  ctx->gl_context=NULL;
	ctx->image=NULL;
	ctx->drawable=NULL;

  return (GLAContext) ctx;
}

/*
 * DestroyContext
* Supprimer la palette si elle est différente de NULL
 */
void glADestroyContext(GLAContext ctx1)
{
	TinyGLAContext *ctx = (TinyGLAContext *) ctx1;
  if (ctx->gl_context != NULL) {
    glClose();
  }
  gl_free(ctx);
}

/* resize the glx viewport : we try to use the xsize and ysize
given. We return the effective size which is guaranted to be smaller */

static int glA_resize_viewport(GLContext *c, int *xsize_ptr, int *ysize_ptr)
{
	TinyGLAContext *ctx;
	int xsize,ysize;

	ctx=(TinyGLAContext *)c->opaque;

	xsize=*xsize_ptr;
	ysize=*ysize_ptr;

	/* we ensure that xsize and ysize are multiples of 2 for the zbuffer.
TODO: find a better solution */
	xsize&=~3;
	ysize&=~3;

	if (xsize == 0 || ysize == 0) return -1;

	*xsize_ptr=xsize;
	*ysize_ptr=ysize;
													
	if (ctx->image == NULL){
		ctx->image = (unsigned char *)gl_malloc(xsize * ysize);
	}else{
		if ((xsize !=	ctx->xsize) || (ysize != ctx->ysize)){
			gl_free(ctx->image);
			ctx->image = (unsigned char *)gl_malloc(xsize * ysize);
		}
	}

	ctx->xsize=xsize;
	ctx->ysize=ysize;
	
	if (ctx->image == NULL){
		return -1;
	}
   
	/* resize the Z buffer */
	ZB_resize(c->zb,NULL,xsize,ysize);
	
	return 0;
}

/*
 * MakeCurrent
 */
/* we assume here that drawable is a window */
int glAMakeCurrent(GLADrawable drawable, GLAContext ctx1)
{
  TinyGLAContext *ctx = (TinyGLAContext *) ctx1;
  int xsize,ysize;
  ZBuffer *zb;
  unsigned int palette[ZB_NB_COLORS];
  unsigned char color_indexes[ZB_NB_COLORS];
	unsigned long *new_palette;
	int i;
	int mode;
																						
	int bpp;
   
	//if((dpy==NULL)||(ctx1==NULL)) return(0);
	
	bpp = GetBitMapAttr(drawable->RPort->BitMap, BMA_DEPTH);
	ctx->bpp = bpp;
   
  if (ctx->gl_context == NULL) {

    /* create the TinyGL context */
    // Affectation du drawable

		//ctx->display=dpy;
		ctx->drawable=drawable;
     
		xsize = drawable->Width;
		ysize = drawable->Height;
 
    /* ximage structure */
		//ctx->ximage=NULL;
		//ctx->shm_use=0; /* no shm */

		// La partie qui suit équivaut à la fonction locale init() de igl.c
		/*
    {
        int mode, bpp;

				// RGB 16/24/32
        bpp = bits_per_pixel(ctx->display,&ctx->visual_info);

        //mode = ZB_MODE_RGB24;
				// currently, we only support 16 bit rendering
	      //mode = ZB_MODE_5R6G5B; // nglx ne supporte que le mode 16 bits
											
		*/
		mode = ZB_MODE_INDEX; //5R6G5B;
						
		if (mode == ZB_MODE_INDEX){

		//if (attr.depth == 8) {
      /* get the colormap from the window */
			/*
      ctx->cmap = attr.colormap;

      if ( XAllocColorCells(ctx->display,ctx->cmap,True,&tmp_plane,0,
                            pixel,ZB_NB_COLORS) == 0) {
				// private cmap
        ctx->cmap = XCreateColormap(ctx->display, drawable,
                                    ctx->visual_info.visual, AllocAll);
        XSetWindowColormap(ctx->display, drawable, ctx->cmap);
        for(i=0;i<ZB_NB_COLORS;i++) pixel[i]=i;
      }
			*/

      for(i=0;i<ZB_NB_COLORS;i++){
				color_indexes[i]=i;
      }

      /* Open the Z Buffer - 256 colors */
      zb=ZB_open(xsize,ysize,ZB_MODE_INDEX,ZB_NB_COLORS,color_indexes,palette,NULL);
      if (zb == NULL) {
        fprintf(stderr, "Error while initializing Z buffer\n");
        exit(1);
      }

      // Affectation de la cmap au drawable

			new_palette = recup_cmap(ZB_NB_COLORS, (unsigned long *)palette);
			LoadRGB32(&drawable->WScreen->ViewPort, new_palette);
			free(new_palette);

			// construction de la cmap du contexte
			//
			//for (i=0; i<ZB_NB_COLORS; i++) {
			//	xcolor.flags = DoRed | DoGreen | DoBlue;
			//
			//	xcolor.red = (palette[i]>>8) & 0xFF00;
			//	xcolor.green = (palette[i] & 0xFF00);
			//	xcolor.blue = (palette[i] << 8) & 0xFF00;
			//	xcolor.pixel = pixel[i];
			//	XStoreColor(ctx->display,ctx->cmap,&xcolor);
			//}
			//ctx->do_convert = 1;
		}else{
			// mode 16 bits
			zb = ZB_open(xsize, ysize, mode, 0, NULL, NULL, NULL);
		}
 
		//}

    /* initialisation of the TinyGL interpreter */
    glInit(zb);

    ctx->gl_context=gl_get_context();
    ctx->gl_context->opaque=(void *) ctx;
    ctx->gl_context->gl_resize_viewport=glA_resize_viewport; //igl_resize_viewport

    /* set the viewport : we force a call to glX_resize_viewport */
    ctx->gl_context->viewport.xsize=-1;
    ctx->gl_context->viewport.ysize=-1;

		glViewport(0, 0, xsize, ysize);
  }

  return 1;
}

/*
 * SwapBuffers
 */
void glASwapBuffers(GLADrawable drawable)
{
  GLContext *gl_context;
  TinyGLAContext *ctx;
	int i;
	int comp = 0;
	unsigned char *ptr;
	unsigned long *new_palette;
	unsigned short *seize;
	unsigned short s;
	unsigned char *buf;
	unsigned char r,g,b;
   
  /* retrieve the current GLXContext */
  gl_context=gl_get_context();
  ctx=(TinyGLAContext *)gl_context->opaque;

	if (ctx->bpp == 8){
		ZB_copyFrameBuffer(ctx->gl_context->zb, ctx->image, ctx->xsize);
		
		WriteChunkyPixels(drawable->RPort, 0, 0, drawable->Width - 1, drawable->Height - 1, (unsigned char *)ctx->image/*ctx->gl_context->zb->pbuf*/, drawable->Width);
	}else{
		printf("gla.c: cybergfx bpp = %d\n", ctx->bpp);
		
		ZB_copyFrameBuffer(ctx->gl_context->zb, ctx->image, ctx->xsize);

		(void)WritePixelArray(ctx->image,
												0,0,
												drawable->Width*ctx->bpp/8,
												drawable->RPort,
												0, 0,
												drawable->Width,
												drawable->Height,
												RECTFMT_RGB);
	}
}

/* Create an AmigaOS color map (usable with LoadRGB32()) */
static unsigned long *recup_cmap(int nc, unsigned long *cr)
{
	int c;
	unsigned long *colourtable;
	unsigned char r, g, b;

	if ((colourtable = (unsigned long *)malloc((1 + 3 * nc + 1) * sizeof(unsigned long))))
	{
		colourtable[0] = (nc << 16) + 0;

		for (c = 0; c < nc; c++)
		{
			r = (unsigned char)((cr[c]>>16) & 0xFF);
			g = (unsigned char)((cr[c]>>8) & 0xFF);
			b = (unsigned char)((cr[c]) & 0xFF);
       
			colourtable[3 * c + 1] = (unsigned long)(r * 0x01010101);
			colourtable[3 * c + 2] = (unsigned long)(g * 0x01010101);
			colourtable[3 * c + 3] = (unsigned long)(b * 0x01010101);
		}

		colourtable[1 + 3 * nc] = 0;
	}

	return colourtable;
}

