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