ftp.nice.ch/pub/next/developer/resources/libraries/Mesa.2.0.s.tar.gz#/Mesa-2.0/nt/MesaGl32.c

This is MesaGl32.c in view mode; [Download] [Up]

/*
	MesaGL32.c
*/
#define MESAGL32_C

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <mesagl/MesaGL32.h>
#include "../../src/context.h"
#include "../../src/dd.h"
#include "../../src/xform.h"
#include "../../src/vb.h"
#ifdef PROFILE
#include "../../src/profile.h"
#endif
#include "../../src/wmesadef.h"
#include <wing.h>

/* Bit's used for dest: */
#define FRONT_PIXMAP	1
#define BACK_PIXMAP	2
#define BACK_XIMAGE	4

static PWMC Current = NULL;
WMesaContext WC = NULL;

#ifdef NDEBUG
  #define assert(ignore)	((void) 0)
#else
  void Mesa_Assert(void *Cond,void *File,unsigned Line)
  {
    char Msg[512];
    sprintf(Msg,"%s %s %d",Cond,File,Line);
    MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
    exit(1);
  }
  #define assert(e)	if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
#endif

#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC)
#define DD_RELEASEDC

#define BEGINGDICALL	if(Current->rgb_flag)wmFlushBits(Current);
#define ENDGDICALL		if(Current->rgb_flag)wmGetBits(Current);

#define FLIP(Y)  (Current->height-(Y)-1)


static void FlushToFile(PWMC pwc, PSTR	szFile);


/* Finish all pending operations and synchronize. */
static void finish(void)
{
   /* no op */
}


//
// We cache all gl draw routines until a flush is made
//
static void flush(void)
{
	STARTPROFILE
	if(Current->rgb_flag && !(Current->dib.fFlushed)){
		wmFlush(Current);
	}
	ENDPROFILE(flush)
   
}



/*
 * Set the color index used to clear the color buffer.
 */
static void clear_index(GLuint index)
{
	STARTPROFILE
  Current->clearpixel = index;
	ENDPROFILE(clear_index)
}



/*
 * Set the color used to clear the color buffer.
 */
static void clear_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
   STARTPROFILE
  Current->clearpixel=RGB(r, g, b );
  ENDPROFILE(clear_color)
}



/*
 * Clear the specified region of the color buffer using the clear color
 * or index as specified by one of the two functions above.
 */
static void clear(GLboolean all,GLint x, GLint y, GLint width, GLint height )
{
    STARTPROFILE
	DWORD	dwColor;	
	WORD	wColor;
	LPDWORD	lpdw = (LPDWORD)Current->pbPixels;
	LPWORD	lpw = (LPWORD)Current->pbPixels;
	LPBYTE	lpb;
	BYTE	bPix[12];
	LPBYTE	lpb = Current->pbPixels;

	if (all){
		x=y=0;
		width=Current->width;
		height=Current->height;
	}
	if (Current->rgb_flag==GL_TRUE){
		UINT	nBypp = Current->cColorBits / 8;
		int		i = 0;
		int		iSize;

		if(nBypp == 2){
			iSize = (Current->width * Current->height) / nBypp;

			wColor = BGR16(GetRValue(Current->clearpixel), 
						   GetGValue(Current->clearpixel), 
						   GetBValue(Current->clearpixel));
			dwColor = MAKELONG(wColor, wColor);
		}
		else if nBypp == 4{
			iSize = (Current->width * Current->height);

			dwColor = BGR32(GetRValue(Current->clearpixel), 
						   GetGValue(Current->clearpixel), 
						   GetBValue(Current->clearpixel));
		}
		//
		// This is the 24bit case
		//
		else {

			iSize = (Current->width * Current->height) / nBypp;

			dwColor = BGR24(GetRValue(Current->clearpixel), 
						   GetGValue(Current->clearpixel), 
						   GetBValue(Current->clearpixel));


			while(i < iSize){
				*lpdw = dwColor;
				lpb += nBypp;
				lpdw = (LPDWORD)lpb;
				i++;
			}

			ENDPROFILE(clear)

			return;
		}

		while(i < iSize){
			*lpdw = dwColor;
			lpdw++;
			i++;
		}
	}

	else {
		int i;
		char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
		for (i=0; i<height; i++){
			memset(Mem,Current->clearpixel,width);
			Mem+=width;
		}
	}

	ENDPROFILE(clear)
}



/* Set the current color index. */
static void set_index(GLuint index)
{
   STARTPROFILE
  Current->pixel=index;
   ENDPROFILE(set_index)
}



/* Set the current RGBA color. */
static void set_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
   STARTPROFILE
  Current->pixel = RGB( r, g, b );
   ENDPROFILE(set_color)
}



/* Set the index mode bitplane mask. */
static GLboolean index_mask(GLuint mask)
{
   /* can't implement */
   return GL_FALSE;
}



