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