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