/* Set the RGBA drawing mask. */
static GLboolean color_mask( GLboolean rmask, GLboolean gmask,
							 GLboolean bmask, GLboolean amask)
{
   /* can't implement */
   return GL_FALSE;
}



/*
 * Set the pixel logic operation.  Return GL_TRUE if the device driver
 * can perform the operation, otherwise return GL_FALSE.  If GL_FALSE
 * is returned, the logic op will be done in software by Mesa.
 */
GLboolean logicop( GLenum op )
{
   /* can't implement */
   return GL_FALSE;
}


static void dither( GLboolean enable )
{
   /* No op */
}



static GLboolean set_buffer( GLenum mode )
{
   STARTPROFILE
   /* TODO: this could be better */
   if (mode==GL_FRONT || mode==GL_BACK) {
      return GL_TRUE;
   }
   else {
      return GL_FALSE;
   }
   ENDPROFILE(set_buffer)
}



/* Return characteristics of the output buffer. */
static void buffer_size( GLuint *width, GLuint *height, GLuint *depth )
{
	STARTPROFILE
	int New_Size;
	RECT CR;
	
	GetClientRect(Current->Window,&CR);

	*width=CR.right;
	*height=CR.bottom;
	*depth = Current->depth;

	New_Size=((*width)!=Current->width) || ((*height)!=Current->height);

	if (New_Size){
		Current->width=*width;
		Current->ScanWidth=Current->width;
		Current->height=*height;

		if (Current->db_flag){
			if (Current->rgb_flag==GL_TRUE){
				wmDeleteBackingStore(Current);
				wmCreateBackingStore(Current, Current->width, current->height);
			}
			else{
				Current->IndexFormat->bmiHeader.biWidth=Current->width;

				if (Current->IndexFormat->bmiHeader.biHeight<0)
					Current->IndexFormat->bmiHeader.biHeight=-Current->height;
				else
					Current->IndexFormat->bmiHeader.biHeight=Current->height;

				Current->Compat_BM=WinGCreateBitmap(Current->dib.hDC,Current->IndexFormat,&((void *) Current->ScreenMem));

				DeleteObject(SelectObject(Current->dib.hDC,Current->Compat_BM));
			}
		}
	}

	ENDPROFILE(buffer_size)
}



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


static void fast_rgb_points( GLuint first, GLuint last )
{
   STARTPROFILE
   GLuint i;
   HDC DC=DD_GETDC;
	PWMC	pwc = Current;
   if (VB.MonoColor) {
      /* all drawn with current color */
      for (i=first;i<=last;i++) {
         if (VB.Unclipped[i]) {
            int x, y;
            x =       (GLint) VB.Win[i][0];
            y = FLIP( (GLint) VB.Win[i][1] );
			wmSetPixel(pwc, y,x,GetRValue(Current->pixel), 
					    GetGValue(Current->pixel), GetBValue(Current->pixel));
         }
      }
   }
   else {
      /* draw points of different colors */
      for (i=first;i<=last;i++) {
         if (VB.Unclipped[i]) {
            int x, y;
            unsigned long pixel=RGB(VB.Color[i][0]*255.0,
                                    VB.Color[i][1]*255.0,
                                    VB.Color[i][2]*255.0);
            x =       (GLint) VB.Win[i][0];
            y = FLIP( (GLint) VB.Win[i][1] );
			wmSetPixel(pwc, y,x,VB.Color[i][0]*255.0, 
                                    VB.Color[i][1]*255.0,
                                    VB.Color[i][2]*255.0);
         }
      }
   }
   DD_RELEASEDC;
   ENDPROFILE(fast_rgb_points)
}



/* Return pointer to accerated points function */
static points_func choose_points_function( void )
{
   STARTPROFILE
   if (CC.Point.Size==1.0 && !CC.Point.SmoothFlag && CC.RasterMask==0
       && !CC.Texture.Enabled  && Current->rgb_flag) {
   ENDPROFILE(choose_points_function)
      return fast_rgb_points;
   }
   else {
   ENDPROFILE(choose_points_function)
      return NULL;
   }
}



/* Draw a line using the color specified by VB.Color[pv] */
static void fast_flat_rgb_line( GLuint v0, GLuint v1, GLuint pv )
{
	STARTPROFILE
	int x0, y0, x1, y1;
	unsigned long pixel;
	HDC DC=DD_GETDC;
	HPEN Pen;
	HPEN Old_Pen;

	if (VB.MonoColor) {
	  pixel = Current->pixel;  /* use current color */
	}
	else {
	  pixel = RGB(VB.Color[pv][0]*255.0, VB.Color[pv][1]*255.0, VB.Color[pv][2]*255.0);
	}

	x0 =       (int) VB.Win[v0][0];
	y0 = FLIP( (int) VB.Win[v0][1] );
	x1 =       (int) VB.Win[v1][0];
	y1 = FLIP( (int) VB.Win[v1][1] );


	BEGINGDICALL

	Pen=CreatePen(PS_SOLID,1,pixel);
	Old_Pen=SelectObject(DC,Pen);
	MoveToEx(DC,x0,y0,NULL);
	LineTo(DC,x1,y1);
	SelectObject(DC,Old_Pen);
	DeleteObject(Pen);
	DD_RELEASEDC;

	ENDGDICALL

	ENDPROFILE(fast_flat_rgb_line)
}



