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