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