/* Return pointer to accerated line function */
static line_func choose_line_function( void )
{
   STARTPROFILE
   if (CC.Line.Width==1.0 && !CC.Line.SmoothFlag && !CC.Line.StippleFlag
       && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
       && !CC.Texture.Enabled && Current->rgb_flag) {
   ENDPROFILE(choose_line_function)
      return fast_flat_rgb_line;
   }
   else {
   ENDPROFILE(choose_line_function)
      return NULL;
   }
}


/* Draw a convex polygon using color VB.Color[pv] */
static void fast_flat_rgb_polygon( GLuint n, GLuint vlist[], GLuint pv )
{
   STARTPROFILE
   POINT *Pts=(POINT *) malloc(n*sizeof(POINT));
   HDC DC=DD_GETDC;
   HPEN Pen;
   HBRUSH Brush;
   HPEN Old_Pen;
   HBRUSH Old_Brush;
   GLint pixel;
   GLuint i;

   if (VB.MonoColor) {
      pixel = Current->pixel;  /* use current color */
   }
   else {
      pixel = RGB(VB.Color[pv][0]*255.0, VB.Color[pv][1]*255.0, VB.Color[pv][2]*255.0);
   }

   Pen=CreatePen(PS_SOLID,1,pixel);
   Brush=CreateSolidBrush(pixel);
   Old_Pen=SelectObject(DC,Pen);
   Old_Brush=SelectObject(DC,Brush);

   for (i=0; i<n; i++) {
      int j = vlist[i];
      Pts[i].x =       (int) VB.Win[j][0];
      Pts[i].y = FLIP( (int) VB.Win[j][1] );
   }

   BEGINGDICALL

   Polygon(DC,Pts,n);
   SelectObject(DC,Old_Pen);
   SelectObject(DC,Old_Brush);
   DeleteObject(Pen);
   DeleteObject(Brush);
   DD_RELEASEDC;
   free(Pts);

   ENDGDICALL

   ENDPROFILE(fast_flat_rgb_polygon)
}



/* Return pointer to accerated polygon function */
static polygon_func choose_polygon_function( void )
{
   STARTPROFILE
   if (!CC.Polygon.SmoothFlag && !CC.Polygon.StippleFlag
       && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
       && !CC.Texture.Enabled && Current->rgb_flag==GL_TRUE) {
   ENDPROFILE(choose_polygon_function)
      return fast_flat_rgb_polygon;
   }
   else {
   ENDPROFILE(choose_polygon_function)
      return NULL;
   }
}



/**********************************************************************/
/*****                 Span-based pixel drawing                   *****/
/**********************************************************************/


/* Write a horizontal span of color-index pixels with a boolean mask. */
static void write_index_span( GLuint n, GLint x, GLint y,
							  const GLuint index[],
                              const GLubyte mask[] )
{
   STARTPROFILE
  GLuint i;
  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  assert(Current->rgb_flag==GL_FALSE);
  for (i=0; i<n; i++)
    if (mask[i])
      Mem[i]=index[i];
   ENDPROFILE(write_index_span)
}



/*
 * Write a horizontal span of pixels with a boolean mask.  The current
 * color index is used for all pixels.
 */
static void write_monoindex_span(GLuint n,GLint x,GLint y,const GLubyte mask[])
{
   STARTPROFILE
  GLuint i;
  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  assert(Current->rgb_flag==GL_FALSE);
  for (i=0; i<n; i++)
    if (mask[i])
      Mem[i]=Current->pixel;
   ENDPROFILE(write_monoindex_span)
}

/*
	To improve the performance of this routine, frob the data into an actual scanline
	and call bitblt on the complete scan line instead of SetPixel.
*/

/* Write a horizontal span of color pixels with a boolean mask. */
static void write_color_span( GLuint n, GLint x, GLint y,
			  const GLubyte
			  red[], const GLubyte green[],
			  const GLubyte blue[], const GLubyte alpha[],
			  const GLubyte mask[] )
{
	STARTPROFILE

	PWMC	pwc = Current;

	if (pwc->rgb_flag==GL_TRUE)
	{
		GLuint i;
		HDC DC=DD_GETDC;
		y=FLIP(y);

		if (mask) {
			for (i=0; i<n; i++)
				if (mask[i])
					wmSetPixel(pwc, y, x + i,red[i], green[i], blue[i]);
		}

		else {
			for (i=0; i<n; i++)
				wmSetPixel(pwc, y, x + i, red[i], green[i], blue[i]);
		}

		DD_RELEASEDC;

	}

  else
  {
    GLuint i;
    char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
    if (mask) {
       for (i=0; i<n; i++)
         if (mask[i])
           Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
    }
    else {
       for (i=0; i<n; i++)
         Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
    }
  }
   ENDPROFILE(write_color_span)

}

