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