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