/*
 * Write a horizontal span of pixels with a boolean mask.  The current color
 * is used for all pixels.
 */
static void write_monocolor_span( GLuint n, GLint x, GLint y,const GLubyte mask[])
{
   STARTPROFILE
  GLuint i;
  HDC DC=DD_GETDC;
  assert(Current->rgb_flag==GL_TRUE);
  y=FLIP(y);

  if(Current->rgb_flag==GL_TRUE){
	  for (i=0; i<n; i++)
		if (mask[i])
		  wmSetPixel(DC,x+i,y,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
  }
  else {
	  for (i=0; i<n; i++)
		if (mask[i])
			SetPixel(DC, y, x+i, Current->pixel);
  }

	DD_RELEASEDC;

	ENDPROFILE(write_monocolor_span)
}



/**********************************************************************/
/*****                   Array-based pixel drawing                *****/
/**********************************************************************/


/* Write an array of pixels with a boolean mask. */
static void write_index_pixels( GLuint n, const GLint x[], const GLint y[],
								const GLuint index[], const GLubyte mask[] )
{
   STARTPROFILE
   GLuint i;
   assert(Current->rgb_flag==GL_FALSE);
   for (i=0; i<n; i++) {
      if (mask[i]) {
         char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
         *Mem = index[i];
      }
   }
   ENDPROFILE(write_index_pixels)
}



/*
 * Write an array of pixels with a boolean mask.  The current color
 * index is used for all pixels.
 */
static void write_monoindex_pixels( GLuint n,
									const GLint x[], const GLint y[],
                                    const GLubyte mask[] )
{
   STARTPROFILE
   GLuint i;
   assert(Current->rgb_flag==GL_FALSE);
   for (i=0; i<n; i++) {
      if (mask[i]) {
         char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
         *Mem = Current->pixel;
      }
   }
   ENDPROFILE(write_monoindex_pixels)
}



/* Write an array of pixels with a boolean mask. */
static void write_color_pixels( GLuint n, const GLint x[], const GLint y[],
								const GLubyte r[], const GLubyte g[],
                                const GLubyte b[], const GLubyte a[],
                                const GLubyte mask[] )
{
	STARTPROFILE
	GLuint i;
	PWMC	pwc = Current;
	HDC DC=DD_GETDC;
	assert(Current->rgb_flag==GL_TRUE);
	for (i=0; i<n; i++)
		if (mask[i])
			wmSetPixel(pwc, FLIP(y[i]),x[i],r[i],g[i],b[i]);
	DD_RELEASEDC;
	ENDPROFILE(write_color_pixels)
}



/*
 * Write an array of pixels with a boolean mask.  The current color
 * is used for all pixels.
 */
static void write_monocolor_pixels( GLuint n,
									const GLint x[], const GLint y[],
                                    const GLubyte mask[] )
{
	STARTPROFILE
	GLuint i;
	PWMC	pwc = Current;
	HDC DC=DD_GETDC;
	assert(Current->rgb_flag==GL_TRUE);
	for (i=0; i<n; i++)
		if (mask[i])
			wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel), 
					    GetGValue(Current->pixel), GetBValue(Current->pixel));
	DD_RELEASEDC;
	ENDPROFILE(write_monocolor_pixels)
}



/**********************************************************************/
/*****            Read spans/arrays of pixels                     *****/
/**********************************************************************/


/* Read a horizontal span of color-index pixels. */
static void read_index_span( GLuint n, GLint x, GLint y, GLuint index[])
{
   STARTPROFILE
   GLuint i;
  char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  assert(Current->rgb_flag==GL_FALSE);
  for (i=0; i<n; i++)
    index[i]=Mem[i];
   ENDPROFILE(read_index_span)
}




/* Read an array of color index pixels. */
static void read_index_pixels( GLuint n, const GLint x[], const GLint y[],
							   GLuint indx[], const GLubyte mask[] )
{
   STARTPROFILE
   GLuint i;
  assert(Current->rgb_flag==GL_FALSE);
  for (i=0; i<n; i++) {
     if (mask[i]) {
        indx[i]=*(Current->ScreenMem+y[i]*Current->ScanWidth+x[i]);
     }
  }
   ENDPROFILE(read_index_pixels)
}



/* Read a horizontal span of color pixels. */
static void read_color_span( GLuint n, GLint x, GLint y,
							 GLubyte red[], GLubyte green[],
                             GLubyte blue[], GLubyte alpha[] )
{
   STARTPROFILE
  UINT i;
  COLORREF Color;
  HDC DC=DD_GETDC;
  assert(Current->rgb_flag==GL_TRUE);
  y=FLIP(y);
  for (i=0; i<n; i++)
  {
    Color=GetPixel(DC,x+i,y);
    red[i]=GetRValue(Color);
    green[i]=GetGValue(Color);
    blue[i]=GetBValue(Color);
    alpha[i]=255;
  }
  DD_RELEASEDC;
  memset(alpha,0,n*sizeof(GLint));
   ENDPROFILE(read_color_span)
}


