2 * Windows (Win32/Win64) device driver for Mesa
11 #include "extensions.h"
12 #include "framebuffer.h"
13 #include "renderbuffer.h"
14 #include "drivers/common/driverfuncs.h"
16 #include "swrast/swrast.h"
17 #include "swrast_setup/swrast_setup.h"
19 #include "tnl/t_context.h"
20 #include "tnl/t_pipeline.h"
23 /* linked list of our Framebuffers (windows) */
24 static WMesaFramebuffer FirstFramebuffer
= NULL
;
28 * Create a new WMesaFramebuffer object which will correspond to the
29 * given HDC (Window handle).
32 wmesa_new_framebuffer(HDC hdc
, GLvisual
*visual
)
35 = (WMesaFramebuffer
) malloc(sizeof(struct wmesa_framebuffer
));
37 _mesa_initialize_framebuffer(&pwfb
->Base
, visual
);
39 /* insert at head of list */
40 pwfb
->next
= FirstFramebuffer
;
41 FirstFramebuffer
= pwfb
;
47 * Given an hdc, free the corresponding WMesaFramebuffer
50 wmesa_free_framebuffer(HDC hdc
)
52 WMesaFramebuffer pwfb
, prev
;
53 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
59 if (pwfb
== FirstFramebuffer
)
60 FirstFramebuffer
= pwfb
->next
;
62 prev
->next
= pwfb
->next
;
68 * Given an hdc, return the corresponding WMesaFramebuffer
71 wmesa_lookup_framebuffer(HDC hdc
)
73 WMesaFramebuffer pwfb
;
74 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
83 * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
85 static WMesaFramebuffer
wmesa_framebuffer(GLframebuffer
*fb
)
87 return (WMesaFramebuffer
) fb
;
92 * Given a GLcontext, return the corresponding WMesaContext.
94 static WMesaContext
wmesa_context(const GLcontext
*ctx
)
96 return (WMesaContext
) ctx
;
101 * Every driver should implement a GetString function in order to
102 * return a meaningful GL_RENDERER string.
104 static const GLubyte
*wmesa_get_string(GLcontext
*ctx
, GLenum name
)
106 return (name
== GL_RENDERER
) ?
107 (GLubyte
*) "Mesa Windows GDI Driver" : NULL
;
112 * Determine the pixel format based on the pixel size.
114 static void wmSetPixelFormat(WMesaFramebuffer pwfb
, HDC hDC
)
116 pwfb
->cColorBits
= GetDeviceCaps(hDC
, BITSPIXEL
);
118 /* Only 16 and 32 bit targets are supported now */
119 assert(pwfb
->cColorBits
== 0 ||
120 pwfb
->cColorBits
== 16 ||
121 pwfb
->cColorBits
== 32);
123 switch(pwfb
->cColorBits
){
125 pwfb
->pixelformat
= PF_INDEX8
;
128 pwfb
->pixelformat
= PF_5R6G5B
;
131 pwfb
->pixelformat
= PF_8R8G8B
;
134 pwfb
->pixelformat
= PF_BADFORMAT
;
140 * Create DIB for back buffer.
141 * We write into this memory with the span routines and then blit it
142 * to the window on a buffer swap.
144 BOOL
wmCreateBackingStore(WMesaFramebuffer pwfb
, long lxSize
, long lySize
)
147 LPBITMAPINFO pbmi
= &(pwfb
->bmi
);
150 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
151 pbmi
->bmiHeader
.biWidth
= lxSize
;
152 pbmi
->bmiHeader
.biHeight
= -lySize
;
153 pbmi
->bmiHeader
.biPlanes
= 1;
154 pbmi
->bmiHeader
.biBitCount
= GetDeviceCaps(pwfb
->hDC
, BITSPIXEL
);
155 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
156 pbmi
->bmiHeader
.biSizeImage
= 0;
157 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
158 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
159 pbmi
->bmiHeader
.biClrUsed
= 0;
160 pbmi
->bmiHeader
.biClrImportant
= 0;
162 pwfb
->cColorBits
= pbmi
->bmiHeader
.biBitCount
;
163 pwfb
->ScanWidth
= (lxSize
* (pwfb
->cColorBits
/ 8) + 3) & ~3;
165 hic
= CreateIC("display", NULL
, NULL
, NULL
);
166 pwfb
->dib_hDC
= CreateCompatibleDC(hic
);
168 pwfb
->hbmDIB
= CreateDIBSection(hic
,
171 (void **)&(pwfb
->pbPixels
),
174 pwfb
->hOldBitmap
= SelectObject(pwfb
->dib_hDC
, pwfb
->hbmDIB
);
178 wmSetPixelFormat(pwfb
, pwfb
->hDC
);
183 static wmDeleteBackingStore(WMesaFramebuffer pwfb
)
186 SelectObject(pwfb
->dib_hDC
, pwfb
->hOldBitmap
);
187 DeleteDC(pwfb
->dib_hDC
);
188 DeleteObject(pwfb
->hbmDIB
);
194 * Find the width and height of the window named by hdc.
197 get_window_size(HDC hdc
, GLuint
*width
, GLuint
*height
)
199 if (WindowFromDC(hdc
)) {
201 GetClientRect(WindowFromDC(hdc
), &rect
);
202 *width
= rect
.right
- rect
.left
;
203 *height
= rect
.bottom
- rect
.top
;
205 else { /* Memory context */
206 /* From contributed code - use the size of the desktop
207 * for the size of a memory context (?) */
208 *width
= GetDeviceCaps(hdc
, HORZRES
);
209 *height
= GetDeviceCaps(hdc
, VERTRES
);
215 wmesa_get_buffer_size(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
217 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
218 get_window_size(pwfb
->hDC
, width
, height
);
222 static void wmesa_flush(GLcontext
*ctx
)
224 WMesaContext pwc
= wmesa_context(ctx
);
225 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->WinSysDrawBuffer
);
227 if (ctx
->Visual
.doubleBufferMode
== 1) {
228 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
229 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
232 /* Do nothing for single buffer */
237 /**********************************************************************/
238 /***** CLEAR Functions *****/
239 /**********************************************************************/
241 /* If we do not implement these, Mesa clears the buffers via the pixel
242 * span writing interface, which is very slow for a clear operation.
246 * Set the color index used to clear the color buffer.
248 static void clear_index(GLcontext
*ctx
, GLuint index
)
250 WMesaContext pwc
= wmesa_context(ctx
);
251 /* Note that indexed mode is not supported yet */
252 pwc
->clearColorRef
= RGB(0,0,0);
256 * Set the color used to clear the color buffer.
258 static void clear_color(GLcontext
*ctx
, const GLfloat color
[4])
260 WMesaContext pwc
= wmesa_context(ctx
);
261 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
263 UINT bytesPerPixel
= pwfb
->cColorBits
/ 8;
265 CLAMPED_FLOAT_TO_UBYTE(col
[0], color
[0]);
266 CLAMPED_FLOAT_TO_UBYTE(col
[1], color
[1]);
267 CLAMPED_FLOAT_TO_UBYTE(col
[2], color
[2]);
268 pwc
->clearColorRef
= RGB(col
[0], col
[1], col
[2]);
269 DeleteObject(pwc
->clearPen
);
270 DeleteObject(pwc
->clearBrush
);
271 pwc
->clearPen
= CreatePen(PS_SOLID
, 1, pwc
->clearColorRef
);
272 pwc
->clearBrush
= CreateSolidBrush(pwc
->clearColorRef
);
277 * Clear the specified region of the color buffer using the clear color
278 * or index as specified by one of the two functions above.
280 * This procedure clears either the front and/or the back COLOR buffers.
281 * Only the "left" buffer is cleared since we are not stereo.
282 * Clearing of the other non-color buffers is left to the swrast.
285 static void clear(GLcontext
*ctx
, GLbitfield mask
)
287 #define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
288 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
289 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
290 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
291 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
293 WMesaContext pwc
= wmesa_context(ctx
);
294 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
297 /* Let swrast do all the work if the masks are not set to
298 * clear all channels. */
299 if (ctx
->Color
.ColorMask
[0] != 0xff ||
300 ctx
->Color
.ColorMask
[1] != 0xff ||
301 ctx
->Color
.ColorMask
[2] != 0xff ||
302 ctx
->Color
.ColorMask
[3] != 0xff) {
303 _swrast_Clear(ctx
, mask
);
308 if (mask
& BUFFER_BIT_BACK_LEFT
) {
311 UINT bytesPerPixel
= pwfb
->cColorBits
/ 8;
312 LPBYTE lpb
, clearRow
;
320 /* Try for a fast clear - clearing entire buffer with a single
322 if (width
== ctx
->DrawBuffer
->Width
&&
323 height
== ctx
->DrawBuffer
->Height
) { /* entire buffer */
324 /* Now check for an easy clear value */
325 switch (bytesPerPixel
) {
327 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
328 GetGValue(pwc
->clearColorRef
),
329 GetBValue(pwc
->clearColorRef
));
330 memset(pwfb
->pbPixels
, bColor
,
331 pwfb
->ScanWidth
* height
);
335 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
336 GetGValue(pwc
->clearColorRef
),
337 GetBValue(pwc
->clearColorRef
));
338 if (((wColor
>> 8) & 0xff) == (wColor
& 0xff)) {
339 memset(pwfb
->pbPixels
, wColor
& 0xff,
340 pwfb
->ScanWidth
* height
);
347 if (GetRValue(pwc
->clearColorRef
) ==
348 GetGValue(pwc
->clearColorRef
) &&
349 GetRValue(pwc
->clearColorRef
) ==
350 GetBValue(pwc
->clearColorRef
)) {
351 memset(pwfb
->pbPixels
,
352 GetRValue(pwc
->clearColorRef
),
353 pwfb
->ScanWidth
* height
);
363 /* Need to clear a row at a time. Begin by setting the first
364 * row in the area to be cleared to the clear color. */
366 clearRow
= pwfb
->pbPixels
+
367 pwfb
->ScanWidth
* FLIP(y
) +
369 switch (bytesPerPixel
) {
372 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
373 GetGValue(pwc
->clearColorRef
),
374 GetBValue(pwc
->clearColorRef
));
375 memset(lpb
, bColor
, width
);
378 lpw
= (LPWORD
)clearRow
;
379 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
380 GetGValue(pwc
->clearColorRef
),
381 GetBValue(pwc
->clearColorRef
));
382 for (i
=0; i
<width
; i
++)
387 r
= GetRValue(pwc
->clearColorRef
);
388 g
= GetGValue(pwc
->clearColorRef
);
389 b
= GetBValue(pwc
->clearColorRef
);
390 for (i
=0; i
<width
; i
++) {
397 lpdw
= (LPDWORD
)clearRow
;
398 dwColor
= BGR32(GetRValue(pwc
->clearColorRef
),
399 GetGValue(pwc
->clearColorRef
),
400 GetBValue(pwc
->clearColorRef
));
401 for (i
=0; i
<width
; i
++)
408 /* copy cleared row to other rows in buffer */
409 lpb
= clearRow
- pwfb
->ScanWidth
;
410 rowSize
= width
* bytesPerPixel
;
411 for (i
=1; i
<height
; i
++) {
412 memcpy(lpb
, clearRow
, rowSize
);
413 lpb
-= pwfb
->ScanWidth
;
416 mask
&= ~BUFFER_BIT_BACK_LEFT
;
420 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
422 HPEN Old_Pen
= SelectObject(DC
, pwc
->clearPen
);
423 HBRUSH Old_Brush
= SelectObject(DC
, pwc
->clearBrush
);
428 FLIP(y
) - height
+ 1);
429 SelectObject(DC
, Old_Pen
);
430 SelectObject(DC
, Old_Brush
);
431 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
434 /* Call swrast if there is anything left to clear (like DEPTH) */
436 _swrast_Clear(ctx
, mask
);
442 /**********************************************************************/
443 /***** PIXEL Functions *****/
444 /**********************************************************************/
446 #define FLIP(Y) (rb->Height - (Y) - 1)
450 ** Front Buffer reading/writing
451 ** These are slow, but work with all non-indexed visual types.
454 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
455 static void write_rgba_span_front(const GLcontext
*ctx
,
456 struct gl_renderbuffer
*rb
,
457 GLuint n
, GLint x
, GLint y
,
458 const GLubyte rgba
[][4],
459 const GLubyte mask
[] )
461 WMesaContext pwc
= wmesa_context(ctx
);
469 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
474 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
480 /* Write a horizontal span of RGB color pixels with a boolean mask. */
481 static void write_rgb_span_front(const GLcontext
*ctx
,
482 struct gl_renderbuffer
*rb
,
483 GLuint n
, GLint x
, GLint y
,
484 const GLubyte rgb
[][3],
485 const GLubyte mask
[] )
487 WMesaContext pwc
= wmesa_context(ctx
);
495 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
500 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
507 * Write a horizontal span of pixels with a boolean mask. The current color
508 * is used for all pixels.
510 static void write_mono_rgba_span_front(const GLcontext
*ctx
,
511 struct gl_renderbuffer
*rb
,
512 GLuint n
, GLint x
, GLint y
,
513 const GLchan color
[4],
514 const GLubyte mask
[])
517 WMesaContext pwc
= wmesa_context(ctx
);
521 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
526 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
530 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
534 /* Write an array of RGBA pixels with a boolean mask. */
535 static void write_rgba_pixels_front(const GLcontext
*ctx
,
536 struct gl_renderbuffer
*rb
,
538 const GLint x
[], const GLint y
[],
539 const GLubyte rgba
[][4],
540 const GLubyte mask
[] )
543 WMesaContext pwc
= wmesa_context(ctx
);
547 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]),
548 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
555 * Write an array of pixels with a boolean mask. The current color
556 * is used for all pixels.
558 static void write_mono_rgba_pixels_front(const GLcontext
*ctx
,
559 struct gl_renderbuffer
*rb
,
561 const GLint x
[], const GLint y
[],
562 const GLchan color
[4],
563 const GLubyte mask
[] )
566 WMesaContext pwc
= wmesa_context(ctx
);
569 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
572 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]), colorref
);
575 /* Read a horizontal span of color pixels. */
576 static void read_rgba_span_front(const GLcontext
*ctx
,
577 struct gl_renderbuffer
*rb
,
578 GLuint n
, GLint x
, GLint y
,
581 WMesaContext pwc
= wmesa_context(ctx
);
585 for (i
=0; i
<n
; i
++) {
586 Color
= GetPixel(pwc
->hDC
, x
+i
, y
);
587 rgba
[i
][RCOMP
] = GetRValue(Color
);
588 rgba
[i
][GCOMP
] = GetGValue(Color
);
589 rgba
[i
][BCOMP
] = GetBValue(Color
);
590 rgba
[i
][ACOMP
] = 255;
595 /* Read an array of color pixels. */
596 static void read_rgba_pixels_front(const GLcontext
*ctx
,
597 struct gl_renderbuffer
*rb
,
598 GLuint n
, const GLint x
[], const GLint y
[],
601 WMesaContext pwc
= wmesa_context(ctx
);
604 for (i
=0; i
<n
; i
++) {
605 GLint y2
= FLIP(y
[i
]);
606 Color
= GetPixel(pwc
->hDC
, x
[i
], y2
);
607 rgba
[i
][RCOMP
] = GetRValue(Color
);
608 rgba
[i
][GCOMP
] = GetGValue(Color
);
609 rgba
[i
][BCOMP
] = GetBValue(Color
);
610 rgba
[i
][ACOMP
] = 255;
614 /*********************************************************************/
616 /* DOUBLE BUFFER 32-bit */
618 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
619 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
620 *lpdw = BGR32((r),(g),(b)); }
624 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
625 static void write_rgba_span_32(const GLcontext
*ctx
,
626 struct gl_renderbuffer
*rb
,
627 GLuint n
, GLint x
, GLint y
,
628 const GLubyte rgba
[][4],
629 const GLubyte mask
[] )
631 WMesaContext pwc
= wmesa_context(ctx
);
632 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
639 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
643 lpdw
[i
] = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
648 *lpdw
++ = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
654 /* Write a horizontal span of RGB color pixels with a boolean mask. */
655 static void write_rgb_span_32(const GLcontext
*ctx
,
656 struct gl_renderbuffer
*rb
,
657 GLuint n
, GLint x
, GLint y
,
658 const GLubyte rgb
[][3],
659 const GLubyte mask
[] )
661 WMesaContext pwc
= wmesa_context(ctx
);
662 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
669 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
673 lpdw
[i
] = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
678 *lpdw
++ = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
684 * Write a horizontal span of pixels with a boolean mask. The current color
685 * is used for all pixels.
687 static void write_mono_rgba_span_32(const GLcontext
*ctx
,
688 struct gl_renderbuffer
*rb
,
689 GLuint n
, GLint x
, GLint y
,
690 const GLchan color
[4],
691 const GLubyte mask
[])
696 WMesaContext pwc
= wmesa_context(ctx
);
697 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
698 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
700 pixel
= BGR32(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
712 /* Write an array of RGBA pixels with a boolean mask. */
713 static void write_rgba_pixels_32(const GLcontext
*ctx
,
714 struct gl_renderbuffer
*rb
,
715 GLuint n
, const GLint x
[], const GLint y
[],
716 const GLubyte rgba
[][4],
717 const GLubyte mask
[])
720 WMesaContext pwc
= wmesa_context(ctx
);
721 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
724 WMSETPIXEL32(pwfb
, FLIP(y
[i
]), x
[i
],
725 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
729 * Write an array of pixels with a boolean mask. The current color
730 * is used for all pixels.
732 static void write_mono_rgba_pixels_32(const GLcontext
*ctx
,
733 struct gl_renderbuffer
*rb
,
735 const GLint x
[], const GLint y
[],
736 const GLchan color
[4],
737 const GLubyte mask
[])
740 WMesaContext pwc
= wmesa_context(ctx
);
741 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
744 WMSETPIXEL32(pwfb
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
745 color
[GCOMP
], color
[BCOMP
]);
748 /* Read a horizontal span of color pixels. */
749 static void read_rgba_span_32(const GLcontext
*ctx
,
750 struct gl_renderbuffer
*rb
,
751 GLuint n
, GLint x
, GLint y
,
757 WMesaContext pwc
= wmesa_context(ctx
);
758 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
761 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
762 for (i
=0; i
<n
; i
++) {
764 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
765 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
766 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
767 rgba
[i
][ACOMP
] = 255;
772 /* Read an array of color pixels. */
773 static void read_rgba_pixels_32(const GLcontext
*ctx
,
774 struct gl_renderbuffer
*rb
,
775 GLuint n
, const GLint x
[], const GLint y
[],
781 WMesaContext pwc
= wmesa_context(ctx
);
782 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
784 for (i
=0; i
<n
; i
++) {
785 GLint y2
= FLIP(y
[i
]);
786 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
788 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
789 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
790 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
791 rgba
[i
][ACOMP
] = 255;
796 /*********************************************************************/
798 /* DOUBLE BUFFER 16-bit */
800 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
801 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
802 *lpw = BGR16((r),(g),(b)); }
806 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
807 static void write_rgba_span_16(const GLcontext
*ctx
,
808 struct gl_renderbuffer
*rb
,
809 GLuint n
, GLint x
, GLint y
,
810 const GLubyte rgba
[][4],
811 const GLubyte mask
[] )
813 WMesaContext pwc
= wmesa_context(ctx
);
814 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
821 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
825 lpw
[i
] = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
830 *lpw
++ = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
836 /* Write a horizontal span of RGB color pixels with a boolean mask. */
837 static void write_rgb_span_16(const GLcontext
*ctx
,
838 struct gl_renderbuffer
*rb
,
839 GLuint n
, GLint x
, GLint y
,
840 const GLubyte rgb
[][3],
841 const GLubyte mask
[] )
843 WMesaContext pwc
= wmesa_context(ctx
);
844 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
851 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
855 lpw
[i
] = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
860 *lpw
++ = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
866 * Write a horizontal span of pixels with a boolean mask. The current color
867 * is used for all pixels.
869 static void write_mono_rgba_span_16(const GLcontext
*ctx
,
870 struct gl_renderbuffer
*rb
,
871 GLuint n
, GLint x
, GLint y
,
872 const GLchan color
[4],
873 const GLubyte mask
[])
878 WMesaContext pwc
= wmesa_context(ctx
);
879 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
881 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
883 pixel
= BGR16(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
895 /* Write an array of RGBA pixels with a boolean mask. */
896 static void write_rgba_pixels_16(const GLcontext
*ctx
,
897 struct gl_renderbuffer
*rb
,
898 GLuint n
, const GLint x
[], const GLint y
[],
899 const GLubyte rgba
[][4],
900 const GLubyte mask
[])
903 WMesaContext pwc
= wmesa_context(ctx
);
904 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
908 WMSETPIXEL16(pwfb
, FLIP(y
[i
]), x
[i
],
909 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
913 * Write an array of pixels with a boolean mask. The current color
914 * is used for all pixels.
916 static void write_mono_rgba_pixels_16(const GLcontext
*ctx
,
917 struct gl_renderbuffer
*rb
,
919 const GLint x
[], const GLint y
[],
920 const GLchan color
[4],
921 const GLubyte mask
[])
924 WMesaContext pwc
= wmesa_context(ctx
);
925 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
929 WMSETPIXEL16(pwfb
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
930 color
[GCOMP
], color
[BCOMP
]);
933 /* Read a horizontal span of color pixels. */
934 static void read_rgba_span_16(const GLcontext
*ctx
,
935 struct gl_renderbuffer
*rb
,
936 GLuint n
, GLint x
, GLint y
,
941 WMesaContext pwc
= wmesa_context(ctx
);
942 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
945 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
946 for (i
=0; i
<n
; i
++) {
948 /* Windows uses 5,5,5 for 16-bit */
949 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
950 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
951 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
952 rgba
[i
][ACOMP
] = 255;
957 /* Read an array of color pixels. */
958 static void read_rgba_pixels_16(const GLcontext
*ctx
,
959 struct gl_renderbuffer
*rb
,
960 GLuint n
, const GLint x
[], const GLint y
[],
965 WMesaContext pwc
= wmesa_context(ctx
);
966 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
968 for (i
=0; i
<n
; i
++) {
969 GLint y2
= FLIP(y
[i
]);
970 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
972 /* Windows uses 5,5,5 for 16-bit */
973 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
974 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
975 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
976 rgba
[i
][ACOMP
] = 255;
983 /**********************************************************************/
984 /***** BUFFER Functions *****/
985 /**********************************************************************/
991 wmesa_delete_renderbuffer(struct gl_renderbuffer
*rb
)
998 * This is called by Mesa whenever it determines that the window size
999 * has changed. Do whatever's needed to cope with that.
1002 wmesa_renderbuffer_storage(GLcontext
*ctx
,
1003 struct gl_renderbuffer
*rb
,
1004 GLenum internalFormat
,
1009 rb
->Height
= height
;
1015 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1016 * on if we're drawing to the front or back color buffer.
1018 void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer
*rb
, int pixelformat
,
1021 if (double_buffer
) {
1023 /* Picking the correct span functions is important because
1024 * the DIB was allocated with the indicated depth. */
1025 switch(pixelformat
) {
1027 rb
->PutRow
= write_rgba_span_16
;
1028 rb
->PutRowRGB
= write_rgb_span_16
;
1029 rb
->PutMonoRow
= write_mono_rgba_span_16
;
1030 rb
->PutValues
= write_rgba_pixels_16
;
1031 rb
->PutMonoValues
= write_mono_rgba_pixels_16
;
1032 rb
->GetRow
= read_rgba_span_16
;
1033 rb
->GetValues
= read_rgba_pixels_16
;
1039 rb
->PutRow
= write_rgba_span_32
;
1040 rb
->PutRowRGB
= write_rgb_span_32
;
1041 rb
->PutMonoRow
= write_mono_rgba_span_32
;
1042 rb
->PutValues
= write_rgba_pixels_32
;
1043 rb
->PutMonoValues
= write_mono_rgba_pixels_32
;
1044 rb
->GetRow
= read_rgba_span_32
;
1045 rb
->GetValues
= read_rgba_pixels_32
;
1055 /* front buffer (actual Windows window) */
1056 rb
->PutRow
= write_rgba_span_front
;
1057 rb
->PutRowRGB
= write_rgb_span_front
;
1058 rb
->PutMonoRow
= write_mono_rgba_span_front
;
1059 rb
->PutValues
= write_rgba_pixels_front
;
1060 rb
->PutMonoValues
= write_mono_rgba_pixels_front
;
1061 rb
->GetRow
= read_rgba_span_front
;
1062 rb
->GetValues
= read_rgba_pixels_front
;
1063 rb
->RedBits
= 8; /* XXX fix these (565?) */
1070 * Called by ctx->Driver.ResizeBuffers()
1071 * Resize the front/back colorbuffers to match the latest window size.
1074 wmesa_resize_buffers(GLcontext
*ctx
, GLframebuffer
*buffer
,
1075 GLuint width
, GLuint height
)
1077 WMesaContext pwc
= wmesa_context(ctx
);
1078 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
1080 if (pwfb
->Base
.Width
!= width
|| pwfb
->Base
.Height
!= height
) {
1081 /* Realloc back buffer */
1082 if (ctx
->Visual
.doubleBufferMode
== 1) {
1083 wmDeleteBackingStore(pwfb
);
1084 wmCreateBackingStore(pwfb
, width
, height
);
1087 _mesa_resize_framebuffer(ctx
, buffer
, width
, height
);
1092 * Called by glViewport.
1093 * This is a good time for us to poll the current window size and adjust
1094 * our renderbuffers to match the current window size.
1095 * Remember, we have no opportunity to respond to conventional
1096 * resize events since the driver has no event loop.
1098 * MakeCurrent also ends up making a call here, so that ensures
1099 * we get the viewport set correctly, even if the app does not call
1100 * glViewport and relies on the defaults.
1102 static void wmesa_viewport(GLcontext
*ctx
,
1104 GLsizei width
, GLsizei height
)
1106 WMesaContext pwc
= wmesa_context(ctx
);
1107 GLuint new_width
, new_height
;
1109 wmesa_get_buffer_size(ctx
->WinSysDrawBuffer
, &new_width
, &new_height
);
1112 * Resize buffers if the window size changed.
1114 wmesa_resize_buffers(ctx
, ctx
->WinSysDrawBuffer
, new_width
, new_height
);
1115 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
1122 * Called when the driver should update it's state, based on the new_state
1125 static void wmesa_update_state(GLcontext
*ctx
, GLuint new_state
)
1127 _swrast_InvalidateState(ctx
, new_state
);
1128 _swsetup_InvalidateState(ctx
, new_state
);
1129 _vbo_InvalidateState(ctx
, new_state
);
1130 _tnl_InvalidateState(ctx
, new_state
);
1132 /* TODO - This code is not complete yet because I
1133 * don't know what to do for all state updates.
1136 if (new_state
& _NEW_BUFFERS
) {
1144 /**********************************************************************/
1145 /***** WMESA Functions *****/
1146 /**********************************************************************/
1148 WMesaContext
WMesaCreateContext(HDC hDC
,
1152 GLboolean alpha_flag
)
1155 struct dd_function_table functions
;
1156 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1162 /* Indexed mode not supported */
1166 /* Allocate wmesa context */
1167 c
= CALLOC_STRUCT(wmesa_context
);
1172 /* I do not understand this contributed code */
1173 /* Support memory and device contexts */
1174 if(WindowFromDC(hDC
) != NULL
) {
1175 c
->hDC
= GetDC(WindowFromDC(hDC
)); /* huh ???? */
1184 /* Get data for visual */
1185 /* Dealing with this is actually a bit of overkill because Mesa will end
1186 * up treating all color component size requests less than 8 by using
1187 * a single byte per channel. In addition, the interface to the span
1188 * routines passes colors as an entire byte per channel anyway, so there
1189 * is nothing to be saved by telling the visual to be 16 bits if the device
1190 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
1192 * But we go through the motions here anyway.
1194 switch (GetDeviceCaps(c
->hDC
, BITSPIXEL
)) {
1196 red_bits
= green_bits
= blue_bits
= 5;
1200 red_bits
= green_bits
= blue_bits
= 8;
1204 /* Create visual based on flags */
1205 visual
= _mesa_create_visual(rgb_flag
,
1206 db_flag
, /* db_flag */
1207 GL_FALSE
, /* stereo */
1208 red_bits
, green_bits
, blue_bits
, /* color RGB */
1209 alpha_flag
? alpha_bits
: 0, /* color A */
1211 DEFAULT_SOFTWARE_DEPTH_BITS
, /* depth_bits */
1212 8, /* stencil_bits */
1213 16,16,16, /* accum RGB */
1214 alpha_flag
? 16 : 0, /* accum A */
1215 1); /* num samples */
1222 /* Set up driver functions */
1223 _mesa_init_driver_functions(&functions
);
1224 functions
.GetString
= wmesa_get_string
;
1225 functions
.UpdateState
= wmesa_update_state
;
1226 functions
.GetBufferSize
= wmesa_get_buffer_size
;
1227 functions
.Flush
= wmesa_flush
;
1228 functions
.Clear
= clear
;
1229 functions
.ClearIndex
= clear_index
;
1230 functions
.ClearColor
= clear_color
;
1231 functions
.ResizeBuffers
= wmesa_resize_buffers
;
1232 functions
.Viewport
= wmesa_viewport
;
1234 /* initialize the Mesa context data */
1236 _mesa_initialize_context(ctx
, visual
, NULL
, &functions
, (void *)c
);
1238 _mesa_enable_sw_extensions(ctx
);
1239 _mesa_enable_1_3_extensions(ctx
);
1240 _mesa_enable_1_4_extensions(ctx
);
1241 _mesa_enable_1_5_extensions(ctx
);
1242 _mesa_enable_2_0_extensions(ctx
);
1243 _mesa_enable_2_1_extensions(ctx
);
1245 /* Initialize the software rasterizer and helper modules. */
1246 if (!_swrast_CreateContext(ctx
) ||
1247 !_vbo_CreateContext(ctx
) ||
1248 !_tnl_CreateContext(ctx
) ||
1249 !_swsetup_CreateContext(ctx
)) {
1250 _mesa_free_context_data(ctx
);
1254 _swsetup_Wakeup(ctx
);
1255 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
1261 void WMesaDestroyContext( WMesaContext pwc
)
1263 GLcontext
*ctx
= &pwc
->gl_ctx
;
1264 WMesaFramebuffer pwfb
;
1265 GET_CURRENT_CONTEXT(cur_ctx
);
1267 if (cur_ctx
== ctx
) {
1268 /* unbind current if deleting current context */
1269 WMesaMakeCurrent(NULL
, NULL
);
1272 /* clean up frame buffer resources */
1273 pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
1275 if (ctx
->Visual
.doubleBufferMode
== 1)
1276 wmDeleteBackingStore(pwfb
);
1277 wmesa_free_framebuffer(pwc
->hDC
);
1280 /* Release for device, not memory contexts */
1281 if (WindowFromDC(pwc
->hDC
) != NULL
)
1283 ReleaseDC(WindowFromDC(pwc
->hDC
), pwc
->hDC
);
1285 DeleteObject(pwc
->clearPen
);
1286 DeleteObject(pwc
->clearBrush
);
1288 _swsetup_DestroyContext(ctx
);
1289 _tnl_DestroyContext(ctx
);
1290 _vbo_DestroyContext(ctx
);
1291 _swrast_DestroyContext(ctx
);
1293 _mesa_free_context_data(ctx
);
1299 * Create a new color renderbuffer.
1301 struct gl_renderbuffer
*
1302 wmesa_new_renderbuffer(void)
1304 struct gl_renderbuffer
*rb
= CALLOC_STRUCT(gl_renderbuffer
);
1308 _mesa_init_renderbuffer(rb
, (GLuint
)0);
1310 rb
->_BaseFormat
= GL_RGBA
;
1311 rb
->InternalFormat
= GL_RGBA
;
1312 rb
->DataType
= CHAN_TYPE
;
1313 rb
->Delete
= wmesa_delete_renderbuffer
;
1314 rb
->AllocStorage
= wmesa_renderbuffer_storage
;
1319 void WMesaMakeCurrent(WMesaContext c
, HDC hdc
)
1321 WMesaFramebuffer pwfb
;
1324 /* return if already current */
1325 GET_CURRENT_CONTEXT(ctx
);
1326 WMesaContext pwc
= wmesa_context(ctx
);
1327 if (pwc
&& c
== pwc
&& pwc
->hDC
== hdc
)
1331 pwfb
= wmesa_lookup_framebuffer(hdc
);
1333 /* Lazy creation of framebuffers */
1334 if (c
&& !pwfb
&& hdc
) {
1335 struct gl_renderbuffer
*rb
;
1336 GLvisual
*visual
= &c
->gl_ctx
.Visual
;
1337 GLuint width
, height
;
1339 get_window_size(hdc
, &width
, &height
);
1341 c
->clearPen
= CreatePen(PS_SOLID
, 1, 0);
1342 c
->clearBrush
= CreateSolidBrush(0);
1344 pwfb
= wmesa_new_framebuffer(hdc
, visual
);
1346 /* Create back buffer if double buffered */
1347 if (visual
->doubleBufferMode
== 1) {
1348 wmCreateBackingStore(pwfb
, width
, height
);
1351 /* make render buffers */
1352 if (visual
->doubleBufferMode
== 1) {
1353 rb
= wmesa_new_renderbuffer();
1354 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_BACK_LEFT
, rb
);
1355 wmesa_set_renderbuffer_funcs(rb
, pwfb
->pixelformat
, 1);
1357 rb
= wmesa_new_renderbuffer();
1358 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_FRONT_LEFT
, rb
);
1359 wmesa_set_renderbuffer_funcs(rb
, pwfb
->pixelformat
, 0);
1361 /* Let Mesa own the Depth, Stencil, and Accum buffers */
1362 _mesa_add_soft_renderbuffers(&pwfb
->Base
,
1363 GL_FALSE
, /* color */
1364 visual
->depthBits
> 0,
1365 visual
->stencilBits
> 0,
1366 visual
->accumRedBits
> 0,
1367 visual
->alphaBits
>0,
1372 _mesa_make_current(&c
->gl_ctx
, &pwfb
->Base
, &pwfb
->Base
);
1374 _mesa_make_current(NULL
, NULL
, NULL
);
1378 void WMesaSwapBuffers( HDC hdc
)
1380 GET_CURRENT_CONTEXT(ctx
);
1381 WMesaContext pwc
= wmesa_context(ctx
);
1382 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(hdc
);
1385 _mesa_problem(NULL
, "wmesa: swapbuffers on unknown hdc");
1389 /* If we're swapping the buffer associated with the current context
1390 * we have to flush any pending rendering commands first.
1392 if (pwc
->hDC
== hdc
) {
1393 _mesa_notifySwapBuffers(ctx
);
1395 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
1396 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
1399 /* XXX for now only allow swapping current window */
1400 _mesa_problem(NULL
, "wmesa: can't swap non-current window");
1404 /* This is hopefully a temporary hack to define some needed dispatch
1405 * table entries. Hopefully, I'll find a better solution. The
1406 * dispatch table generation scripts ought to be making these dummy
1408 #if !defined(__MINGW32__) || !defined(GL_NO_STDCALL)
1409 void gl_dispatch_stub_543(void){}
1410 void gl_dispatch_stub_544(void){}
1411 void gl_dispatch_stub_545(void){}
1412 void gl_dispatch_stub_546(void){}
1413 void gl_dispatch_stub_547(void){}
1414 void gl_dispatch_stub_548(void){}
1415 void gl_dispatch_stub_549(void){}
1416 void gl_dispatch_stub_550(void){}
1417 void gl_dispatch_stub_551(void){}
1418 void gl_dispatch_stub_552(void){}
1419 void gl_dispatch_stub_553(void){}
1420 void gl_dispatch_stub_554(void){}
1421 void gl_dispatch_stub_555(void){}
1422 void gl_dispatch_stub_556(void){}
1423 void gl_dispatch_stub_557(void){}
1424 void gl_dispatch_stub_558(void){}
1425 void gl_dispatch_stub_559(void){}
1426 void gl_dispatch_stub_560(void){}
1427 void gl_dispatch_stub_561(void){}
1428 void gl_dispatch_stub_565(void){}
1429 void gl_dispatch_stub_566(void){}
1430 void gl_dispatch_stub_577(void){}
1431 void gl_dispatch_stub_578(void){}
1432 void gl_dispatch_stub_603(void){}
1433 void gl_dispatch_stub_645(void){}
1434 void gl_dispatch_stub_646(void){}
1435 void gl_dispatch_stub_647(void){}
1436 void gl_dispatch_stub_648(void){}
1437 void gl_dispatch_stub_649(void){}
1438 void gl_dispatch_stub_650(void){}
1439 void gl_dispatch_stub_651(void){}
1440 void gl_dispatch_stub_652(void){}
1441 void gl_dispatch_stub_653(void){}
1442 void gl_dispatch_stub_734(void){}
1443 void gl_dispatch_stub_735(void){}
1444 void gl_dispatch_stub_736(void){}
1445 void gl_dispatch_stub_737(void){}
1446 void gl_dispatch_stub_738(void){}
1447 void gl_dispatch_stub_745(void){}
1448 void gl_dispatch_stub_746(void){}
1449 void gl_dispatch_stub_760(void){}
1450 void gl_dispatch_stub_761(void){}
1451 void gl_dispatch_stub_766(void){}
1452 void gl_dispatch_stub_767(void){}
1453 void gl_dispatch_stub_768(void){}
1455 void gl_dispatch_stub_562(void){}
1456 void gl_dispatch_stub_563(void){}
1457 void gl_dispatch_stub_564(void){}
1458 void gl_dispatch_stub_567(void){}
1459 void gl_dispatch_stub_568(void){}
1460 void gl_dispatch_stub_569(void){}
1461 void gl_dispatch_stub_580(void){}
1462 void gl_dispatch_stub_581(void){}
1463 void gl_dispatch_stub_606(void){}
1464 void gl_dispatch_stub_654(void){}
1465 void gl_dispatch_stub_655(void){}
1466 void gl_dispatch_stub_656(void){}
1467 void gl_dispatch_stub_739(void){}
1468 void gl_dispatch_stub_740(void){}
1469 void gl_dispatch_stub_741(void){}
1470 void gl_dispatch_stub_748(void){}
1471 void gl_dispatch_stub_749(void){}
1472 void gl_dispatch_stub_769(void){}
1473 void gl_dispatch_stub_770(void){}
1474 void gl_dispatch_stub_771(void){}