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
wmesa_new_framebuffer(HDC hdc,struct gl_config * visual)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
wmesa_free_framebuffer(HDC hdc)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
wmesa_lookup_framebuffer(HDC hdc)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  */
wmesa_framebuffer(struct gl_framebuffer * fb)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  */
wmesa_context(const struct gl_context * ctx)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  */
wmesa_get_string(struct gl_context * ctx,GLenum name)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  */
wmSetPixelFormat(WMesaFramebuffer pwfb,HDC hDC)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  */
wmCreateBackingStore(WMesaFramebuffer pwfb,long lxSize,long lySize)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 
wmDeleteBackingStore(WMesaFramebuffer pwfb)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
get_window_size(HDC hdc,GLuint * width,GLuint * height)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
wmesa_get_buffer_size(struct gl_framebuffer * buffer,GLuint * width,GLuint * height)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 
wmesa_flush(struct gl_context * ctx)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  */
clear(struct gl_context * ctx,GLbitfield mask)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. */
write_rgba_span_front(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,const void * values,const GLubyte * 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. */
write_rgba_pixels_front(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],const void * values,const GLubyte * 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. */
read_rgba_span_front(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,void * values)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. */
read_rgba_pixels_front(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],void * values)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. */
write_rgba_span_32(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,const void * values,const GLubyte * 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. */
write_rgba_pixels_32(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],const void * values,const GLubyte * 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. */
read_rgba_span_32(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,void * values)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. */
read_rgba_pixels_32(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],void * values)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. */
write_rgba_span_24(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,const void * values,const GLubyte * 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. */
write_rgba_pixels_24(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],const void * values,const GLubyte * 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. */
read_rgba_span_24(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,void * values)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. */
read_rgba_pixels_24(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],void * values)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. */
write_rgba_span_16(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,const void * values,const GLubyte * 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. */
write_rgba_pixels_16(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],const void * values,const GLubyte * 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. */
read_rgba_span_16(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,GLint x,GLint y,void * values)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. */
read_rgba_pixels_16(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint n,const GLint x[],const GLint y[],void * values)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
wmesa_delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)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
wmesa_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)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
wmesa_resize_buffers(struct gl_context * ctx,struct gl_framebuffer * buffer,GLuint width,GLuint height)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  */
wmesa_viewport(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height)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  */
wmesa_update_state(struct gl_context * ctx,GLuint new_state)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 
WMesaCreateContext(HDC hDC,HPALETTE * Pal,GLboolean rgb_flag,GLboolean db_flag,GLboolean alpha_flag)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 
WMesaDestroyContext(WMesaContext pwc)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 *
wmesa_new_renderbuffer(void)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 
WMesaMakeCurrent(WMesaContext c,HDC hdc)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 
WMesaSwapBuffers(HDC hdc)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 
WMesaShareLists(WMesaContext ctx_to_share,WMesaContext ctx)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