/* Read an array of color pixels. */
static void read_color_pixels( GLuint n, const GLint x[], const GLint y[],
							   GLubyte red[], GLubyte green[],
                               GLubyte blue[], GLubyte alpha[],
                               const GLubyte mask[] )
{
   STARTPROFILE
  GLuint i;
  COLORREF Color;
  HDC DC=DD_GETDC;
  assert(Current->rgb_flag==GL_TRUE);
  for (i=0; i<n; i++) {
     if (mask[i]) {
        Color=GetPixel(DC,x[i],FLIP(y[i]));
        red[i]=GetRValue(Color);
        green[i]=GetGValue(Color);
        blue[i]=GetBValue(Color);
        alpha[i]=255;
     }
  }
  DD_RELEASEDC;
  memset(alpha,0,n*sizeof(GLint));
   ENDPROFILE(read_color_pixels)
}



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



void setup_DD_pointers( void )
{
   DD.finish = finish;
   DD.flush = flush;

   DD.clear_index = clear_index;
   DD.clear_color = clear_color;
   DD.clear = clear;

   DD.index = set_index;
   DD.color = set_color;
   DD.index_mask = index_mask;
   DD.color_mask = color_mask;

   DD.logicop = logicop;
   DD.dither = dither;

   DD.set_buffer = set_buffer;
   DD.buffer_size = buffer_size;

   DD.get_points_func = choose_points_function;
   DD.get_line_func = choose_line_function;
   DD.get_polygon_func = choose_polygon_function;

   /* Pixel/span writing functions: */
   DD.write_color_span       = write_color_span;
   DD.write_monocolor_span   = write_monocolor_span;
   DD.write_color_pixels     = write_color_pixels;
   DD.write_monocolor_pixels = write_monocolor_pixels;
   DD.write_index_span       = write_index_span;
   DD.write_monoindex_span   = write_monoindex_span;
   DD.write_index_pixels     = write_index_pixels;
   DD.write_monoindex_pixels = write_monoindex_pixels;

   /* Pixel/span reading functions: */
   DD.read_index_span = read_index_span;
   DD.read_color_span = read_color_span;
   DD.read_index_pixels = read_index_pixels;
   DD.read_color_pixels = read_color_pixels;
}

//
// MesaGL32 is the DLL version of MesaGL for Win32
//

/**********************************************************************/
/*****                  WMesa API Functions                       *****/
/**********************************************************************/



#define PAL_SIZE 256
static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
{
   STARTPROFILE
	int i;
	HDC hdc;
	struct
	{
		WORD Version;
		WORD NumberOfEntries;
		PALETTEENTRY aEntries[PAL_SIZE];
	} Palette =
	{
		0x300,
		PAL_SIZE
	};
	hdc=GetDC(NULL);
	if (Pal!=NULL)
    GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
  else
    GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
	if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
	{
		for(i = 0; i <PAL_SIZE; i++)
			Palette.aEntries[i].peFlags = PC_RESERVED;
		Palette.aEntries[255].peRed = 255;
		Palette.aEntries[255].peGreen = 255;
		Palette.aEntries[255].peBlue = 255;
		Palette.aEntries[255].peFlags = 0;
		Palette.aEntries[0].peRed = 0;
		Palette.aEntries[0].peGreen = 0;
		Palette.aEntries[0].peBlue = 0;
		Palette.aEntries[0].peFlags = 0;
	}
	else
	{
		int nStaticColors;
		int nUsableColors;
		nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
		for (i=0; i<nStaticColors; i++)
			Palette.aEntries[i].peFlags = 0;
		nUsableColors = PAL_SIZE-nStaticColors;
		for (; i<nUsableColors; i++)
			Palette.aEntries[i].peFlags = PC_RESERVED;
		for (; i<PAL_SIZE-nStaticColors; i++)
			Palette.aEntries[i].peFlags = PC_RESERVED;
		for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
			Palette.aEntries[i].peFlags = 0;
	}
	ReleaseDC(NULL,hdc);
  for (i=0; i<PAL_SIZE; i++)
  {
    aRGB[i].rgbRed=Palette.aEntries[i].peRed;
    aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
    aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
    aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
  }
  	  ENDPROFILE(GetPalette)
}


