wmesa.c revision 157eeb5c3b1ed16d67247f41e83dad3cda6e31ef
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   WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
463   CONST BITMAPINFO bmi=
464   {
465      {
466         sizeof(BITMAPINFOHEADER),
467         n, 1, 1, 32, BI_RGB, 0, 1, 1, 0, 0
468      }
469   };
470   HBITMAP bmp=0;
471   HDC mdc=0;
472   typedef union
473   {
474      unsigned i;
475      struct {
476         unsigned b:8, g:8, r:8, a:8;
477      };
478   } BGRA;
479   BGRA *bgra, c;
480   int i;
481
482   if (n < 16) {   // the value 16 is just guessed
483      y=FLIP(y);
484      if (mask) {
485         for (i=0; i<n; i++)
486            if (mask[i])
487               SetPixel(pwc->hDC, x+i, y,
488                        RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
489      }
490      else {
491         for (i=0; i<n; i++)
492            SetPixel(pwc->hDC, x+i, y,
493                     RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
494      }
495   }
496   else {
497      if (!pwfb) {
498         _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
499         return;
500      }
501      bgra=malloc(n*sizeof(BGRA));
502      if (!bgra) {
503         _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
504         return;
505      }
506      c.a=0;
507      if (mask) {
508         for (i=0; i<n; i++) {
509            if (mask[i]) {
510               c.r=rgba[i][RCOMP];
511               c.g=rgba[i][GCOMP];
512               c.b=rgba[i][BCOMP];
513               c.a=rgba[i][ACOMP];
514               bgra[i]=c;
515            }
516            else
517               bgra[i].i=0;
518         }
519      }
520      else {
521         for (i=0; i<n; i++) {
522            c.r=rgba[i][RCOMP];
523            c.g=rgba[i][GCOMP];
524            c.b=rgba[i][BCOMP];
525            c.a=rgba[i][ACOMP];
526            bgra[i]=c;
527         }
528      }
529      bmp=CreateBitmap(n, 1,  1, 32, bgra);
530      mdc=CreateCompatibleDC(pwfb->hDC);
531      SelectObject(mdc, bmp);
532      y=FLIP(y);
533      BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
534      SelectObject(mdc, 0);
535      DeleteObject(bmp);
536      DeleteDC(mdc);
537      free(bgra);
538   }
539}
540
541/* Write a horizontal span of RGB color pixels with a boolean mask. */
542static void write_rgb_span_front(const GLcontext *ctx,
543				  struct gl_renderbuffer *rb,
544				  GLuint n, GLint x, GLint y,
545				  const GLubyte rgb[][3],
546				  const GLubyte mask[] )
547{
548    WMesaContext pwc = wmesa_context(ctx);
549    GLuint i;
550
551    (void) ctx;
552    y=FLIP(y);
553    if (mask) {
554	for (i=0; i<n; i++)
555	    if (mask[i])
556		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
557					       rgb[i][BCOMP]));
558    }
559    else {
560	for (i=0; i<n; i++)
561	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
562					   rgb[i][BCOMP]));
563    }
564
565}
566
567/*
568 * Write a horizontal span of pixels with a boolean mask.  The current color
569 * is used for all pixels.
570 */
571static void write_mono_rgba_span_front(const GLcontext *ctx,
572					struct gl_renderbuffer *rb,
573					GLuint n, GLint x, GLint y,
574					const GLchan color[4],
575					const GLubyte mask[])
576{
577    GLuint i;
578    WMesaContext pwc = wmesa_context(ctx);
579    COLORREF colorref;
580
581    (void) ctx;
582    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
583    y=FLIP(y);
584    if (mask) {
585	for (i=0; i<n; i++)
586	    if (mask[i])
587		SetPixel(pwc->hDC, x+i, y, colorref);
588    }
589    else
590	for (i=0; i<n; i++)
591	    SetPixel(pwc->hDC, x+i, y, colorref);
592
593}
594
595/* Write an array of RGBA pixels with a boolean mask. */
596static void write_rgba_pixels_front(const GLcontext *ctx,
597				     struct gl_renderbuffer *rb,
598				     GLuint n,
599				     const GLint x[], const GLint y[],
600				     const GLubyte rgba[][4],
601				     const GLubyte mask[] )
602{
603    GLuint i;
604    WMesaContext pwc = wmesa_context(ctx);
605    (void) ctx;
606    for (i=0; i<n; i++)
607	if (mask[i])
608	    SetPixel(pwc->hDC, x[i], FLIP(y[i]),
609		     RGB(rgba[i][RCOMP], rgba[i][GCOMP],
610			 rgba[i][BCOMP]));
611}
612
613
614
615/*
616 * Write an array of pixels with a boolean mask.  The current color
617 * is used for all pixels.
618 */
619static void write_mono_rgba_pixels_front(const GLcontext *ctx,
620					  struct gl_renderbuffer *rb,
621					  GLuint n,
622					  const GLint x[], const GLint y[],
623					  const GLchan color[4],
624					  const GLubyte mask[] )
625{
626    GLuint i;
627    WMesaContext pwc = wmesa_context(ctx);
628    COLORREF colorref;
629    (void) ctx;
630    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
631    for (i=0; i<n; i++)
632	if (mask[i])
633	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
634}
635
636/* Read a horizontal span of color pixels. */
637static void read_rgba_span_front(const GLcontext *ctx,
638				  struct gl_renderbuffer *rb,
639				  GLuint n, GLint x, GLint y,
640				  GLubyte rgba[][4] )
641{
642    WMesaContext pwc = wmesa_context(ctx);
643    GLuint i;
644    COLORREF Color;
645    y = FLIP(y);
646    for (i=0; i<n; i++) {
647	Color = GetPixel(pwc->hDC, x+i, y);
648	rgba[i][RCOMP] = GetRValue(Color);
649	rgba[i][GCOMP] = GetGValue(Color);
650	rgba[i][BCOMP] = GetBValue(Color);
651	rgba[i][ACOMP] = 255;
652    }
653}
654
655
656/* Read an array of color pixels. */
657static void read_rgba_pixels_front(const GLcontext *ctx,
658				    struct gl_renderbuffer *rb,
659				    GLuint n, const GLint x[], const GLint y[],
660				    GLubyte rgba[][4])
661{
662    WMesaContext pwc = wmesa_context(ctx);
663    GLuint i;
664    COLORREF Color;
665    for (i=0; i<n; i++) {
666        GLint y2 = FLIP(y[i]);
667        Color = GetPixel(pwc->hDC, x[i], y2);
668        rgba[i][RCOMP] = GetRValue(Color);
669        rgba[i][GCOMP] = GetGValue(Color);
670        rgba[i][BCOMP] = GetBValue(Color);
671        rgba[i][ACOMP] = 255;
672    }
673}
674
675/*********************************************************************/
676
677/* DOUBLE BUFFER 32-bit */
678
679#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
680LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
681*lpdw = BGR32((r),(g),(b)); }
682
683
684
685/* Write a horizontal span of RGBA color pixels with a boolean mask. */
686static void write_rgba_span_32(const GLcontext *ctx,
687			       struct gl_renderbuffer *rb,
688			       GLuint n, GLint x, GLint y,
689			       const GLubyte rgba[][4],
690			       const GLubyte mask[] )
691{
692    WMesaContext pwc = wmesa_context(ctx);
693    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
694    GLuint i;
695    LPDWORD lpdw;
696
697    (void) ctx;
698
699    y=FLIP(y);
700    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
701    if (mask) {
702	for (i=0; i<n; i++)
703	    if (mask[i])
704                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
705				rgba[i][BCOMP]);
706    }
707    else {
708	for (i=0; i<n; i++)
709                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
710				rgba[i][BCOMP]);
711    }
712}
713
714
715/* Write a horizontal span of RGB color pixels with a boolean mask. */
716static void write_rgb_span_32(const GLcontext *ctx,
717			      struct gl_renderbuffer *rb,
718			      GLuint n, GLint x, GLint y,
719			      const GLubyte rgb[][3],
720			      const GLubyte mask[] )
721{
722    WMesaContext pwc = wmesa_context(ctx);
723    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
724    GLuint i;
725    LPDWORD lpdw;
726
727    (void) ctx;
728
729    y=FLIP(y);
730    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
731    if (mask) {
732	for (i=0; i<n; i++)
733	    if (mask[i])
734                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
735				rgb[i][BCOMP]);
736    }
737    else {
738	for (i=0; i<n; i++)
739                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
740				rgb[i][BCOMP]);
741    }
742}
743
744/*
745 * Write a horizontal span of pixels with a boolean mask.  The current color
746 * is used for all pixels.
747 */
748static void write_mono_rgba_span_32(const GLcontext *ctx,
749				    struct gl_renderbuffer *rb,
750				    GLuint n, GLint x, GLint y,
751				    const GLchan color[4],
752				    const GLubyte mask[])
753{
754    LPDWORD lpdw;
755    DWORD pixel;
756    GLuint i;
757    WMesaContext pwc = wmesa_context(ctx);
758    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
759    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
760    y=FLIP(y);
761    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
762    if (mask) {
763	for (i=0; i<n; i++)
764	    if (mask[i])
765                lpdw[i] = pixel;
766    }
767    else
768	for (i=0; i<n; i++)
769                *lpdw++ = pixel;
770
771}
772
773/* Write an array of RGBA pixels with a boolean mask. */
774static void write_rgba_pixels_32(const GLcontext *ctx,
775				 struct gl_renderbuffer *rb,
776				 GLuint n, const GLint x[], const GLint y[],
777				 const GLubyte rgba[][4],
778				 const GLubyte mask[])
779{
780    GLuint i;
781    WMesaContext pwc = wmesa_context(ctx);
782    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
783    for (i=0; i<n; i++)
784	if (mask[i])
785	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
786			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
787}
788
789/*
790 * Write an array of pixels with a boolean mask.  The current color
791 * is used for all pixels.
792 */
793static void write_mono_rgba_pixels_32(const GLcontext *ctx,
794				      struct gl_renderbuffer *rb,
795				      GLuint n,
796				      const GLint x[], const GLint y[],
797				      const GLchan color[4],
798				      const GLubyte mask[])
799{
800    GLuint i;
801    WMesaContext pwc = wmesa_context(ctx);
802    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
803    for (i=0; i<n; i++)
804	if (mask[i])
805	    WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
806			 color[GCOMP], color[BCOMP]);
807}
808
809/* Read a horizontal span of color pixels. */
810static void read_rgba_span_32(const GLcontext *ctx,
811			      struct gl_renderbuffer *rb,
812			      GLuint n, GLint x, GLint y,
813			      GLubyte rgba[][4] )
814{
815    GLuint i;
816    DWORD pixel;
817    LPDWORD lpdw;
818    WMesaContext pwc = wmesa_context(ctx);
819    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
820
821    y = FLIP(y);
822    lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
823    for (i=0; i<n; i++) {
824	pixel = lpdw[i];
825	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
826	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
827	rgba[i][BCOMP] = (pixel & 0x000000ff);
828	rgba[i][ACOMP] = 255;
829    }
830}
831
832
833/* Read an array of color pixels. */
834static void read_rgba_pixels_32(const GLcontext *ctx,
835				struct gl_renderbuffer *rb,
836				GLuint n, const GLint x[], const GLint y[],
837				GLubyte rgba[][4])
838{
839    GLuint i;
840    DWORD pixel;
841    LPDWORD lpdw;
842    WMesaContext pwc = wmesa_context(ctx);
843    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
844
845    for (i=0; i<n; i++) {
846	GLint y2 = FLIP(y[i]);
847	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
848	pixel = *lpdw;
849	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
850	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
851	rgba[i][BCOMP] = (pixel & 0x000000ff);
852	rgba[i][ACOMP] = 255;
853  }
854}
855
856
857/*********************************************************************/
858
859/* DOUBLE BUFFER 16-bit */
860
861#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
862LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
863*lpw = BGR16((r),(g),(b)); }
864
865
866
867/* Write a horizontal span of RGBA color pixels with a boolean mask. */
868static void write_rgba_span_16(const GLcontext *ctx,
869			       struct gl_renderbuffer *rb,
870			       GLuint n, GLint x, GLint y,
871			       const GLubyte rgba[][4],
872			       const GLubyte mask[] )
873{
874    WMesaContext pwc = wmesa_context(ctx);
875    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
876    GLuint i;
877    LPWORD lpw;
878
879    (void) ctx;
880
881    y=FLIP(y);
882    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
883    if (mask) {
884	for (i=0; i<n; i++)
885	    if (mask[i])
886                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
887			       rgba[i][BCOMP]);
888    }
889    else {
890	for (i=0; i<n; i++)
891                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
892			       rgba[i][BCOMP]);
893    }
894}
895
896
897/* Write a horizontal span of RGB color pixels with a boolean mask. */
898static void write_rgb_span_16(const GLcontext *ctx,
899			      struct gl_renderbuffer *rb,
900			      GLuint n, GLint x, GLint y,
901			      const GLubyte rgb[][3],
902			      const GLubyte mask[] )
903{
904    WMesaContext pwc = wmesa_context(ctx);
905    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
906    GLuint i;
907    LPWORD lpw;
908
909    (void) ctx;
910
911    y=FLIP(y);
912    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
913    if (mask) {
914	for (i=0; i<n; i++)
915	    if (mask[i])
916                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
917			       rgb[i][BCOMP]);
918    }
919    else {
920	for (i=0; i<n; i++)
921                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
922			       rgb[i][BCOMP]);
923    }
924}
925
926/*
927 * Write a horizontal span of pixels with a boolean mask.  The current color
928 * is used for all pixels.
929 */
930static void write_mono_rgba_span_16(const GLcontext *ctx,
931				    struct gl_renderbuffer *rb,
932				    GLuint n, GLint x, GLint y,
933				    const GLchan color[4],
934				    const GLubyte mask[])
935{
936    LPWORD lpw;
937    WORD pixel;
938    GLuint i;
939    WMesaContext pwc = wmesa_context(ctx);
940    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
941    (void) ctx;
942    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
943    y=FLIP(y);
944    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
945    if (mask) {
946	for (i=0; i<n; i++)
947	    if (mask[i])
948                lpw[i] = pixel;
949    }
950    else
951	for (i=0; i<n; i++)
952                *lpw++ = pixel;
953
954}
955
956/* Write an array of RGBA pixels with a boolean mask. */
957static void write_rgba_pixels_16(const GLcontext *ctx,
958				 struct gl_renderbuffer *rb,
959				 GLuint n, const GLint x[], const GLint y[],
960				 const GLubyte rgba[][4],
961				 const GLubyte mask[])
962{
963    GLuint i;
964    WMesaContext pwc = wmesa_context(ctx);
965    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
966    (void) ctx;
967    for (i=0; i<n; i++)
968	if (mask[i])
969	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
970			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
971}
972
973/*
974 * Write an array of pixels with a boolean mask.  The current color
975 * is used for all pixels.
976 */
977static void write_mono_rgba_pixels_16(const GLcontext *ctx,
978				      struct gl_renderbuffer *rb,
979				      GLuint n,
980				      const GLint x[], const GLint y[],
981				      const GLchan color[4],
982				      const GLubyte mask[])
983{
984    GLuint i;
985    WMesaContext pwc = wmesa_context(ctx);
986    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
987    (void) ctx;
988    for (i=0; i<n; i++)
989	if (mask[i])
990	    WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
991			 color[GCOMP], color[BCOMP]);
992}
993
994/* Read a horizontal span of color pixels. */
995static void read_rgba_span_16(const GLcontext *ctx,
996			      struct gl_renderbuffer *rb,
997			      GLuint n, GLint x, GLint y,
998			      GLubyte rgba[][4] )
999{
1000    GLuint i, pixel;
1001    LPWORD lpw;
1002    WMesaContext pwc = wmesa_context(ctx);
1003    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1004
1005    y = FLIP(y);
1006    lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1007    for (i=0; i<n; i++) {
1008	pixel = lpw[i];
1009	/* Windows uses 5,5,5 for 16-bit */
1010	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1011	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1012	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1013	rgba[i][ACOMP] = 255;
1014    }
1015}
1016
1017
1018/* Read an array of color pixels. */
1019static void read_rgba_pixels_16(const GLcontext *ctx,
1020				struct gl_renderbuffer *rb,
1021				GLuint n, const GLint x[], const GLint y[],
1022				GLubyte rgba[][4])
1023{
1024    GLuint i, pixel;
1025    LPWORD lpw;
1026    WMesaContext pwc = wmesa_context(ctx);
1027    WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1028
1029    for (i=0; i<n; i++) {
1030	GLint y2 = FLIP(y[i]);
1031	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
1032	pixel = *lpw;
1033	/* Windows uses 5,5,5 for 16-bit */
1034	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1035	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1036	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1037	rgba[i][ACOMP] = 255;
1038  }
1039}
1040
1041
1042
1043
1044/**********************************************************************/
1045/*****                   BUFFER Functions                         *****/
1046/**********************************************************************/
1047
1048
1049
1050
1051static void
1052wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1053{
1054    _mesa_free(rb);
1055}
1056
1057
1058/**
1059 * This is called by Mesa whenever it determines that the window size
1060 * has changed.  Do whatever's needed to cope with that.
1061 */
1062static GLboolean
1063wmesa_renderbuffer_storage(GLcontext *ctx,
1064			   struct gl_renderbuffer *rb,
1065			   GLenum internalFormat,
1066			   GLuint width,
1067			   GLuint height)
1068{
1069    rb->Width = width;
1070    rb->Height = height;
1071    return GL_TRUE;
1072}
1073
1074
1075/**
1076 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1077 * on if we're drawing to the front or back color buffer.
1078 */
1079void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
1080                                  int double_buffer)
1081{
1082    if (double_buffer) {
1083        /* back buffer */
1084	/* Picking the correct span functions is important because
1085	 * the DIB was allocated with the indicated depth. */
1086	switch(pixelformat) {
1087	case PF_5R6G5B:
1088	    rb->PutRow = write_rgba_span_16;
1089	    rb->PutRowRGB = write_rgb_span_16;
1090	    rb->PutMonoRow = write_mono_rgba_span_16;
1091	    rb->PutValues = write_rgba_pixels_16;
1092	    rb->PutMonoValues = write_mono_rgba_pixels_16;
1093	    rb->GetRow = read_rgba_span_16;
1094	    rb->GetValues = read_rgba_pixels_16;
1095            rb->RedBits = 5;
1096            rb->GreenBits = 6;
1097            rb->BlueBits = 5;
1098	    break;
1099	case PF_8R8G8B:
1100	    rb->PutRow = write_rgba_span_32;
1101	    rb->PutRowRGB = write_rgb_span_32;
1102	    rb->PutMonoRow = write_mono_rgba_span_32;
1103	    rb->PutValues = write_rgba_pixels_32;
1104	    rb->PutMonoValues = write_mono_rgba_pixels_32;
1105	    rb->GetRow = read_rgba_span_32;
1106	    rb->GetValues = read_rgba_pixels_32;
1107            rb->RedBits = 8;
1108            rb->GreenBits = 8;
1109            rb->BlueBits = 8;
1110	    break;
1111	default:
1112	    break;
1113	}
1114    }
1115    else {
1116        /* front buffer (actual Windows window) */
1117	rb->PutRow = write_rgba_span_front;
1118	rb->PutRowRGB = write_rgb_span_front;
1119	rb->PutMonoRow = write_mono_rgba_span_front;
1120	rb->PutValues = write_rgba_pixels_front;
1121	rb->PutMonoValues = write_mono_rgba_pixels_front;
1122	rb->GetRow = read_rgba_span_front;
1123	rb->GetValues = read_rgba_pixels_front;
1124        rb->RedBits = 8; /* XXX fix these (565?) */
1125        rb->GreenBits = 8;
1126        rb->BlueBits = 8;
1127    }
1128}
1129
1130/**
1131 * Called by ctx->Driver.ResizeBuffers()
1132 * Resize the front/back colorbuffers to match the latest window size.
1133 */
1134static void
1135wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
1136                     GLuint width, GLuint height)
1137{
1138    WMesaContext pwc = wmesa_context(ctx);
1139    WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
1140
1141    if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
1142	/* Realloc back buffer */
1143	if (ctx->Visual.doubleBufferMode == 1) {
1144	    wmDeleteBackingStore(pwfb);
1145	    wmCreateBackingStore(pwfb, width, height);
1146	}
1147    }
1148    _mesa_resize_framebuffer(ctx, buffer, width, height);
1149}
1150
1151
1152/**
1153 * Called by glViewport.
1154 * This is a good time for us to poll the current window size and adjust
1155 * our renderbuffers to match the current window size.
1156 * Remember, we have no opportunity to respond to conventional
1157 * resize events since the driver has no event loop.
1158 * Thus, we poll.
1159 * MakeCurrent also ends up making a call here, so that ensures
1160 * we get the viewport set correctly, even if the app does not call
1161 * glViewport and relies on the defaults.
1162 */
1163static void wmesa_viewport(GLcontext *ctx,
1164			   GLint x, GLint y,
1165			   GLsizei width, GLsizei height)
1166{
1167    WMesaContext pwc = wmesa_context(ctx);
1168    GLuint new_width, new_height;
1169
1170    wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
1171
1172    /**
1173     * Resize buffers if the window size changed.
1174     */
1175    wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
1176    ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
1177}
1178
1179
1180
1181
1182/**
1183 * Called when the driver should update it's state, based on the new_state
1184 * flags.
1185 */
1186static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
1187{
1188    _swrast_InvalidateState(ctx, new_state);
1189    _swsetup_InvalidateState(ctx, new_state);
1190    _vbo_InvalidateState(ctx, new_state);
1191    _tnl_InvalidateState(ctx, new_state);
1192
1193    /* TODO - This code is not complete yet because I
1194     * don't know what to do for all state updates.
1195     */
1196
1197    if (new_state & _NEW_BUFFERS) {
1198    }
1199}
1200
1201
1202
1203
1204
1205/**********************************************************************/
1206/*****                   WMESA Functions                          *****/
1207/**********************************************************************/
1208
1209WMesaContext WMesaCreateContext(HDC hDC,
1210				HPALETTE* Pal,
1211				GLboolean rgb_flag,
1212				GLboolean db_flag,
1213				GLboolean alpha_flag)
1214{
1215    WMesaContext c;
1216    struct dd_function_table functions;
1217    GLint red_bits, green_bits, blue_bits, alpha_bits;
1218    GLcontext *ctx;
1219    GLvisual *visual;
1220
1221    (void) Pal;
1222
1223    /* Indexed mode not supported */
1224    if (!rgb_flag)
1225	return NULL;
1226
1227    /* Allocate wmesa context */
1228    c = CALLOC_STRUCT(wmesa_context);
1229    if (!c)
1230	return NULL;
1231
1232#if 0
1233    /* I do not understand this contributed code */
1234    /* Support memory and device contexts */
1235    if(WindowFromDC(hDC) != NULL) {
1236	c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
1237    }
1238    else {
1239	c->hDC = hDC;
1240    }
1241#else
1242    c->hDC = hDC;
1243#endif
1244
1245    /* Get data for visual */
1246    /* Dealing with this is actually a bit of overkill because Mesa will end
1247     * up treating all color component size requests less than 8 by using
1248     * a single byte per channel.  In addition, the interface to the span
1249     * routines passes colors as an entire byte per channel anyway, so there
1250     * is nothing to be saved by telling the visual to be 16 bits if the device
1251     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
1252     * channel anyway.
1253     * But we go through the motions here anyway.
1254     */
1255    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
1256    case 16:
1257	red_bits = green_bits = blue_bits = 5;
1258	alpha_bits = 0;
1259	break;
1260    default:
1261	red_bits = green_bits = blue_bits = 8;
1262	alpha_bits = 8;
1263	break;
1264    }
1265    /* Create visual based on flags */
1266    visual = _mesa_create_visual(rgb_flag,
1267                                 db_flag,    /* db_flag */
1268                                 GL_FALSE,   /* stereo */
1269                                 red_bits, green_bits, blue_bits, /* color RGB */
1270                                 alpha_flag ? alpha_bits : 0, /* color A */
1271                                 0,          /* index bits */
1272                                 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
1273                                 8,          /* stencil_bits */
1274                                 16,16,16,   /* accum RGB */
1275                                 alpha_flag ? 16 : 0, /* accum A */
1276                                 1);         /* num samples */
1277
1278    if (!visual) {
1279	_mesa_free(c);
1280	return NULL;
1281    }
1282
1283    /* Set up driver functions */
1284    _mesa_init_driver_functions(&functions);
1285    functions.GetString = wmesa_get_string;
1286    functions.UpdateState = wmesa_update_state;
1287    functions.GetBufferSize = wmesa_get_buffer_size;
1288    functions.Flush = wmesa_flush;
1289    functions.Clear = clear;
1290    functions.ClearIndex = clear_index;
1291    functions.ClearColor = clear_color;
1292    functions.ResizeBuffers = wmesa_resize_buffers;
1293    functions.Viewport = wmesa_viewport;
1294
1295    /* initialize the Mesa context data */
1296    ctx = &c->gl_ctx;
1297    _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c);
1298
1299    _mesa_enable_sw_extensions(ctx);
1300    _mesa_enable_1_3_extensions(ctx);
1301    _mesa_enable_1_4_extensions(ctx);
1302    _mesa_enable_1_5_extensions(ctx);
1303    _mesa_enable_2_0_extensions(ctx);
1304    _mesa_enable_2_1_extensions(ctx);
1305
1306    /* Initialize the software rasterizer and helper modules. */
1307    if (!_swrast_CreateContext(ctx) ||
1308        !_vbo_CreateContext(ctx) ||
1309        !_tnl_CreateContext(ctx) ||
1310	!_swsetup_CreateContext(ctx)) {
1311	_mesa_free_context_data(ctx);
1312	_mesa_free(c);
1313	return NULL;
1314    }
1315    _swsetup_Wakeup(ctx);
1316    TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1317
1318    return c;
1319}
1320
1321
1322void WMesaDestroyContext( WMesaContext pwc )
1323{
1324    GLcontext *ctx = &pwc->gl_ctx;
1325    WMesaFramebuffer pwfb;
1326    GET_CURRENT_CONTEXT(cur_ctx);
1327
1328    if (cur_ctx == ctx) {
1329        /* unbind current if deleting current context */
1330        WMesaMakeCurrent(NULL, NULL);
1331    }
1332
1333    /* clean up frame buffer resources */
1334    pwfb = wmesa_lookup_framebuffer(pwc->hDC);
1335    if (pwfb) {
1336	if (ctx->Visual.doubleBufferMode == 1)
1337	    wmDeleteBackingStore(pwfb);
1338	wmesa_free_framebuffer(pwc->hDC);
1339    }
1340
1341    /* Release for device, not memory contexts */
1342    if (WindowFromDC(pwc->hDC) != NULL)
1343    {
1344      ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
1345    }
1346    DeleteObject(pwc->clearPen);
1347    DeleteObject(pwc->clearBrush);
1348
1349    _swsetup_DestroyContext(ctx);
1350    _tnl_DestroyContext(ctx);
1351    _vbo_DestroyContext(ctx);
1352    _swrast_DestroyContext(ctx);
1353
1354    _mesa_free_context_data(ctx);
1355    _mesa_free(pwc);
1356}
1357
1358
1359/**
1360 * Create a new color renderbuffer.
1361 */
1362struct gl_renderbuffer *
1363wmesa_new_renderbuffer(void)
1364{
1365    struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1366    if (!rb)
1367        return NULL;
1368
1369    _mesa_init_renderbuffer(rb, (GLuint)0);
1370
1371    rb->_BaseFormat = GL_RGBA;
1372    rb->InternalFormat = GL_RGBA;
1373    rb->DataType = CHAN_TYPE;
1374    rb->Delete = wmesa_delete_renderbuffer;
1375    rb->AllocStorage = wmesa_renderbuffer_storage;
1376    return rb;
1377}
1378
1379
1380void WMesaMakeCurrent(WMesaContext c, HDC hdc)
1381{
1382    WMesaFramebuffer pwfb;
1383
1384    {
1385        /* return if already current */
1386        GET_CURRENT_CONTEXT(ctx);
1387        WMesaContext pwc = wmesa_context(ctx);
1388        if (pwc && c == pwc && pwc->hDC == hdc)
1389            return;
1390    }
1391
1392    pwfb = wmesa_lookup_framebuffer(hdc);
1393
1394    /* Lazy creation of framebuffers */
1395    if (c && !pwfb && hdc) {
1396        struct gl_renderbuffer *rb;
1397        GLvisual *visual = &c->gl_ctx.Visual;
1398        GLuint width, height;
1399
1400        get_window_size(hdc, &width, &height);
1401
1402	c->clearPen = CreatePen(PS_SOLID, 1, 0);
1403	c->clearBrush = CreateSolidBrush(0);
1404
1405        pwfb = wmesa_new_framebuffer(hdc, visual);
1406
1407	/* Create back buffer if double buffered */
1408	if (visual->doubleBufferMode == 1) {
1409	    wmCreateBackingStore(pwfb, width, height);
1410	}
1411
1412        /* make render buffers */
1413        if (visual->doubleBufferMode == 1) {
1414            rb = wmesa_new_renderbuffer();
1415            _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
1416            wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 1);
1417	}
1418        rb = wmesa_new_renderbuffer();
1419        _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
1420        wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 0);
1421
1422	/* Let Mesa own the Depth, Stencil, and Accum buffers */
1423        _mesa_add_soft_renderbuffers(&pwfb->Base,
1424                                     GL_FALSE, /* color */
1425                                     visual->depthBits > 0,
1426                                     visual->stencilBits > 0,
1427                                     visual->accumRedBits > 0,
1428                                     visual->alphaBits >0,
1429                                     GL_FALSE);
1430    }
1431
1432    if (c && pwfb)
1433	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
1434    else
1435        _mesa_make_current(NULL, NULL, NULL);
1436}
1437
1438
1439void WMesaSwapBuffers( HDC hdc )
1440{
1441    GET_CURRENT_CONTEXT(ctx);
1442    WMesaContext pwc = wmesa_context(ctx);
1443    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
1444
1445    if (!pwfb) {
1446        _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
1447        return;
1448    }
1449
1450    /* If we're swapping the buffer associated with the current context
1451     * we have to flush any pending rendering commands first.
1452     */
1453    if (pwc->hDC == hdc) {
1454	_mesa_notifySwapBuffers(ctx);
1455
1456	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
1457	       pwfb->dib_hDC, 0, 0, SRCCOPY);
1458    }
1459    else {
1460        /* XXX for now only allow swapping current window */
1461        _mesa_problem(NULL, "wmesa: can't swap non-current window");
1462    }
1463}
1464
1465void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
1466{
1467	_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
1468}
1469
1470/* This is hopefully a temporary hack to define some needed dispatch
1471 * table entries.  Hopefully, I'll find a better solution.  The
1472 * dispatch table generation scripts ought to be making these dummy
1473 * stubs as well. */
1474#if !defined(__MINGW32__) || !defined(GL_NO_STDCALL)
1475void gl_dispatch_stub_543(void){}
1476void gl_dispatch_stub_544(void){}
1477void gl_dispatch_stub_545(void){}
1478void gl_dispatch_stub_546(void){}
1479void gl_dispatch_stub_547(void){}
1480void gl_dispatch_stub_548(void){}
1481void gl_dispatch_stub_549(void){}
1482void gl_dispatch_stub_550(void){}
1483void gl_dispatch_stub_551(void){}
1484void gl_dispatch_stub_552(void){}
1485void gl_dispatch_stub_553(void){}
1486void gl_dispatch_stub_554(void){}
1487void gl_dispatch_stub_555(void){}
1488void gl_dispatch_stub_556(void){}
1489void gl_dispatch_stub_557(void){}
1490void gl_dispatch_stub_558(void){}
1491void gl_dispatch_stub_559(void){}
1492void gl_dispatch_stub_560(void){}
1493void gl_dispatch_stub_561(void){}
1494void gl_dispatch_stub_565(void){}
1495void gl_dispatch_stub_566(void){}
1496void gl_dispatch_stub_577(void){}
1497void gl_dispatch_stub_578(void){}
1498void gl_dispatch_stub_603(void){}
1499void gl_dispatch_stub_645(void){}
1500void gl_dispatch_stub_646(void){}
1501void gl_dispatch_stub_647(void){}
1502void gl_dispatch_stub_648(void){}
1503void gl_dispatch_stub_649(void){}
1504void gl_dispatch_stub_650(void){}
1505void gl_dispatch_stub_651(void){}
1506void gl_dispatch_stub_652(void){}
1507void gl_dispatch_stub_653(void){}
1508void gl_dispatch_stub_734(void){}
1509void gl_dispatch_stub_735(void){}
1510void gl_dispatch_stub_736(void){}
1511void gl_dispatch_stub_737(void){}
1512void gl_dispatch_stub_738(void){}
1513void gl_dispatch_stub_745(void){}
1514void gl_dispatch_stub_746(void){}
1515void gl_dispatch_stub_760(void){}
1516void gl_dispatch_stub_761(void){}
1517void gl_dispatch_stub_766(void){}
1518void gl_dispatch_stub_767(void){}
1519void gl_dispatch_stub_768(void){}
1520
1521void gl_dispatch_stub_562(void){}
1522void gl_dispatch_stub_563(void){}
1523void gl_dispatch_stub_564(void){}
1524void gl_dispatch_stub_567(void){}
1525void gl_dispatch_stub_568(void){}
1526void gl_dispatch_stub_569(void){}
1527void gl_dispatch_stub_580(void){}
1528void gl_dispatch_stub_581(void){}
1529void gl_dispatch_stub_606(void){}
1530void gl_dispatch_stub_654(void){}
1531void gl_dispatch_stub_655(void){}
1532void gl_dispatch_stub_656(void){}
1533void gl_dispatch_stub_739(void){}
1534void gl_dispatch_stub_740(void){}
1535void gl_dispatch_stub_741(void){}
1536void gl_dispatch_stub_748(void){}
1537void gl_dispatch_stub_749(void){}
1538void gl_dispatch_stub_769(void){}
1539void gl_dispatch_stub_770(void){}
1540void gl_dispatch_stub_771(void){}
1541
1542#endif
1543