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