WMesaContext APIENTRY WMesaCreateContext( HWND hWnd, HPALETTE Pal, HDC hDC, GLboolean rgb_flag,
                                 GLboolean db_flag )
{
  BITMAPINFO *Rec;
  HDC DC;
  RECT CR;
  WMesaContext c;

  c = (wmesa_context *) calloc(1,sizeof(wmesa_context));
  if (!c)
    return NULL;

  c->Window=hWnd;

  if (rgb_flag==GL_FALSE)
  {
    c->rgb_flag = GL_FALSE;
    c->pixel = 1;
    db_flag=GL_TRUE; // WinG requires double buffering
    //c->gl_ctx->BufferDepth = windepth;
  }
  else
  {
    c->rgb_flag = GL_TRUE;
    c->pixel = 0;
  }
  GetClientRect(c->Window,&CR);
  c->width=CR.right;
  c->height=CR.bottom;
  if (db_flag)
  {
    c->db_flag = 1;
    /* Double buffered */
    if (c->rgb_flag==GL_TRUE)
    {
      DC = c->hDC = hDC;
	  wmCreateBackingStore(c, c->width, c->height);
    }
    else
    {
      c->dib.hDC=WinGCreateDC();
      Rec=(BITMAPINFO *) malloc(sizeof(BITMAPINFO)+(PAL_SIZE-1)*sizeof(RGBQUAD));
      c->hPal=Pal;
      GetPalette(Pal,Rec->bmiColors);
      WinGRecommendDIBFormat(Rec);
      Rec->bmiHeader.biWidth=c->width;
      Rec->bmiHeader.biHeight*=c->height;
      Rec->bmiHeader.biClrUsed=PAL_SIZE;
      if (Rec->bmiHeader.biPlanes!=1 || Rec->bmiHeader.biBitCount!=8)
      {
        MessageBox(NULL,"Error.","This code presumes a 256 color, single plane, WinG Device.\n",MB_OK);
        exit(1);
      }
      c->Compat_BM=WinGCreateBitmap(c->dib.hDC,Rec,&((void *) c->ScreenMem));
      c->Old_Compat_BM=SelectObject(c->dib.hDC,c->Compat_BM);
      WinGSetDIBColorTable(c->dib.hDC,0,PAL_SIZE,Rec->bmiColors);
      c->IndexFormat=Rec;
      c->ScanWidth=c->width;
      if ((c->ScanWidth%sizeof(long))!=0)
        c->ScanWidth+=(sizeof(long)-(c->ScanWidth%sizeof(long)));
    }
  }
  else
  {
    /* Single Buffered */
	c->db_flag = 0;
	DC = c->hDC = hDC;
	wmCreateBackingStore(c, c->width, c->height);
  }

  /* allocate a new Mesa context */
  c->gl_ctx = gl_new_context( rgb_flag,
                              255.0, 255.0, 255.0, 255.0,
                              db_flag, NULL);

  setup_DD_pointers();

  return c;
}



void APIENTRY WMesaDestroyContext( WMesaContext c )
{
	WC = c;
	gl_destroy_context( c->gl_ctx );

	if (c->db_flag){
		wmDeleteBackingStore(c);
	}
	free( (void *) c );
}



void APIENTRY WMesaMakeCurrent( WMesaContext c )
{
	if(!c){
		Current = c;
		return;
	}
	
	//
	// A little optimization
	// If it already is current,
	// don't set it again
	//
	if(Current == c)
		return;

	gl_set_context( c->gl_ctx );
	Current = c;
	setup_DD_pointers();
	if (Current->gl_ctx->Viewport.Width==0) {
	  /* initialize viewport to window size */
	  gl_viewport( 0, 0, Current->width, Current->height );
	}
}



void APIENTRY WMesaSwapBuffers( void )
{
  HDC DC = Current->hDC;
  if (Current->db_flag)
  {
    if (Current->rgb_flag)
		wmFlush(Current);
    else
      WinGBitBlt(DC,0,0,Current->width,Current->height,Current->dib.hDC,0,0);
  }
}



void APIENTRY WMesaPaletteChange(HPALETTE Pal)
{
  if (Current && Current->rgb_flag==GL_FALSE)
  {
    Current->hPal=Pal;
    GetPalette(Pal,Current->IndexFormat->bmiColors);
    WinGSetDIBColorTable(Current->dib.hDC,0,PAL_SIZE,Current->IndexFormat->bmiColors);
  }
}

//
// Free up the dib section that was created
//
BOOL wmDeleteBackingStore(PWMC pwc)
{
	SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
	DeleteDC(pwc->dib.hDC);
	DeleteObject(pwc->hbmDIB);
	UnmapViewOfFile(pwc->dib.base);
	CloseHandle(pwc->dib.hFileMap);

}


//
// This function creates the DIB section that is used for combined
// GL and GDI calls
//
BOOL WINAPI wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
{
    HDC hdc = pwc->hDC;
    LPBITMAPINFO pbmi = &(pwc->bmi);
	int		iUsage;

    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = lxSize;
    pbmi->bmiHeader.biHeight= -lySize;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
    pbmi->bmiHeader.biCompression = BI_RGB;
    pbmi->bmiHeader.biSizeImage = 0;
    pbmi->bmiHeader.biXPelsPerMeter = 0;
    pbmi->bmiHeader.biYPelsPerMeter = 0;
    pbmi->bmiHeader.biClrUsed = 0;
    pbmi->bmiHeader.biClrImportant = 0;

	iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;

	pwc->cColorBits = pbmi->bmiHeader.biBitCount;
	pwc->ScanWidth = lxSize;

	wmCreateDIBSection(hdc, pwc, pbmi, iUsage, (void **)&(pwc->pbPixels));

	if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
		wmCreatePalette( pwc );
		wmSetDibColors( pwc );
	}

	return(TRUE);

}


