/* $Id: Exp $
***************************************************************************

   X server for LibGLTEX - graphic accelerated functions

   Copyright (C) 2002 Christopher Alexander North-Keys
                      http://www.talisman.org/~erlkonig/

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

#define PSZ 8
#include "mi.h"
#include "cfb.h"
#include "../../hw/xfree86/common/cfb16.h"
#include "../../hw/xfree86/common/cfb24.h"
#include "../../hw/xfree86/common/cfb32.h"

#include "scrnintstr.h"
#include "mibstore.h"
#include "gcstruct.h"

#include "xgltex.h"

static unsigned long mask2offset(unsigned long mask)
{
	int i;
	for (i = 0 ; (mask & 1) == 0 ; ++i)
		mask >>= 1;
	return i;
}

/* xgltexScreenInit */

extern miBSFuncRec mfbBSFuncRec, cfbBSFuncRec, cfb16BSFuncRec;
extern miBSFuncRec cfb24BSFuncRec, cfb32BSFuncRec;

Bool xgltexScreenInit(ScreenPtr pScreen, pointer pbits,
					  int xsize, int ysize, int dpix, int dpiy, int width)
{
	xgltexTexture_t *tex = &(xgltexVars.tex);
	VisualPtr visuals;
	DepthPtr depths;
	int nvisuals;
	int ndepths;
	int rootdepth = 0;
	VisualID defaultVisual;
	int bitsPerRGB;
	int	i;
	Bool Rstatus;
	VisualPtr visual;
	pointer oldDevPrivate = 0;
	miBSFuncPtr bsFuncs;

	if(tex->pixel_bits > 8)
	{
		int significant_bits = tex->comp_bits * tex->zsize;
		fprintf(stderr, "cfbSetVisualTypes(%d, %d, %d)\n",
				significant_bits, 1 << TrueColor, tex->comp_bits);

		if ( ! cfbSetVisualTypes(significant_bits,
								 1 << TrueColor,
								 tex->comp_bits))
		{
			ErrorF("cfbSetVisualTypes failed\n");
			return FALSE;
		}
	}
	if ( ! cfbInitVisuals(&visuals, &depths, &nvisuals, 
						  &ndepths, &rootdepth, &defaultVisual,
						  1 << (tex->pixel_bits - 1),
						  tex->comp_bits))
	{
		ErrorF("cfbInitVisuals failed\n");
		return FALSE;
	}
	fprintf(stderr,
			"cfbInitVisuals results: nvisuals %d, ndepths %d, rootdepth %d, "
			"defaultVisual %d)\n",
			nvisuals, ndepths, rootdepth, defaultVisual);

	if (rootdepth > 8) {
		for (i = 0, visual = visuals; i < nvisuals; i++, visual++) {
			if (visual->class == DirectColor
			    || visual->class == TrueColor) {
				/* XXX probably needs to be pushed left for RGBA */
				visual->redMask     = 0x0000ff;  /* used for 8bit greyscale */
				visual->greenMask   = 0x00ff00;  /* useless to lum */
				visual->blueMask    = 0xff0000;  /* useless to lum, lum+alph */
				fprintf(stderr, "Masks: r %#lx, g %#lx, b %#lx\n",
						(unsigned long int)visual->redMask,
						(unsigned long int)visual->greenMask,
						(unsigned long int)visual->blueMask);
				visual->offsetRed   = mask2offset(visual->redMask);
				visual->offsetGreen = mask2offset(visual->greenMask);
				visual->offsetBlue  = mask2offset(visual->blueMask);
			}
			else ErrorF(__FUNCTION__" warning: visual not Direct/TrueColor\n");
		}
	}

	cfbWindowPrivateIndex = cfbGCPrivateIndex = -1;  /* for screen 0 only */

	pScreen->defColormap   = FakeClientID(0);
	pScreen->whitePixel    = (Pixel) 1;
	pScreen->blackPixel    = (Pixel) 0;
	pScreen->QueryBestSize = mfbQueryBestSize;
	pScreen->RealizeFont   = mfbRealizeFont;
	pScreen->UnrealizeFont = mfbUnrealizeFont;

	switch (rootdepth) {
	case 1:
		bsFuncs          = &mfbBSFuncRec;
		pScreen->GetImage               = mfbGetImage;
		pScreen->GetSpans               = mfbGetSpans;
		pScreen->PaintWindowBackground  = mfbPaintWindow;
		pScreen->PaintWindowBorder      = mfbPaintWindow;
		pScreen->CreateGC               = mfbCreateGC;
		if ( ! mfbAllocatePrivates(pScreen, NULL, NULL)) {
			ErrorF("mfbAllocatePrivates failed\n");
			return FALSE;
		}
		pScreen->CreateWindow           = mfbCreateWindow;
		pScreen->DestroyWindow          = mfbDestroyWindow;
		pScreen->PositionWindow         = mfbPositionWindow;
		pScreen->ChangeWindowAttributes = mfbChangeWindowAttributes;
		pScreen->RealizeWindow          = mfbMapWindow;
		pScreen->UnrealizeWindow        = mfbUnmapWindow;
		pScreen->CreatePixmap           = mfbCreatePixmap;
		pScreen->DestroyPixmap          = mfbDestroyPixmap;
		pScreen->CopyWindow             = mfbCopyWindow;
		mfbRegisterCopyPlaneProc(pScreen, mfbCopyPlane);
		break;
	case 8:
		bsFuncs = &cfbBSFuncRec;
		pScreen->GetImage               = cfbGetImage;
		pScreen->GetSpans               = cfbGetSpans;
		pScreen->PaintWindowBackground  = cfbPaintWindow;
		pScreen->PaintWindowBorder      = cfbPaintWindow;
		pScreen->CreateGC               = cfbCreateGC;
		if ( ! cfbAllocatePrivates(pScreen, NULL, NULL)) {
			ErrorF("cfbAllocatePrivates failed\n");
			return FALSE;
		}
		pScreen->CreateWindow           = cfbCreateWindow;
		pScreen->DestroyWindow          = cfbDestroyWindow;
		pScreen->PositionWindow         = cfbPositionWindow;
		pScreen->ChangeWindowAttributes = cfbChangeWindowAttributes;
		pScreen->RealizeWindow          = cfbMapWindow;
		pScreen->UnrealizeWindow        = cfbUnmapWindow;
		pScreen->CreatePixmap           = cfbCreatePixmap;
		pScreen->DestroyPixmap          = cfbDestroyPixmap;
		pScreen->CopyWindow             = cfbCopyWindow;
		mfbRegisterCopyPlaneProc(pScreen, cfbCopyPlane);
		break;
	case 16:
		bsFuncs = &cfb16BSFuncRec;
		pScreen->GetImage               = cfb16GetImage;
		pScreen->GetSpans               = cfb16GetSpans;
		pScreen->PaintWindowBackground  = cfb16PaintWindow;
		pScreen->PaintWindowBorder      = cfb16PaintWindow;
		pScreen->CreateGC               = cfb16CreateGC;
		if ( ! cfb16AllocatePrivates(pScreen, NULL, NULL)) {
			ErrorF("cfb16AllocatePrivates failed\n");
			return FALSE;
		}
		pScreen->CreateWindow           = cfb16CreateWindow;
		pScreen->DestroyWindow          = cfb16DestroyWindow;
		pScreen->PositionWindow         = cfb16PositionWindow;
		pScreen->ChangeWindowAttributes = cfb16ChangeWindowAttributes;
		pScreen->RealizeWindow          = cfb16MapWindow;
		pScreen->UnrealizeWindow        = cfb16UnmapWindow;
		pScreen->CreatePixmap           = cfb16CreatePixmap;
		pScreen->DestroyPixmap          = cfb16DestroyPixmap;
		pScreen->CopyWindow             = cfb16CopyWindow;
		mfbRegisterCopyPlaneProc(pScreen, cfb16CopyPlane);
		break;
	case 24:
	case 32:
		if(24 == (tex->comp_bits * tex->zsize))	/* last 8 bits just padding? */
		{
			bsFuncs = &cfb24BSFuncRec;
			pScreen->GetImage               = cfb24GetImage;
			pScreen->GetSpans               = cfb24GetSpans;
			pScreen->PaintWindowBackground  = cfb24PaintWindow;
			pScreen->PaintWindowBorder      = cfb24PaintWindow;
			pScreen->CreateGC               = cfb24CreateGC;
			if ( ! cfb24AllocatePrivates(pScreen, NULL, NULL)) {
				ErrorF("cfb24AllocatePrivates failed\n");
				return FALSE;
			}
			pScreen->CreateWindow           = cfb24CreateWindow;
			pScreen->DestroyWindow          = cfb24DestroyWindow;
			pScreen->PositionWindow         = cfb24PositionWindow;
			pScreen->ChangeWindowAttributes = cfb24ChangeWindowAttributes;
			pScreen->RealizeWindow          = cfb24MapWindow;
			pScreen->UnrealizeWindow        = cfb24UnmapWindow;
			pScreen->CreatePixmap           = cfb24CreatePixmap;
			pScreen->DestroyPixmap          = cfb24DestroyPixmap;
			pScreen->CopyWindow             = cfb24CopyWindow;
			mfbRegisterCopyPlaneProc(pScreen, cfb24CopyPlane);
		} else {
			bsFuncs = &cfb32BSFuncRec;
			pScreen->GetImage               = cfb32GetImage;
			pScreen->GetSpans               = cfb32GetSpans;
			pScreen->PaintWindowBackground  = cfb32PaintWindow;
			pScreen->PaintWindowBorder      = cfb32PaintWindow;
			pScreen->CreateGC               = cfb32CreateGC;
			if ( ! cfb32AllocatePrivates(pScreen, NULL, NULL)) {
				ErrorF("cfb32AllocatePrivates failed\n");
				return FALSE;
			}
			pScreen->CreateWindow           = cfb32CreateWindow;
			pScreen->DestroyWindow          = cfb32DestroyWindow;
			pScreen->PositionWindow         = cfb32PositionWindow;
			pScreen->ChangeWindowAttributes = cfb32ChangeWindowAttributes;
			pScreen->RealizeWindow          = cfb32MapWindow;
			pScreen->UnrealizeWindow        = cfb32UnmapWindow;
			pScreen->CreatePixmap           = cfb32CreatePixmap;
			pScreen->DestroyPixmap          = cfb32DestroyPixmap;
			pScreen->CopyWindow             = cfb32CopyWindow;
			mfbRegisterCopyPlaneProc(pScreen, cfb32CopyPlane);
		}
		break;
	default:
		FatalError("root depth %d not supported\n", rootdepth);
	}

	pScreen->CreateColormap = cfbInitializeColormap;
	pScreen->DestroyColormap = (DestroyColormapProcPtr)NoopDDA;

	if (rootdepth == 1) {
		pScreen->ResolveColor = mfbResolveColor;
	} else {
		pScreen->ResolveColor = cfbResolveColor;
	}
	pScreen->BitmapToRegion = mfbPixmapToRegion;

	if (rootdepth != 8) {
		oldDevPrivate = pScreen->devPrivate;
	}

	fprintf(stderr,
			"miScreenInit(%#lx, %d, %d, %d, "  /* pS pbi xs ys */
			"%d, %d, %d, %d,\n"    /* dpx dpy wid rootd */
			"             %d, %d, %d, "        /* ndep dep defVis */
			"%d, %#lx, %#lx)\n",   /* nvis vis bsF */
			pScreen, pbits,                   /* < caller */
			xsize, ysize, dpix, dpiy, width,  /* < caller */
			rootdepth, ndepths, depths, defaultVisual, /*<init*/
			nvisuals, visuals,      /* < initVisuals*/
			bsFuncs);
	Rstatus = miScreenInit(pScreen, pbits,                   /* < caller */
						   xsize, ysize, dpix, dpiy, width,  /* < caller */
						   rootdepth, ndepths, depths, defaultVisual, /*<init*/
						   nvisuals, visuals,      /* < initVisuals*/
						   bsFuncs);               /* < switch(rootdepth) */

	switch (rootdepth) {
	case 1:
		pScreen->CloseScreen = mfbCloseScreen;
		break;
	case 8:
		pScreen->CloseScreen = cfbCloseScreen;
		break;
	case 15:
	case 16:
		pScreen->CloseScreen           = cfb16CloseScreen;
		pScreen->CreateScreenResources = cfb16CreateScreenResources;
		pScreen->devPrivates[cfb16ScreenPrivateIndex].ptr
			= pScreen->devPrivate;
		pScreen->devPrivate = oldDevPrivate;
		break;
	case 24:
	case 32:
		if (tex->pixel_bits == 24) {
			pScreen->CloseScreen           = cfb24CloseScreen;
			pScreen->CreateScreenResources = cfb24CreateScreenResources;
			pScreen->devPrivates[cfb24ScreenPrivateIndex].ptr
				= pScreen->devPrivate;
			pScreen->devPrivate = oldDevPrivate;
		} else {
			pScreen->CloseScreen           = cfb32CloseScreen;
			pScreen->CreateScreenResources = cfb32CreateScreenResources;
			pScreen->devPrivates[cfb32ScreenPrivateIndex].ptr
				= pScreen->devPrivate;
			pScreen->devPrivate = oldDevPrivate;
		}
		break;
	}
	
	return Rstatus;
}


