#include "X.h"
#include "Xproto.h"
#include "scrnintstr.h"
#include "cmapst.h"
#include "resource.h"
#include "svga.h"

static ColormapPtr InstalledMaps[MAXSCREENS];

int
svgaListInstalledColormaps(pScreen, pmaps)
ScreenPtr	pScreen;
Colormap	*pmaps;
{
#if MAXSCREENS == 1
	*pmaps = InstalledMaps[0]->mid;
#else
	*pmaps = InstalledMaps[pScreen->myNum]->mid;
#endif
	return 1;
}

void
svgaInstallColormap(pmap)
    ColormapPtr	pmap;
{
#if MAXSCREENS == 1
#define index 0
#else
    int index = pmap->pScreen->myNum;
#endif
    ColormapPtr oldpmap = InstalledMaps[index];

    if(pmap != oldpmap)
    {
	register Entry *pent = pmap->red;
	unsigned char red, green, blue;
	int i;

	if(oldpmap != (ColormapPtr)None)
	    WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
	/* Install pmap */
	outp(0x3c8, 0);	/* use colormap 0 */
	for (i = 0; i < pmap->pVisual->ColormapEntries; i++, pent++) {
	    if (pent->fShared) {
		red = (unsigned char)(pent->co.shco.red->color >> 8) >> 2;
		green = (unsigned char)(pent->co.shco.green->color >> 8) >> 2;
		blue = (unsigned char)(pent->co.shco.blue->color >> 8) >> 2;
	    } else {
		red = (unsigned char)(pent->co.local.red >> 8) >> 2;
		green = (unsigned char)(pent->co.local.green >> 8) >> 2;
		blue = (unsigned char)(pent->co.local.blue >> 8) >> 2;
	    }
	    outp(0x3c9, red);
	    outp(0x3c9, green);
	    outp(0x3c9, blue);
	}
	InstalledMaps[index] = pmap;
	svgapriv.colormap = pmap;
	WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);

    }
#undef index
}

void
svgaUninstallColormap(pmap)
    ColormapPtr	pmap;
{
    ColormapPtr defmap = (ColormapPtr)
	    LookupIDByType(pmap->pScreen->defColormap, RT_COLORMAP);

    /* Simple - just install the default colormap.  vgaInstallColormap
     * will uninstall this map. */
    svgaInstallColormap(defmap);
}

void
svgaResolveColor(pred, pgreen, pblue, pVisual)
unsigned short	*pred, *pgreen, *pblue;
VisualPtr	pVisual;
{
	/* We get 6 bits for each color.  round to nearest value */
	if (*pred < 0xfc00)
		*pred += 0x0200;
	*pred &= 0xfc00;
	if (*pgreen < 0xfc00)
		*pgreen += 0x0200;
	*pgreen &= 0xfc00;
	if (*pblue < 0xfc00)
		*pblue += 0x0200;
	*pblue &= 0xfc00;
}

Bool
svgaCreateColormap(pmap)
ColormapPtr pmap;
{
	/* This code from cfbInitialize332Colormap() cfb/cfbcmap.c */
	int i;

	/* Each color is 6 bits, assume ColormapEntries is 256. */

	for (i = 0; i < pmap->pVisual->ColormapEntries; i++) {
		pmap->red[i].co.local.red = (i & 0x7) << 13;
		pmap->red[i].co.local.green = (i & 0x38) << 10;
		pmap->red[i].co.local.blue = (i & 0xc0) << 8;
	}
	return TRUE;
}

void
svgaDestroyColormap(pmap)
ColormapPtr pmap;
{
	/* Don't worry about it.  We didn't allocate any private data
	 * anyway.
	 */
}

void
svgaStoreColors(pmap, ndef, pdefs)
ColormapPtr pmap;
int ndef;
xColorItem *pdefs;
{
	int pixel;
	register Entry *pent;
	unsigned char red, green, blue;
#define hardware_index 0

	if (pmap != InstalledMaps[0])
		return;
	while (ndef-- > 0) {
		pixel = (int)pdefs->pixel;
		/* We have to store red, green, and blue, so ignore
		 * pdefs->flags and get the values out of the colormap
		 * itself.
		 */
		pent = pmap->red + pixel;
		if (pent->fShared) {
		    red = (unsigned char)(pent->co.shco.red->color >> 8) >> 2;
		    green = (unsigned char)(pent->co.shco.green->color >> 8) >> 2;
		    blue = (unsigned char)(pent->co.shco.blue->color >> 8) >> 2;
		} else {
		    red = (unsigned char)(pent->co.local.red >> 8) >> 2;
		    green = (unsigned char)(pent->co.local.green >> 8) >> 2;
		    blue = (unsigned char)(pent->co.local.blue >> 8) >> 2;
		}
		outp(0x3c8,  (hardware_index << 4) + pixel);
		outp(0x3c9, red);
		outp(0x3c9, green);
		outp(0x3c9, blue);
		pdefs++;
	}
#undef hardware_index
}
