2 * Windows (Win32/Win64) device driver for Mesa
10 #include "extensions.h"
11 #include "framebuffer.h"
12 #include "renderbuffer.h"
13 #include "drivers/common/driverfuncs.h"
14 #include "array_cache/acache.h"
15 #include "swrast/swrast.h"
16 #include "swrast_setup/swrast_setup.h"
18 #include "tnl/t_context.h"
19 #include "tnl/t_pipeline.h"
22 /* linked list of our Framebuffers (windows) */
23 static WMesaFramebuffer FirstFramebuffer
= NULL
;
27 * Create a new WMesaFramebuffer object which will correspond to the
28 * given HDC (Window handle).
31 wmesa_new_framebuffer(HDC hdc
, GLvisual
*visual
)
34 = (WMesaFramebuffer
) malloc(sizeof(struct wmesa_framebuffer
));
36 _mesa_initialize_framebuffer(&pwfb
->Base
, visual
);
38 /* insert at head of list */
39 pwfb
->next
= FirstFramebuffer
;
40 FirstFramebuffer
= pwfb
;
47 * Given an hdc, return the corresponding WMesaFramebuffer
50 wmesa_lookup_framebuffer(HDC hdc
)
52 WMesaFramebuffer pwfb
;
53 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
62 * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
64 static WMesaFramebuffer
wmesa_framebuffer(GLframebuffer
*fb
)
66 return (WMesaFramebuffer
) fb
;
71 * Given a GLcontext, return the corresponding WMesaContext.
73 static WMesaContext
wmesa_context(const GLcontext
*ctx
)
75 return (WMesaContext
) ctx
;
80 * Every driver should implement a GetString function in order to
81 * return a meaningful GL_RENDERER string.
83 static const GLubyte
*wmesa_get_string(GLcontext
*ctx
, GLenum name
)
85 return (name
== GL_RENDERER
) ?
86 (GLubyte
*) "Mesa Windows GDI Driver" : NULL
;
91 * Determine the pixel format based on the pixel size.
93 static void wmSetPixelFormat(WMesaContext pwc
, HDC hDC
)
95 pwc
->cColorBits
= GetDeviceCaps(hDC
, BITSPIXEL
);
97 // Only 16 and 32 bit targets are supported now
98 assert(pwc
->cColorBits
== 0 ||
99 pwc
->cColorBits
== 16 ||
100 pwc
->cColorBits
== 32);
102 switch(pwc
->cColorBits
){
104 pwc
->pixelformat
= PF_INDEX8
;
107 pwc
->pixelformat
= PF_5R6G5B
;
110 pwc
->pixelformat
= PF_8R8G8B
;
113 pwc
->pixelformat
= PF_BADFORMAT
;
119 * Create DIB for back buffer.
120 * We write into this memory with the span routines and then blit it
121 * to the window on a buffer swap.
123 * XXX we should probably pass a WMesaFramebuffer ptr, not a WMesaContext!
125 BOOL
wmCreateBackingStore(WMesaContext pwc
, long lxSize
, long lySize
)
128 LPBITMAPINFO pbmi
= &(pwc
->bmi
);
131 assert(pwc
->db_flag
== GL_TRUE
);
133 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
134 pbmi
->bmiHeader
.biWidth
= lxSize
;
135 pbmi
->bmiHeader
.biHeight
= -lySize
;
136 pbmi
->bmiHeader
.biPlanes
= 1;
137 pbmi
->bmiHeader
.biBitCount
= GetDeviceCaps(pwc
->hDC
, BITSPIXEL
);
138 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
139 pbmi
->bmiHeader
.biSizeImage
= 0;
140 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
141 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
142 pbmi
->bmiHeader
.biClrUsed
= 0;
143 pbmi
->bmiHeader
.biClrImportant
= 0;
145 pwc
->cColorBits
= pbmi
->bmiHeader
.biBitCount
;
146 pwc
->ScanWidth
= (lxSize
* (pwc
->cColorBits
/ 8) + 3) & ~3;
148 hic
= CreateIC("display", NULL
, NULL
, NULL
);
149 pwc
->dib
.hDC
= CreateCompatibleDC(hic
);
151 pwc
->hbmDIB
= CreateDIBSection(hic
,
154 (void **)&(pwc
->pbPixels
),
157 pwc
->hOldBitmap
= SelectObject(pwc
->dib
.hDC
, pwc
->hbmDIB
);
161 wmSetPixelFormat(pwc
, pwc
->hDC
);
166 /* XXX pass WMesaFramebuffer, not WMesaContext.
168 static wmDeleteBackingStore(WMesaContext pwc
)
171 SelectObject(pwc
->dib
.hDC
, pwc
->hOldBitmap
);
172 DeleteDC(pwc
->dib
.hDC
);
173 DeleteObject(pwc
->hbmDIB
);
179 * Find the width and height of the window named by hdc.
182 get_window_size(HDC hdc
, GLuint
*width
, GLuint
*height
)
184 if (WindowFromDC(hdc
)) {
186 GetClientRect(WindowFromDC(hdc
), &rect
);
187 *width
= rect
.right
- rect
.left
;
188 *height
= rect
.bottom
- rect
.top
;
190 else { /* Memory context */
191 /* From contributed code - use the size of the desktop
192 * for the size of a memory context (?) */
193 *width
= GetDeviceCaps(hdc
, HORZRES
);
194 *height
= GetDeviceCaps(hdc
, VERTRES
);
200 wmesa_get_buffer_size(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
202 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
203 get_window_size(pwfb
->hdc
, width
, height
);
207 static void wmesa_flush(GLcontext
*ctx
)
209 WMesaContext pwc
= wmesa_context(ctx
);
210 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->WinSysDrawBuffer
);
212 /* XXX I guess we're _always_ double buffered and render to the back
213 * buffer. So flushing involves copying the back color buffer to
217 BitBlt(pwc
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
218 pwc
->dib
.hDC
, 0, 0, SRCCOPY
);
221 /* Do nothing for single buffer */
226 /**********************************************************************/
227 /***** CLEAR Functions *****/
228 /**********************************************************************/
230 /* If we do not implement these, Mesa clears the buffers via the pixel
231 * span writing interface, which is very slow for a clear operation.
235 * Set the color index used to clear the color buffer.
237 static void clear_index(GLcontext
*ctx
, GLuint index
)
239 WMesaContext pwc
= wmesa_context(ctx
);
240 /* Note that indexed mode is not supported yet */
241 pwc
->clearColorRef
= RGB(0,0,0);
245 * Set the color used to clear the color buffer.
247 static void clear_color(GLcontext
*ctx
, const GLfloat color
[4])
249 WMesaContext pwc
= wmesa_context(ctx
);
251 UINT bytesPerPixel
= pwc
->cColorBits
/ 8;
253 CLAMPED_FLOAT_TO_UBYTE(col
[0], color
[0]);
254 CLAMPED_FLOAT_TO_UBYTE(col
[1], color
[1]);
255 CLAMPED_FLOAT_TO_UBYTE(col
[2], color
[2]);
256 pwc
->clearColorRef
= RGB(col
[0], col
[1], col
[2]);
257 DeleteObject(pwc
->clearPen
);
258 DeleteObject(pwc
->clearBrush
);
259 pwc
->clearPen
= CreatePen(PS_SOLID
, 1, pwc
->clearColorRef
);
260 pwc
->clearBrush
= CreateSolidBrush(pwc
->clearColorRef
);
265 * Clear the specified region of the color buffer using the clear color
266 * or index as specified by one of the two functions above.
268 * This procedure clears either the front and/or the back COLOR buffers.
269 * Only the "left" buffer is cleared since we are not stereo.
270 * Clearing of the other non-color buffers is left to the swrast.
273 static void clear(GLcontext
*ctx
,
277 GLint width
, GLint height
)
279 #define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
281 WMesaContext pwc
= wmesa_context(ctx
);
284 /* Let swrast do all the work if the masks are not set to
285 * clear all channels. */
286 if (ctx
->Color
.ColorMask
[0] != 0xff ||
287 ctx
->Color
.ColorMask
[1] != 0xff ||
288 ctx
->Color
.ColorMask
[2] != 0xff ||
289 ctx
->Color
.ColorMask
[3] != 0xff) {
290 _swrast_Clear(ctx
, mask
, all
, x
, y
, width
, height
);
295 if (mask
& BUFFER_BIT_BACK_LEFT
) {
298 UINT bytesPerPixel
= pwc
->cColorBits
/ 8;
299 LPBYTE lpb
, clearRow
;
307 /* Try for a fast clear - clearing entire buffer with a single
309 if (all
) { /* entire buffer */
310 /* Now check for an easy clear value */
311 switch (bytesPerPixel
) {
313 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
314 GetGValue(pwc
->clearColorRef
),
315 GetBValue(pwc
->clearColorRef
));
316 memset(pwc
->pbPixels
, bColor
,
317 pwc
->ScanWidth
* height
);
321 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
322 GetGValue(pwc
->clearColorRef
),
323 GetBValue(pwc
->clearColorRef
));
324 if (((wColor
>> 8) & 0xff) == (wColor
& 0xff)) {
325 memset(pwc
->pbPixels
, wColor
& 0xff,
326 pwc
->ScanWidth
* height
);
333 if (GetRValue(pwc
->clearColorRef
) ==
334 GetGValue(pwc
->clearColorRef
) &&
335 GetRValue(pwc
->clearColorRef
) ==
336 GetBValue(pwc
->clearColorRef
)) {
337 memset(pwc
->pbPixels
,
338 GetRValue(pwc
->clearColorRef
),
339 pwc
->ScanWidth
* height
);
349 /* Need to clear a row at a time. Begin by setting the first
350 * row in the area to be cleared to the clear color. */
352 clearRow
= pwc
->pbPixels
+
353 pwc
->ScanWidth
* FLIP(y
) +
355 switch (bytesPerPixel
) {
358 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
359 GetGValue(pwc
->clearColorRef
),
360 GetBValue(pwc
->clearColorRef
));
361 memset(lpb
, bColor
, width
);
364 lpw
= (LPWORD
)clearRow
;
365 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
366 GetGValue(pwc
->clearColorRef
),
367 GetBValue(pwc
->clearColorRef
));
368 for (i
=0; i
<width
; i
++)
373 r
= GetRValue(pwc
->clearColorRef
);
374 g
= GetGValue(pwc
->clearColorRef
);
375 b
= GetBValue(pwc
->clearColorRef
);
376 for (i
=0; i
<width
; i
++) {
383 lpdw
= (LPDWORD
)clearRow
;
384 dwColor
= BGR32(GetRValue(pwc
->clearColorRef
),
385 GetGValue(pwc
->clearColorRef
),
386 GetBValue(pwc
->clearColorRef
));
387 for (i
=0; i
<width
; i
++)
394 /* copy cleared row to other rows in buffer */
395 lpb
= clearRow
- pwc
->ScanWidth
;
396 rowSize
= width
* bytesPerPixel
;
397 for (i
=1; i
<height
; i
++) {
398 memcpy(lpb
, clearRow
, rowSize
);
399 lpb
-= pwc
->ScanWidth
;
402 mask
&= ~BUFFER_BIT_BACK_LEFT
;
406 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
408 HPEN Old_Pen
= SelectObject(DC
, pwc
->clearPen
);
409 HBRUSH Old_Brush
= SelectObject(DC
, pwc
->clearBrush
);
414 FLIP(y
) - height
+ 1);
415 SelectObject(DC
, Old_Pen
);
416 SelectObject(DC
, Old_Brush
);
417 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
420 /* Call swrast if there is anything left to clear (like DEPTH) */
422 _swrast_Clear(ctx
, mask
, all
, x
, y
, width
, height
);
428 /**********************************************************************/
429 /***** PIXEL Functions *****/
430 /**********************************************************************/
432 #define FLIP(Y) (rb->Height - (Y) - 1)
437 /* These are slow, but work with all non-indexed visual types */
439 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
440 static void write_rgba_span_single(const GLcontext
*ctx
,
441 struct gl_renderbuffer
*rb
,
442 GLuint n
, GLint x
, GLint y
,
443 const GLubyte rgba
[][4],
444 const GLubyte mask
[] )
446 WMesaContext pwc
= wmesa_context(ctx
);
454 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
459 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
465 /* Write a horizontal span of RGB color pixels with a boolean mask. */
466 static void write_rgb_span_single(const GLcontext
*ctx
,
467 struct gl_renderbuffer
*rb
,
468 GLuint n
, GLint x
, GLint y
,
469 const GLubyte rgb
[][3],
470 const GLubyte mask
[] )
472 WMesaContext pwc
= wmesa_context(ctx
);
480 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
485 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
492 * Write a horizontal span of pixels with a boolean mask. The current color
493 * is used for all pixels.
495 static void write_mono_rgba_span_single(const GLcontext
*ctx
,
496 struct gl_renderbuffer
*rb
,
497 GLuint n
, GLint x
, GLint y
,
498 const GLchan color
[4],
499 const GLubyte mask
[])
502 WMesaContext pwc
= wmesa_context(ctx
);
506 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
511 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
515 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
519 /* Write an array of RGBA pixels with a boolean mask. */
520 static void write_rgba_pixels_single(const GLcontext
*ctx
,
521 struct gl_renderbuffer
*rb
,
523 const GLint x
[], const GLint y
[],
524 const GLubyte rgba
[][4],
525 const GLubyte mask
[] )
528 WMesaContext pwc
= wmesa_context(ctx
);
532 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]),
533 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
540 * Write an array of pixels with a boolean mask. The current color
541 * is used for all pixels.
543 static void write_mono_rgba_pixels_single(const GLcontext
*ctx
,
544 struct gl_renderbuffer
*rb
,
546 const GLint x
[], const GLint y
[],
547 const GLchan color
[4],
548 const GLubyte mask
[] )
551 WMesaContext pwc
= wmesa_context(ctx
);
554 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
557 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]), colorref
);
560 /* Read a horizontal span of color pixels. */
561 static void read_rgba_span_single(const GLcontext
*ctx
,
562 struct gl_renderbuffer
*rb
,
563 GLuint n
, GLint x
, GLint y
,
566 WMesaContext pwc
= wmesa_context(ctx
);
570 for (i
=0; i
<n
; i
++) {
571 Color
= GetPixel(pwc
->hDC
, x
+i
, y
);
572 rgba
[i
][RCOMP
] = GetRValue(Color
);
573 rgba
[i
][GCOMP
] = GetGValue(Color
);
574 rgba
[i
][BCOMP
] = GetBValue(Color
);
575 rgba
[i
][ACOMP
] = 255;
580 /* Read an array of color pixels. */
581 static void read_rgba_pixels_single(const GLcontext
*ctx
,
582 struct gl_renderbuffer
*rb
,
583 GLuint n
, const GLint x
[], const GLint y
[],
586 WMesaContext pwc
= wmesa_context(ctx
);
589 for (i
=0; i
<n
; i
++) {
590 GLint y2
= FLIP(y
[i
]);
591 Color
= GetPixel(pwc
->hDC
, x
[i
], y2
);
592 rgba
[i
][RCOMP
] = GetRValue(Color
);
593 rgba
[i
][GCOMP
] = GetGValue(Color
);
594 rgba
[i
][BCOMP
] = GetBValue(Color
);
595 rgba
[i
][ACOMP
] = 255;
599 /*********************************************************************/
601 /* DOUBLE BUFFER 32-bit */
603 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
604 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
605 *lpdw = BGR32((r),(g),(b)); }
609 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
610 static void write_rgba_span_32(const GLcontext
*ctx
,
611 struct gl_renderbuffer
*rb
,
612 GLuint n
, GLint x
, GLint y
,
613 const GLubyte rgba
[][4],
614 const GLubyte mask
[] )
616 WMesaContext pwc
= wmesa_context(ctx
);
623 lpdw
= ((LPDWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
627 lpdw
[i
] = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
632 *lpdw
++ = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
638 /* Write a horizontal span of RGB color pixels with a boolean mask. */
639 static void write_rgb_span_32(const GLcontext
*ctx
,
640 struct gl_renderbuffer
*rb
,
641 GLuint n
, GLint x
, GLint y
,
642 const GLubyte rgb
[][3],
643 const GLubyte mask
[] )
645 WMesaContext pwc
= wmesa_context(ctx
);
652 lpdw
= ((LPDWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
656 lpdw
[i
] = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
661 *lpdw
++ = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
667 * Write a horizontal span of pixels with a boolean mask. The current color
668 * is used for all pixels.
670 static void write_mono_rgba_span_32(const GLcontext
*ctx
,
671 struct gl_renderbuffer
*rb
,
672 GLuint n
, GLint x
, GLint y
,
673 const GLchan color
[4],
674 const GLubyte mask
[])
679 WMesaContext pwc
= wmesa_context(ctx
);
680 lpdw
= ((LPDWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
682 pixel
= BGR32(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
694 /* Write an array of RGBA pixels with a boolean mask. */
695 static void write_rgba_pixels_32(const GLcontext
*ctx
,
696 struct gl_renderbuffer
*rb
,
697 GLuint n
, const GLint x
[], const GLint y
[],
698 const GLubyte rgba
[][4],
699 const GLubyte mask
[])
702 WMesaContext pwc
= wmesa_context(ctx
);;
705 WMSETPIXEL32(pwc
, FLIP(y
[i
]), x
[i
],
706 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
710 * Write an array of pixels with a boolean mask. The current color
711 * is used for all pixels.
713 static void write_mono_rgba_pixels_32(const GLcontext
*ctx
,
714 struct gl_renderbuffer
*rb
,
716 const GLint x
[], const GLint y
[],
717 const GLchan color
[4],
718 const GLubyte mask
[])
721 WMesaContext pwc
= wmesa_context(ctx
);
724 WMSETPIXEL32(pwc
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
725 color
[GCOMP
], color
[BCOMP
]);
728 /* Read a horizontal span of color pixels. */
729 static void read_rgba_span_32(const GLcontext
*ctx
,
730 struct gl_renderbuffer
*rb
,
731 GLuint n
, GLint x
, GLint y
,
737 WMesaContext pwc
= wmesa_context(ctx
);
740 lpdw
= ((LPDWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
741 for (i
=0; i
<n
; i
++) {
743 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
744 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
745 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
746 rgba
[i
][ACOMP
] = 255;
751 /* Read an array of color pixels. */
752 static void read_rgba_pixels_32(const GLcontext
*ctx
,
753 struct gl_renderbuffer
*rb
,
754 GLuint n
, const GLint x
[], const GLint y
[],
760 WMesaContext pwc
= wmesa_context(ctx
);
762 for (i
=0; i
<n
; i
++) {
763 GLint y2
= FLIP(y
[i
]);
764 lpdw
= ((LPDWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y2
)) + x
[i
];
766 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
767 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
768 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
769 rgba
[i
][ACOMP
] = 255;
774 /*********************************************************************/
776 /* DOUBLE BUFFER 16-bit */
778 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
779 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
780 *lpw = BGR16((r),(g),(b)); }
784 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
785 static void write_rgba_span_16(const GLcontext
*ctx
,
786 struct gl_renderbuffer
*rb
,
787 GLuint n
, GLint x
, GLint y
,
788 const GLubyte rgba
[][4],
789 const GLubyte mask
[] )
791 WMesaContext pwc
= wmesa_context(ctx
);
798 lpw
= ((LPWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
802 lpw
[i
] = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
807 *lpw
++ = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
813 /* Write a horizontal span of RGB color pixels with a boolean mask. */
814 static void write_rgb_span_16(const GLcontext
*ctx
,
815 struct gl_renderbuffer
*rb
,
816 GLuint n
, GLint x
, GLint y
,
817 const GLubyte rgb
[][3],
818 const GLubyte mask
[] )
820 WMesaContext pwc
= wmesa_context(ctx
);
827 lpw
= ((LPWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
831 lpw
[i
] = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
836 *lpw
++ = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
842 * Write a horizontal span of pixels with a boolean mask. The current color
843 * is used for all pixels.
845 static void write_mono_rgba_span_16(const GLcontext
*ctx
,
846 struct gl_renderbuffer
*rb
,
847 GLuint n
, GLint x
, GLint y
,
848 const GLchan color
[4],
849 const GLubyte mask
[])
854 WMesaContext pwc
= wmesa_context(ctx
);
856 lpw
= ((LPWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
858 pixel
= BGR16(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
870 /* Write an array of RGBA pixels with a boolean mask. */
871 static void write_rgba_pixels_16(const GLcontext
*ctx
,
872 struct gl_renderbuffer
*rb
,
873 GLuint n
, const GLint x
[], const GLint y
[],
874 const GLubyte rgba
[][4],
875 const GLubyte mask
[])
878 WMesaContext pwc
= wmesa_context(ctx
);
882 WMSETPIXEL16(pwc
, FLIP(y
[i
]), x
[i
],
883 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
887 * Write an array of pixels with a boolean mask. The current color
888 * is used for all pixels.
890 static void write_mono_rgba_pixels_16(const GLcontext
*ctx
,
891 struct gl_renderbuffer
*rb
,
893 const GLint x
[], const GLint y
[],
894 const GLchan color
[4],
895 const GLubyte mask
[])
898 WMesaContext pwc
= wmesa_context(ctx
);
902 WMSETPIXEL16(pwc
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
903 color
[GCOMP
], color
[BCOMP
]);
906 /* Read a horizontal span of color pixels. */
907 static void read_rgba_span_16(const GLcontext
*ctx
,
908 struct gl_renderbuffer
*rb
,
909 GLuint n
, GLint x
, GLint y
,
914 WMesaContext pwc
= wmesa_context(ctx
);
917 lpw
= ((LPWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y
)) + x
;
918 for (i
=0; i
<n
; i
++) {
920 /* Windows uses 5,5,5 for 16-bit */
921 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
922 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
923 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
924 rgba
[i
][ACOMP
] = 255;
929 /* Read an array of color pixels. */
930 static void read_rgba_pixels_16(const GLcontext
*ctx
,
931 struct gl_renderbuffer
*rb
,
932 GLuint n
, const GLint x
[], const GLint y
[],
937 WMesaContext pwc
= wmesa_context(ctx
);
939 for (i
=0; i
<n
; i
++) {
940 GLint y2
= FLIP(y
[i
]);
941 lpw
= ((LPWORD
)(pwc
->pbPixels
+ pwc
->ScanWidth
* y2
)) + x
[i
];
943 /* Windows uses 5,5,5 for 16-bit */
944 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
945 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
946 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
947 rgba
[i
][ACOMP
] = 255;
954 /**********************************************************************/
955 /***** BUFFER Functions *****/
956 /**********************************************************************/
962 wmesa_delete_renderbuffer(struct gl_renderbuffer
*rb
)
969 * This is called by Mesa whenever it determines that the window size
970 * has changed. Do whatever's needed to cope with that.
973 wmesa_renderbuffer_storage(GLcontext
*ctx
,
974 struct gl_renderbuffer
*rb
,
975 GLenum internalFormat
,
984 void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer
*rb
, int pixelformat
,
988 /* Picking the correct span functions is important because
989 * the DIB was allocated with the indicated depth. */
990 switch(pixelformat
) {
992 rb
->PutRow
= write_rgba_span_16
;
993 rb
->PutRowRGB
= write_rgb_span_16
;
994 rb
->PutMonoRow
= write_mono_rgba_span_16
;
995 rb
->PutValues
= write_rgba_pixels_16
;
996 rb
->PutMonoValues
= write_mono_rgba_pixels_16
;
997 rb
->GetRow
= read_rgba_span_16
;
998 rb
->GetValues
= read_rgba_pixels_16
;
1001 rb
->PutRow
= write_rgba_span_32
;
1002 rb
->PutRowRGB
= write_rgb_span_32
;
1003 rb
->PutMonoRow
= write_mono_rgba_span_32
;
1004 rb
->PutValues
= write_rgba_pixels_32
;
1005 rb
->PutMonoValues
= write_mono_rgba_pixels_32
;
1006 rb
->GetRow
= read_rgba_span_32
;
1007 rb
->GetValues
= read_rgba_pixels_32
;
1013 else { /* single buffer */
1014 rb
->PutRow
= write_rgba_span_single
;
1015 rb
->PutRowRGB
= write_rgb_span_single
;
1016 rb
->PutMonoRow
= write_mono_rgba_span_single
;
1017 rb
->PutValues
= write_rgba_pixels_single
;
1018 rb
->PutMonoValues
= write_mono_rgba_pixels_single
;
1019 rb
->GetRow
= read_rgba_span_single
;
1020 rb
->GetValues
= read_rgba_pixels_single
;
1025 * Called by ctx->Driver.ResizeBuffers()
1026 * Resize the front/back colorbuffers to match the latest window size.
1029 wmesa_resize_buffers(GLcontext
*ctx
, GLframebuffer
*buffer
,
1030 GLuint width
, GLuint height
)
1032 WMesaContext pwc
= wmesa_context(ctx
);
1033 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
1035 if (pwfb
->Base
.Width
!= width
|| pwfb
->Base
.Height
!= height
) {
1036 /* Realloc back buffer */
1038 wmDeleteBackingStore(pwc
);
1039 wmCreateBackingStore(pwc
, width
, height
);
1042 _mesa_resize_framebuffer(ctx
, buffer
, width
, height
);
1047 * Called by glViewport.
1048 * This is a good time for us to poll the current window size and adjust
1049 * our renderbuffers to match the current window size.
1050 * Remember, we have no opportunity to respond to conventional
1051 * resize events since the driver has no event loop.
1053 * MakeCurrent also ends up making a call here, so that ensures
1054 * we get the viewport set correctly, even if the app does not call
1055 * glViewport and relies on the defaults.
1057 static void wmesa_viewport(GLcontext
*ctx
,
1059 GLsizei width
, GLsizei height
)
1061 WMesaContext pwc
= wmesa_context(ctx
);
1062 GLuint new_width
, new_height
;
1064 wmesa_get_buffer_size(ctx
->WinSysDrawBuffer
, &new_width
, &new_height
);
1066 if (new_width
!= width
|| new_height
!= height
) {
1068 * Either the window was resized or the viewport changed - not sure which.
1069 * So call resize buffers to resize them if the window size changed.
1071 wmesa_resize_buffers(ctx
, ctx
->WinSysDrawBuffer
, new_width
, new_height
);
1072 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
1080 * Called when the driver should update it's state, based on the new_state
1083 static void wmesa_update_state(GLcontext
*ctx
, GLuint new_state
)
1085 _swrast_InvalidateState(ctx
, new_state
);
1086 _swsetup_InvalidateState(ctx
, new_state
);
1087 _ac_InvalidateState(ctx
, new_state
);
1088 _tnl_InvalidateState(ctx
, new_state
);
1090 /* TODO - need code to update the span functions in case the
1091 * renderer changes the target buffer (like a DB app writing to
1092 * the front buffer). */
1095 { /* could check _NEW_BUFFERS bit flag here in new_state */
1096 /* In progress - Need to make the wmesa context inherit (by containment)
1097 the gl_context, so I can get access to the pixel format */
1098 struct gl_renderbuffer
*rb
;
1099 int pixelformat
, double_buffer
;
1101 rb
= ctx
->DrawBuffer
->Attachment
[BUFFER_BACK_LEFT
].Renderbuffer
;
1102 pixelformat
= PF_5R6G5B
; // hard code for now - see note above
1103 double_buffer
= ctx
->DrawBuffer
->ColorDrawBuffer
[0] == GL_BACK
? 1 : 0;
1105 wmesa_set_renderbuffer_funcs(rb
, pixelformat
, double_buffer
);
1114 /**********************************************************************/
1115 /***** WMESA Functions *****/
1116 /**********************************************************************/
1118 WMesaContext
WMesaCreateContext(HDC hDC
,
1122 GLboolean alpha_flag
)
1125 struct dd_function_table functions
;
1126 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1132 /* Indexed mode not supported */
1136 /* Allocate wmesa context */
1137 c
= CALLOC_STRUCT(wmesa_context
);
1142 /* I do not understand this contributed code */
1143 /* Support memory and device contexts */
1144 if(WindowFromDC(hDC
) != NULL
) {
1145 c
->hDC
= GetDC(WindowFromDC(hDC
)); // huh ????
1154 /* rememember DC and flag settings */
1155 c
->rgb_flag
= rgb_flag
;
1156 c
->db_flag
= db_flag
;
1157 c
->alpha_flag
= alpha_flag
;
1159 /* Get data for visual */
1160 /* Dealing with this is actually a bit of overkill because Mesa will end
1161 * up treating all color component size requests less than 8 by using
1162 * a single byte per channel. In addition, the interface to the span
1163 * routines passes colors as an entire byte per channel anyway, so there
1164 * is nothing to be saved by telling the visual to be 16 bits if the device
1165 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
1167 * But we go through the motions here anyway.
1169 switch (GetDeviceCaps(c
->hDC
, BITSPIXEL
)) {
1171 red_bits
= green_bits
= blue_bits
= 5;
1175 red_bits
= green_bits
= blue_bits
= 8;
1179 /* Create visual based on flags */
1180 visual
= _mesa_create_visual(rgb_flag
,
1181 db_flag
, /* db_flag */
1182 GL_FALSE
, /* stereo */
1183 red_bits
, green_bits
, blue_bits
, /* color RGB */
1184 alpha_flag
? alpha_bits
: 0, /* color A */
1186 DEFAULT_SOFTWARE_DEPTH_BITS
, /* depth_bits */
1187 8, /* stencil_bits */
1188 16,16,16, /* accum RGB */
1189 alpha_flag
? 16 : 0, /* accum A */
1190 1); /* num samples */
1197 /* Set up driver functions */
1198 _mesa_init_driver_functions(&functions
);
1199 functions
.GetString
= wmesa_get_string
;
1200 functions
.UpdateState
= wmesa_update_state
;
1201 functions
.GetBufferSize
= wmesa_get_buffer_size
;
1202 functions
.Flush
= wmesa_flush
;
1203 functions
.Clear
= clear
;
1204 functions
.ClearIndex
= clear_index
;
1205 functions
.ClearColor
= clear_color
;
1206 functions
.ResizeBuffers
= wmesa_resize_buffers
;
1207 functions
.Viewport
= wmesa_viewport
;
1209 /* initialize the Mesa context data */
1211 _mesa_initialize_context(ctx
, visual
, NULL
, &functions
, (void *)c
);
1213 _mesa_enable_sw_extensions(ctx
);
1214 _mesa_enable_1_3_extensions(ctx
);
1215 _mesa_enable_1_4_extensions(ctx
);
1216 _mesa_enable_1_5_extensions(ctx
);
1217 _mesa_enable_2_0_extensions(ctx
);
1219 /* Initialize the software rasterizer and helper modules. */
1220 if (!_swrast_CreateContext(ctx
) ||
1221 !_ac_CreateContext(ctx
) ||
1222 !_tnl_CreateContext(ctx
) ||
1223 !_swsetup_CreateContext(ctx
)) {
1224 _mesa_free_context_data(ctx
);
1228 _swsetup_Wakeup(ctx
);
1229 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
1235 void WMesaDestroyContext( WMesaContext pwc
)
1237 GLcontext
*ctx
= &pwc
->gl_ctx
;
1238 GET_CURRENT_CONTEXT(cur_ctx
);
1240 if (cur_ctx
== ctx
) {
1241 /* unbind current if deleting current context */
1242 WMesaMakeCurrent(NULL
, NULL
);
1245 /* Release for device, not memory contexts */
1246 if (WindowFromDC(pwc
->hDC
) != NULL
)
1248 ReleaseDC(WindowFromDC(pwc
->hDC
), pwc
->hDC
);
1250 DeleteObject(pwc
->clearPen
);
1251 DeleteObject(pwc
->clearBrush
);
1254 wmDeleteBackingStore(pwc
);
1256 _swsetup_DestroyContext(ctx
);
1257 _tnl_DestroyContext(ctx
);
1258 _ac_DestroyContext(ctx
);
1259 _swrast_DestroyContext(ctx
);
1261 _mesa_free_context_data(ctx
);
1267 * Create a new color renderbuffer.
1269 struct gl_renderbuffer
*
1270 wmesa_new_renderbuffer(void)
1272 struct gl_renderbuffer
*rb
= CALLOC_STRUCT(gl_renderbuffer
);
1276 _mesa_init_renderbuffer(rb
, (GLuint
)0);
1278 rb
->_BaseFormat
= GL_RGBA
;
1279 rb
->InternalFormat
= GL_RGBA
;
1280 rb
->DataType
= CHAN_TYPE
;
1281 rb
->Delete
= wmesa_delete_renderbuffer
;
1282 rb
->AllocStorage
= wmesa_renderbuffer_storage
;
1287 void WMesaMakeCurrent(WMesaContext c
, HDC hdc
)
1289 WMesaFramebuffer pwfb
;
1292 /* return if already current */
1293 GET_CURRENT_CONTEXT(ctx
);
1294 WMesaContext pwc
= wmesa_context(ctx
);
1295 if (c
== pwc
&& pwc
->hDC
== hdc
)
1299 pwfb
= wmesa_lookup_framebuffer(hdc
);
1301 /* Lazy creation of framebuffers */
1303 struct gl_renderbuffer
*rb
;
1304 GLvisual
*visual
= &c
->gl_ctx
.Visual
;
1305 GLuint width
, height
;
1307 get_window_size(hdc
, &width
, &height
);
1309 c
->clearPen
= CreatePen(PS_SOLID
, 1, 0);
1310 c
->clearBrush
= CreateSolidBrush(0);
1312 /* Create back buffer if double buffered */
1314 wmCreateBackingStore(c
, width
, height
);
1317 pwfb
= wmesa_new_framebuffer(hdc
, visual
);
1319 /* need a color renderbuffer */
1320 rb
= wmesa_new_renderbuffer();
1322 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_BACK_LEFT
, rb
);
1324 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_FRONT_LEFT
, rb
);
1325 wmesa_set_renderbuffer_funcs(rb
, c
->pixelformat
, c
->db_flag
);
1327 /* Let Mesa own the Depth, Stencil, and Accum buffers */
1328 _mesa_add_soft_renderbuffers(&pwfb
->Base
,
1329 GL_FALSE
, /* color */
1330 visual
->depthBits
> 0,
1331 visual
->stencilBits
> 0,
1332 visual
->accumRedBits
> 0,
1338 _mesa_make_current(&c
->gl_ctx
, &pwfb
->Base
, &pwfb
->Base
);
1340 _mesa_make_current(NULL
, NULL
, NULL
);
1344 void WMesaSwapBuffers( HDC hdc
)
1346 GET_CURRENT_CONTEXT(ctx
);
1347 WMesaContext pwc
= wmesa_context(ctx
);
1348 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(hdc
);
1351 _mesa_problem(NULL
, "wmesa: swapbuffers on unknown hdc");
1355 /* If we're swapping the buffer associated with the current context
1356 * we have to flush any pending rendering commands first.
1358 if (pwc
->hDC
== hdc
) {
1359 _mesa_notifySwapBuffers(ctx
);
1361 BitBlt(pwc
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
1362 pwc
->dib
.hDC
, 0, 0, SRCCOPY
);
1365 /* XXX for now only allow swapping current window */
1366 _mesa_problem(NULL
, "wmesa: can't swap non-current window");