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