wmesa.c revision 29280ac69eeeb7ebddd07f027e65357e50508d93
1/*
2 * Windows (Win32/Win64) device driver for Mesa
3 *
4 */
5
6#include "wmesadef.h"
7#include "colors.h"
8#include <GL/wmesa.h>
9#include <winuser.h>
10#include "context.h"
11#include "extensions.h"
12#include "framebuffer.h"
13#include "renderbuffer.h"
14#include "drivers/common/driverfuncs.h"
15#include "vbo/vbo.h"
16#include "swrast/swrast.h"
17#include "swrast_setup/swrast_setup.h"
18#include "tnl/tnl.h"
19#include "tnl/t_context.h"
20#include "tnl/t_pipeline.h"
21
22
23/* linked list of our Framebuffers (windows) */
24static WMesaFramebuffer FirstFramebuffer = NULL;
25
26
27/**
28 * Create a new WMesaFramebuffer object which will correspond to the
29 * given HDC (Window handle).
30 */
31WMesaFramebuffer
32wmesa_new_framebuffer(HDC hdc, GLvisual *visual)
33{
34    WMesaFramebuffer pwfb
35        = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
36    if (pwfb) {
37        _mesa_initialize_framebuffer(&pwfb->Base, visual);
38        pwfb->hDC = hdc;
39        /* insert at head of list */
40        pwfb->next = FirstFramebuffer;
41        FirstFramebuffer = pwfb;
42    }
43    return pwfb;
44}
45
46/**
47 * Given an hdc, free the corresponding WMesaFramebuffer
48 */
49void
50wmesa_free_framebuffer(HDC hdc)
51{
52    WMesaFramebuffer pwfb, prev;
53    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
54        if (pwfb->hDC == hdc)
55            break;
56	prev = pwfb;
57    }
58    if (pwfb) {
59        struct gl_framebuffer *fb;
60	if (pwfb == FirstFramebuffer)
61	    FirstFramebuffer = pwfb->next;
62	else
63	    prev->next = pwfb->next;
64        fb = &pwfb->Base;
65        _mesa_reference_framebuffer(&fb, NULL);
66    }
67}
68
69/**
70 * Given an hdc, return the corresponding WMesaFramebuffer
71 */
72WMesaFramebuffer
73wmesa_lookup_framebuffer(HDC hdc)
74{
75    WMesaFramebuffer pwfb;
76    for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
77        if (pwfb->hDC == hdc)
78            return pwfb;
79    }
80    return NULL;
81}
82
83
84/**
85 * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
86 */
87static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb)
88{
89    return (WMesaFramebuffer) fb;
90}
91
92
93/**
94 * Given a GLcontext, return the corresponding WMesaContext.
95 */
96static WMesaContext wmesa_context(const GLcontext *ctx)
97{
98    return (WMesaContext) ctx;
99}
100
101
102/*
103 * Every driver should implement a GetString function in order to
104 * return a meaningful GL_RENDERER string.
105 */
106static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
107{
108    return (name == GL_RENDERER) ?
109	(GLubyte *) "Mesa Windows GDI Driver" : NULL;
110}
111
112
113/*
114 * Determine the pixel format based on the pixel size.
115 */
116static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
117{
118    pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
119
120    /* Only 16 and 32 bit targets are supported now */
121    assert(pwfb->cColorBits == 0 ||
122	   pwfb->cColorBits == 16 ||
123	   pwfb->cColorBits == 24 ||
124	   pwfb->cColorBits == 32);
125
126    switch(pwfb->cColorBits){
127    case 8:
128	pwfb->pixelformat = PF_INDEX8;
129	break;
130    case 16:
131	pwfb->pixelformat = PF_5R6G5B;
132	break;
133    case 24:
134    case 32:
135	pwfb->pixelformat = PF_8R8G8B;
136	break;
137    default:
138	pwfb->pixelformat = PF_BADFORMAT;
139    }
140}
141
142
143/**
144 * Create DIB for back buffer.
145 * We write into this memory with the span routines and then blit it
146 * to the window on a buffer swap.
147 */
148BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
149{
150    HDC          hdc = pwfb->hDC;
151    LPBITMAPINFO pbmi = &(pwfb->bmi);
152    HDC          hic;
153
154    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
155    pbmi->bmiHeader.biWidth = lxSize;
156    pbmi->bmiHeader.biHeight= -lySize;
157    pbmi->bmiHeader.biPlanes = 1;
158    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
159    pbmi->bmiHeader.biCompression = BI_RGB;
160    pbmi->bmiHeader.biSizeImage = 0;
161    pbmi->bmiHeader.biXPelsPerMeter = 0;
162    pbmi->bmiHeader.biYPelsPerMeter = 0;
163    pbmi->bmiHeader.biClrUsed = 0;
164    pbmi->bmiHeader.biClrImportant = 0;
165
166    pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
167    pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
168
169    hic = CreateIC("display", NULL, NULL, NULL);
170    pwfb->dib_hDC = CreateCompatibleDC(hic);
171
172    pwfb->hbmDIB = CreateDIBSection(hic,
173				   &pwfb->bmi,
174				   DIB_RGB_COLORS,
175				   (void **)&(pwfb->pbPixels),
176				   0,
177				   0);
178    pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
179
180    DeleteDC(hic);
181
182    wmSetPixelFormat(pwfb, pwfb->hDC);
183    return TRUE;
184}
185
186
187static wmDeleteBackingStore(WMesaFramebuffer pwfb)
188{
189    if (pwfb->hbmDIB) {
190	SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
191	DeleteDC(pwfb->dib_hDC);
192	DeleteObject(pwfb->hbmDIB);
193    }
194}
195
196
197/**
198 * Find the width and height of the window named by hdc.
199 */
200static void
201get_window_size(HDC hdc, GLuint *width, GLuint *height)
202{
203    if (WindowFromDC(hdc)) {
204        RECT rect;
205        GetClientRect(WindowFromDC(hdc), &rect);
206        *width = rect.right - rect.left;
207        *height = rect.bottom - rect.top;
208    }
209    else { /* Memory context */
210        /* From contributed code - use the size of the desktop
211         * for the size of a memory context (?) */
212        *width = GetDeviceCaps(hdc, HORZRES);
213        *height = GetDeviceCaps(hdc, VERTRES);
214    }
215}
216
217
218static void
219wmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height)
220{
221    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
222    get_window_size(pwfb->hDC, width, height);
223}
224
225
226static void wmesa_flush(GLcontext *ctx)
227{
228    WMesaContext pwc = wmesa_context(ctx);
229    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
230
231    if (ctx->Visual.doubleBufferMode == 1) {
232	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
233	       pwfb->dib_hDC, 0, 0, SRCCOPY);
234    }
235    else {
236	/* Do nothing for single buffer */
237    }
238}
239
240
241/**********************************************************************/
242/*****                   CLEAR Functions                          *****/
243/**********************************************************************/
244
245/* If we do not implement these, Mesa clears the buffers via the pixel
246 * span writing interface, which is very slow for a clear operation.
247 */
248
249/*
250 * Set the color index used to clear the color buffer.
251 */
252static void clear_index(GLcontext *ctx, GLuint index)
253{
254    WMesaContext pwc = wmesa_context(ctx);
255    /* Note that indexed mode is not supported yet */
256    pwc->clearColorRef = RGB(0,0,0);
257}
258
259/*
260 * Set the color used to clear the color buffer.
261 */
262static void clear_color(GLcontext *ctx, const GLfloat color[4])
263{
264    WMesaContext pwc = wmesa_context(ctx);
265    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
266    GLubyte col[3];
267    UINT    bytesPerPixel = pwfb->cColorBits / 8;
268
269    CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
270    CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
271    CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
272    pwc->clearColorRef = RGB(col[0], col[1], col[2]);
273    DeleteObject(pwc->clearPen);
274    DeleteObject(pwc->clearBrush);
275    pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
276    pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
277}
278
279
280/*
281 * Clear the specified region of the color buffer using the clear color
282 * or index as specified by one of the two functions above.
283 *
284 * This procedure clears either the front and/or the back COLOR buffers.
285 * Only the "left" buffer is cleared since we are not stereo.
286 * Clearing of the other non-color buffers is left to the swrast.
287 */
288
289static void clear(GLcontext *ctx, GLbitfield mask)
290{
291#define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
292    const GLint x = ctx->DrawBuffer->_Xmin;
293    const GLint y = ctx->DrawBuffer->_Ymin;
294    const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
295    const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
296
297    WMesaContext pwc = wmesa_context(ctx);
298    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
299    int done = 0;
300
301    /* Let swrast do all the work if the masks are not set to
302     * clear all channels. */
303    if (ctx->Color.ColorMask[0] != 0xff ||
304	ctx->Color.ColorMask[1] != 0xff ||
305	ctx->Color.ColorMask[2] != 0xff ||
306	ctx->Color.ColorMask[3] != 0xff) {
307	_swrast_Clear(ctx, mask);
308	return;
309    }
310
311    /* Back buffer */
312    if (mask & BUFFER_BIT_BACK_LEFT) {
313
314	int     i, rowSize;
315	UINT    bytesPerPixel = pwfb->cColorBits / 8;
316	LPBYTE  lpb, clearRow;
317	LPWORD  lpw;
318	BYTE    bColor;
319	WORD    wColor;
320	BYTE    r, g, b;
321	DWORD   dwColor;
322	LPDWORD lpdw;
323
324	/* Try for a fast clear - clearing entire buffer with a single
325	 * byte value. */
326	if (width == ctx->DrawBuffer->Width &&
327            height == ctx->DrawBuffer->Height) { /* entire buffer */
328	    /* Now check for an easy clear value */
329	    switch (bytesPerPixel) {
330	    case 1:
331		bColor = BGR8(GetRValue(pwc->clearColorRef),
332			      GetGValue(pwc->clearColorRef),
333			      GetBValue(pwc->clearColorRef));
334		memset(pwfb->pbPixels, bColor,
335		       pwfb->ScanWidth * height);
336		done = 1;
337		break;
338	    case 2:
339		wColor = BGR16(GetRValue(pwc->clearColorRef),
340			       GetGValue(pwc->clearColorRef),
341			       GetBValue(pwc->clearColorRef));
342		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
343		    memset(pwfb->pbPixels, wColor & 0xff,
344			   pwfb->ScanWidth * height);
345		    done = 1;
346		}
347		break;
348	    case 3:
349		/* fall through */
350	    case 4:
351		if (GetRValue(pwc->clearColorRef) ==
352		    GetGValue(pwc->clearColorRef) &&
353		    GetRValue(pwc->clearColorRef) ==
354		    GetBValue(pwc->clearColorRef)) {
355		    memset(pwfb->pbPixels,
356			   GetRValue(pwc->clearColorRef),
357			   pwfb->ScanWidth * height);
358		    done = 1;
359		}
360		break;
361	    default:
362		break;
363	    }
364	} /* all */
365
366	if (!done) {
367	    /* Need to clear a row at a time.  Begin by setting the first
368	     * row in the area to be cleared to the clear color. */
369
370	    clearRow = pwfb->pbPixels +
371		pwfb->ScanWidth * FLIP(y) +
372		bytesPerPixel * x;
373	    switch (bytesPerPixel) {
374	    case 1:
375		lpb = clearRow;
376		bColor = BGR8(GetRValue(pwc->clearColorRef),
377			      GetGValue(pwc->clearColorRef),
378			      GetBValue(pwc->clearColorRef));
379		memset(lpb, bColor, width);
380		break;
381	    case 2:
382		lpw = (LPWORD)clearRow;
383		wColor = BGR16(GetRValue(pwc->clearColorRef),
384			       GetGValue(pwc->clearColorRef),
385			       GetBValue(pwc->clearColorRef));
386		for (i=0; i<width; i++)
387		    *lpw++ = wColor;
388		break;
389	    case 3:
390		lpb = clearRow;
391		r = GetRValue(pwc->clearColorRef);
392		g = GetGValue(pwc->clearColorRef);
393		b = GetBValue(pwc->clearColorRef);
394		for (i=0; i<width; i++) {
395		    *lpb++ = b;
396		    *lpb++ = g;
397		    *lpb++ = r;
398		}
399		break;
400	    case 4:
401		lpdw = (LPDWORD)clearRow;
402		dwColor = BGR32(GetRValue(pwc->clearColorRef),
403				GetGValue(pwc->clearColorRef),
404				GetBValue(pwc->clearColorRef));
405		for (i=0; i<width; i++)
406		    *lpdw++ = dwColor;
407		break;
408	    default:
409		break;
410	    } /* switch */
411
412	    /* copy cleared row to other rows in buffer */
413	    lpb = clearRow - pwfb->ScanWidth;
414	    rowSize = width * bytesPerPixel;
415	    for (i=1; i<height; i++) {
416		memcpy(lpb, clearRow, rowSize);
417		lpb -= pwfb->ScanWidth;
418	    }
419	} /* not done */
420	mask &= ~BUFFER_BIT_BACK_LEFT;
421    } /* back buffer */
422
423    /* front buffer */
424    if (mask & BUFFER_BIT_FRONT_LEFT) {
425	HDC DC = pwc->hDC;
426	HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
427	HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
428	Rectangle(DC,
429		  x,
430		  FLIP(y) + 1,
431		  x + width + 1,
432		  FLIP(y) - height + 1);
433	SelectObject(DC, Old_Pen);
434	SelectObject(DC, Old_Brush);
435	mask &= ~BUFFER_BIT_FRONT_LEFT;
436    } /* front buffer */
437
438    /* Call swrast if there is anything left to clear (like DEPTH) */
439    if (mask)
440	_swrast_Clear(ctx, mask);
441
442#undef FLIP
443}
444
445
446/**********************************************************************/
447/*****                   PIXEL Functions                          *****/
448/**********************************************************************/
449
450#define FLIP(Y)  (rb->Height - (Y) - 1)
451
452
453/**
454 ** Front Buffer reading/writing
455 ** These are slow, but work with all non-indexed visual types.
456 **/
457
458/* Write a horizontal span of RGBA color pixels with a boolean mask. */
459static void write_rgba_span_front(const GLcontext *ctx,
460				   struct gl_renderbuffer *rb,
461				   GLuint n, GLint x, GLint y,
462				   const GLubyte rgba[][4],
463				   const GLubyte mask[] )
464{
465   WMesaContext pwc = wmesa_context(ctx);
466   WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
467   CONST BITMAPINFO bmi=
468   {
469      {
470         sizeof(BITMAPINFOHEADER),
471         n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
472      }
473   };
474   HBITMAP bmp=0;
475   HDC mdc=0;
476   typedef union
477   {
478      unsigned i;
479      struct {
480         unsigned b:8, g:8, r:8, a:8;
481      };
482   } BGRA;
483   BGRA *bgra, c;
484   int i;
485
486   if (n < 16) {   // the value 16 is just guessed
487      y=FLIP(y);
488      if (mask) {
489         for (i=0; i<n; i++)
490            if (mask[i])
491               SetPixel(pwc->hDC, x+i, y,
492                        RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
493      }
494      else {
495         for (i=0; i<n; i++)
496            SetPixel(pwc->hDC, x+i, y,
497                     RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
498      }
499   }
500   else {
501      if (!pwfb) {
502         _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
503         return;
504      }
505      bgra=malloc(n*sizeof(BGRA));
506      if (!bgra) {
507         _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
508         return;
509      }
510      c.a=0;
511      if (mask) {
512         for (i=0; i<n; i++) {
513            if (mask[i]) {
514               c.r=rgba[i][RCOMP];
515               c.g=rgba[i][GCOMP];
516               c.b=rgba[i][BCOMP];
517               c.a=rgba[i][ACOMP];
518               bgra[i]=c;
519            }
520            else
521               bgra[i].i=0;
522         }
523      }
524      else {
525         for (i=0; i<n; i++) {
526            c.r=rgba[i][RCOMP];
527            c.g=rgba[i][GCOMP];
528            c.b=rgba[i][BCOMP];
529            c.a=rgba[i][ACOMP];
530            bgra[i]=c;
531         }
532      }
533      bmp=CreateBitmap(n, 1,  1, 32, bgra);
534      mdc=CreateCompatibleDC(pwfb->hDC);
535      SelectObject(mdc, bmp);
536      y=FLIP(y);
537      BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
538      SelectObject(mdc, 0);
539      DeleteObject(bmp);
540      DeleteDC(mdc);
541      free(bgra);
542   }
543}
544
545/* Write a horizontal span of RGB color pixels with a boolean mask. */
546static void write_rgb_span_front(const GLcontext *ctx,
547				  struct gl_renderbuffer *rb,
548				  GLuint n, GLint x, GLint y,
549				  const GLubyte rgb[][3],
550				  const GLubyte mask[] )
551{
552    WMesaContext pwc = wmesa_context(ctx);
553    GLuint i;
554
555    (void) ctx;
556    y=FLIP(y);
557    if (mask) {
558	for (i=0; i<n; i++)
559	    if (mask[i])
560		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
561					       rgb[i][BCOMP]));
562    }
563    else {
564	for (i=0; i<n; i++)
565	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
566					   rgb[i][BCOMP]));
567    }
568
569}
570
571/*
572 * Write a horizontal span of pixels with a boolean mask.  The current color
573 * is used for all pixels.
574 */
575static void write_mono_rgba_span_front(const GLcontext *ctx,
576					struct gl_renderbuffer *rb,
577					GLuint n, GLint x, GLint y,
578					const GLchan color[4],
579					const GLubyte mask[])
580{
581    GLuint i;
582    WMesaContext pwc = wmesa_context(ctx);
583    COLORREF colorref;
584
585    (void) ctx;
586    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
587    y=FLIP(y);
588    if (mask) {
589	for (i=0; i<n; i++)
590	    if (mask[i])
591		SetPixel(pwc->hDC, x+i, y, colorref);
592    }
593    else
594	for (i=0; i<n; i++)
595	    SetPixel(pwc->hDC, x+i, y, colorref);
596
597}
598
599/* Write an array of RGBA pixels with a boolean mask. */
600static void write_rgba_pixels_front(const GLcontext *ctx,
601				     struct gl_renderbuffer *rb,
602				     GLuint n,
603				     const GLint x[], const GLint y[],
604				     const GLubyte rgba[][4],
605				     const GLubyte mask[] )
606{
607    GLuint i;
608    WMesaContext pwc = wmesa_context(ctx);
609    (void) ctx;
610    for (i=0; i<n; i++)
611	if (mask[i])
612	    SetPixel(pwc->hDC, x[i], FLIP(y[i]),
613		     RGB(rgba[i][RCOMP], rgba[i][GCOMP],
614			 rgba[i][BCOMP]));
615}
616
617
618
619/*
620 * Write an array of pixels with a boolean mask.  The current color
621 * is used for all pixels.
622 */
623static void write_mono_rgba_pixels_front(const GLcontext *ctx,
624					  struct gl_renderbuffer *rb,
625					  GLuint n,
626					  const GLint x[], const GLint y[],
627					  const GLchan color[4],
628					  const GLubyte mask[] )
629{
630    GLuint i;
631    WMesaContext pwc = wmesa_context(ctx);
632    COLORREF colorref;
633    (void) ctx;
634    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
635    for (i=0; i<n; i++)
636	if (mask[i])
637	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
638}
639
640/* Read a horizontal span of color pixels. */
641static void read_rgba_span_front(const GLcontext *ctx,
642				  struct gl_renderbuffer *rb,
643				  GLuint n, GLint x, GLint y,
644				  GLubyte rgba[][4] )
645{
646    WMesaContext pwc = wmesa_context(ctx);
647    GLuint i;
648    COLORREF Color;
649    y = FLIP(y);
650    for (i=0; i<n; i++) {
651	Color = GetPixel(pwc->hDC, x+i, y);
652	rgba[i][RCOMP] = GetRValue(Color);
653	rgba[i][GCOMP] = GetGValue(Color);
654	rgba[i][BCOMP] = GetBValue(Color);
655	rgba[i][ACOMP] = 255;
656    }
657}
658
659
660/* Read an array of color pixels. */
661static void read_rgba_pixels_front(const GLcontext *ctx,
662				    struct gl_renderbuffer *rb,
663				    GLuint n, const GLint x[], const GLint y[],
664				    GLubyte rgba[][4])
665{
666    WMesaContext pwc = wmesa_context(ctx);
667    GLuint i;
668    COLORREF Color;
669    for (i=0; i<n; i++) {
670        GLint y2 = FLIP(y[i]);
671        Color = GetPixel(pwc->hDC, x[i], y2);
672        rgba[i][RCOMP] = GetRValue(Color);
673        rgba[i][GCOMP] = GetGValue(Color);
674        rgba[i][BCOMP] = GetBValue(Color);
675        rgba[i][ACOMP] = 255;
676    }
677}
678
679/*********************************************************************/
680
681/* DOUBLE BUFFER 32-bit */
682
683#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
684LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
685*lpdw = BGR32((r),(g),(b)); }
686
687
688
689/* Write a horizontal span of RGBA color pixels with a boolean mask. */
690static void write_rgba_span_32(const GLcontext *ctx,
691			       struct gl_renderbuffer *rb,
692			       GLuint n, GLint x, GLint y,
693			       const GLubyte rgba[][4],
694			       const GLubyte mask[] )
695{
696    WMesaContext pwc = wmesa_context(ctx);
697    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
698    GLuint i;
699    LPDWORD lpdw;
700
701    (void) ctx;
702
703    y=FLIP(y);
704    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
705    if (mask) {
706	for (i=0; i<n; i++)
707	    if (mask[i])
708                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
709				rgba[i][BCOMP]);
710    }
711    else {
712	for (i=0; i<n; i++)
713                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
714				rgba[i][BCOMP]);
715    }
716}
717
718
719/* Write a horizontal span of RGB color pixels with a boolean mask. */
720static void write_rgb_span_32(const GLcontext *ctx,
721			      struct gl_renderbuffer *rb,
722			      GLuint n, GLint x, GLint y,
723			      const GLubyte rgb[][3],
724			      const GLubyte mask[] )
725{
726    WMesaContext pwc = wmesa_context(ctx);
727    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
728    GLuint i;
729    LPDWORD lpdw;
730
731    (void) ctx;
732
733    y=FLIP(y);
734    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
735    if (mask) {
736	for (i=0; i<n; i++)
737	    if (mask[i])
738                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
739				rgb[i][BCOMP]);
740    }
741    else {
742	for (i=0; i<n; i++)
743                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
744				rgb[i][BCOMP]);
745    }
746}
747
748/*
749 * Write a horizontal span of pixels with a boolean mask.  The current color
750 * is used for all pixels.
751 */
752static void write_mono_rgba_span_32(const GLcontext *ctx,
753				    struct gl_renderbuffer *rb,
754				    GLuint n, GLint x, GLint y,
755				    const GLchan color[4],
756				    const GLubyte mask[])
757{
758    LPDWORD lpdw;
759    DWORD pixel;
760    GLuint i;
761    WMesaContext pwc = wmesa_context(ctx);
762    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
763    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
764    y=FLIP(y);
765    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
766    if (mask) {
767	for (i=0; i<n; i++)
768	    if (mask[i])
769                lpdw[i] = pixel;
770    }
771    else
772	for (i=0; i<n; i++)
773                *lpdw++ = pixel;
774
775}
776
777/* Write an array of RGBA pixels with a boolean mask. */
778static void write_rgba_pixels_32(const GLcontext *ctx,
779				 struct gl_renderbuffer *rb,
780				 GLuint n, const GLint x[], const GLint y[],
781				 const GLubyte rgba[][4],
782				 const GLubyte mask[])
783{
784    GLuint i;
785    WMesaContext pwc = wmesa_context(ctx);
786    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
787    for (i=0; i<n; i++)
788	if (mask[i])
789	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
790			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
791}
792
793/*
794 * Write an array of pixels with a boolean mask.  The current color
795 * is used for all pixels.
796 */
797static void write_mono_rgba_pixels_32(const GLcontext *ctx,
798				      struct gl_renderbuffer *rb,
799				      GLuint n,
800				      const GLint x[], const GLint y[],
801				      const GLchan color[4],
802				      const GLubyte mask[])
803{
804    GLuint i;
805    WMesaContext pwc = wmesa_context(ctx);
806    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
807    for (i=0; i<n; i++)
808	if (mask[i])
809	    WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
810			 color[GCOMP], color[BCOMP]);
811}
812
813/* Read a horizontal span of color pixels. */
814static void read_rgba_span_32(const GLcontext *ctx,
815			      struct gl_renderbuffer *rb,
816			      GLuint n, GLint x, GLint y,
817			      GLubyte rgba[][4] )
818{
819    GLuint i;
820    DWORD pixel;
821    LPDWORD lpdw;
822    WMesaContext pwc = wmesa_context(ctx);
823    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
824
825    y = FLIP(y);
826    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
827    for (i=0; i<n; i++) {
828	pixel = lpdw[i];
829	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
830	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
831	rgba[i][BCOMP] = (pixel & 0x000000ff);
832	rgba[i][ACOMP] = 255;
833    }
834}
835
836
837/* Read an array of color pixels. */
838static void read_rgba_pixels_32(const GLcontext *ctx,
839				struct gl_renderbuffer *rb,
840				GLuint n, const GLint x[], const GLint y[],
841				GLubyte rgba[][4])
842{
843    GLuint i;
844    DWORD pixel;
845    LPDWORD lpdw;
846    WMesaContext pwc = wmesa_context(ctx);
847    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
848
849    for (i=0; i<n; i++) {
850	GLint y2 = FLIP(y[i]);
851	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
852	pixel = *lpdw;
853	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
854	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
855	rgba[i][BCOMP] = (pixel & 0x000000ff);
856	rgba[i][ACOMP] = 255;
857  }
858}
859
860
861/*********************************************************************/
862
863/* DOUBLE BUFFER 24-bit */
864
865#define WMSETPIXEL24(pwc, y, x, r, g, b) { \
866LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
867lpb[0] = (b); \
868lpb[1] = (g); \
869lpb[2] = (r); }
870
871/* Write a horizontal span of RGBA color pixels with a boolean mask. */
872static void write_rgba_span_24(const GLcontext *ctx,
873			       struct gl_renderbuffer *rb,
874			       GLuint n, GLint x, GLint y,
875			       const GLubyte rgba[][4],
876			       const GLubyte mask[] )
877{
878    WMesaContext pwc = wmesa_context(ctx);
879    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
880    GLuint i;
881    LPBYTE lpb;
882
883    (void) ctx;
884
885    y=FLIP(y);
886    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
887    if (mask) {
888	for (i=0; i<n; i++)
889	    if (mask[i]) {
890                lpb[3*i] = rgba[i][BCOMP];
891                lpb[3*i+1] = rgba[i][GCOMP];
892                lpb[3*i+2] = rgba[i][RCOMP];
893	    }
894    }
895    else {
896	    for (i=0; i<n; i++) {
897            *lpb++ = rgba[i][BCOMP];
898            *lpb++ = rgba[i][GCOMP];
899            *lpb++ = rgba[i][RCOMP];
900	    }
901    }
902}
903
904
905/* Write a horizontal span of RGB color pixels with a boolean mask. */
906static void write_rgb_span_24(const GLcontext *ctx,
907			      struct gl_renderbuffer *rb,
908			      GLuint n, GLint x, GLint y,
909			      const GLubyte rgb[][3],
910			      const GLubyte mask[] )
911{
912    WMesaContext pwc = wmesa_context(ctx);
913    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
914    GLuint i;
915    LPBYTE lpb;
916
917    (void) ctx;
918
919    y=FLIP(y);
920    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
921    if (mask) {
922	for (i=0; i<n; i++)
923	    if (mask[i]) {
924            lpb[3*i] = rgb[i][BCOMP];
925            lpb[3*i+1] = rgb[i][GCOMP];
926            lpb[3*i+2] = rgb[i][RCOMP];
927	    }
928    }
929    else {
930    	for (i=0; i<n; i++) {
931    		*lpb++ = rgb[i][BCOMP];
932    		*lpb++ = rgb[i][GCOMP];
933    		*lpb++ = rgb[i][RCOMP];
934    	}
935    }
936}
937
938/*
939 * Write a horizontal span of pixels with a boolean mask.  The current color
940 * is used for all pixels.
941 */
942static void write_mono_rgba_span_24(const GLcontext *ctx,
943				    struct gl_renderbuffer *rb,
944				    GLuint n, GLint x, GLint y,
945				    const GLchan color[4],
946				    const GLubyte mask[])
947{
948    LPBYTE lpb;
949    GLuint i;
950    WMesaContext pwc = wmesa_context(ctx);
951    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
952    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
953    y=FLIP(y);
954    if (mask) {
955	for (i=0; i<n; i++)
956	    if (mask[i]) {
957	    	lpb[3*i] = color[BCOMP];
958	    	lpb[3*i+1] = color[GCOMP];
959	    	lpb[3*i+2] = color[RCOMP];
960	    }
961    }
962    else
963	for (i=0; i<n; i++) {
964		*lpb++ = color[BCOMP];
965		*lpb++ = color[GCOMP];
966		*lpb++ = color[RCOMP];
967	}
968}
969
970/* Write an array of RGBA pixels with a boolean mask. */
971static void write_rgba_pixels_24(const GLcontext *ctx,
972				 struct gl_renderbuffer *rb,
973				 GLuint n, const GLint x[], const GLint y[],
974				 const GLubyte rgba[][4],
975				 const GLubyte mask[])
976{
977    GLuint i;
978    WMesaContext pwc = wmesa_context(ctx);
979    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
980    for (i=0; i<n; i++)
981	if (mask[i])
982	    WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
983			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
984}
985
986/*
987 * Write an array of pixels with a boolean mask.  The current color
988 * is used for all pixels.
989 */
990static void write_mono_rgba_pixels_24(const GLcontext *ctx,
991				      struct gl_renderbuffer *rb,
992				      GLuint n,
993				      const GLint x[], const GLint y[],
994				      const GLchan color[4],
995				      const GLubyte mask[])
996{
997    GLuint i;
998    WMesaContext pwc = wmesa_context(ctx);
999    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1000    for (i=0; i<n; i++)
1001	if (mask[i])
1002	    WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
1003			 color[GCOMP], color[BCOMP]);
1004}
1005
1006/* Read a horizontal span of color pixels. */
1007static void read_rgba_span_24(const GLcontext *ctx,
1008			      struct gl_renderbuffer *rb,
1009			      GLuint n, GLint x, GLint y,
1010			      GLubyte rgba[][4] )
1011{
1012    GLuint i;
1013    LPBYTE lpb;
1014    WMesaContext pwc = wmesa_context(ctx);
1015    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1016
1017    y = FLIP(y);
1018    lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
1019    for (i=0; i<n; i++) {
1020	rgba[i][RCOMP] = lpb[3*i+2];
1021	rgba[i][GCOMP] = lpb[3*i+1];
1022	rgba[i][BCOMP] = lpb[3*i];
1023	rgba[i][ACOMP] = 255;
1024    }
1025}
1026
1027
1028/* Read an array of color pixels. */
1029static void read_rgba_pixels_24(const GLcontext *ctx,
1030				struct gl_renderbuffer *rb,
1031				GLuint n, const GLint x[], const GLint y[],
1032				GLubyte rgba[][4])
1033{
1034    GLuint i;
1035    LPBYTE lpb;
1036    WMesaContext pwc = wmesa_context(ctx);
1037    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1038
1039    for (i=0; i<n; i++) {
1040	GLint y2 = FLIP(y[i]);
1041	lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
1042	rgba[i][RCOMP] = lpb[3*i+2];
1043	rgba[i][GCOMP] = lpb[3*i+1];
1044	rgba[i][BCOMP] = lpb[3*i];
1045	rgba[i][ACOMP] = 255;
1046  }
1047}
1048
1049
1050/*********************************************************************/
1051
1052/* DOUBLE BUFFER 16-bit */
1053
1054#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
1055LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
1056*lpw = BGR16((r),(g),(b)); }
1057
1058
1059
1060/* Write a horizontal span of RGBA color pixels with a boolean mask. */
1061static void write_rgba_span_16(const GLcontext *ctx,
1062			       struct gl_renderbuffer *rb,
1063			       GLuint n, GLint x, GLint y,
1064			       const GLubyte rgba[][4],
1065			       const GLubyte mask[] )
1066{
1067    WMesaContext pwc = wmesa_context(ctx);
1068    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1069    GLuint i;
1070    LPWORD lpw;
1071
1072    (void) ctx;
1073
1074    y=FLIP(y);
1075    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1076    if (mask) {
1077	for (i=0; i<n; i++)
1078	    if (mask[i])
1079                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
1080			       rgba[i][BCOMP]);
1081    }
1082    else {
1083	for (i=0; i<n; i++)
1084                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
1085			       rgba[i][BCOMP]);
1086    }
1087}
1088
1089
1090/* Write a horizontal span of RGB color pixels with a boolean mask. */
1091static void write_rgb_span_16(const GLcontext *ctx,
1092			      struct gl_renderbuffer *rb,
1093			      GLuint n, GLint x, GLint y,
1094			      const GLubyte rgb[][3],
1095			      const GLubyte mask[] )
1096{
1097    WMesaContext pwc = wmesa_context(ctx);
1098    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1099    GLuint i;
1100    LPWORD lpw;
1101
1102    (void) ctx;
1103
1104    y=FLIP(y);
1105    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1106    if (mask) {
1107	for (i=0; i<n; i++)
1108	    if (mask[i])
1109                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
1110			       rgb[i][BCOMP]);
1111    }
1112    else {
1113	for (i=0; i<n; i++)
1114                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
1115			       rgb[i][BCOMP]);
1116    }
1117}
1118
1119/*
1120 * Write a horizontal span of pixels with a boolean mask.  The current color
1121 * is used for all pixels.
1122 */
1123static void write_mono_rgba_span_16(const GLcontext *ctx,
1124				    struct gl_renderbuffer *rb,
1125				    GLuint n, GLint x, GLint y,
1126				    const GLchan color[4],
1127				    const GLubyte mask[])
1128{
1129    LPWORD lpw;
1130    WORD pixel;
1131    GLuint i;
1132    WMesaContext pwc = wmesa_context(ctx);
1133    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1134    (void) ctx;
1135    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1136    y=FLIP(y);
1137    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
1138    if (mask) {
1139	for (i=0; i<n; i++)
1140	    if (mask[i])
1141                lpw[i] = pixel;
1142    }
1143    else
1144	for (i=0; i<n; i++)
1145                *lpw++ = pixel;
1146
1147}
1148
1149/* Write an array of RGBA pixels with a boolean mask. */
1150static void write_rgba_pixels_16(const GLcontext *ctx,
1151				 struct gl_renderbuffer *rb,
1152				 GLuint n, const GLint x[], const GLint y[],
1153				 const GLubyte rgba[][4],
1154				 const GLubyte mask[])
1155{
1156    GLuint i;
1157    WMesaContext pwc = wmesa_context(ctx);
1158    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1159    (void) ctx;
1160    for (i=0; i<n; i++)
1161	if (mask[i])
1162	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
1163			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1164}
1165
1166/*
1167 * Write an array of pixels with a boolean mask.  The current color
1168 * is used for all pixels.
1169 */
1170static void write_mono_rgba_pixels_16(const GLcontext *ctx,
1171				      struct gl_renderbuffer *rb,
1172				      GLuint n,
1173				      const GLint x[], const GLint y[],
1174				      const GLchan color[4],
1175				      const GLubyte mask[])
1176{
1177    GLuint i;
1178    WMesaContext pwc = wmesa_context(ctx);
1179    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1180    (void) ctx;
1181    for (i=0; i<n; i++)
1182	if (mask[i])
1183	    WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
1184			 color[GCOMP], color[BCOMP]);
1185}
1186
1187/* Read a horizontal span of color pixels. */
1188static void read_rgba_span_16(const GLcontext *ctx,
1189			      struct gl_renderbuffer *rb,
1190			      GLuint n, GLint x, GLint y,
1191			      GLubyte rgba[][4] )
1192{
1193    GLuint i, pixel;
1194    LPWORD lpw;
1195    WMesaContext pwc = wmesa_context(ctx);
1196    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1197
1198    y = FLIP(y);
1199    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1200    for (i=0; i<n; i++) {
1201	pixel = lpw[i];
1202	/* Windows uses 5,5,5 for 16-bit */
1203	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1204	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1205	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1206	rgba[i][ACOMP] = 255;
1207    }
1208}
1209
1210
1211/* Read an array of color pixels. */
1212static void read_rgba_pixels_16(const GLcontext *ctx,
1213				struct gl_renderbuffer *rb,
1214				GLuint n, const GLint x[], const GLint y[],
1215				GLubyte rgba[][4])
1216{
1217    GLuint i, pixel;
1218    LPWORD lpw;
1219    WMesaContext pwc = wmesa_context(ctx);
1220    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1221
1222    for (i=0; i<n; i++) {
1223	GLint y2 = FLIP(y[i]);
1224	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
1225	pixel = *lpw;
1226	/* Windows uses 5,5,5 for 16-bit */
1227	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1228	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1229	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1230	rgba[i][ACOMP] = 255;
1231  }
1232}
1233
1234
1235
1236
1237/**********************************************************************/
1238/*****                   BUFFER Functions                         *****/
1239/**********************************************************************/
1240
1241
1242
1243
1244static void
1245wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1246{
1247    _mesa_free(rb);
1248}
1249
1250
1251/**
1252 * This is called by Mesa whenever it determines that the window size
1253 * has changed.  Do whatever's needed to cope with that.
1254 */
1255static GLboolean
1256wmesa_renderbuffer_storage(GLcontext *ctx,
1257			   struct gl_renderbuffer *rb,
1258			   GLenum internalFormat,
1259			   GLuint width,
1260			   GLuint height)
1261{
1262    rb->Width = width;
1263    rb->Height = height;
1264    return GL_TRUE;
1265}
1266
1267
1268/**
1269 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1270 * on if we're drawing to the front or back color buffer.
1271 */
1272void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
1273                                  BYTE cColorBits, int double_buffer)
1274{
1275    if (double_buffer) {
1276        /* back buffer */
1277	/* Picking the correct span functions is important because
1278	 * the DIB was allocated with the indicated depth. */
1279	switch(pixelformat) {
1280	case PF_5R6G5B:
1281	    rb->PutRow = write_rgba_span_16;
1282	    rb->PutRowRGB = write_rgb_span_16;
1283	    rb->PutMonoRow = write_mono_rgba_span_16;
1284	    rb->PutValues = write_rgba_pixels_16;
1285	    rb->PutMonoValues = write_mono_rgba_pixels_16;
1286	    rb->GetRow = read_rgba_span_16;
1287	    rb->GetValues = read_rgba_pixels_16;
1288            rb->RedBits = 5;
1289            rb->GreenBits = 6;
1290            rb->BlueBits = 5;
1291	    break;
1292	case PF_8R8G8B:
1293		if (cColorBits == 24)
1294		{
1295		    rb->PutRow = write_rgba_span_24;
1296		    rb->PutRowRGB = write_rgb_span_24;
1297		    rb->PutMonoRow = write_mono_rgba_span_24;
1298		    rb->PutValues = write_rgba_pixels_24;
1299		    rb->PutMonoValues = write_mono_rgba_pixels_24;
1300		    rb->GetRow = read_rgba_span_24;
1301		    rb->GetValues = read_rgba_pixels_24;
1302	        rb->RedBits = 8;
1303	        rb->GreenBits = 8;
1304	        rb->BlueBits = 8;
1305		}
1306		else
1307		{
1308	        rb->PutRow = write_rgba_span_32;
1309	        rb->PutRowRGB = write_rgb_span_32;
1310	        rb->PutMonoRow = write_mono_rgba_span_32;
1311	        rb->PutValues = write_rgba_pixels_32;
1312	        rb->PutMonoValues = write_mono_rgba_pixels_32;
1313	        rb->GetRow = read_rgba_span_32;
1314	        rb->GetValues = read_rgba_pixels_32;
1315            rb->RedBits = 8;
1316            rb->GreenBits = 8;
1317            rb->BlueBits = 8;
1318		}
1319	    break;
1320	default:
1321	    break;
1322	}
1323    }
1324    else {
1325        /* front buffer (actual Windows window) */
1326	rb->PutRow = write_rgba_span_front;
1327	rb->PutRowRGB = write_rgb_span_front;
1328	rb->PutMonoRow = write_mono_rgba_span_front;
1329	rb->PutValues = write_rgba_pixels_front;
1330	rb->PutMonoValues = write_mono_rgba_pixels_front;
1331	rb->GetRow = read_rgba_span_front;
1332	rb->GetValues = read_rgba_pixels_front;
1333        rb->RedBits = 8; /* XXX fix these (565?) */
1334        rb->GreenBits = 8;
1335        rb->BlueBits = 8;
1336    }
1337}
1338
1339/**
1340 * Called by ctx->Driver.ResizeBuffers()
1341 * Resize the front/back colorbuffers to match the latest window size.
1342 */
1343static void
1344wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
1345                     GLuint width, GLuint height)
1346{
1347    WMesaContext pwc = wmesa_context(ctx);
1348    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
1349
1350    if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
1351	/* Realloc back buffer */
1352	if (ctx->Visual.doubleBufferMode == 1) {
1353	    wmDeleteBackingStore(pwfb);
1354	    wmCreateBackingStore(pwfb, width, height);
1355	}
1356    }
1357    _mesa_resize_framebuffer(ctx, buffer, width, height);
1358}
1359
1360
1361/**
1362 * Called by glViewport.
1363 * This is a good time for us to poll the current window size and adjust
1364 * our renderbuffers to match the current window size.
1365 * Remember, we have no opportunity to respond to conventional
1366 * resize events since the driver has no event loop.
1367 * Thus, we poll.
1368 * MakeCurrent also ends up making a call here, so that ensures
1369 * we get the viewport set correctly, even if the app does not call
1370 * glViewport and relies on the defaults.
1371 */
1372static void wmesa_viewport(GLcontext *ctx,
1373			   GLint x, GLint y,
1374			   GLsizei width, GLsizei height)
1375{
1376    WMesaContext pwc = wmesa_context(ctx);
1377    GLuint new_width, new_height;
1378
1379    wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
1380
1381    /**
1382     * Resize buffers if the window size changed.
1383     */
1384    wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
1385    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
1386}
1387
1388
1389
1390
1391/**
1392 * Called when the driver should update it's state, based on the new_state
1393 * flags.
1394 */
1395static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
1396{
1397    _swrast_InvalidateState(ctx, new_state);
1398    _swsetup_InvalidateState(ctx, new_state);
1399    _vbo_InvalidateState(ctx, new_state);
1400    _tnl_InvalidateState(ctx, new_state);
1401
1402    /* TODO - This code is not complete yet because I
1403     * don't know what to do for all state updates.
1404     */
1405
1406    if (new_state & _NEW_BUFFERS) {
1407    }
1408}
1409
1410
1411
1412
1413
1414/**********************************************************************/
1415/*****                   WMESA Functions                          *****/
1416/**********************************************************************/
1417
1418WMesaContext WMesaCreateContext(HDC hDC,
1419				HPALETTE* Pal,
1420				GLboolean rgb_flag,
1421				GLboolean db_flag,
1422				GLboolean alpha_flag)
1423{
1424    WMesaContext c;
1425    struct dd_function_table functions;
1426    GLint red_bits, green_bits, blue_bits, alpha_bits;
1427    GLcontext *ctx;
1428    GLvisual *visual;
1429
1430    (void) Pal;
1431
1432    /* Indexed mode not supported */
1433    if (!rgb_flag)
1434	return NULL;
1435
1436    /* Allocate wmesa context */
1437    c = CALLOC_STRUCT(wmesa_context);
1438    if (!c)
1439	return NULL;
1440
1441#if 0
1442    /* I do not understand this contributed code */
1443    /* Support memory and device contexts */
1444    if(WindowFromDC(hDC) != NULL) {
1445	c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
1446    }
1447    else {
1448	c->hDC = hDC;
1449    }
1450#else
1451    c->hDC = hDC;
1452#endif
1453
1454    /* Get data for visual */
1455    /* Dealing with this is actually a bit of overkill because Mesa will end
1456     * up treating all color component size requests less than 8 by using
1457     * a single byte per channel.  In addition, the interface to the span
1458     * routines passes colors as an entire byte per channel anyway, so there
1459     * is nothing to be saved by telling the visual to be 16 bits if the device
1460     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
1461     * channel anyway.
1462     * But we go through the motions here anyway.
1463     */
1464    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
1465    case 16:
1466	red_bits = green_bits = blue_bits = 5;
1467	alpha_bits = 0;
1468	break;
1469    default:
1470	red_bits = green_bits = blue_bits = 8;
1471	alpha_bits = 8;
1472	break;
1473    }
1474    /* Create visual based on flags */
1475    visual = _mesa_create_visual(rgb_flag,
1476                                 db_flag,    /* db_flag */
1477                                 GL_FALSE,   /* stereo */
1478                                 red_bits, green_bits, blue_bits, /* color RGB */
1479                                 alpha_flag ? alpha_bits : 0, /* color A */
1480                                 0,          /* index bits */
1481                                 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
1482                                 8,          /* stencil_bits */
1483                                 16,16,16,   /* accum RGB */
1484                                 alpha_flag ? 16 : 0, /* accum A */
1485                                 1);         /* num samples */
1486
1487    if (!visual) {
1488	_mesa_free(c);
1489	return NULL;
1490    }
1491
1492    /* Set up driver functions */
1493    _mesa_init_driver_functions(&functions);
1494    functions.GetString = wmesa_get_string;
1495    functions.UpdateState = wmesa_update_state;
1496    functions.GetBufferSize = wmesa_get_buffer_size;
1497    functions.Flush = wmesa_flush;
1498    functions.Clear = clear;
1499    functions.ClearIndex = clear_index;
1500    functions.ClearColor = clear_color;
1501    functions.ResizeBuffers = wmesa_resize_buffers;
1502    functions.Viewport = wmesa_viewport;
1503
1504    /* initialize the Mesa context data */
1505    ctx = &c->gl_ctx;
1506    _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
1507
1508    /* visual no longer needed - it was copied by _mesa_initialize_context() */
1509    _mesa_destroy_visual(visual);
1510
1511    _mesa_enable_sw_extensions(ctx);
1512    _mesa_enable_1_3_extensions(ctx);
1513    _mesa_enable_1_4_extensions(ctx);
1514    _mesa_enable_1_5_extensions(ctx);
1515    _mesa_enable_2_0_extensions(ctx);
1516    _mesa_enable_2_1_extensions(ctx);
1517
1518    /* Initialize the software rasterizer and helper modules. */
1519    if (!_swrast_CreateContext(ctx) ||
1520        !_vbo_CreateContext(ctx) ||
1521        !_tnl_CreateContext(ctx) ||
1522	!_swsetup_CreateContext(ctx)) {
1523	_mesa_free_context_data(ctx);
1524	_mesa_free(c);
1525	return NULL;
1526    }
1527    _swsetup_Wakeup(ctx);
1528    TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1529
1530    return c;
1531}
1532
1533
1534void WMesaDestroyContext( WMesaContext pwc )
1535{
1536    GLcontext *ctx = &pwc->gl_ctx;
1537    WMesaFramebuffer pwfb;
1538    GET_CURRENT_CONTEXT(cur_ctx);
1539
1540    if (cur_ctx == ctx) {
1541        /* unbind current if deleting current context */
1542        WMesaMakeCurrent(NULL, NULL);
1543    }
1544
1545    /* clean up frame buffer resources */
1546    pwfb = wmesa_lookup_framebuffer(pwc->hDC);
1547    if (pwfb) {
1548	if (ctx->Visual.doubleBufferMode == 1)
1549	    wmDeleteBackingStore(pwfb);
1550	wmesa_free_framebuffer(pwc->hDC);
1551    }
1552
1553    /* Release for device, not memory contexts */
1554    if (WindowFromDC(pwc->hDC) != NULL)
1555    {
1556      ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
1557    }
1558    DeleteObject(pwc->clearPen);
1559    DeleteObject(pwc->clearBrush);
1560
1561    _swsetup_DestroyContext(ctx);
1562    _tnl_DestroyContext(ctx);
1563    _vbo_DestroyContext(ctx);
1564    _swrast_DestroyContext(ctx);
1565
1566    _mesa_free_context_data(ctx);
1567    _mesa_free(pwc);
1568}
1569
1570
1571/**
1572 * Create a new color renderbuffer.
1573 */
1574struct gl_renderbuffer *
1575wmesa_new_renderbuffer(void)
1576{
1577    struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1578    if (!rb)
1579        return NULL;
1580
1581    _mesa_init_renderbuffer(rb, (GLuint)0);
1582
1583    rb->_BaseFormat = GL_RGBA;
1584    rb->InternalFormat = GL_RGBA;
1585    rb->DataType = CHAN_TYPE;
1586    rb->Delete = wmesa_delete_renderbuffer;
1587    rb->AllocStorage = wmesa_renderbuffer_storage;
1588    return rb;
1589}
1590
1591
1592void WMesaMakeCurrent(WMesaContext c, HDC hdc)
1593{
1594    WMesaFramebuffer pwfb;
1595
1596    {
1597        /* return if already current */
1598        GET_CURRENT_CONTEXT(ctx);
1599        WMesaContext pwc = wmesa_context(ctx);
1600        if (pwc && c == pwc && pwc->hDC == hdc)
1601            return;
1602    }
1603
1604    pwfb = wmesa_lookup_framebuffer(hdc);
1605
1606    /* Lazy creation of framebuffers */
1607    if (c && !pwfb && hdc) {
1608        struct gl_renderbuffer *rb;
1609        GLvisual *visual = &c->gl_ctx.Visual;
1610        GLuint width, height;
1611
1612        get_window_size(hdc, &width, &height);
1613
1614	c->clearPen = CreatePen(PS_SOLID, 1, 0);
1615	c->clearBrush = CreateSolidBrush(0);
1616
1617        pwfb = wmesa_new_framebuffer(hdc, visual);
1618
1619	/* Create back buffer if double buffered */
1620	if (visual->doubleBufferMode == 1) {
1621	    wmCreateBackingStore(pwfb, width, height);
1622	}
1623
1624        /* make render buffers */
1625        if (visual->doubleBufferMode == 1) {
1626            rb = wmesa_new_renderbuffer();
1627            _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
1628            wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
1629	}
1630        rb = wmesa_new_renderbuffer();
1631        _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
1632        wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
1633
1634	/* Let Mesa own the Depth, Stencil, and Accum buffers */
1635        _mesa_add_soft_renderbuffers(&pwfb->Base,
1636                                     GL_FALSE, /* color */
1637                                     visual->depthBits > 0,
1638                                     visual->stencilBits > 0,
1639                                     visual->accumRedBits > 0,
1640                                     visual->alphaBits >0,
1641                                     GL_FALSE);
1642    }
1643
1644    if (c && pwfb)
1645	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
1646    else
1647        _mesa_make_current(NULL, NULL, NULL);
1648}
1649
1650
1651void WMesaSwapBuffers( HDC hdc )
1652{
1653    GET_CURRENT_CONTEXT(ctx);
1654    WMesaContext pwc = wmesa_context(ctx);
1655    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
1656
1657    if (!pwfb) {
1658        _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
1659        return;
1660    }
1661
1662    /* If we're swapping the buffer associated with the current context
1663     * we have to flush any pending rendering commands first.
1664     */
1665    if (pwc->hDC == hdc) {
1666	_mesa_notifySwapBuffers(ctx);
1667
1668	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
1669	       pwfb->dib_hDC, 0, 0, SRCCOPY);
1670    }
1671    else {
1672        /* XXX for now only allow swapping current window */
1673        _mesa_problem(NULL, "wmesa: can't swap non-current window");
1674    }
1675}
1676
1677void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
1678{
1679	_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
1680}
1681
1682