//
// This function copies one scan line in a DIB section to another
//
BOOL WINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
{
	UINT uiScans = 0;
	LPBYTE	pDest = pwc->pbPixels;
	DWORD	dwNextScan = uiScanWidth;
	DWORD	dwNewScan = uiNewWidth;
	DWORD	dwScanWidth = (uiScanWidth * nBypp);

	//
	// We need to round up to the nearest DWORD
	// and multiply by the number of bytes per
	// pixel
	//
	dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
	dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);

	for(uiScans = 0; uiScans < uiNumScans; uiScans++){
		CopyMemory(pDest, pBits, dwScanWidth);
		pBits += dwNextScan;
		pDest += dwNewScan;
	}

	return(TRUE);

}

BOOL WINAPI wmSetPixelFormat( PWMC pwdc, HDC hDC, DWORD dwFlags )
{
	return(TRUE);
}

static unsigned char threeto8[8] = {
	0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
};

static unsigned char twoto8[4] = {
	0, 0x55, 0xaa, 0xff
};

static unsigned char oneto8[2] = {
	0, 255
};

static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
{
	unsigned char val;

	val = i >> shift;
	switch (nbits) {

		case 1:
			val &= 0x1;
			return oneto8[val];

		case 2:
			val &= 0x3;
			return twoto8[val];

		case 3:
			val &= 0x7;
			return threeto8[val];

		default:
			return 0;
	}
}

void WINAPI wmCreatePalette( PWMC pwdc )
{
    /* Create a compressed and re-expanded 3:3:2 palette */
  	BYTE            i;
	LOGPALETTE     *pPal;
    BYTE           rb, rs, gb, gs, bb, bs;

    pwdc->nColors = 0x100;

	pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
    memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );

	pPal->palVersion = 0x300;

    rb = REDBITS;
    rs = REDSHIFT;
    gb = GREENBITS;
    gs = GREENSHIFT;
    bb = BLUEBITS;
    bs = BLUESHIFT;

    if (pwdc->db_flag) {

        /* Need to make two palettes: one for the screen DC and one for the DIB. */
	    pPal->palNumEntries = pwdc->nColors;
	    for (i = 0; i < pwdc->nColors; i++) {
		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
		    pPal->palPalEntry[i].peFlags = 0;
	    }
    	pwdc->hGLPalette = CreatePalette( pPal );
    	pwdc->hPalette = CreatePalette( pPal );
    } 

	else {
	    pPal->palNumEntries = pwdc->nColors;
	    for (i = 0; i < pwdc->nColors; i++) {
		    pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
		    pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
		    pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
		    pPal->palPalEntry[i].peFlags = 0;
	    }
    	pwdc->hGLPalette = CreatePalette( pPal );
    }
	
	free(pPal);

}

//
// This function sets the color table of a DIB section
// to match that of the destination DC
//
BOOL WINAPI wmSetDibColors(PWMC pwc)
{
    RGBQUAD			*pColTab, *pRGB;
    PALETTEENTRY	*pPal, *pPE;
    int				i, nColors;
	BOOL			bRet=TRUE;
	DWORD			dwErr=0;

    /* Build a color table in the DIB that maps to the
       selected palette in the DC.
	*/
    nColors = 1 << pwc->cColorBits;
	pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
    memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
    GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
    pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
    for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
        pRGB->rgbRed = pPE->peRed;
        pRGB->rgbGreen = pPE->peGreen;
        pRGB->rgbBlue = pPE->peBlue;
    }
	if(pwc->db_flag)
	    bRet = SetDIBColorTable(pwc->hDC, 0, nColors, pColTab );

	if(!bRet)
		dwErr = GetLastError();

    free( pColTab );
    free( pPal );

	return(bRet);
}

void WINAPI wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
{
	LPBYTE	lpb = pwc->pbPixels;
	LPDWORD	lpdw;
	LPWORD	lpw;
	UINT	nBypp = pwc->cColorBits / 8;
	UINT	nOffset = iPixel % nBypp;

	// Move the pixel buffer pointer to the scanline that we
	// want to access

	pwc->dib.fFlushed = FALSE;

	lpb += pwc->ScanWidth * iScanLine;
	// Now move to the desired pixel
	lpb += iPixel * nBypp;

	lpdw = (LPDWORD)lpb;
	lpw = (LPWORD)lpb;

	if(nBypp == 2)
		*lpw = BGR16(r,g,b);
	else if (nBypp == 3){
		*lpdw = BGR24(r,g,b);
	}
	else
		*lpdw = BGR32(r,g,b);

}

