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