/* $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 "xggi.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 xggiScreenInit(ScreenPtr pScreen, pointer pbits,
					int xsize, int ysize, int dpix, int dpiy, int width)
{
	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 defined(XGGI_DEBUG) || 1
	ErrorF("depth: %d, bpp:%d\n", xggiScreen.depth, xggiScreen.bitsPerPixel);
#endif

	switch (xggiScreen.depth) {
	case  8: bitsPerRGB = 8; break;
	case 15: bitsPerRGB = 5; break;
	case 16: bitsPerRGB = 6; break;
	default: bitsPerRGB = 8; break;
	}

	if (xggiScreen.bitsPerPixel > 8) {
		if ( ! cfbSetVisualTypes(xggiScreen.depth,
								 1 << TrueColor, bitsPerRGB)) {
			ErrorF("cfbSetVisualTypes failed\n");
			return FALSE;
		}
	}
	if ( ! cfbInitVisuals(&visuals, &depths, &nvisuals, 
						  &ndepths, &rootdepth, &defaultVisual,
						  1 << (xggiScreen.bitsPerPixel - 1),
						  bitsPerRGB)) {
		ErrorF("cfbInitVisuals failed\n");
		return FALSE;
	}

#ifdef XGGI_DEBUG
	ErrorF("rootdepth: %d\n", rootdepth);
#endif

	if (rootdepth > 8) {
		for (i = 0, visual = visuals; i < nvisuals; i++, visual++) {
			if (visual->class == DirectColor
			    || visual->class == TrueColor) {
#define PIXFMT(scr)	((scr).dbuf->buffer.plb.pixelformat)
				visual->redMask     = PIXFMT(xggiScreen)->red_mask;
				visual->greenMask   = PIXFMT(xggiScreen)->green_mask;
				visual->blueMask    = PIXFMT(xggiScreen)->blue_mask;
#undef PIXFMT
				visual->offsetRed   = mask2offset(visual->redMask);
				visual->offsetGreen = mask2offset(visual->greenMask);
				visual->offsetBlue  = mask2offset(visual->blueMask);
			}
		}
	}

	cfbWindowPrivateIndex = cfbGCPrivateIndex = -1;  /* 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 15:
	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 (xggiScreen.bitsPerPixel == 24) {
			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;
	}

	Rstatus = miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width,
						   rootdepth, ndepths, depths, defaultVisual,
						   nvisuals, visuals, bsFuncs);

	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 (xggiScreen.bitsPerPixel == 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;
}


