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"
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
;
46 * Given an hdc, free the corresponding WMesaFramebuffer
49 wmesa_free_framebuffer(HDC hdc
)
51 WMesaFramebuffer pwfb
, prev
;
52 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
58 if (pwfb
== FirstFramebuffer
)
59 FirstFramebuffer
= pwfb
->next
;
61 prev
->next
= pwfb
->next
;
67 * Given an hdc, return the corresponding WMesaFramebuffer
70 wmesa_lookup_framebuffer(HDC hdc
)
72 WMesaFramebuffer pwfb
;
73 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
82 * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
84 static WMesaFramebuffer
wmesa_framebuffer(GLframebuffer
*fb
)
86 return (WMesaFramebuffer
) fb
;
91 * Given a GLcontext, return the corresponding WMesaContext.
93 static WMesaContext
wmesa_context(const GLcontext
*ctx
)
95 return (WMesaContext
) ctx
;
100 * Every driver should implement a GetString function in order to
101 * return a meaningful GL_RENDERER string.
103 static const GLubyte
*wmesa_get_string(GLcontext
*ctx
, GLenum name
)
105 return (name
== GL_RENDERER
) ?
106 (GLubyte
*) "Mesa Windows GDI Driver" : NULL
;
111 * Determine the pixel format based on the pixel size.
113 static void wmSetPixelFormat(WMesaFramebuffer pwfb
, HDC hDC
)
115 pwfb
->cColorBits
= GetDeviceCaps(hDC
, BITSPIXEL
);
117 // Only 16 and 32 bit targets are supported now
118 assert(pwfb
->cColorBits
== 0 ||
119 pwfb
->cColorBits
== 16 ||
120 pwfb
->cColorBits
== 32);
122 switch(pwfb
->cColorBits
){
124 pwfb
->pixelformat
= PF_INDEX8
;
127 pwfb
->pixelformat
= PF_5R6G5B
;
130 pwfb
->pixelformat
= PF_8R8G8B
;
133 pwfb
->pixelformat
= PF_BADFORMAT
;
139 * Create DIB for back buffer.
140 * We write into this memory with the span routines and then blit it
141 * to the window on a buffer swap.
143 BOOL
wmCreateBackingStore(WMesaFramebuffer pwfb
, long lxSize
, long lySize
)
146 LPBITMAPINFO pbmi
= &(pwfb
->bmi
);
149 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
150 pbmi
->bmiHeader
.biWidth
= lxSize
;
151 pbmi
->bmiHeader
.biHeight
= -lySize
;
152 pbmi
->bmiHeader
.biPlanes
= 1;
153 pbmi
->bmiHeader
.biBitCount
= GetDeviceCaps(pwfb
->hDC
, BITSPIXEL
);
154 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
155 pbmi
->bmiHeader
.biSizeImage
= 0;
156 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
157 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
158 pbmi
->bmiHeader
.biClrUsed
= 0;
159 pbmi
->bmiHeader
.biClrImportant
= 0;
161 pwfb
->cColorBits
= pbmi
->bmiHeader
.biBitCount
;
162 pwfb
->ScanWidth
= (lxSize
* (pwfb
->cColorBits
/ 8) + 3) & ~3;
164 hic
= CreateIC("display", NULL
, NULL
, NULL
);
165 pwfb
->dib_hDC
= CreateCompatibleDC(hic
);
167 pwfb
->hbmDIB
= CreateDIBSection(hic
,
170 (void **)&(pwfb
->pbPixels
),
173 pwfb
->hOldBitmap
= SelectObject(pwfb
->dib_hDC
, pwfb
->hbmDIB
);
177 wmSetPixelFormat(pwfb
, pwfb
->hDC
);
182 static wmDeleteBackingStore(WMesaFramebuffer pwfb
)
185 SelectObject(pwfb
->dib_hDC
, pwfb
->hOldBitmap
);
186 DeleteDC(pwfb
->dib_hDC
);
187 DeleteObject(pwfb
->hbmDIB
);
193 * Find the width and height of the window named by hdc.
196 get_window_size(HDC hdc
, GLuint
*width
, GLuint
*height
)
198 if (WindowFromDC(hdc
)) {
200 GetClientRect(WindowFromDC(hdc
), &rect
);
201 *width
= rect
.right
- rect
.left
;
202 *height
= rect
.bottom
- rect
.top
;
204 else { /* Memory context */
205 /* From contributed code - use the size of the desktop
206 * for the size of a memory context (?) */
207 *width
= GetDeviceCaps(hdc
, HORZRES
);
208 *height
= GetDeviceCaps(hdc
, VERTRES
);
214 wmesa_get_buffer_size(GLframebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
216 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
217 get_window_size(pwfb
->hDC
, width
, height
);
221 static void wmesa_flush(GLcontext
*ctx
)
223 WMesaContext pwc
= wmesa_context(ctx
);
224 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->WinSysDrawBuffer
);
226 if (ctx
->Visual
.doubleBufferMode
== 1) {
227 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
228 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
231 /* Do nothing for single buffer */
236 /**********************************************************************/
237 /***** CLEAR Functions *****/
238 /**********************************************************************/
240 /* If we do not implement these, Mesa clears the buffers via the pixel
241 * span writing interface, which is very slow for a clear operation.
245 * Set the color index used to clear the color buffer.
247 static void clear_index(GLcontext
*ctx
, GLuint index
)
249 WMesaContext pwc
= wmesa_context(ctx
);
250 /* Note that indexed mode is not supported yet */
251 pwc
->clearColorRef
= RGB(0,0,0);
255 * Set the color used to clear the color buffer.
257 static void clear_color(GLcontext
*ctx
, const GLfloat color
[4])
259 WMesaContext pwc
= wmesa_context(ctx
);
260 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
262 UINT bytesPerPixel
= pwfb
->cColorBits
/ 8;
264 CLAMPED_FLOAT_TO_UBYTE(col
[0], color
[0]);
265 CLAMPED_FLOAT_TO_UBYTE(col
[1], color
[1]);
266 CLAMPED_FLOAT_TO_UBYTE(col
[2], color
[2]);
267 pwc
->clearColorRef
= RGB(col
[0], col
[1], col
[2]);
268 DeleteObject(pwc
->clearPen
);
269 DeleteObject(pwc
->clearBrush
);
270 pwc
->clearPen
= CreatePen(PS_SOLID
, 1, pwc
->clearColorRef
);
271 pwc
->clearBrush
= CreateSolidBrush(pwc
->clearColorRef
);
276 * Clear the specified region of the color buffer using the clear color
277 * or index as specified by one of the two functions above.
279 * This procedure clears either the front and/or the back COLOR buffers.
280 * Only the "left" buffer is cleared since we are not stereo.
281 * Clearing of the other non-color buffers is left to the swrast.
284 static void clear(GLcontext
*ctx
, GLbitfield mask
)
286 #define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
287 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
288 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
289 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
290 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
292 WMesaContext pwc
= wmesa_context(ctx
);
293 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
296 /* Let swrast do all the work if the masks are not set to
297 * clear all channels. */
298 if (ctx
->Color
.ColorMask
[0] != 0xff ||
299 ctx
->Color
.ColorMask
[1] != 0xff ||
300 ctx
->Color
.ColorMask
[2] != 0xff ||
301 ctx
->Color
.ColorMask
[3] != 0xff) {
302 _swrast_Clear(ctx
, mask
);
307 if (mask
& BUFFER_BIT_BACK_LEFT
) {
310 UINT bytesPerPixel
= pwfb
->cColorBits
/ 8;
311 LPBYTE lpb
, clearRow
;
319 /* Try for a fast clear - clearing entire buffer with a single
321 if (width
== ctx
->DrawBuffer
->Width
&&
322 height
== ctx
->DrawBuffer
->Height
) { /* entire buffer */
323 /* Now check for an easy clear value */
324 switch (bytesPerPixel
) {
326 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
327 GetGValue(pwc
->clearColorRef
),
328 GetBValue(pwc
->clearColorRef
));
329 memset(pwfb
->pbPixels
, bColor
,
330 pwfb
->ScanWidth
* height
);
334 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
335 GetGValue(pwc
->clearColorRef
),
336 GetBValue(pwc
->clearColorRef
));
337 if (((wColor
>> 8) & 0xff) == (wColor
& 0xff)) {
338 memset(pwfb
->pbPixels
, wColor
& 0xff,
339 pwfb
->ScanWidth
* height
);
346 if (GetRValue(pwc
->clearColorRef
) ==
347 GetGValue(pwc
->clearColorRef
) &&
348 GetRValue(pwc
->clearColorRef
) ==
349 GetBValue(pwc
->clearColorRef
)) {
350 memset(pwfb
->pbPixels
,
351 GetRValue(pwc
->clearColorRef
),
352 pwfb
->ScanWidth
* height
);
362 /* Need to clear a row at a time. Begin by setting the first
363 * row in the area to be cleared to the clear color. */
365 clearRow
= pwfb
->pbPixels
+
366 pwfb
->ScanWidth
* FLIP(y
) +
368 switch (bytesPerPixel
) {
371 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
372 GetGValue(pwc
->clearColorRef
),
373 GetBValue(pwc
->clearColorRef
));
374 memset(lpb
, bColor
, width
);
377 lpw
= (LPWORD
)clearRow
;
378 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
379 GetGValue(pwc
->clearColorRef
),
380 GetBValue(pwc
->clearColorRef
));
381 for (i
=0; i
<width
; i
++)
386 r
= GetRValue(pwc
->clearColorRef
);
387 g
= GetGValue(pwc
->clearColorRef
);
388 b
= GetBValue(pwc
->clearColorRef
);
389 for (i
=0; i
<width
; i
++) {
396 lpdw
= (LPDWORD
)clearRow
;
397 dwColor
= BGR32(GetRValue(pwc
->clearColorRef
),
398 GetGValue(pwc
->clearColorRef
),
399 GetBValue(pwc
->clearColorRef
));
400 for (i
=0; i
<width
; i
++)
407 /* copy cleared row to other rows in buffer */
408 lpb
= clearRow
- pwfb
->ScanWidth
;
409 rowSize
= width
* bytesPerPixel
;
410 for (i
=1; i
<height
; i
++) {
411 memcpy(lpb
, clearRow
, rowSize
);
412 lpb
-= pwfb
->ScanWidth
;
415 mask
&= ~BUFFER_BIT_BACK_LEFT
;
419 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
421 HPEN Old_Pen
= SelectObject(DC
, pwc
->clearPen
);
422 HBRUSH Old_Brush
= SelectObject(DC
, pwc
->clearBrush
);
427 FLIP(y
) - height
+ 1);
428 SelectObject(DC
, Old_Pen
);
429 SelectObject(DC
, Old_Brush
);
430 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
433 /* Call swrast if there is anything left to clear (like DEPTH) */
435 _swrast_Clear(ctx
, mask
);
441 /**********************************************************************/
442 /***** PIXEL Functions *****/
443 /**********************************************************************/
445 #define FLIP(Y) (rb->Height - (Y) - 1)
449 ** Front Buffer reading/writing
450 ** These are slow, but work with all non-indexed visual types.
453 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
454 static void write_rgba_span_front(const GLcontext
*ctx
,
455 struct gl_renderbuffer
*rb
,
456 GLuint n
, GLint x
, GLint y
,
457 const GLubyte rgba
[][4],
458 const GLubyte mask
[] )
460 WMesaContext pwc
= wmesa_context(ctx
);
468 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
473 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
479 /* Write a horizontal span of RGB color pixels with a boolean mask. */
480 static void write_rgb_span_front(const GLcontext
*ctx
,
481 struct gl_renderbuffer
*rb
,
482 GLuint n
, GLint x
, GLint y
,
483 const GLubyte rgb
[][3],
484 const GLubyte mask
[] )
486 WMesaContext pwc
= wmesa_context(ctx
);
494 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
499 SetPixel(pwc
->hDC
, x
+i
, y
, RGB(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
506 * Write a horizontal span of pixels with a boolean mask. The current color
507 * is used for all pixels.
509 static void write_mono_rgba_span_front(const GLcontext
*ctx
,
510 struct gl_renderbuffer
*rb
,
511 GLuint n
, GLint x
, GLint y
,
512 const GLchan color
[4],
513 const GLubyte mask
[])
516 WMesaContext pwc
= wmesa_context(ctx
);
520 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
525 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
529 SetPixel(pwc
->hDC
, x
+i
, y
, colorref
);
533 /* Write an array of RGBA pixels with a boolean mask. */
534 static void write_rgba_pixels_front(const GLcontext
*ctx
,
535 struct gl_renderbuffer
*rb
,
537 const GLint x
[], const GLint y
[],
538 const GLubyte rgba
[][4],
539 const GLubyte mask
[] )
542 WMesaContext pwc
= wmesa_context(ctx
);
546 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]),
547 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
554 * Write an array of pixels with a boolean mask. The current color
555 * is used for all pixels.
557 static void write_mono_rgba_pixels_front(const GLcontext
*ctx
,
558 struct gl_renderbuffer
*rb
,
560 const GLint x
[], const GLint y
[],
561 const GLchan color
[4],
562 const GLubyte mask
[] )
565 WMesaContext pwc
= wmesa_context(ctx
);
568 colorref
= RGB(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
571 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]), colorref
);
574 /* Read a horizontal span of color pixels. */
575 static void read_rgba_span_front(const GLcontext
*ctx
,
576 struct gl_renderbuffer
*rb
,
577 GLuint n
, GLint x
, GLint y
,
580 WMesaContext pwc
= wmesa_context(ctx
);
584 for (i
=0; i
<n
; i
++) {
585 Color
= GetPixel(pwc
->hDC
, x
+i
, y
);
586 rgba
[i
][RCOMP
] = GetRValue(Color
);
587 rgba
[i
][GCOMP
] = GetGValue(Color
);
588 rgba
[i
][BCOMP
] = GetBValue(Color
);
589 rgba
[i
][ACOMP
] = 255;
594 /* Read an array of color pixels. */
595 static void read_rgba_pixels_front(const GLcontext
*ctx
,
596 struct gl_renderbuffer
*rb
,
597 GLuint n
, const GLint x
[], const GLint y
[],
600 WMesaContext pwc
= wmesa_context(ctx
);
603 for (i
=0; i
<n
; i
++) {
604 GLint y2
= FLIP(y
[i
]);
605 Color
= GetPixel(pwc
->hDC
, x
[i
], y2
);
606 rgba
[i
][RCOMP
] = GetRValue(Color
);
607 rgba
[i
][GCOMP
] = GetGValue(Color
);
608 rgba
[i
][BCOMP
] = GetBValue(Color
);
609 rgba
[i
][ACOMP
] = 255;
613 /*********************************************************************/
615 /* DOUBLE BUFFER 32-bit */
617 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
618 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
619 *lpdw = BGR32((r),(g),(b)); }
623 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
624 static void write_rgba_span_32(const GLcontext
*ctx
,
625 struct gl_renderbuffer
*rb
,
626 GLuint n
, GLint x
, GLint y
,
627 const GLubyte rgba
[][4],
628 const GLubyte mask
[] )
630 WMesaContext pwc
= wmesa_context(ctx
);
631 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
638 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
642 lpdw
[i
] = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
647 *lpdw
++ = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
653 /* Write a horizontal span of RGB color pixels with a boolean mask. */
654 static void write_rgb_span_32(const GLcontext
*ctx
,
655 struct gl_renderbuffer
*rb
,
656 GLuint n
, GLint x
, GLint y
,
657 const GLubyte rgb
[][3],
658 const GLubyte mask
[] )
660 WMesaContext pwc
= wmesa_context(ctx
);
661 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
668 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
672 lpdw
[i
] = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
677 *lpdw
++ = BGR32(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
683 * Write a horizontal span of pixels with a boolean mask. The current color
684 * is used for all pixels.
686 static void write_mono_rgba_span_32(const GLcontext
*ctx
,
687 struct gl_renderbuffer
*rb
,
688 GLuint n
, GLint x
, GLint y
,
689 const GLchan color
[4],
690 const GLubyte mask
[])
695 WMesaContext pwc
= wmesa_context(ctx
);
696 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
697 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
699 pixel
= BGR32(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
711 /* Write an array of RGBA pixels with a boolean mask. */
712 static void write_rgba_pixels_32(const GLcontext
*ctx
,
713 struct gl_renderbuffer
*rb
,
714 GLuint n
, const GLint x
[], const GLint y
[],
715 const GLubyte rgba
[][4],
716 const GLubyte mask
[])
719 WMesaContext pwc
= wmesa_context(ctx
);
720 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
723 WMSETPIXEL32(pwfb
, FLIP(y
[i
]), x
[i
],
724 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
728 * Write an array of pixels with a boolean mask. The current color
729 * is used for all pixels.
731 static void write_mono_rgba_pixels_32(const GLcontext
*ctx
,
732 struct gl_renderbuffer
*rb
,
734 const GLint x
[], const GLint y
[],
735 const GLchan color
[4],
736 const GLubyte mask
[])
739 WMesaContext pwc
= wmesa_context(ctx
);
740 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
743 WMSETPIXEL32(pwfb
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
744 color
[GCOMP
], color
[BCOMP
]);
747 /* Read a horizontal span of color pixels. */
748 static void read_rgba_span_32(const GLcontext
*ctx
,
749 struct gl_renderbuffer
*rb
,
750 GLuint n
, GLint x
, GLint y
,
756 WMesaContext pwc
= wmesa_context(ctx
);
757 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
760 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
761 for (i
=0; i
<n
; i
++) {
763 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
764 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
765 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
766 rgba
[i
][ACOMP
] = 255;
771 /* Read an array of color pixels. */
772 static void read_rgba_pixels_32(const GLcontext
*ctx
,
773 struct gl_renderbuffer
*rb
,
774 GLuint n
, const GLint x
[], const GLint y
[],
780 WMesaContext pwc
= wmesa_context(ctx
);
781 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
783 for (i
=0; i
<n
; i
++) {
784 GLint y2
= FLIP(y
[i
]);
785 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
787 rgba
[i
][RCOMP
] = (pixel
& 0x00ff0000) >> 16;
788 rgba
[i
][GCOMP
] = (pixel
& 0x0000ff00) >> 8;
789 rgba
[i
][BCOMP
] = (pixel
& 0x000000ff);
790 rgba
[i
][ACOMP
] = 255;
795 /*********************************************************************/
797 /* DOUBLE BUFFER 16-bit */
799 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
800 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
801 *lpw = BGR16((r),(g),(b)); }
805 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
806 static void write_rgba_span_16(const GLcontext
*ctx
,
807 struct gl_renderbuffer
*rb
,
808 GLuint n
, GLint x
, GLint y
,
809 const GLubyte rgba
[][4],
810 const GLubyte mask
[] )
812 WMesaContext pwc
= wmesa_context(ctx
);
813 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
820 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
824 lpw
[i
] = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
829 *lpw
++ = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
835 /* Write a horizontal span of RGB color pixels with a boolean mask. */
836 static void write_rgb_span_16(const GLcontext
*ctx
,
837 struct gl_renderbuffer
*rb
,
838 GLuint n
, GLint x
, GLint y
,
839 const GLubyte rgb
[][3],
840 const GLubyte mask
[] )
842 WMesaContext pwc
= wmesa_context(ctx
);
843 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
850 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
854 lpw
[i
] = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
859 *lpw
++ = BGR16(rgb
[i
][RCOMP
], rgb
[i
][GCOMP
],
865 * Write a horizontal span of pixels with a boolean mask. The current color
866 * is used for all pixels.
868 static void write_mono_rgba_span_16(const GLcontext
*ctx
,
869 struct gl_renderbuffer
*rb
,
870 GLuint n
, GLint x
, GLint y
,
871 const GLchan color
[4],
872 const GLubyte mask
[])
877 WMesaContext pwc
= wmesa_context(ctx
);
878 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
880 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
882 pixel
= BGR16(color
[RCOMP
], color
[GCOMP
], color
[BCOMP
]);
894 /* Write an array of RGBA pixels with a boolean mask. */
895 static void write_rgba_pixels_16(const GLcontext
*ctx
,
896 struct gl_renderbuffer
*rb
,
897 GLuint n
, const GLint x
[], const GLint y
[],
898 const GLubyte rgba
[][4],
899 const GLubyte mask
[])
902 WMesaContext pwc
= wmesa_context(ctx
);
903 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
907 WMSETPIXEL16(pwfb
, FLIP(y
[i
]), x
[i
],
908 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
912 * Write an array of pixels with a boolean mask. The current color
913 * is used for all pixels.
915 static void write_mono_rgba_pixels_16(const GLcontext
*ctx
,
916 struct gl_renderbuffer
*rb
,
918 const GLint x
[], const GLint y
[],
919 const GLchan color
[4],
920 const GLubyte mask
[])
923 WMesaContext pwc
= wmesa_context(ctx
);
924 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
928 WMSETPIXEL16(pwfb
, FLIP(y
[i
]),x
[i
],color
[RCOMP
],
929 color
[GCOMP
], color
[BCOMP
]);
932 /* Read a horizontal span of color pixels. */
933 static void read_rgba_span_16(const GLcontext
*ctx
,
934 struct gl_renderbuffer
*rb
,
935 GLuint n
, GLint x
, GLint y
,
940 WMesaContext pwc
= wmesa_context(ctx
);
941 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
944 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
945 for (i
=0; i
<n
; i
++) {
947 /* Windows uses 5,5,5 for 16-bit */
948 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
949 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
950 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
951 rgba
[i
][ACOMP
] = 255;
956 /* Read an array of color pixels. */
957 static void read_rgba_pixels_16(const GLcontext
*ctx
,
958 struct gl_renderbuffer
*rb
,
959 GLuint n
, const GLint x
[], const GLint y
[],
964 WMesaContext pwc
= wmesa_context(ctx
);
965 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
967 for (i
=0; i
<n
; i
++) {
968 GLint y2
= FLIP(y
[i
]);
969 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
971 /* Windows uses 5,5,5 for 16-bit */
972 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
973 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
974 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
975 rgba
[i
][ACOMP
] = 255;
982 /**********************************************************************/
983 /***** BUFFER Functions *****/
984 /**********************************************************************/
990 wmesa_delete_renderbuffer(struct gl_renderbuffer
*rb
)
997 * This is called by Mesa whenever it determines that the window size
998 * has changed. Do whatever's needed to cope with that.
1001 wmesa_renderbuffer_storage(GLcontext
*ctx
,
1002 struct gl_renderbuffer
*rb
,
1003 GLenum internalFormat
,
1008 rb
->Height
= height
;
1014 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1015 * on if we're drawing to the front or back color buffer.
1017 void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer
*rb
, int pixelformat
,
1020 if (double_buffer
) {
1022 /* Picking the correct span functions is important because
1023 * the DIB was allocated with the indicated depth. */
1024 switch(pixelformat
) {
1026 rb
->PutRow
= write_rgba_span_16
;
1027 rb
->PutRowRGB
= write_rgb_span_16
;
1028 rb
->PutMonoRow
= write_mono_rgba_span_16
;
1029 rb
->PutValues
= write_rgba_pixels_16
;
1030 rb
->PutMonoValues
= write_mono_rgba_pixels_16
;
1031 rb
->GetRow
= read_rgba_span_16
;
1032 rb
->GetValues
= read_rgba_pixels_16
;
1038 rb
->PutRow
= write_rgba_span_32
;
1039 rb
->PutRowRGB
= write_rgb_span_32
;
1040 rb
->PutMonoRow
= write_mono_rgba_span_32
;
1041 rb
->PutValues
= write_rgba_pixels_32
;
1042 rb
->PutMonoValues
= write_mono_rgba_pixels_32
;
1043 rb
->GetRow
= read_rgba_span_32
;
1044 rb
->GetValues
= read_rgba_pixels_32
;
1054 /* front buffer (actual Windows window) */
1055 rb
->PutRow
= write_rgba_span_front
;
1056 rb
->PutRowRGB
= write_rgb_span_front
;
1057 rb
->PutMonoRow
= write_mono_rgba_span_front
;
1058 rb
->PutValues
= write_rgba_pixels_front
;
1059 rb
->PutMonoValues
= write_mono_rgba_pixels_front
;
1060 rb
->GetRow
= read_rgba_span_front
;
1061 rb
->GetValues
= read_rgba_pixels_front
;
1062 rb
->RedBits
= 8; /* XXX fix these (565?) */
1069 * Called by ctx->Driver.ResizeBuffers()
1070 * Resize the front/back colorbuffers to match the latest window size.
1073 wmesa_resize_buffers(GLcontext
*ctx
, GLframebuffer
*buffer
,
1074 GLuint width
, GLuint height
)
1076 WMesaContext pwc
= wmesa_context(ctx
);
1077 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
1079 if (pwfb
->Base
.Width
!= width
|| pwfb
->Base
.Height
!= height
) {
1080 /* Realloc back buffer */
1081 if (ctx
->Visual
.doubleBufferMode
== 1) {
1082 wmDeleteBackingStore(pwfb
);
1083 wmCreateBackingStore(pwfb
, width
, height
);
1086 _mesa_resize_framebuffer(ctx
, buffer
, width
, height
);
1091 * Called by glViewport.
1092 * This is a good time for us to poll the current window size and adjust
1093 * our renderbuffers to match the current window size.
1094 * Remember, we have no opportunity to respond to conventional
1095 * resize events since the driver has no event loop.
1097 * MakeCurrent also ends up making a call here, so that ensures
1098 * we get the viewport set correctly, even if the app does not call
1099 * glViewport and relies on the defaults.
1101 static void wmesa_viewport(GLcontext
*ctx
,
1103 GLsizei width
, GLsizei height
)
1105 WMesaContext pwc
= wmesa_context(ctx
);
1106 GLuint new_width
, new_height
;
1108 wmesa_get_buffer_size(ctx
->WinSysDrawBuffer
, &new_width
, &new_height
);
1111 * Resize buffers if the window size changed.
1113 wmesa_resize_buffers(ctx
, ctx
->WinSysDrawBuffer
, new_width
, new_height
);
1114 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
1121 * Called when the driver should update it's state, based on the new_state
1124 static void wmesa_update_state(GLcontext
*ctx
, GLuint new_state
)
1126 _swrast_InvalidateState(ctx
, new_state
);
1127 _swsetup_InvalidateState(ctx
, new_state
);
1128 _vbo_InvalidateState(ctx
, new_state
);
1129 _tnl_InvalidateState(ctx
, new_state
);
1131 /* TODO - This code is not complete yet because I
1132 * don't know what to do for all state updates.
1135 if (new_state
& _NEW_BUFFERS
) {
1143 /**********************************************************************/
1144 /***** WMESA Functions *****/
1145 /**********************************************************************/
1147 WMesaContext
WMesaCreateContext(HDC hDC
,
1151 GLboolean alpha_flag
)
1154 struct dd_function_table functions
;
1155 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1161 /* Indexed mode not supported */
1165 /* Allocate wmesa context */
1166 c
= CALLOC_STRUCT(wmesa_context
);
1171 /* I do not understand this contributed code */
1172 /* Support memory and device contexts */
1173 if(WindowFromDC(hDC
) != NULL
) {
1174 c
->hDC
= GetDC(WindowFromDC(hDC
)); // huh ????
1183 /* Get data for visual */
1184 /* Dealing with this is actually a bit of overkill because Mesa will end
1185 * up treating all color component size requests less than 8 by using
1186 * a single byte per channel. In addition, the interface to the span
1187 * routines passes colors as an entire byte per channel anyway, so there
1188 * is nothing to be saved by telling the visual to be 16 bits if the device
1189 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
1191 * But we go through the motions here anyway.
1193 switch (GetDeviceCaps(c
->hDC
, BITSPIXEL
)) {
1195 red_bits
= green_bits
= blue_bits
= 5;
1199 red_bits
= green_bits
= blue_bits
= 8;
1203 /* Create visual based on flags */
1204 visual
= _mesa_create_visual(rgb_flag
,
1205 db_flag
, /* db_flag */
1206 GL_FALSE
, /* stereo */
1207 red_bits
, green_bits
, blue_bits
, /* color RGB */
1208 alpha_flag
? alpha_bits
: 0, /* color A */
1210 DEFAULT_SOFTWARE_DEPTH_BITS
, /* depth_bits */
1211 8, /* stencil_bits */
1212 16,16,16, /* accum RGB */
1213 alpha_flag
? 16 : 0, /* accum A */
1214 1); /* num samples */
1221 /* Set up driver functions */
1222 _mesa_init_driver_functions(&functions
);
1223 functions
.GetString
= wmesa_get_string
;
1224 functions
.UpdateState
= wmesa_update_state
;
1225 functions
.GetBufferSize
= wmesa_get_buffer_size
;
1226 functions
.Flush
= wmesa_flush
;
1227 functions
.Clear
= clear
;
1228 functions
.ClearIndex
= clear_index
;
1229 functions
.ClearColor
= clear_color
;
1230 functions
.ResizeBuffers
= wmesa_resize_buffers
;
1231 functions
.Viewport
= wmesa_viewport
;
1233 /* initialize the Mesa context data */
1235 _mesa_initialize_context(ctx
, visual
, NULL
, &functions
, (void *)c
);
1237 _mesa_enable_sw_extensions(ctx
);
1238 _mesa_enable_1_3_extensions(ctx
);
1239 _mesa_enable_1_4_extensions(ctx
);
1240 _mesa_enable_1_5_extensions(ctx
);
1241 _mesa_enable_2_0_extensions(ctx
);
1243 /* Initialize the software rasterizer and helper modules. */
1244 if (!_swrast_CreateContext(ctx
) ||
1245 !_vbo_CreateContext(ctx
) ||
1246 !_tnl_CreateContext(ctx
) ||
1247 !_swsetup_CreateContext(ctx
)) {
1248 _mesa_free_context_data(ctx
);
1252 _swsetup_Wakeup(ctx
);
1253 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
1259 void WMesaDestroyContext( WMesaContext pwc
)
1261 GLcontext
*ctx
= &pwc
->gl_ctx
;
1262 WMesaFramebuffer pwfb
;
1263 GET_CURRENT_CONTEXT(cur_ctx
);
1265 if (cur_ctx
== ctx
) {
1266 /* unbind current if deleting current context */
1267 WMesaMakeCurrent(NULL
, NULL
);
1270 /* clean up frame buffer resources */
1271 pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
1273 if (ctx
->Visual
.doubleBufferMode
== 1)
1274 wmDeleteBackingStore(pwfb
);
1275 wmesa_free_framebuffer(pwc
->hDC
);
1278 /* Release for device, not memory contexts */
1279 if (WindowFromDC(pwc
->hDC
) != NULL
)
1281 ReleaseDC(WindowFromDC(pwc
->hDC
), pwc
->hDC
);
1283 DeleteObject(pwc
->clearPen
);
1284 DeleteObject(pwc
->clearBrush
);
1286 _swsetup_DestroyContext(ctx
);
1287 _tnl_DestroyContext(ctx
);
1288 _vbo_DestroyContext(ctx
);
1289 _swrast_DestroyContext(ctx
);
1291 _mesa_free_context_data(ctx
);
1297 * Create a new color renderbuffer.
1299 struct gl_renderbuffer
*
1300 wmesa_new_renderbuffer(void)
1302 struct gl_renderbuffer
*rb
= CALLOC_STRUCT(gl_renderbuffer
);
1306 _mesa_init_renderbuffer(rb
, (GLuint
)0);
1308 rb
->_BaseFormat
= GL_RGBA
;
1309 rb
->InternalFormat
= GL_RGBA
;
1310 rb
->DataType
= CHAN_TYPE
;
1311 rb
->Delete
= wmesa_delete_renderbuffer
;
1312 rb
->AllocStorage
= wmesa_renderbuffer_storage
;
1317 void WMesaMakeCurrent(WMesaContext c
, HDC hdc
)
1319 WMesaFramebuffer pwfb
;
1322 /* return if already current */
1323 GET_CURRENT_CONTEXT(ctx
);
1324 WMesaContext pwc
= wmesa_context(ctx
);
1325 if (pwc
&& c
== pwc
&& pwc
->hDC
== hdc
)
1329 pwfb
= wmesa_lookup_framebuffer(hdc
);
1331 /* Lazy creation of framebuffers */
1332 if (c
&& !pwfb
&& hdc
) {
1333 struct gl_renderbuffer
*rb
;
1334 GLvisual
*visual
= &c
->gl_ctx
.Visual
;
1335 GLuint width
, height
;
1337 get_window_size(hdc
, &width
, &height
);
1339 c
->clearPen
= CreatePen(PS_SOLID
, 1, 0);
1340 c
->clearBrush
= CreateSolidBrush(0);
1342 pwfb
= wmesa_new_framebuffer(hdc
, visual
);
1344 /* Create back buffer if double buffered */
1345 if (visual
->doubleBufferMode
== 1) {
1346 wmCreateBackingStore(pwfb
, width
, height
);
1349 /* make render buffers */
1350 if (visual
->doubleBufferMode
== 1) {
1351 rb
= wmesa_new_renderbuffer();
1352 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_BACK_LEFT
, rb
);
1353 wmesa_set_renderbuffer_funcs(rb
, pwfb
->pixelformat
, 1);
1355 rb
= wmesa_new_renderbuffer();
1356 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_FRONT_LEFT
, rb
);
1357 wmesa_set_renderbuffer_funcs(rb
, pwfb
->pixelformat
, 0);
1359 /* Let Mesa own the Depth, Stencil, and Accum buffers */
1360 _mesa_add_soft_renderbuffers(&pwfb
->Base
,
1361 GL_FALSE
, /* color */
1362 visual
->depthBits
> 0,
1363 visual
->stencilBits
> 0,
1364 visual
->accumRedBits
> 0,
1365 visual
->alphaBits
>0,
1370 _mesa_make_current(&c
->gl_ctx
, &pwfb
->Base
, &pwfb
->Base
);
1372 _mesa_make_current(NULL
, NULL
, NULL
);
1376 void WMesaSwapBuffers( HDC hdc
)
1378 GET_CURRENT_CONTEXT(ctx
);
1379 WMesaContext pwc
= wmesa_context(ctx
);
1380 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(hdc
);
1383 _mesa_problem(NULL
, "wmesa: swapbuffers on unknown hdc");
1387 /* If we're swapping the buffer associated with the current context
1388 * we have to flush any pending rendering commands first.
1390 if (pwc
->hDC
== hdc
) {
1391 _mesa_notifySwapBuffers(ctx
);
1393 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
1394 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
1397 /* XXX for now only allow swapping current window */
1398 _mesa_problem(NULL
, "wmesa: can't swap non-current window");
1402 /* This is hopefully a temporary hack to define some needed dispatch
1403 * table entries. Hopefully, I'll find a better solution. The
1404 * dispatch table generation scripts ought to be making these dummy
1406 void gl_dispatch_stub_543(void){};
1407 void gl_dispatch_stub_544(void){};
1408 void gl_dispatch_stub_545(void){};
1409 void gl_dispatch_stub_546(void){};
1410 void gl_dispatch_stub_547(void){};
1411 void gl_dispatch_stub_548(void){};
1412 void gl_dispatch_stub_549(void){};
1413 void gl_dispatch_stub_550(void){};
1414 void gl_dispatch_stub_551(void){};
1415 void gl_dispatch_stub_552(void){};
1416 void gl_dispatch_stub_553(void){};
1417 void gl_dispatch_stub_554(void){};
1418 void gl_dispatch_stub_555(void){};
1419 void gl_dispatch_stub_556(void){};
1420 void gl_dispatch_stub_557(void){};
1421 void gl_dispatch_stub_558(void){};
1422 void gl_dispatch_stub_559(void){};
1423 void gl_dispatch_stub_560(void){};
1424 void gl_dispatch_stub_561(void){};
1425 void gl_dispatch_stub_565(void){};
1426 void gl_dispatch_stub_566(void){};
1427 void gl_dispatch_stub_577(void){};
1428 void gl_dispatch_stub_578(void){};
1429 void gl_dispatch_stub_603(void){};
1430 void gl_dispatch_stub_645(void){};
1431 void gl_dispatch_stub_646(void){};
1432 void gl_dispatch_stub_647(void){};
1433 void gl_dispatch_stub_648(void){};
1434 void gl_dispatch_stub_649(void){};
1435 void gl_dispatch_stub_650(void){};
1436 void gl_dispatch_stub_651(void){};
1437 void gl_dispatch_stub_652(void){};
1438 void gl_dispatch_stub_653(void){};
1439 void gl_dispatch_stub_734(void){};
1440 void gl_dispatch_stub_735(void){};
1441 void gl_dispatch_stub_736(void){};
1442 void gl_dispatch_stub_737(void){};
1443 void gl_dispatch_stub_738(void){};
1444 void gl_dispatch_stub_745(void){};
1445 void gl_dispatch_stub_746(void){};
1446 void gl_dispatch_stub_760(void){};
1447 void gl_dispatch_stub_761(void){};
1448 void gl_dispatch_stub_766(void){};
1449 void gl_dispatch_stub_767(void){};
1450 void gl_dispatch_stub_768(void){};