void WINAPI wmCreateDIBSection(
	HDC	 hDC,
    PWMC pwc,	// handle of device context
    CONST BITMAPINFO *pbmi,	// address of structure containing bitmap size, format, and color data
    UINT iUsage,	// color data type indicator: RGB values or palette indices
    VOID **ppvBits	// pointer to variable to receive a pointer to the bitmap's bit values
)
{
	DWORD	dwSize = 0;
	DWORD	dwScanWidth;
	UINT	nBypp = pwc->cColorBits / 8;
	HDC		hic;

	dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);

	pwc->ScanWidth = dwScanWidth;

	dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);

	pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
										  NULL,
										  PAGE_READWRITE | SEC_COMMIT,
										  0,
										  dwSize,
										  NULL);

	if (!pwc->dib.hFileMap)
		return;

	pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
								  FILE_MAP_ALL_ACCESS,
								  0,
								  0,
								  0);

	if(!pwc->dib.base){
		CloseHandle(pwc->dib.hFileMap);
		return;
	}

	*ppvBits = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);

	pwc->dib.hDC = CreateCompatibleDC(hDC);

	CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));

	hic = CreateIC("display", NULL, NULL, NULL);

	pwc->hbmDIB = CreateDIBitmap(hic,
						 &(pwc->bmi.bmiHeader),
						 CBM_INIT,
						 pwc->pbPixels,
						 &(pwc->bmi),
						 DIB_RGB_COLORS);

	pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);

	DeleteDC(hic);

	return;

}

//
// Get bits from memory DC and read into "back buffer"
//
BOOL wmGetBits(PWMC pwc)
{
	int		iRet;

	iRet = GetDIBits(pwc->dib.hDC,
			  pwc->hbmDIB,
			  0,
			  pwc->height,
			  pwc->pbPixels,
			  &(pwc->bmi),
			  DIB_RGB_COLORS);

	return(iRet);

}



//
// Flush the DIBits from memory buffer to the memory DC
// and clear the buffer
//
BOOL wmFlushBits(PWMC pwc)
{
	int		iRet;

	iRet = SetDIBits(pwc->dib.hDC,
			  pwc->hbmDIB,
			  0,
			  pwc->height,
			  pwc->pbPixels,
			  &(pwc->bmi),
			  DIB_RGB_COLORS);

	ZeroMemory(pwc->pbPixels, pwc->ScanWidth * pwc->height);

	return(iRet);

}

//
// Blit memory DC to screen DC
//
BOOL WINAPI wmFlush(PWMC pwc)
{
	BOOL	bRet = 0;
	DWORD	dwErr = 0;


	wmFlushBits(pwc);

	bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height, 
		   pwc->dib.hDC, 0, 0, SRCCOPY);

	if(!bRet)
		dwErr = GetLastError();

	pwc->dib.fFlushed = TRUE;

	return(TRUE);

}

/************************************************************
wgl Stubs
************************************************************/
HGLRC WINAPI wglCreateContext(HDC  hdc)
{
	return(NULL);
}

HDC WINAPI wglGetCurrentDC(VOID)
{
	return(NULL);
}

BOOL WINAPI wglDeleteContext(HGLRC  hglrc)
{
	WMesaDestroyContext((WMesaContext)hglrc );
	return(TRUE);
}

HGLRC WINAPI wglGetCurrentContext(VOID)
{
	return((HGLRC)Current);
}

PROC WINAPI wglGetProcAddress(LPCSTR  lpszProc)
{
	return(NULL);
}

BOOL WINAPI wglMakeCurrent(HDC  hdc, HGLRC  hglrc)
{
	WMesaMakeCurrent((WMesaContext)hglrc);
	return(TRUE);
}

BOOL WINAPI wlgMakeShareLists(HGLRC  hglrc1, HGLRC  hglrc2)
{
	return(FALSE);
}

BOOL WINAPI wglUseFontBitmaps(
    HDC  hdc,	//Device context whose font will be used
    DWORD  first,	//Glyph that is the first of a run of glyphs to be turned into bitmap display lists
    DWORD  count,	//Number of glyphs to turn into bitmap display lists
    DWORD  listBase 	//Specifies starting display list
)
{
	return(FALSE);
}

BOOL WINAPI wglUseFontOutlines(
    HDC  hdc,	//Device context of the outline font
    DWORD  first,	//First glyph to be turned into a display list
    DWORD  count,	//Number of glyphs to be turned into display lists
    DWORD  listBase,	//Specifies the starting display list
    FLOAT  deviation,	//Specifies the maximum chordal deviation from the true outlines
    FLOAT  extrusion,	//Extrusion value in the negative z direction
    int  format,	//Specifies line segments or polygons in display lists
    LPGLYPHMETRICSFLOAT  lpgmf 	//Address of buffer to receive glyphs metric data
)
{
	return(FALSE);
}

BOOL WINAPI SwapBuffers(
    HDC  hdc	//Device context whose buffers get swapped
)
{
	WMesaSwapBuffers();
	return(TRUE);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.