wmesa.c revision 174ce730c6c9739121c02c7d58e7d8be377d2231
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,
285		  GLbitfield mask,
286		  GLboolean all,
287		  GLint x, GLint y,
288		  GLint width, GLint height)
289{
290#define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
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, all, x, y, width, height);
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 (all) { /* entire buffer */
322	    /* Now check for an easy clear value */
323	    switch (bytesPerPixel) {
324	    case 1:
325		bColor = BGR8(GetRValue(pwc->clearColorRef),
326			      GetGValue(pwc->clearColorRef),
327			      GetBValue(pwc->clearColorRef));
328		memset(pwfb->pbPixels, bColor,
329		       pwfb->ScanWidth * height);
330		done = 1;
331		break;
332	    case 2:
333		wColor = BGR16(GetRValue(pwc->clearColorRef),
334			       GetGValue(pwc->clearColorRef),
335			       GetBValue(pwc->clearColorRef));
336		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
337		    memset(pwfb->pbPixels, wColor & 0xff,
338			   pwfb->ScanWidth * height);
339		    done = 1;
340		}
341		break;
342	    case 3:
343		/* fall through */
344	    case 4:
345		if (GetRValue(pwc->clearColorRef) ==
346		    GetGValue(pwc->clearColorRef) &&
347		    GetRValue(pwc->clearColorRef) ==
348		    GetBValue(pwc->clearColorRef)) {
349		    memset(pwfb->pbPixels,
350			   GetRValue(pwc->clearColorRef),
351			   pwfb->ScanWidth * height);
352		    done = 1;
353		}
354		break;
355	    default:
356		break;
357	    }
358	} /* all */
359
360	if (!done) {
361	    /* Need to clear a row at a time.  Begin by setting the first
362	     * row in the area to be cleared to the clear color. */
363
364	    clearRow = pwfb->pbPixels +
365		pwfb->ScanWidth * FLIP(y) +
366		bytesPerPixel * x;
367	    switch (bytesPerPixel) {
368	    case 1:
369		lpb = clearRow;
370		bColor = BGR8(GetRValue(pwc->clearColorRef),
371			      GetGValue(pwc->clearColorRef),
372			      GetBValue(pwc->clearColorRef));
373		memset(lpb, bColor, width);
374		break;
375	    case 2:
376		lpw = (LPWORD)clearRow;
377		wColor = BGR16(GetRValue(pwc->clearColorRef),
378			       GetGValue(pwc->clearColorRef),
379			       GetBValue(pwc->clearColorRef));
380		for (i=0; i<width; i++)
381		    *lpw++ = wColor;
382		break;
383	    case 3:
384		lpb = clearRow;
385		r = GetRValue(pwc->clearColorRef);
386		g = GetGValue(pwc->clearColorRef);
387		b = GetBValue(pwc->clearColorRef);
388		for (i=0; i<width; i++) {
389		    *lpb++ = b;
390		    *lpb++ = g;
391		    *lpb++ = r;
392		}
393		break;
394	    case 4:
395		lpdw = (LPDWORD)clearRow;
396		dwColor = BGR32(GetRValue(pwc->clearColorRef),
397				GetGValue(pwc->clearColorRef),
398				GetBValue(pwc->clearColorRef));
399		for (i=0; i<width; i++)
400		    *lpdw++ = dwColor;
401		break;
402	    default:
403		break;
404	    } /* switch */
405
406	    /* copy cleared row to other rows in buffer */
407	    lpb = clearRow - pwfb->ScanWidth;
408	    rowSize = width * bytesPerPixel;
409	    for (i=1; i<height; i++) {
410		memcpy(lpb, clearRow, rowSize);
411		lpb -= pwfb->ScanWidth;
412	    }
413	} /* not done */
414	mask &= ~BUFFER_BIT_BACK_LEFT;
415    } /* back buffer */
416
417    /* front buffer */
418    if (mask & BUFFER_BIT_FRONT_LEFT) {
419	HDC DC = pwc->hDC;
420	HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
421	HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
422	Rectangle(DC,
423		  x,
424		  FLIP(y) + 1,
425		  x + width + 1,
426		  FLIP(y) - height + 1);
427	SelectObject(DC, Old_Pen);
428	SelectObject(DC, Old_Brush);
429	mask &= ~BUFFER_BIT_FRONT_LEFT;
430    } /* front buffer */
431
432    /* Call swrast if there is anything left to clear (like DEPTH) */
433    if (mask)
434	_swrast_Clear(ctx, mask, all, x, y, width, height);
435
436#undef FLIP
437}
438
439
440/**********************************************************************/
441/*****                   PIXEL Functions                          *****/
442/**********************************************************************/
443
444#define FLIP(Y)  (rb->Height - (Y) - 1)
445
446
447/**
448 ** Front Buffer reading/writing
449 ** These are slow, but work with all non-indexed visual types.
450 **/
451
452/* Write a horizontal span of RGBA color pixels with a boolean mask. */
453static void write_rgba_span_front(const GLcontext *ctx,
454				   struct gl_renderbuffer *rb,
455				   GLuint n, GLint x, GLint y,
456				   const GLubyte rgba[][4],
457				   const GLubyte mask[] )
458{
459    WMesaContext pwc = wmesa_context(ctx);
460    GLuint i;
461
462    (void) ctx;
463    y=FLIP(y);
464    if (mask) {
465	for (i=0; i<n; i++)
466	    if (mask[i])
467		SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
468					       rgba[i][BCOMP]));
469    }
470    else {
471	for (i=0; i<n; i++)
472	    SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
473					   rgba[i][BCOMP]));
474    }
475
476}
477
478/* Write a horizontal span of RGB color pixels with a boolean mask. */
479static void write_rgb_span_front(const GLcontext *ctx,
480				  struct gl_renderbuffer *rb,
481				  GLuint n, GLint x, GLint y,
482				  const GLubyte rgb[][3],
483				  const GLubyte mask[] )
484{
485    WMesaContext pwc = wmesa_context(ctx);
486    GLuint i;
487
488    (void) ctx;
489    y=FLIP(y);
490    if (mask) {
491	for (i=0; i<n; i++)
492	    if (mask[i])
493		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
494					       rgb[i][BCOMP]));
495    }
496    else {
497	for (i=0; i<n; i++)
498	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
499					   rgb[i][BCOMP]));
500    }
501
502}
503
504/*
505 * Write a horizontal span of pixels with a boolean mask.  The current color
506 * is used for all pixels.
507 */
508static void write_mono_rgba_span_front(const GLcontext *ctx,
509					struct gl_renderbuffer *rb,
510					GLuint n, GLint x, GLint y,
511					const GLchan color[4],
512					const GLubyte mask[])
513{
514    GLuint i;
515    WMesaContext pwc = wmesa_context(ctx);
516    COLORREF colorref;
517
518    (void) ctx;
519    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
520    y=FLIP(y);
521    if (mask) {
522	for (i=0; i<n; i++)
523	    if (mask[i])
524		SetPixel(pwc->hDC, x+i, y, colorref);
525    }
526    else
527	for (i=0; i<n; i++)
528	    SetPixel(pwc->hDC, x+i, y, colorref);
529
530}
531
532/* Write an array of RGBA pixels with a boolean mask. */
533static void write_rgba_pixels_front(const GLcontext *ctx,
534				     struct gl_renderbuffer *rb,
535				     GLuint n,
536				     const GLint x[], const GLint y[],
537				     const GLubyte rgba[][4],
538				     const GLubyte mask[] )
539{
540    GLuint i;
541    WMesaContext pwc = wmesa_context(ctx);
542    (void) ctx;
543    for (i=0; i<n; i++)
544	if (mask[i])
545	    SetPixel(pwc->hDC, x[i], FLIP(y[i]),
546		     RGB(rgba[i][RCOMP], rgba[i][GCOMP],
547			 rgba[i][BCOMP]));
548}
549
550
551
552/*
553 * Write an array of pixels with a boolean mask.  The current color
554 * is used for all pixels.
555 */
556static void write_mono_rgba_pixels_front(const GLcontext *ctx,
557					  struct gl_renderbuffer *rb,
558					  GLuint n,
559					  const GLint x[], const GLint y[],
560					  const GLchan color[4],
561					  const GLubyte mask[] )
562{
563    GLuint i;
564    WMesaContext pwc = wmesa_context(ctx);
565    COLORREF colorref;
566    (void) ctx;
567    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
568    for (i=0; i<n; i++)
569	if (mask[i])
570	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
571}
572
573/* Read a horizontal span of color pixels. */
574static void read_rgba_span_front(const GLcontext *ctx,
575				  struct gl_renderbuffer *rb,
576				  GLuint n, GLint x, GLint y,
577				  GLubyte rgba[][4] )
578{
579    WMesaContext pwc = wmesa_context(ctx);
580    GLuint i;
581    COLORREF Color;
582    y = FLIP(y);
583    for (i=0; i<n; i++) {
584	Color = GetPixel(pwc->hDC, x+i, y);
585	rgba[i][RCOMP] = GetRValue(Color);
586	rgba[i][GCOMP] = GetGValue(Color);
587	rgba[i][BCOMP] = GetBValue(Color);
588	rgba[i][ACOMP] = 255;
589    }
590}
591
592
593/* Read an array of color pixels. */
594static void read_rgba_pixels_front(const GLcontext *ctx,
595				    struct gl_renderbuffer *rb,
596				    GLuint n, const GLint x[], const GLint y[],
597				    GLubyte rgba[][4])
598{
599    WMesaContext pwc = wmesa_context(ctx);
600    GLuint i;
601    COLORREF Color;
602    for (i=0; i<n; i++) {
603        GLint y2 = FLIP(y[i]);
604        Color = GetPixel(pwc->hDC, x[i], y2);
605        rgba[i][RCOMP] = GetRValue(Color);
606        rgba[i][GCOMP] = GetGValue(Color);
607        rgba[i][BCOMP] = GetBValue(Color);
608        rgba[i][ACOMP] = 255;
609    }
610}
611
612/*********************************************************************/
613
614/* DOUBLE BUFFER 32-bit */
615
616#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
617LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
618*lpdw = BGR32((r),(g),(b)); }
619
620
621
622/* Write a horizontal span of RGBA color pixels with a boolean mask. */
623static void write_rgba_span_32(const GLcontext *ctx,
624			       struct gl_renderbuffer *rb,
625			       GLuint n, GLint x, GLint y,
626			       const GLubyte rgba[][4],
627			       const GLubyte mask[] )
628{
629    WMesaContext pwc = wmesa_context(ctx);
630    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
631    GLuint i;
632    LPDWORD lpdw;
633
634    (void) ctx;
635
636    y=FLIP(y);
637    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
638    if (mask) {
639	for (i=0; i<n; i++)
640	    if (mask[i])
641                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
642				rgba[i][BCOMP]);
643    }
644    else {
645	for (i=0; i<n; i++)
646                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
647				rgba[i][BCOMP]);
648    }
649}
650
651
652/* Write a horizontal span of RGB color pixels with a boolean mask. */
653static void write_rgb_span_32(const GLcontext *ctx,
654			      struct gl_renderbuffer *rb,
655			      GLuint n, GLint x, GLint y,
656			      const GLubyte rgb[][3],
657			      const GLubyte mask[] )
658{
659    WMesaContext pwc = wmesa_context(ctx);
660    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
661    GLuint i;
662    LPDWORD lpdw;
663
664    (void) ctx;
665
666    y=FLIP(y);
667    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
668    if (mask) {
669	for (i=0; i<n; i++)
670	    if (mask[i])
671                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
672				rgb[i][BCOMP]);
673    }
674    else {
675	for (i=0; i<n; i++)
676                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
677				rgb[i][BCOMP]);
678    }
679}
680
681/*
682 * Write a horizontal span of pixels with a boolean mask.  The current color
683 * is used for all pixels.
684 */
685static void write_mono_rgba_span_32(const GLcontext *ctx,
686				    struct gl_renderbuffer *rb,
687				    GLuint n, GLint x, GLint y,
688				    const GLchan color[4],
689				    const GLubyte mask[])
690{
691    LPDWORD lpdw;
692    DWORD pixel;
693    GLuint i;
694    WMesaContext pwc = wmesa_context(ctx);
695    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
696    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
697    y=FLIP(y);
698    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
699    if (mask) {
700	for (i=0; i<n; i++)
701	    if (mask[i])
702                lpdw[i] = pixel;
703    }
704    else
705	for (i=0; i<n; i++)
706                *lpdw++ = pixel;
707
708}
709
710/* Write an array of RGBA pixels with a boolean mask. */
711static void write_rgba_pixels_32(const GLcontext *ctx,
712				 struct gl_renderbuffer *rb,
713				 GLuint n, const GLint x[], const GLint y[],
714				 const GLubyte rgba[][4],
715				 const GLubyte mask[])
716{
717    GLuint i;
718    WMesaContext pwc = wmesa_context(ctx);
719    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
720    for (i=0; i<n; i++)
721	if (mask[i])
722	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
723			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
724}
725
726/*
727 * Write an array of pixels with a boolean mask.  The current color
728 * is used for all pixels.
729 */
730static void write_mono_rgba_pixels_32(const GLcontext *ctx,
731				      struct gl_renderbuffer *rb,
732				      GLuint n,
733				      const GLint x[], const GLint y[],
734				      const GLchan color[4],
735				      const GLubyte mask[])
736{
737    GLuint i;
738    WMesaContext pwc = wmesa_context(ctx);
739    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
740    for (i=0; i<n; i++)
741	if (mask[i])
742	    WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
743			 color[GCOMP], color[BCOMP]);
744}
745
746/* Read a horizontal span of color pixels. */
747static void read_rgba_span_32(const GLcontext *ctx,
748			      struct gl_renderbuffer *rb,
749			      GLuint n, GLint x, GLint y,
750			      GLubyte rgba[][4] )
751{
752    GLuint i;
753    DWORD pixel;
754    LPDWORD lpdw;
755    WMesaContext pwc = wmesa_context(ctx);
756    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
757
758    y = FLIP(y);
759    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
760    for (i=0; i<n; i++) {
761	pixel = lpdw[i];
762	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
763	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
764	rgba[i][BCOMP] = (pixel & 0x000000ff);
765	rgba[i][ACOMP] = 255;
766    }
767}
768
769
770/* Read an array of color pixels. */
771static void read_rgba_pixels_32(const GLcontext *ctx,
772				struct gl_renderbuffer *rb,
773				GLuint n, const GLint x[], const GLint y[],
774				GLubyte rgba[][4])
775{
776    GLuint i;
777    DWORD pixel;
778    LPDWORD lpdw;
779    WMesaContext pwc = wmesa_context(ctx);
780    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
781
782    for (i=0; i<n; i++) {
783	GLint y2 = FLIP(y[i]);
784	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
785	pixel = lpdw[i];
786	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
787	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
788	rgba[i][BCOMP] = (pixel & 0x000000ff);
789	rgba[i][ACOMP] = 255;
790  }
791}
792
793
794/*********************************************************************/
795
796/* DOUBLE BUFFER 16-bit */
797
798#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
799LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
800*lpw = BGR16((r),(g),(b)); }
801
802
803
804/* Write a horizontal span of RGBA color pixels with a boolean mask. */
805static void write_rgba_span_16(const GLcontext *ctx,
806			       struct gl_renderbuffer *rb,
807			       GLuint n, GLint x, GLint y,
808			       const GLubyte rgba[][4],
809			       const GLubyte mask[] )
810{
811    WMesaContext pwc = wmesa_context(ctx);
812    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
813    GLuint i;
814    LPWORD lpw;
815
816    (void) ctx;
817
818    y=FLIP(y);
819    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
820    if (mask) {
821	for (i=0; i<n; i++)
822	    if (mask[i])
823                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
824			       rgba[i][BCOMP]);
825    }
826    else {
827	for (i=0; i<n; i++)
828                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
829			       rgba[i][BCOMP]);
830    }
831}
832
833
834/* Write a horizontal span of RGB color pixels with a boolean mask. */
835static void write_rgb_span_16(const GLcontext *ctx,
836			      struct gl_renderbuffer *rb,
837			      GLuint n, GLint x, GLint y,
838			      const GLubyte rgb[][3],
839			      const GLubyte mask[] )
840{
841    WMesaContext pwc = wmesa_context(ctx);
842    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
843    GLuint i;
844    LPWORD lpw;
845
846    (void) ctx;
847
848    y=FLIP(y);
849    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
850    if (mask) {
851	for (i=0; i<n; i++)
852	    if (mask[i])
853                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
854			       rgb[i][BCOMP]);
855    }
856    else {
857	for (i=0; i<n; i++)
858                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
859			       rgb[i][BCOMP]);
860    }
861}
862
863/*
864 * Write a horizontal span of pixels with a boolean mask.  The current color
865 * is used for all pixels.
866 */
867static void write_mono_rgba_span_16(const GLcontext *ctx,
868				    struct gl_renderbuffer *rb,
869				    GLuint n, GLint x, GLint y,
870				    const GLchan color[4],
871				    const GLubyte mask[])
872{
873    LPWORD lpw;
874    WORD pixel;
875    GLuint i;
876    WMesaContext pwc = wmesa_context(ctx);
877    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
878    (void) ctx;
879    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
880    y=FLIP(y);
881    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
882    if (mask) {
883	for (i=0; i<n; i++)
884	    if (mask[i])
885                lpw[i] = pixel;
886    }
887    else
888	for (i=0; i<n; i++)
889                *lpw++ = pixel;
890
891}
892
893/* Write an array of RGBA pixels with a boolean mask. */
894static void write_rgba_pixels_16(const GLcontext *ctx,
895				 struct gl_renderbuffer *rb,
896				 GLuint n, const GLint x[], const GLint y[],
897				 const GLubyte rgba[][4],
898				 const GLubyte mask[])
899{
900    GLuint i;
901    WMesaContext pwc = wmesa_context(ctx);
902    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
903    (void) ctx;
904    for (i=0; i<n; i++)
905	if (mask[i])
906	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
907			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
908}
909
910/*
911 * Write an array of pixels with a boolean mask.  The current color
912 * is used for all pixels.
913 */
914static void write_mono_rgba_pixels_16(const GLcontext *ctx,
915				      struct gl_renderbuffer *rb,
916				      GLuint n,
917				      const GLint x[], const GLint y[],
918				      const GLchan color[4],
919				      const GLubyte mask[])
920{
921    GLuint i;
922    WMesaContext pwc = wmesa_context(ctx);
923    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
924    (void) ctx;
925    for (i=0; i<n; i++)
926	if (mask[i])
927	    WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
928			 color[GCOMP], color[BCOMP]);
929}
930
931/* Read a horizontal span of color pixels. */
932static void read_rgba_span_16(const GLcontext *ctx,
933			      struct gl_renderbuffer *rb,
934			      GLuint n, GLint x, GLint y,
935			      GLubyte rgba[][4] )
936{
937    GLuint i, pixel;
938    LPWORD lpw;
939    WMesaContext pwc = wmesa_context(ctx);
940    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
941
942    y = FLIP(y);
943    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
944    for (i=0; i<n; i++) {
945	pixel = lpw[i];
946	/* Windows uses 5,5,5 for 16-bit */
947	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
948	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
949	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
950	rgba[i][ACOMP] = 255;
951    }
952}
953
954
955/* Read an array of color pixels. */
956static void read_rgba_pixels_16(const GLcontext *ctx,
957				struct gl_renderbuffer *rb,
958				GLuint n, const GLint x[], const GLint y[],
959				GLubyte rgba[][4])
960{
961    GLuint i, pixel;
962    LPWORD lpw;
963    WMesaContext pwc = wmesa_context(ctx);
964    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
965
966    for (i=0; i<n; i++) {
967	GLint y2 = FLIP(y[i]);
968	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
969	pixel = lpw[i];
970	/* Windows uses 5,5,5 for 16-bit */
971	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
972	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
973	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
974	rgba[i][ACOMP] = 255;
975  }
976}
977
978
979
980
981/**********************************************************************/
982/*****                   BUFFER Functions                         *****/
983/**********************************************************************/
984
985
986
987
988static void
989wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
990{
991    _mesa_free(rb);
992}
993
994
995/**
996 * This is called by Mesa whenever it determines that the window size
997 * has changed.  Do whatever's needed to cope with that.
998 */
999static GLboolean
1000wmesa_renderbuffer_storage(GLcontext *ctx,
1001			   struct gl_renderbuffer *rb,
1002			   GLenum internalFormat,
1003			   GLuint width,
1004			   GLuint height)
1005{
1006    rb->Width = width;
1007    rb->Height = height;
1008    return GL_TRUE;
1009}
1010
1011
1012/**
1013 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1014 * on if we're drawing to the front or back color buffer.
1015 */
1016void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
1017                                  int double_buffer)
1018{
1019    if (double_buffer) {
1020        /* back buffer */
1021	/* Picking the correct span functions is important because
1022	 * the DIB was allocated with the indicated depth. */
1023	switch(pixelformat) {
1024	case PF_5R6G5B:
1025	    rb->PutRow = write_rgba_span_16;
1026	    rb->PutRowRGB = write_rgb_span_16;
1027	    rb->PutMonoRow = write_mono_rgba_span_16;
1028	    rb->PutValues = write_rgba_pixels_16;
1029	    rb->PutMonoValues = write_mono_rgba_pixels_16;
1030	    rb->GetRow = read_rgba_span_16;
1031	    rb->GetValues = read_rgba_pixels_16;
1032            rb->RedBits = 5;
1033            rb->GreenBits = 6;
1034            rb->BlueBits = 5;
1035	    break;
1036	case PF_8R8G8B:
1037	    rb->PutRow = write_rgba_span_32;
1038	    rb->PutRowRGB = write_rgb_span_32;
1039	    rb->PutMonoRow = write_mono_rgba_span_32;
1040	    rb->PutValues = write_rgba_pixels_32;
1041	    rb->PutMonoValues = write_mono_rgba_pixels_32;
1042	    rb->GetRow = read_rgba_span_32;
1043	    rb->GetValues = read_rgba_pixels_32;
1044            rb->RedBits = 8;
1045            rb->GreenBits = 8;
1046            rb->BlueBits = 8;
1047	    break;
1048	default:
1049	    break;
1050	}
1051    }
1052    else {
1053        /* front buffer (actual Windows window) */
1054	rb->PutRow = write_rgba_span_front;
1055	rb->PutRowRGB = write_rgb_span_front;
1056	rb->PutMonoRow = write_mono_rgba_span_front;
1057	rb->PutValues = write_rgba_pixels_front;
1058	rb->PutMonoValues = write_mono_rgba_pixels_front;
1059	rb->GetRow = read_rgba_span_front;
1060	rb->GetValues = read_rgba_pixels_front;
1061        rb->RedBits = 8; /* XXX fix these (565?) */
1062        rb->GreenBits = 8;
1063        rb->BlueBits = 8;
1064    }
1065}
1066
1067/**
1068 * Called by ctx->Driver.ResizeBuffers()
1069 * Resize the front/back colorbuffers to match the latest window size.
1070 */
1071static void
1072wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
1073                     GLuint width, GLuint height)
1074{
1075    WMesaContext pwc = wmesa_context(ctx);
1076    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
1077
1078    if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
1079	/* Realloc back buffer */
1080	if (ctx->Visual.doubleBufferMode == 1) {
1081	    wmDeleteBackingStore(pwfb);
1082	    wmCreateBackingStore(pwfb, width, height);
1083	}
1084    }
1085    _mesa_resize_framebuffer(ctx, buffer, width, height);
1086}
1087
1088
1089/**
1090 * Called by glViewport.
1091 * This is a good time for us to poll the current window size and adjust
1092 * our renderbuffers to match the current window size.
1093 * Remember, we have no opportunity to respond to conventional
1094 * resize events since the driver has no event loop.
1095 * Thus, we poll.
1096 * MakeCurrent also ends up making a call here, so that ensures
1097 * we get the viewport set correctly, even if the app does not call
1098 * glViewport and relies on the defaults.
1099 */
1100static void wmesa_viewport(GLcontext *ctx,
1101			   GLint x, GLint y,
1102			   GLsizei width, GLsizei height)
1103{
1104    WMesaContext pwc = wmesa_context(ctx);
1105    GLuint new_width, new_height;
1106
1107    wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
1108
1109    /**
1110     * Resize buffers if the window size changed.
1111     */
1112    wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
1113    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
1114}
1115
1116
1117
1118
1119/**
1120 * Called when the driver should update it's state, based on the new_state
1121 * flags.
1122 */
1123static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
1124{
1125    _swrast_InvalidateState(ctx, new_state);
1126    _swsetup_InvalidateState(ctx, new_state);
1127    _ac_InvalidateState(ctx, new_state);
1128    _tnl_InvalidateState(ctx, new_state);
1129
1130    /* TODO - This code is not complete yet because I
1131     * don't know what to do for all state updates.
1132     */
1133
1134    if (new_state & _NEW_BUFFERS) {
1135    }
1136}
1137
1138
1139
1140
1141
1142/**********************************************************************/
1143/*****                   WMESA Functions                          *****/
1144/**********************************************************************/
1145
1146WMesaContext WMesaCreateContext(HDC hDC,
1147				HPALETTE* Pal,
1148				GLboolean rgb_flag,
1149				GLboolean db_flag,
1150				GLboolean alpha_flag)
1151{
1152    WMesaContext c;
1153    struct dd_function_table functions;
1154    GLint red_bits, green_bits, blue_bits, alpha_bits;
1155    GLcontext *ctx;
1156    GLvisual *visual;
1157
1158    (void) Pal;
1159
1160    /* Indexed mode not supported */
1161    if (!rgb_flag)
1162	return NULL;
1163
1164    /* Allocate wmesa context */
1165    c = CALLOC_STRUCT(wmesa_context);
1166    if (!c)
1167	return NULL;
1168
1169#if 0
1170    /* I do not understand this contributed code */
1171    /* Support memory and device contexts */
1172    if(WindowFromDC(hDC) != NULL) {
1173	c->hDC = GetDC(WindowFromDC(hDC)); // huh ????
1174    }
1175    else {
1176	c->hDC = hDC;
1177    }
1178#else
1179    c->hDC = hDC;
1180#endif
1181
1182    /* Get data for visual */
1183    /* Dealing with this is actually a bit of overkill because Mesa will end
1184     * up treating all color component size requests less than 8 by using
1185     * a single byte per channel.  In addition, the interface to the span
1186     * routines passes colors as an entire byte per channel anyway, so there
1187     * is nothing to be saved by telling the visual to be 16 bits if the device
1188     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
1189     * channel anyway.
1190     * But we go through the motions here anyway.
1191     */
1192    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
1193    case 16:
1194	red_bits = green_bits = blue_bits = 5;
1195	alpha_bits = 0;
1196	break;
1197    default:
1198	red_bits = green_bits = blue_bits = 8;
1199	alpha_bits = 8;
1200	break;
1201    }
1202    /* Create visual based on flags */
1203    visual = _mesa_create_visual(rgb_flag,
1204                                 db_flag,    /* db_flag */
1205                                 GL_FALSE,   /* stereo */
1206                                 red_bits, green_bits, blue_bits, /* color RGB */
1207                                 alpha_flag ? alpha_bits : 0, /* color A */
1208                                 0,          /* index bits */
1209                                 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
1210                                 8,          /* stencil_bits */
1211                                 16,16,16,   /* accum RGB */
1212                                 alpha_flag ? 16 : 0, /* accum A */
1213                                 1);         /* num samples */
1214
1215    if (!visual) {
1216	_mesa_free(c);
1217	return NULL;
1218    }
1219
1220    /* Set up driver functions */
1221    _mesa_init_driver_functions(&functions);
1222    functions.GetString = wmesa_get_string;
1223    functions.UpdateState = wmesa_update_state;
1224    functions.GetBufferSize = wmesa_get_buffer_size;
1225    functions.Flush = wmesa_flush;
1226    functions.Clear = clear;
1227    functions.ClearIndex = clear_index;
1228    functions.ClearColor = clear_color;
1229    functions.ResizeBuffers = wmesa_resize_buffers;
1230    functions.Viewport = wmesa_viewport;
1231
1232    /* initialize the Mesa context data */
1233    ctx = &c->gl_ctx;
1234    _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
1235
1236    _mesa_enable_sw_extensions(ctx);
1237    _mesa_enable_1_3_extensions(ctx);
1238    _mesa_enable_1_4_extensions(ctx);
1239    _mesa_enable_1_5_extensions(ctx);
1240    _mesa_enable_2_0_extensions(ctx);
1241
1242    /* Initialize the software rasterizer and helper modules. */
1243    if (!_swrast_CreateContext(ctx) ||
1244        !_ac_CreateContext(ctx) ||
1245        !_tnl_CreateContext(ctx) ||
1246	!_swsetup_CreateContext(ctx)) {
1247	_mesa_free_context_data(ctx);
1248	_mesa_free(c);
1249	return NULL;
1250    }
1251    _swsetup_Wakeup(ctx);
1252    TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1253
1254    return c;
1255}
1256
1257
1258void WMesaDestroyContext( WMesaContext pwc )
1259{
1260    GLcontext *ctx = &pwc->gl_ctx;
1261    WMesaFramebuffer pwfb;
1262    GET_CURRENT_CONTEXT(cur_ctx);
1263
1264    if (cur_ctx == ctx) {
1265        /* unbind current if deleting current context */
1266        WMesaMakeCurrent(NULL, NULL);
1267    }
1268
1269    /* clean up frame buffer resources */
1270    pwfb = wmesa_lookup_framebuffer(pwc->hDC);
1271    if (pwfb) {
1272	if (ctx->Visual.doubleBufferMode == 1)
1273	    wmDeleteBackingStore(pwfb);
1274	wmesa_free_framebuffer(pwc->hDC);
1275    }
1276
1277    /* Release for device, not memory contexts */
1278    if (WindowFromDC(pwc->hDC) != NULL)
1279    {
1280      ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
1281    }
1282    DeleteObject(pwc->clearPen);
1283    DeleteObject(pwc->clearBrush);
1284
1285    _swsetup_DestroyContext(ctx);
1286    _tnl_DestroyContext(ctx);
1287    _ac_DestroyContext(ctx);
1288    _swrast_DestroyContext(ctx);
1289
1290    _mesa_free_context_data(ctx);
1291    _mesa_free(pwc);
1292}
1293
1294
1295/**
1296 * Create a new color renderbuffer.
1297 */
1298struct gl_renderbuffer *
1299wmesa_new_renderbuffer(void)
1300{
1301    struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1302    if (!rb)
1303        return NULL;
1304
1305    _mesa_init_renderbuffer(rb, (GLuint)0);
1306
1307    rb->_BaseFormat = GL_RGBA;
1308    rb->InternalFormat = GL_RGBA;
1309    rb->DataType = CHAN_TYPE;
1310    rb->Delete = wmesa_delete_renderbuffer;
1311    rb->AllocStorage = wmesa_renderbuffer_storage;
1312    return rb;
1313}
1314
1315
1316void WMesaMakeCurrent(WMesaContext c, HDC hdc)
1317{
1318    WMesaFramebuffer pwfb;
1319
1320    {
1321        /* return if already current */
1322        GET_CURRENT_CONTEXT(ctx);
1323        WMesaContext pwc = wmesa_context(ctx);
1324        if (c == pwc && pwc->hDC == hdc)
1325            return;
1326    }
1327
1328    pwfb = wmesa_lookup_framebuffer(hdc);
1329
1330    /* Lazy creation of framebuffers */
1331    if (c && !pwfb && hdc) {
1332        struct gl_renderbuffer *rb;
1333        GLvisual *visual = &c->gl_ctx.Visual;
1334        GLuint width, height;
1335
1336        get_window_size(hdc, &width, &height);
1337
1338	c->clearPen = CreatePen(PS_SOLID, 1, 0);
1339	c->clearBrush = CreateSolidBrush(0);
1340
1341        pwfb = wmesa_new_framebuffer(hdc, visual);
1342
1343	/* Create back buffer if double buffered */
1344	if (visual->doubleBufferMode == 1) {
1345	    wmCreateBackingStore(pwfb, width, height);
1346	}
1347
1348        /* make render buffers */
1349        if (visual->doubleBufferMode == 1) {
1350            rb = wmesa_new_renderbuffer();
1351            _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
1352            wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 1);
1353	}
1354        rb = wmesa_new_renderbuffer();
1355        _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
1356        wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 0);
1357
1358	/* Let Mesa own the Depth, Stencil, and Accum buffers */
1359        _mesa_add_soft_renderbuffers(&pwfb->Base,
1360                                     GL_FALSE, /* color */
1361                                     visual->depthBits > 0,
1362                                     visual->stencilBits > 0,
1363                                     visual->accumRedBits > 0,
1364                                     visual->alphaBits >0,
1365                                     GL_FALSE);
1366    }
1367
1368    if (c && pwfb)
1369	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
1370    else
1371        _mesa_make_current(NULL, NULL, NULL);
1372}
1373
1374
1375void WMesaSwapBuffers( HDC hdc )
1376{
1377    GET_CURRENT_CONTEXT(ctx);
1378    WMesaContext pwc = wmesa_context(ctx);
1379    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
1380
1381    if (!pwfb) {
1382        _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
1383        return;
1384    }
1385
1386    /* If we're swapping the buffer associated with the current context
1387     * we have to flush any pending rendering commands first.
1388     */
1389    if (pwc->hDC == hdc) {
1390	_mesa_notifySwapBuffers(ctx);
1391
1392	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
1393	       pwfb->dib_hDC, 0, 0, SRCCOPY);
1394    }
1395    else {
1396        /* XXX for now only allow swapping current window */
1397        _mesa_problem(NULL, "wmesa: can't swap non-current window");
1398    }
1399}
1400