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