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