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