Home | History | Annotate | Download | only in gdi
      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) */
     27 static WMesaFramebuffer FirstFramebuffer = NULL;
     28 
     29 
     30 /**
     31  * Create a new WMesaFramebuffer object which will correspond to the
     32  * given HDC (Window handle).
     33  */
     34 static WMesaFramebuffer
     35 wmesa_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  */
     52 static void
     53 wmesa_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  */
     75 static WMesaFramebuffer
     76 wmesa_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  */
     90 static 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  */
     99 static 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  */
    109 static 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  */
    119 static 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  */
    151 static 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 
    189 static 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  */
    202 static void
    203 get_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 
    220 static void
    221 wmesa_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 
    228 static 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 /*
    247  * Clear the color/depth/stencil buffers.
    248  */
    249 static void clear(struct gl_context *ctx, GLbitfield mask)
    250 {
    251 #define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
    252     const GLint x = ctx->DrawBuffer->_Xmin;
    253     const GLint y = ctx->DrawBuffer->_Ymin;
    254     const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
    255     const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
    256 
    257     WMesaContext pwc = wmesa_context(ctx);
    258     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    259     int done = 0;
    260 
    261     /* Let swrast do all the work if the masks are not set to
    262      * clear all channels. */
    263     if (!ctx->Color.ColorMask[0][0] ||
    264 	!ctx->Color.ColorMask[0][1] ||
    265 	!ctx->Color.ColorMask[0][2] ||
    266 	!ctx->Color.ColorMask[0][3]) {
    267 	_swrast_Clear(ctx, mask);
    268 	return;
    269     }
    270 
    271     if (mask & BUFFER_BITS_COLOR) {
    272        /* setup the clearing color */
    273        const union gl_color_union color = ctx->Color.ClearColor;
    274        GLubyte col[3];
    275        UNCLAMPED_FLOAT_TO_UBYTE(col[0], color.f[0]);
    276        UNCLAMPED_FLOAT_TO_UBYTE(col[1], color.f[1]);
    277        UNCLAMPED_FLOAT_TO_UBYTE(col[2], color.f[2]);
    278        pwc->clearColorRef = RGB(col[0], col[1], col[2]);
    279        DeleteObject(pwc->clearPen);
    280        DeleteObject(pwc->clearBrush);
    281        pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
    282        pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
    283     }
    284 
    285     /* Back buffer */
    286     if (mask & BUFFER_BIT_BACK_LEFT) {
    287 
    288 	int     i, rowSize;
    289 	UINT    bytesPerPixel = pwfb->cColorBits / 8;
    290 	LPBYTE  lpb, clearRow;
    291 	LPWORD  lpw;
    292 	BYTE    bColor;
    293 	WORD    wColor;
    294 	BYTE    r, g, b;
    295 	DWORD   dwColor;
    296 	LPDWORD lpdw;
    297 
    298 	/* Try for a fast clear - clearing entire buffer with a single
    299 	 * byte value. */
    300 	if (width == ctx->DrawBuffer->Width &&
    301             height == ctx->DrawBuffer->Height) { /* entire buffer */
    302 	    /* Now check for an easy clear value */
    303 	    switch (bytesPerPixel) {
    304 	    case 1:
    305 		bColor = BGR8(GetRValue(pwc->clearColorRef),
    306 			      GetGValue(pwc->clearColorRef),
    307 			      GetBValue(pwc->clearColorRef));
    308 		memset(pwfb->pbPixels, bColor,
    309 		       pwfb->ScanWidth * height);
    310 		done = 1;
    311 		break;
    312 	    case 2:
    313 		wColor = BGR16(GetRValue(pwc->clearColorRef),
    314 			       GetGValue(pwc->clearColorRef),
    315 			       GetBValue(pwc->clearColorRef));
    316 		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
    317 		    memset(pwfb->pbPixels, wColor & 0xff,
    318 			   pwfb->ScanWidth * height);
    319 		    done = 1;
    320 		}
    321 		break;
    322 	    case 3:
    323 		/* fall through */
    324 	    case 4:
    325 		if (GetRValue(pwc->clearColorRef) ==
    326 		    GetGValue(pwc->clearColorRef) &&
    327 		    GetRValue(pwc->clearColorRef) ==
    328 		    GetBValue(pwc->clearColorRef)) {
    329 		    memset(pwfb->pbPixels,
    330 			   GetRValue(pwc->clearColorRef),
    331 			   pwfb->ScanWidth * height);
    332 		    done = 1;
    333 		}
    334 		break;
    335 	    default:
    336 		break;
    337 	    }
    338 	} /* all */
    339 
    340 	if (!done) {
    341 	    /* Need to clear a row at a time.  Begin by setting the first
    342 	     * row in the area to be cleared to the clear color. */
    343 
    344 	    clearRow = pwfb->pbPixels +
    345 		pwfb->ScanWidth * FLIP(y) +
    346 		bytesPerPixel * x;
    347 	    switch (bytesPerPixel) {
    348 	    case 1:
    349 		lpb = clearRow;
    350 		bColor = BGR8(GetRValue(pwc->clearColorRef),
    351 			      GetGValue(pwc->clearColorRef),
    352 			      GetBValue(pwc->clearColorRef));
    353 		memset(lpb, bColor, width);
    354 		break;
    355 	    case 2:
    356 		lpw = (LPWORD)clearRow;
    357 		wColor = BGR16(GetRValue(pwc->clearColorRef),
    358 			       GetGValue(pwc->clearColorRef),
    359 			       GetBValue(pwc->clearColorRef));
    360 		for (i=0; i<width; i++)
    361 		    *lpw++ = wColor;
    362 		break;
    363 	    case 3:
    364 		lpb = clearRow;
    365 		r = GetRValue(pwc->clearColorRef);
    366 		g = GetGValue(pwc->clearColorRef);
    367 		b = GetBValue(pwc->clearColorRef);
    368 		for (i=0; i<width; i++) {
    369 		    *lpb++ = b;
    370 		    *lpb++ = g;
    371 		    *lpb++ = r;
    372 		}
    373 		break;
    374 	    case 4:
    375 		lpdw = (LPDWORD)clearRow;
    376 		dwColor = BGR32(GetRValue(pwc->clearColorRef),
    377 				GetGValue(pwc->clearColorRef),
    378 				GetBValue(pwc->clearColorRef));
    379 		for (i=0; i<width; i++)
    380 		    *lpdw++ = dwColor;
    381 		break;
    382 	    default:
    383 		break;
    384 	    } /* switch */
    385 
    386 	    /* copy cleared row to other rows in buffer */
    387 	    lpb = clearRow - pwfb->ScanWidth;
    388 	    rowSize = width * bytesPerPixel;
    389 	    for (i=1; i<height; i++) {
    390 		memcpy(lpb, clearRow, rowSize);
    391 		lpb -= pwfb->ScanWidth;
    392 	    }
    393 	} /* not done */
    394 	mask &= ~BUFFER_BIT_BACK_LEFT;
    395     } /* back buffer */
    396 
    397     /* front buffer */
    398     if (mask & BUFFER_BIT_FRONT_LEFT) {
    399 	HDC DC = pwc->hDC;
    400 	HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
    401 	HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
    402 	Rectangle(DC,
    403 		  x,
    404 		  FLIP(y) + 1,
    405 		  x + width + 1,
    406 		  FLIP(y) - height + 1);
    407 	SelectObject(DC, Old_Pen);
    408 	SelectObject(DC, Old_Brush);
    409 	mask &= ~BUFFER_BIT_FRONT_LEFT;
    410     } /* front buffer */
    411 
    412     /* Call swrast if there is anything left to clear (like DEPTH) */
    413     if (mask)
    414 	_swrast_Clear(ctx, mask);
    415 
    416 #undef FLIP
    417 }
    418 
    419 
    420 /**********************************************************************/
    421 /*****                   PIXEL Functions                          *****/
    422 /**********************************************************************/
    423 
    424 #define FLIP(Y)  (rb->Height - (Y) - 1)
    425 
    426 
    427 /**
    428  ** Front Buffer reading/writing
    429  ** These are slow, but work with all non-indexed visual types.
    430  **/
    431 
    432 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
    433 static void write_rgba_span_front(struct gl_context *ctx,
    434 				  struct gl_renderbuffer *rb,
    435 				  GLuint n, GLint x, GLint y,
    436 				  const void *values,
    437 				  const GLubyte *mask)
    438 {
    439    const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    440    WMesaContext pwc = wmesa_context(ctx);
    441    WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
    442    HBITMAP bmp=0;
    443    HDC mdc=0;
    444    typedef union
    445    {
    446       unsigned i;
    447       struct {
    448          unsigned b:8, g:8, r:8, a:8;
    449       };
    450    } BGRA;
    451    BGRA *bgra, c;
    452    GLuint i;
    453 
    454    if (n < 16) {   // the value 16 is just guessed
    455       y=FLIP(y);
    456       if (mask) {
    457          for (i=0; i<n; i++)
    458             if (mask[i])
    459                SetPixel(pwc->hDC, x+i, y,
    460                         RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
    461       }
    462       else {
    463          for (i=0; i<n; i++)
    464             SetPixel(pwc->hDC, x+i, y,
    465                      RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
    466       }
    467    }
    468    else {
    469       if (!pwfb) {
    470          _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
    471          return;
    472       }
    473       bgra=malloc(n*sizeof(BGRA));
    474       if (!bgra) {
    475          _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
    476          return;
    477       }
    478       c.a=0;
    479       if (mask) {
    480          for (i=0; i<n; i++) {
    481             if (mask[i]) {
    482                c.r=rgba[i][RCOMP];
    483                c.g=rgba[i][GCOMP];
    484                c.b=rgba[i][BCOMP];
    485                c.a=rgba[i][ACOMP];
    486                bgra[i]=c;
    487             }
    488             else
    489                bgra[i].i=0;
    490          }
    491       }
    492       else {
    493          for (i=0; i<n; i++) {
    494             c.r=rgba[i][RCOMP];
    495             c.g=rgba[i][GCOMP];
    496             c.b=rgba[i][BCOMP];
    497             c.a=rgba[i][ACOMP];
    498             bgra[i]=c;
    499          }
    500       }
    501       bmp=CreateBitmap(n, 1,  1, 32, bgra);
    502       mdc=CreateCompatibleDC(pwfb->hDC);
    503       SelectObject(mdc, bmp);
    504       y=FLIP(y);
    505       BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
    506       SelectObject(mdc, 0);
    507       DeleteObject(bmp);
    508       DeleteDC(mdc);
    509       free(bgra);
    510    }
    511 }
    512 
    513 
    514 /* Write an array of RGBA pixels with a boolean mask. */
    515 static void write_rgba_pixels_front(struct gl_context *ctx,
    516                                     struct gl_renderbuffer *rb,
    517                                     GLuint n,
    518                                     const GLint x[], const GLint y[],
    519                                     const void *values,
    520                                     const GLubyte *mask)
    521 {
    522     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    523     GLuint i;
    524     WMesaContext pwc = wmesa_context(ctx);
    525     (void) ctx;
    526     for (i=0; i<n; i++)
    527 	if (mask[i])
    528 	    SetPixel(pwc->hDC, x[i], FLIP(y[i]),
    529 		     RGB(rgba[i][RCOMP], rgba[i][GCOMP],
    530 			 rgba[i][BCOMP]));
    531 }
    532 
    533 
    534 
    535 /* Read a horizontal span of color pixels. */
    536 static void read_rgba_span_front(struct gl_context *ctx,
    537                                  struct gl_renderbuffer *rb,
    538                                  GLuint n, GLint x, GLint y,
    539                                  void *values)
    540 {
    541     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    542     WMesaContext pwc = wmesa_context(ctx);
    543     GLuint i;
    544     COLORREF Color;
    545     y = FLIP(y);
    546     for (i=0; i<n; i++) {
    547 	Color = GetPixel(pwc->hDC, x+i, y);
    548 	rgba[i][RCOMP] = GetRValue(Color);
    549 	rgba[i][GCOMP] = GetGValue(Color);
    550 	rgba[i][BCOMP] = GetBValue(Color);
    551 	rgba[i][ACOMP] = 255;
    552     }
    553 }
    554 
    555 
    556 /* Read an array of color pixels. */
    557 static void read_rgba_pixels_front(struct gl_context *ctx,
    558                                    struct gl_renderbuffer *rb,
    559                                    GLuint n, const GLint x[], const GLint y[],
    560                                    void *values)
    561 {
    562     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    563     WMesaContext pwc = wmesa_context(ctx);
    564     GLuint i;
    565     COLORREF Color;
    566     for (i=0; i<n; i++) {
    567         GLint y2 = FLIP(y[i]);
    568         Color = GetPixel(pwc->hDC, x[i], y2);
    569         rgba[i][RCOMP] = GetRValue(Color);
    570         rgba[i][GCOMP] = GetGValue(Color);
    571         rgba[i][BCOMP] = GetBValue(Color);
    572         rgba[i][ACOMP] = 255;
    573     }
    574 }
    575 
    576 /*********************************************************************/
    577 
    578 /* DOUBLE BUFFER 32-bit */
    579 
    580 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
    581 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
    582 *lpdw = BGR32((r),(g),(b)); }
    583 
    584 
    585 
    586 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
    587 static void write_rgba_span_32(struct gl_context *ctx,
    588 			       struct gl_renderbuffer *rb,
    589 			       GLuint n, GLint x, GLint y,
    590 			       const void *values,
    591 			       const GLubyte *mask)
    592 {
    593     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    594     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    595     GLuint i;
    596     LPDWORD lpdw;
    597 
    598     (void) ctx;
    599 
    600     y=FLIP(y);
    601     lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
    602     if (mask) {
    603 	for (i=0; i<n; i++)
    604 	    if (mask[i])
    605                 lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
    606 				rgba[i][BCOMP]);
    607     }
    608     else {
    609 	for (i=0; i<n; i++)
    610                 *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
    611 				rgba[i][BCOMP]);
    612     }
    613 }
    614 
    615 
    616 /* Write an array of RGBA pixels with a boolean mask. */
    617 static void write_rgba_pixels_32(struct gl_context *ctx,
    618 				 struct gl_renderbuffer *rb,
    619 				 GLuint n, const GLint x[], const GLint y[],
    620 				 const void *values,
    621 				 const GLubyte *mask)
    622 {
    623     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    624     GLuint i;
    625     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    626     for (i=0; i<n; i++)
    627 	if (mask[i])
    628 	    WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
    629 			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
    630 }
    631 
    632 
    633 /* Read a horizontal span of color pixels. */
    634 static void read_rgba_span_32(struct gl_context *ctx,
    635 			      struct gl_renderbuffer *rb,
    636 			      GLuint n, GLint x, GLint y,
    637 			      void *values)
    638 {
    639     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    640     GLuint i;
    641     DWORD pixel;
    642     LPDWORD lpdw;
    643     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    644 
    645     y = FLIP(y);
    646     lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
    647     for (i=0; i<n; i++) {
    648 	pixel = lpdw[i];
    649 	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
    650 	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
    651 	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
    652 	rgba[i][ACOMP] = 255;
    653     }
    654 }
    655 
    656 
    657 /* Read an array of color pixels. */
    658 static void read_rgba_pixels_32(struct gl_context *ctx,
    659 				struct gl_renderbuffer *rb,
    660 				GLuint n, const GLint x[], const GLint y[],
    661 				void *values)
    662 {
    663     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    664     GLuint i;
    665     DWORD pixel;
    666     LPDWORD lpdw;
    667     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    668 
    669     for (i=0; i<n; i++) {
    670 	GLint y2 = FLIP(y[i]);
    671 	lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
    672 	pixel = *lpdw;
    673 	rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
    674 	rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
    675 	rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
    676 	rgba[i][ACOMP] = 255;
    677   }
    678 }
    679 
    680 
    681 /*********************************************************************/
    682 
    683 /* DOUBLE BUFFER 24-bit */
    684 
    685 #define WMSETPIXEL24(pwc, y, x, r, g, b) { \
    686 LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
    687 lpb[0] = (b); \
    688 lpb[1] = (g); \
    689 lpb[2] = (r); }
    690 
    691 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
    692 static void write_rgba_span_24(struct gl_context *ctx,
    693 			       struct gl_renderbuffer *rb,
    694 			       GLuint n, GLint x, GLint y,
    695 			       const void *values,
    696 			       const GLubyte *mask)
    697 {
    698     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    699     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    700     GLuint i;
    701     LPBYTE lpb;
    702 
    703     (void) ctx;
    704 
    705     y=FLIP(y);
    706     lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
    707     if (mask) {
    708 	for (i=0; i<n; i++)
    709 	    if (mask[i]) {
    710                 lpb[3*i] = rgba[i][BCOMP];
    711                 lpb[3*i+1] = rgba[i][GCOMP];
    712                 lpb[3*i+2] = rgba[i][RCOMP];
    713 	    }
    714     }
    715     else {
    716 	    for (i=0; i<n; i++) {
    717             *lpb++ = rgba[i][BCOMP];
    718             *lpb++ = rgba[i][GCOMP];
    719             *lpb++ = rgba[i][RCOMP];
    720 	    }
    721     }
    722 }
    723 
    724 
    725 /* Write an array of RGBA pixels with a boolean mask. */
    726 static void write_rgba_pixels_24(struct gl_context *ctx,
    727 				 struct gl_renderbuffer *rb,
    728 				 GLuint n, const GLint x[], const GLint y[],
    729 				 const void *values,
    730 				 const GLubyte *mask)
    731 {
    732     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    733     GLuint i;
    734     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    735     for (i=0; i<n; i++)
    736 	if (mask[i])
    737 	    WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
    738 			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
    739 }
    740 
    741 
    742 /* Read a horizontal span of color pixels. */
    743 static void read_rgba_span_24(struct gl_context *ctx,
    744 			      struct gl_renderbuffer *rb,
    745 			      GLuint n, GLint x, GLint y,
    746 			      void *values)
    747 {
    748     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    749     GLuint i;
    750     LPBYTE lpb;
    751     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    752 
    753     y = FLIP(y);
    754     lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
    755     for (i=0; i<n; i++) {
    756 	rgba[i][RCOMP] = lpb[3*i+2];
    757 	rgba[i][GCOMP] = lpb[3*i+1];
    758 	rgba[i][BCOMP] = lpb[3*i];
    759 	rgba[i][ACOMP] = 255;
    760     }
    761 }
    762 
    763 
    764 /* Read an array of color pixels. */
    765 static void read_rgba_pixels_24(struct gl_context *ctx,
    766 				struct gl_renderbuffer *rb,
    767 				GLuint n, const GLint x[], const GLint y[],
    768 				void *values)
    769 {
    770     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    771     GLuint i;
    772     LPBYTE lpb;
    773     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    774 
    775     for (i=0; i<n; i++) {
    776 	GLint y2 = FLIP(y[i]);
    777 	lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
    778 	rgba[i][RCOMP] = lpb[3*i+2];
    779 	rgba[i][GCOMP] = lpb[3*i+1];
    780 	rgba[i][BCOMP] = lpb[3*i];
    781 	rgba[i][ACOMP] = 255;
    782   }
    783 }
    784 
    785 
    786 /*********************************************************************/
    787 
    788 /* DOUBLE BUFFER 16-bit */
    789 
    790 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
    791 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
    792 *lpw = BGR16((r),(g),(b)); }
    793 
    794 
    795 
    796 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
    797 static void write_rgba_span_16(struct gl_context *ctx,
    798 			       struct gl_renderbuffer *rb,
    799 			       GLuint n, GLint x, GLint y,
    800 			       const void *values,
    801 			       const GLubyte *mask)
    802 {
    803     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    804     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    805     GLuint i;
    806     LPWORD lpw;
    807 
    808     (void) ctx;
    809 
    810     y=FLIP(y);
    811     lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
    812     if (mask) {
    813 	for (i=0; i<n; i++)
    814 	    if (mask[i])
    815                 lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
    816 			       rgba[i][BCOMP]);
    817     }
    818     else {
    819 	for (i=0; i<n; i++)
    820                 *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
    821 			       rgba[i][BCOMP]);
    822     }
    823 }
    824 
    825 
    826 
    827 /* Write an array of RGBA pixels with a boolean mask. */
    828 static void write_rgba_pixels_16(struct gl_context *ctx,
    829 				 struct gl_renderbuffer *rb,
    830 				 GLuint n, const GLint x[], const GLint y[],
    831 				 const void *values,
    832 				 const GLubyte *mask)
    833 {
    834     const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
    835     GLuint i;
    836     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    837     (void) ctx;
    838     for (i=0; i<n; i++)
    839 	if (mask[i])
    840 	    WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
    841 			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
    842 }
    843 
    844 
    845 /* Read a horizontal span of color pixels. */
    846 static void read_rgba_span_16(struct gl_context *ctx,
    847 			      struct gl_renderbuffer *rb,
    848 			      GLuint n, GLint x, GLint y,
    849 			      void *values)
    850 {
    851     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    852     GLuint i, pixel;
    853     LPWORD lpw;
    854     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    855 
    856     y = FLIP(y);
    857     lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
    858     for (i=0; i<n; i++) {
    859 	pixel = lpw[i];
    860 	/* Windows uses 5,5,5 for 16-bit */
    861 	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
    862 	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
    863 	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
    864 	rgba[i][ACOMP] = 255;
    865     }
    866 }
    867 
    868 
    869 /* Read an array of color pixels. */
    870 static void read_rgba_pixels_16(struct gl_context *ctx,
    871 				struct gl_renderbuffer *rb,
    872 				GLuint n, const GLint x[], const GLint y[],
    873 				void *values)
    874 {
    875     GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
    876     GLuint i, pixel;
    877     LPWORD lpw;
    878     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
    879 
    880     for (i=0; i<n; i++) {
    881 	GLint y2 = FLIP(y[i]);
    882 	lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
    883 	pixel = *lpw;
    884 	/* Windows uses 5,5,5 for 16-bit */
    885 	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
    886 	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
    887 	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
    888 	rgba[i][ACOMP] = 255;
    889   }
    890 }
    891 
    892 
    893 
    894 
    895 /**********************************************************************/
    896 /*****                   BUFFER Functions                         *****/
    897 /**********************************************************************/
    898 
    899 
    900 
    901 
    902 static void
    903 wmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
    904 {
    905     _mesa_delete_renderbuffer(ctx, rb);
    906 }
    907 
    908 
    909 /**
    910  * This is called by Mesa whenever it determines that the window size
    911  * has changed.  Do whatever's needed to cope with that.
    912  */
    913 static GLboolean
    914 wmesa_renderbuffer_storage(struct gl_context *ctx,
    915 			   struct gl_renderbuffer *rb,
    916 			   GLenum internalFormat,
    917 			   GLuint width,
    918 			   GLuint height)
    919 {
    920     rb->Width = width;
    921     rb->Height = height;
    922     return GL_TRUE;
    923 }
    924 
    925 
    926 /**
    927  * Called by ctx->Driver.ResizeBuffers()
    928  * Resize the front/back colorbuffers to match the latest window size.
    929  */
    930 static void
    931 wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
    932                      GLuint width, GLuint height)
    933 {
    934     WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
    935 
    936     if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
    937 	/* Realloc back buffer */
    938 	if (ctx->Visual.doubleBufferMode == 1) {
    939 	    wmDeleteBackingStore(pwfb);
    940 	    wmCreateBackingStore(pwfb, width, height);
    941 	}
    942     }
    943     _mesa_resize_framebuffer(ctx, buffer, width, height);
    944 }
    945 
    946 
    947 /**
    948  * Called by glViewport.
    949  * This is a good time for us to poll the current window size and adjust
    950  * our renderbuffers to match the current window size.
    951  * Remember, we have no opportunity to respond to conventional
    952  * resize events since the driver has no event loop.
    953  * Thus, we poll.
    954  * MakeCurrent also ends up making a call here, so that ensures
    955  * we get the viewport set correctly, even if the app does not call
    956  * glViewport and relies on the defaults.
    957  */
    958 static void wmesa_viewport(struct gl_context *ctx,
    959 			   GLint x, GLint y,
    960 			   GLsizei width, GLsizei height)
    961 {
    962     GLuint new_width, new_height;
    963 
    964     wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
    965 
    966     /**
    967      * Resize buffers if the window size changed.
    968      */
    969     wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
    970     ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
    971 }
    972 
    973 
    974 
    975 
    976 /**
    977  * Called when the driver should update it's state, based on the new_state
    978  * flags.
    979  */
    980 static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
    981 {
    982     _swrast_InvalidateState(ctx, new_state);
    983     _swsetup_InvalidateState(ctx, new_state);
    984     _vbo_InvalidateState(ctx, new_state);
    985     _tnl_InvalidateState(ctx, new_state);
    986 
    987     /* TODO - This code is not complete yet because I
    988      * don't know what to do for all state updates.
    989      */
    990 
    991     if (new_state & _NEW_BUFFERS) {
    992     }
    993 }
    994 
    995 
    996 
    997 
    998 
    999 /**********************************************************************/
   1000 /*****                   WMESA Functions                          *****/
   1001 /**********************************************************************/
   1002 
   1003 WMesaContext WMesaCreateContext(HDC hDC,
   1004 				HPALETTE* Pal,
   1005 				GLboolean rgb_flag,
   1006 				GLboolean db_flag,
   1007 				GLboolean alpha_flag)
   1008 {
   1009     WMesaContext c;
   1010     struct dd_function_table functions;
   1011     GLint red_bits, green_bits, blue_bits, alpha_bits;
   1012     struct gl_context *ctx;
   1013     struct gl_config *visual;
   1014 
   1015     (void) Pal;
   1016 
   1017     /* Indexed mode not supported */
   1018     if (!rgb_flag)
   1019 	return NULL;
   1020 
   1021     /* Allocate wmesa context */
   1022     c = CALLOC_STRUCT(wmesa_context);
   1023     if (!c)
   1024 	return NULL;
   1025 
   1026 #if 0
   1027     /* I do not understand this contributed code */
   1028     /* Support memory and device contexts */
   1029     if(WindowFromDC(hDC) != NULL) {
   1030 	c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
   1031     }
   1032     else {
   1033 	c->hDC = hDC;
   1034     }
   1035 #else
   1036     c->hDC = hDC;
   1037 #endif
   1038 
   1039     /* Get data for visual */
   1040     /* Dealing with this is actually a bit of overkill because Mesa will end
   1041      * up treating all color component size requests less than 8 by using
   1042      * a single byte per channel.  In addition, the interface to the span
   1043      * routines passes colors as an entire byte per channel anyway, so there
   1044      * is nothing to be saved by telling the visual to be 16 bits if the device
   1045      * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
   1046      * channel anyway.
   1047      * But we go through the motions here anyway.
   1048      */
   1049     switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
   1050     case 16:
   1051 	red_bits = green_bits = blue_bits = 5;
   1052 	alpha_bits = 0;
   1053 	break;
   1054     default:
   1055 	red_bits = green_bits = blue_bits = 8;
   1056 	alpha_bits = 8;
   1057 	break;
   1058     }
   1059     /* Create visual based on flags */
   1060     visual = _mesa_create_visual(db_flag,    /* db_flag */
   1061                                  GL_FALSE,   /* stereo */
   1062                                  red_bits, green_bits, blue_bits, /* color RGB */
   1063                                  alpha_flag ? alpha_bits : 0, /* color A */
   1064                                  DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
   1065                                  8,          /* stencil_bits */
   1066                                  16,16,16,   /* accum RGB */
   1067                                  alpha_flag ? 16 : 0, /* accum A */
   1068                                  1);         /* num samples */
   1069 
   1070     if (!visual) {
   1071 	free(c);
   1072 	return NULL;
   1073     }
   1074 
   1075     /* Set up driver functions */
   1076     _mesa_init_driver_functions(&functions);
   1077     functions.GetString = wmesa_get_string;
   1078     functions.UpdateState = wmesa_update_state;
   1079     functions.GetBufferSize = wmesa_get_buffer_size;
   1080     functions.Flush = wmesa_flush;
   1081     functions.Clear = clear;
   1082     functions.ResizeBuffers = wmesa_resize_buffers;
   1083     functions.Viewport = wmesa_viewport;
   1084 
   1085     /* initialize the Mesa context data */
   1086     ctx = &c->gl_ctx;
   1087     _mesa_initialize_context(ctx, API_OPENGL, visual,
   1088                              NULL, &functions, (void *)c);
   1089 
   1090     /* visual no longer needed - it was copied by _mesa_initialize_context() */
   1091     _mesa_destroy_visual(visual);
   1092 
   1093     _mesa_enable_sw_extensions(ctx);
   1094     _mesa_enable_1_3_extensions(ctx);
   1095     _mesa_enable_1_4_extensions(ctx);
   1096     _mesa_enable_1_5_extensions(ctx);
   1097     _mesa_enable_2_0_extensions(ctx);
   1098     _mesa_enable_2_1_extensions(ctx);
   1099 
   1100     _mesa_meta_init(ctx);
   1101 
   1102     /* Initialize the software rasterizer and helper modules. */
   1103     if (!_swrast_CreateContext(ctx) ||
   1104         !_vbo_CreateContext(ctx) ||
   1105         !_tnl_CreateContext(ctx) ||
   1106 	!_swsetup_CreateContext(ctx)) {
   1107 	_mesa_free_context_data(ctx);
   1108 	free(c);
   1109 	return NULL;
   1110     }
   1111     _swsetup_Wakeup(ctx);
   1112     TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
   1113 
   1114     return c;
   1115 }
   1116 
   1117 
   1118 void WMesaDestroyContext( WMesaContext pwc )
   1119 {
   1120     struct gl_context *ctx = &pwc->gl_ctx;
   1121     WMesaFramebuffer pwfb;
   1122     GET_CURRENT_CONTEXT(cur_ctx);
   1123 
   1124     if (cur_ctx == ctx) {
   1125         /* unbind current if deleting current context */
   1126         WMesaMakeCurrent(NULL, NULL);
   1127     }
   1128 
   1129     /* clean up frame buffer resources */
   1130     pwfb = wmesa_lookup_framebuffer(pwc->hDC);
   1131     if (pwfb) {
   1132 	if (ctx->Visual.doubleBufferMode == 1)
   1133 	    wmDeleteBackingStore(pwfb);
   1134 	wmesa_free_framebuffer(pwc->hDC);
   1135     }
   1136 
   1137     /* Release for device, not memory contexts */
   1138     if (WindowFromDC(pwc->hDC) != NULL)
   1139     {
   1140       ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
   1141     }
   1142     DeleteObject(pwc->clearPen);
   1143     DeleteObject(pwc->clearBrush);
   1144 
   1145     _mesa_meta_free(ctx);
   1146 
   1147     _swsetup_DestroyContext(ctx);
   1148     _tnl_DestroyContext(ctx);
   1149     _vbo_DestroyContext(ctx);
   1150     _swrast_DestroyContext(ctx);
   1151 
   1152     _mesa_free_context_data(ctx);
   1153     free(pwc);
   1154 }
   1155 
   1156 
   1157 /**
   1158  * Create a new color renderbuffer.
   1159  */
   1160 static struct gl_renderbuffer *
   1161 wmesa_new_renderbuffer(void)
   1162 {
   1163     struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
   1164     if (!rb)
   1165         return NULL;
   1166 
   1167     _mesa_init_renderbuffer(rb, (GLuint)0);
   1168 
   1169     rb->_BaseFormat = GL_RGBA;
   1170     rb->InternalFormat = GL_RGBA;
   1171     rb->Delete = wmesa_delete_renderbuffer;
   1172     rb->AllocStorage = wmesa_renderbuffer_storage;
   1173     return rb;
   1174 }
   1175 
   1176 
   1177 void WMesaMakeCurrent(WMesaContext c, HDC hdc)
   1178 {
   1179     WMesaFramebuffer pwfb;
   1180 
   1181     {
   1182         /* return if already current */
   1183         GET_CURRENT_CONTEXT(ctx);
   1184         WMesaContext pwc = wmesa_context(ctx);
   1185         if (pwc && c == pwc && pwc->hDC == hdc)
   1186             return;
   1187     }
   1188 
   1189     pwfb = wmesa_lookup_framebuffer(hdc);
   1190 
   1191     /* Lazy creation of framebuffers */
   1192     if (c && !pwfb && hdc) {
   1193         struct gl_renderbuffer *rb;
   1194         struct gl_config *visual = &c->gl_ctx.Visual;
   1195         GLuint width, height;
   1196 
   1197         get_window_size(hdc, &width, &height);
   1198 
   1199 	c->clearPen = CreatePen(PS_SOLID, 1, 0);
   1200 	c->clearBrush = CreateSolidBrush(0);
   1201 
   1202         pwfb = wmesa_new_framebuffer(hdc, visual);
   1203 
   1204 	/* Create back buffer if double buffered */
   1205 	if (visual->doubleBufferMode == 1) {
   1206 	    wmCreateBackingStore(pwfb, width, height);
   1207 	}
   1208 
   1209         /* make render buffers */
   1210         if (visual->doubleBufferMode == 1) {
   1211             rb = wmesa_new_renderbuffer();
   1212             _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
   1213 	}
   1214         rb = wmesa_new_renderbuffer();
   1215         _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
   1216 
   1217 	/* Let Mesa own the Depth, Stencil, and Accum buffers */
   1218         _swrast_add_soft_renderbuffers(&pwfb->Base,
   1219                                        GL_FALSE, /* color */
   1220                                        visual->depthBits > 0,
   1221                                        visual->stencilBits > 0,
   1222                                        visual->accumRedBits > 0,
   1223                                        visual->alphaBits >0,
   1224                                        GL_FALSE);
   1225     }
   1226 
   1227     if (c && pwfb)
   1228 	_mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
   1229     else
   1230         _mesa_make_current(NULL, NULL, NULL);
   1231 }
   1232 
   1233 
   1234 void WMesaSwapBuffers( HDC hdc )
   1235 {
   1236     GET_CURRENT_CONTEXT(ctx);
   1237     WMesaContext pwc = wmesa_context(ctx);
   1238     WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
   1239 
   1240     if (!pwfb) {
   1241         _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
   1242         return;
   1243     }
   1244 
   1245     /* If we're swapping the buffer associated with the current context
   1246      * we have to flush any pending rendering commands first.
   1247      */
   1248     if (pwc->hDC == hdc) {
   1249 	_mesa_notifySwapBuffers(ctx);
   1250 
   1251 	BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
   1252 	       pwfb->dib_hDC, 0, 0, SRCCOPY);
   1253     }
   1254     else {
   1255         /* XXX for now only allow swapping current window */
   1256         _mesa_problem(NULL, "wmesa: can't swap non-current window");
   1257     }
   1258 }
   1259 
   1260 void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
   1261 {
   1262 	_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
   1263 }
   1264 
   1265