2 * Windows (Win32/Win64) device driver for Mesa
10 #include "main/context.h"
11 #include "main/extensions.h"
12 #include "main/framebuffer.h"
13 #include "main/renderbuffer.h"
14 #include "main/macros.h"
15 #include "drivers/common/driverfuncs.h"
16 #include "drivers/common/meta.h"
18 #include "swrast/swrast.h"
19 #include "swrast/s_renderbuffer.h"
20 #include "swrast_setup/swrast_setup.h"
22 #include "tnl/t_context.h"
23 #include "tnl/t_pipeline.h"
26 /* linked list of our Framebuffers (windows) */
27 static WMesaFramebuffer FirstFramebuffer
= NULL
;
31 * Create a new WMesaFramebuffer object which will correspond to the
32 * given HDC (Window handle).
34 static WMesaFramebuffer
35 wmesa_new_framebuffer(HDC hdc
, struct gl_config
*visual
)
38 = malloc(sizeof(struct wmesa_framebuffer
));
40 _mesa_initialize_window_framebuffer(&pwfb
->Base
, visual
);
42 /* insert at head of list */
43 pwfb
->next
= FirstFramebuffer
;
44 FirstFramebuffer
= pwfb
;
50 * Given an hdc, free the corresponding WMesaFramebuffer
53 wmesa_free_framebuffer(HDC hdc
)
55 WMesaFramebuffer pwfb
, prev
;
56 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
62 struct gl_framebuffer
*fb
;
63 if (pwfb
== FirstFramebuffer
)
64 FirstFramebuffer
= pwfb
->next
;
66 prev
->next
= pwfb
->next
;
68 _mesa_reference_framebuffer(&fb
, NULL
);
73 * Given an hdc, return the corresponding WMesaFramebuffer
75 static WMesaFramebuffer
76 wmesa_lookup_framebuffer(HDC hdc
)
78 WMesaFramebuffer pwfb
;
79 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
88 * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
90 static WMesaFramebuffer
wmesa_framebuffer(struct gl_framebuffer
*fb
)
92 return (WMesaFramebuffer
) fb
;
97 * Given a struct gl_context, return the corresponding WMesaContext.
99 static WMesaContext
wmesa_context(const struct gl_context
*ctx
)
101 return (WMesaContext
) ctx
;
106 * Every driver should implement a GetString function in order to
107 * return a meaningful GL_RENDERER string.
109 static const GLubyte
*wmesa_get_string(struct gl_context
*ctx
, GLenum name
)
111 return (name
== GL_RENDERER
) ?
112 (GLubyte
*) "Mesa Windows GDI Driver" : NULL
;
117 * Determine the pixel format based on the pixel size.
119 static void wmSetPixelFormat(WMesaFramebuffer pwfb
, HDC hDC
)
121 pwfb
->cColorBits
= GetDeviceCaps(hDC
, BITSPIXEL
);
123 /* Only 16 and 32 bit targets are supported now */
124 assert(pwfb
->cColorBits
== 0 ||
125 pwfb
->cColorBits
== 16 ||
126 pwfb
->cColorBits
== 24 ||
127 pwfb
->cColorBits
== 32);
129 switch(pwfb
->cColorBits
){
131 pwfb
->pixelformat
= PF_INDEX8
;
134 pwfb
->pixelformat
= PF_5R6G5B
;
138 pwfb
->pixelformat
= PF_8R8G8B
;
141 pwfb
->pixelformat
= PF_BADFORMAT
;
147 * Create DIB for back buffer.
148 * We write into this memory with the span routines and then blit it
149 * to the window on a buffer swap.
151 static BOOL
wmCreateBackingStore(WMesaFramebuffer pwfb
, long lxSize
, long lySize
)
153 LPBITMAPINFO pbmi
= &(pwfb
->bmi
);
156 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
157 pbmi
->bmiHeader
.biWidth
= lxSize
;
158 pbmi
->bmiHeader
.biHeight
= -lySize
;
159 pbmi
->bmiHeader
.biPlanes
= 1;
160 pbmi
->bmiHeader
.biBitCount
= GetDeviceCaps(pwfb
->hDC
, BITSPIXEL
);
161 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
162 pbmi
->bmiHeader
.biSizeImage
= 0;
163 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
164 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
165 pbmi
->bmiHeader
.biClrUsed
= 0;
166 pbmi
->bmiHeader
.biClrImportant
= 0;
168 pwfb
->cColorBits
= pbmi
->bmiHeader
.biBitCount
;
169 pwfb
->ScanWidth
= (lxSize
* (pwfb
->cColorBits
/ 8) + 3) & ~3;
171 hic
= CreateIC("display", NULL
, NULL
, NULL
);
172 pwfb
->dib_hDC
= CreateCompatibleDC(hic
);
174 pwfb
->hbmDIB
= CreateDIBSection(hic
,
177 (void **)&(pwfb
->pbPixels
),
180 pwfb
->hOldBitmap
= SelectObject(pwfb
->dib_hDC
, pwfb
->hbmDIB
);
184 wmSetPixelFormat(pwfb
, pwfb
->hDC
);
189 static void wmDeleteBackingStore(WMesaFramebuffer pwfb
)
192 SelectObject(pwfb
->dib_hDC
, pwfb
->hOldBitmap
);
193 DeleteDC(pwfb
->dib_hDC
);
194 DeleteObject(pwfb
->hbmDIB
);
200 * Find the width and height of the window named by hdc.
203 get_window_size(HDC hdc
, GLuint
*width
, GLuint
*height
)
205 if (WindowFromDC(hdc
)) {
207 GetClientRect(WindowFromDC(hdc
), &rect
);
208 *width
= rect
.right
- rect
.left
;
209 *height
= rect
.bottom
- rect
.top
;
211 else { /* Memory context */
212 /* From contributed code - use the size of the desktop
213 * for the size of a memory context (?) */
214 *width
= GetDeviceCaps(hdc
, HORZRES
);
215 *height
= GetDeviceCaps(hdc
, VERTRES
);
221 wmesa_get_buffer_size(struct gl_framebuffer
*buffer
, GLuint
*width
, GLuint
*height
)
223 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
224 get_window_size(pwfb
->hDC
, width
, height
);
228 static void wmesa_flush(struct gl_context
*ctx
)
230 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->WinSysDrawBuffer
);
232 if (ctx
->Visual
.doubleBufferMode
== 1) {
233 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
234 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
237 /* Do nothing for single buffer */
242 /**********************************************************************/
243 /***** CLEAR Functions *****/
244 /**********************************************************************/
247 * Clear the color/depth/stencil buffers.
249 static void clear(struct gl_context
*ctx
, GLbitfield mask
)
251 #define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
252 const GLint x
= ctx
->DrawBuffer
->_Xmin
;
253 const GLint y
= ctx
->DrawBuffer
->_Ymin
;
254 const GLint height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
255 const GLint width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
257 WMesaContext pwc
= wmesa_context(ctx
);
258 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
261 /* Let swrast do all the work if the masks are not set to
262 * clear all channels. */
263 if (!ctx
->Color
.ColorMask
[0][0] ||
264 !ctx
->Color
.ColorMask
[0][1] ||
265 !ctx
->Color
.ColorMask
[0][2] ||
266 !ctx
->Color
.ColorMask
[0][3]) {
267 _swrast_Clear(ctx
, mask
);
271 if (mask
& BUFFER_BITS_COLOR
) {
272 /* setup the clearing color */
273 const union gl_color_union color
= ctx
->Color
.ClearColor
;
275 UNCLAMPED_FLOAT_TO_UBYTE(col
[0], color
.f
[0]);
276 UNCLAMPED_FLOAT_TO_UBYTE(col
[1], color
.f
[1]);
277 UNCLAMPED_FLOAT_TO_UBYTE(col
[2], color
.f
[2]);
278 pwc
->clearColorRef
= RGB(col
[0], col
[1], col
[2]);
279 DeleteObject(pwc
->clearPen
);
280 DeleteObject(pwc
->clearBrush
);
281 pwc
->clearPen
= CreatePen(PS_SOLID
, 1, pwc
->clearColorRef
);
282 pwc
->clearBrush
= CreateSolidBrush(pwc
->clearColorRef
);
286 if (mask
& BUFFER_BIT_BACK_LEFT
) {
289 UINT bytesPerPixel
= pwfb
->cColorBits
/ 8;
290 LPBYTE lpb
, clearRow
;
298 /* Try for a fast clear - clearing entire buffer with a single
300 if (width
== ctx
->DrawBuffer
->Width
&&
301 height
== ctx
->DrawBuffer
->Height
) { /* entire buffer */
302 /* Now check for an easy clear value */
303 switch (bytesPerPixel
) {
305 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
306 GetGValue(pwc
->clearColorRef
),
307 GetBValue(pwc
->clearColorRef
));
308 memset(pwfb
->pbPixels
, bColor
,
309 pwfb
->ScanWidth
* height
);
313 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
314 GetGValue(pwc
->clearColorRef
),
315 GetBValue(pwc
->clearColorRef
));
316 if (((wColor
>> 8) & 0xff) == (wColor
& 0xff)) {
317 memset(pwfb
->pbPixels
, wColor
& 0xff,
318 pwfb
->ScanWidth
* height
);
325 if (GetRValue(pwc
->clearColorRef
) ==
326 GetGValue(pwc
->clearColorRef
) &&
327 GetRValue(pwc
->clearColorRef
) ==
328 GetBValue(pwc
->clearColorRef
)) {
329 memset(pwfb
->pbPixels
,
330 GetRValue(pwc
->clearColorRef
),
331 pwfb
->ScanWidth
* height
);
341 /* Need to clear a row at a time. Begin by setting the first
342 * row in the area to be cleared to the clear color. */
344 clearRow
= pwfb
->pbPixels
+
345 pwfb
->ScanWidth
* FLIP(y
) +
347 switch (bytesPerPixel
) {
350 bColor
= BGR8(GetRValue(pwc
->clearColorRef
),
351 GetGValue(pwc
->clearColorRef
),
352 GetBValue(pwc
->clearColorRef
));
353 memset(lpb
, bColor
, width
);
356 lpw
= (LPWORD
)clearRow
;
357 wColor
= BGR16(GetRValue(pwc
->clearColorRef
),
358 GetGValue(pwc
->clearColorRef
),
359 GetBValue(pwc
->clearColorRef
));
360 for (i
=0; i
<width
; i
++)
365 r
= GetRValue(pwc
->clearColorRef
);
366 g
= GetGValue(pwc
->clearColorRef
);
367 b
= GetBValue(pwc
->clearColorRef
);
368 for (i
=0; i
<width
; i
++) {
375 lpdw
= (LPDWORD
)clearRow
;
376 dwColor
= BGR32(GetRValue(pwc
->clearColorRef
),
377 GetGValue(pwc
->clearColorRef
),
378 GetBValue(pwc
->clearColorRef
));
379 for (i
=0; i
<width
; i
++)
386 /* copy cleared row to other rows in buffer */
387 lpb
= clearRow
- pwfb
->ScanWidth
;
388 rowSize
= width
* bytesPerPixel
;
389 for (i
=1; i
<height
; i
++) {
390 memcpy(lpb
, clearRow
, rowSize
);
391 lpb
-= pwfb
->ScanWidth
;
394 mask
&= ~BUFFER_BIT_BACK_LEFT
;
398 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
400 HPEN Old_Pen
= SelectObject(DC
, pwc
->clearPen
);
401 HBRUSH Old_Brush
= SelectObject(DC
, pwc
->clearBrush
);
406 FLIP(y
) - height
+ 1);
407 SelectObject(DC
, Old_Pen
);
408 SelectObject(DC
, Old_Brush
);
409 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
412 /* Call swrast if there is anything left to clear (like DEPTH) */
414 _swrast_Clear(ctx
, mask
);
420 /**********************************************************************/
421 /***** PIXEL Functions *****/
422 /**********************************************************************/
424 #define FLIP(Y) (rb->Height - (Y) - 1)
428 ** Front Buffer reading/writing
429 ** These are slow, but work with all non-indexed visual types.
432 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
433 static void write_rgba_span_front(struct gl_context
*ctx
,
434 struct gl_renderbuffer
*rb
,
435 GLuint n
, GLint x
, GLint y
,
439 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
440 WMesaContext pwc
= wmesa_context(ctx
);
441 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
448 unsigned b
:8, g
:8, r
:8, a
:8;
454 if (n
< 16) { // the value 16 is just guessed
459 SetPixel(pwc
->hDC
, x
+i
, y
,
460 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]));
464 SetPixel(pwc
->hDC
, x
+i
, y
,
465 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]));
470 _mesa_problem(NULL
, "wmesa: write_rgba_span_front on unknown hdc");
473 bgra
=malloc(n
*sizeof(BGRA
));
475 _mesa_problem(NULL
, "wmesa: write_rgba_span_front: out of memory");
480 for (i
=0; i
<n
; i
++) {
493 for (i
=0; i
<n
; i
++) {
501 bmp
=CreateBitmap(n
, 1, 1, 32, bgra
);
502 mdc
=CreateCompatibleDC(pwfb
->hDC
);
503 SelectObject(mdc
, bmp
);
505 BitBlt(pwfb
->hDC
, x
, y
, n
, 1, mdc
, 0, 0, SRCCOPY
);
506 SelectObject(mdc
, 0);
514 /* Write an array of RGBA pixels with a boolean mask. */
515 static void write_rgba_pixels_front(struct gl_context
*ctx
,
516 struct gl_renderbuffer
*rb
,
518 const GLint x
[], const GLint y
[],
522 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
524 WMesaContext pwc
= wmesa_context(ctx
);
528 SetPixel(pwc
->hDC
, x
[i
], FLIP(y
[i
]),
529 RGB(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
535 /* Read a horizontal span of color pixels. */
536 static void read_rgba_span_front(struct gl_context
*ctx
,
537 struct gl_renderbuffer
*rb
,
538 GLuint n
, GLint x
, GLint y
,
541 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
542 WMesaContext pwc
= wmesa_context(ctx
);
546 for (i
=0; i
<n
; i
++) {
547 Color
= GetPixel(pwc
->hDC
, x
+i
, y
);
548 rgba
[i
][RCOMP
] = GetRValue(Color
);
549 rgba
[i
][GCOMP
] = GetGValue(Color
);
550 rgba
[i
][BCOMP
] = GetBValue(Color
);
551 rgba
[i
][ACOMP
] = 255;
556 /* Read an array of color pixels. */
557 static void read_rgba_pixels_front(struct gl_context
*ctx
,
558 struct gl_renderbuffer
*rb
,
559 GLuint n
, const GLint x
[], const GLint y
[],
562 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
563 WMesaContext pwc
= wmesa_context(ctx
);
566 for (i
=0; i
<n
; i
++) {
567 GLint y2
= FLIP(y
[i
]);
568 Color
= GetPixel(pwc
->hDC
, x
[i
], y2
);
569 rgba
[i
][RCOMP
] = GetRValue(Color
);
570 rgba
[i
][GCOMP
] = GetGValue(Color
);
571 rgba
[i
][BCOMP
] = GetBValue(Color
);
572 rgba
[i
][ACOMP
] = 255;
576 /*********************************************************************/
578 /* DOUBLE BUFFER 32-bit */
580 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
581 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
582 *lpdw = BGR32((r),(g),(b)); }
586 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
587 static void write_rgba_span_32(struct gl_context
*ctx
,
588 struct gl_renderbuffer
*rb
,
589 GLuint n
, GLint x
, GLint y
,
593 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
594 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
601 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
605 lpdw
[i
] = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
610 *lpdw
++ = BGR32(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
616 /* Write an array of RGBA pixels with a boolean mask. */
617 static void write_rgba_pixels_32(struct gl_context
*ctx
,
618 struct gl_renderbuffer
*rb
,
619 GLuint n
, const GLint x
[], const GLint y
[],
623 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
625 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
628 WMSETPIXEL32(pwfb
, FLIP(y
[i
]), x
[i
],
629 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
633 /* Read a horizontal span of color pixels. */
634 static void read_rgba_span_32(struct gl_context
*ctx
,
635 struct gl_renderbuffer
*rb
,
636 GLuint n
, GLint x
, GLint y
,
639 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
643 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
646 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
647 for (i
=0; i
<n
; i
++) {
649 rgba
[i
][RCOMP
] = (GLubyte
)((pixel
& 0x00ff0000) >> 16);
650 rgba
[i
][GCOMP
] = (GLubyte
)((pixel
& 0x0000ff00) >> 8);
651 rgba
[i
][BCOMP
] = (GLubyte
)(pixel
& 0x000000ff);
652 rgba
[i
][ACOMP
] = 255;
657 /* Read an array of color pixels. */
658 static void read_rgba_pixels_32(struct gl_context
*ctx
,
659 struct gl_renderbuffer
*rb
,
660 GLuint n
, const GLint x
[], const GLint y
[],
663 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
667 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
669 for (i
=0; i
<n
; i
++) {
670 GLint y2
= FLIP(y
[i
]);
671 lpdw
= ((LPDWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
673 rgba
[i
][RCOMP
] = (GLubyte
)((pixel
& 0x00ff0000) >> 16);
674 rgba
[i
][GCOMP
] = (GLubyte
)((pixel
& 0x0000ff00) >> 8);
675 rgba
[i
][BCOMP
] = (GLubyte
)(pixel
& 0x000000ff);
676 rgba
[i
][ACOMP
] = 255;
681 /*********************************************************************/
683 /* DOUBLE BUFFER 24-bit */
685 #define WMSETPIXEL24(pwc, y, x, r, g, b) { \
686 LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
691 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
692 static void write_rgba_span_24(struct gl_context
*ctx
,
693 struct gl_renderbuffer
*rb
,
694 GLuint n
, GLint x
, GLint y
,
698 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
699 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
706 lpb
= ((LPBYTE
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + (3 * x
);
710 lpb
[3*i
] = rgba
[i
][BCOMP
];
711 lpb
[3*i
+1] = rgba
[i
][GCOMP
];
712 lpb
[3*i
+2] = rgba
[i
][RCOMP
];
716 for (i
=0; i
<n
; i
++) {
717 *lpb
++ = rgba
[i
][BCOMP
];
718 *lpb
++ = rgba
[i
][GCOMP
];
719 *lpb
++ = rgba
[i
][RCOMP
];
725 /* Write an array of RGBA pixels with a boolean mask. */
726 static void write_rgba_pixels_24(struct gl_context
*ctx
,
727 struct gl_renderbuffer
*rb
,
728 GLuint n
, const GLint x
[], const GLint y
[],
732 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
734 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
737 WMSETPIXEL24(pwfb
, FLIP(y
[i
]), x
[i
],
738 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
742 /* Read a horizontal span of color pixels. */
743 static void read_rgba_span_24(struct gl_context
*ctx
,
744 struct gl_renderbuffer
*rb
,
745 GLuint n
, GLint x
, GLint y
,
748 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
751 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
754 lpb
= ((LPBYTE
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + (3 * x
);
755 for (i
=0; i
<n
; i
++) {
756 rgba
[i
][RCOMP
] = lpb
[3*i
+2];
757 rgba
[i
][GCOMP
] = lpb
[3*i
+1];
758 rgba
[i
][BCOMP
] = lpb
[3*i
];
759 rgba
[i
][ACOMP
] = 255;
764 /* Read an array of color pixels. */
765 static void read_rgba_pixels_24(struct gl_context
*ctx
,
766 struct gl_renderbuffer
*rb
,
767 GLuint n
, const GLint x
[], const GLint y
[],
770 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
773 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
775 for (i
=0; i
<n
; i
++) {
776 GLint y2
= FLIP(y
[i
]);
777 lpb
= ((LPBYTE
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + (3 * x
[i
]);
778 rgba
[i
][RCOMP
] = lpb
[3*i
+2];
779 rgba
[i
][GCOMP
] = lpb
[3*i
+1];
780 rgba
[i
][BCOMP
] = lpb
[3*i
];
781 rgba
[i
][ACOMP
] = 255;
786 /*********************************************************************/
788 /* DOUBLE BUFFER 16-bit */
790 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
791 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
792 *lpw = BGR16((r),(g),(b)); }
796 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
797 static void write_rgba_span_16(struct gl_context
*ctx
,
798 struct gl_renderbuffer
*rb
,
799 GLuint n
, GLint x
, GLint y
,
803 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
804 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
811 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
815 lpw
[i
] = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
820 *lpw
++ = BGR16(rgba
[i
][RCOMP
], rgba
[i
][GCOMP
],
827 /* Write an array of RGBA pixels with a boolean mask. */
828 static void write_rgba_pixels_16(struct gl_context
*ctx
,
829 struct gl_renderbuffer
*rb
,
830 GLuint n
, const GLint x
[], const GLint y
[],
834 const GLubyte (*rgba
)[4] = (const GLubyte (*)[4])values
;
836 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
840 WMSETPIXEL16(pwfb
, FLIP(y
[i
]), x
[i
],
841 rgba
[i
][RCOMP
], rgba
[i
][GCOMP
], rgba
[i
][BCOMP
]);
845 /* Read a horizontal span of color pixels. */
846 static void read_rgba_span_16(struct gl_context
*ctx
,
847 struct gl_renderbuffer
*rb
,
848 GLuint n
, GLint x
, GLint y
,
851 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
854 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
857 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y
)) + x
;
858 for (i
=0; i
<n
; i
++) {
860 /* Windows uses 5,5,5 for 16-bit */
861 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
862 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
863 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
864 rgba
[i
][ACOMP
] = 255;
869 /* Read an array of color pixels. */
870 static void read_rgba_pixels_16(struct gl_context
*ctx
,
871 struct gl_renderbuffer
*rb
,
872 GLuint n
, const GLint x
[], const GLint y
[],
875 GLubyte (*rgba
)[4] = (GLubyte (*)[4])values
;
878 WMesaFramebuffer pwfb
= wmesa_framebuffer(ctx
->DrawBuffer
);
880 for (i
=0; i
<n
; i
++) {
881 GLint y2
= FLIP(y
[i
]);
882 lpw
= ((LPWORD
)(pwfb
->pbPixels
+ pwfb
->ScanWidth
* y2
)) + x
[i
];
884 /* Windows uses 5,5,5 for 16-bit */
885 rgba
[i
][RCOMP
] = (pixel
& 0x7c00) >> 7;
886 rgba
[i
][GCOMP
] = (pixel
& 0x03e0) >> 2;
887 rgba
[i
][BCOMP
] = (pixel
& 0x001f) << 3;
888 rgba
[i
][ACOMP
] = 255;
895 /**********************************************************************/
896 /***** BUFFER Functions *****/
897 /**********************************************************************/
903 wmesa_delete_renderbuffer(struct gl_renderbuffer
*rb
)
910 * This is called by Mesa whenever it determines that the window size
911 * has changed. Do whatever's needed to cope with that.
914 wmesa_renderbuffer_storage(struct gl_context
*ctx
,
915 struct gl_renderbuffer
*rb
,
916 GLenum internalFormat
,
927 * Called by ctx->Driver.ResizeBuffers()
928 * Resize the front/back colorbuffers to match the latest window size.
931 wmesa_resize_buffers(struct gl_context
*ctx
, struct gl_framebuffer
*buffer
,
932 GLuint width
, GLuint height
)
934 WMesaFramebuffer pwfb
= wmesa_framebuffer(buffer
);
936 if (pwfb
->Base
.Width
!= width
|| pwfb
->Base
.Height
!= height
) {
937 /* Realloc back buffer */
938 if (ctx
->Visual
.doubleBufferMode
== 1) {
939 wmDeleteBackingStore(pwfb
);
940 wmCreateBackingStore(pwfb
, width
, height
);
943 _mesa_resize_framebuffer(ctx
, buffer
, width
, height
);
948 * Called by glViewport.
949 * This is a good time for us to poll the current window size and adjust
950 * our renderbuffers to match the current window size.
951 * Remember, we have no opportunity to respond to conventional
952 * resize events since the driver has no event loop.
954 * MakeCurrent also ends up making a call here, so that ensures
955 * we get the viewport set correctly, even if the app does not call
956 * glViewport and relies on the defaults.
958 static void wmesa_viewport(struct gl_context
*ctx
,
960 GLsizei width
, GLsizei height
)
962 GLuint new_width
, new_height
;
964 wmesa_get_buffer_size(ctx
->WinSysDrawBuffer
, &new_width
, &new_height
);
967 * Resize buffers if the window size changed.
969 wmesa_resize_buffers(ctx
, ctx
->WinSysDrawBuffer
, new_width
, new_height
);
970 ctx
->NewState
|= _NEW_BUFFERS
; /* to update scissor / window bounds */
977 * Called when the driver should update it's state, based on the new_state
980 static void wmesa_update_state(struct gl_context
*ctx
, GLuint new_state
)
982 _swrast_InvalidateState(ctx
, new_state
);
983 _swsetup_InvalidateState(ctx
, new_state
);
984 _vbo_InvalidateState(ctx
, new_state
);
985 _tnl_InvalidateState(ctx
, new_state
);
987 /* TODO - This code is not complete yet because I
988 * don't know what to do for all state updates.
991 if (new_state
& _NEW_BUFFERS
) {
999 /**********************************************************************/
1000 /***** WMESA Functions *****/
1001 /**********************************************************************/
1003 WMesaContext
WMesaCreateContext(HDC hDC
,
1007 GLboolean alpha_flag
)
1010 struct dd_function_table functions
;
1011 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
1012 struct gl_context
*ctx
;
1013 struct gl_config
*visual
;
1017 /* Indexed mode not supported */
1021 /* Allocate wmesa context */
1022 c
= CALLOC_STRUCT(wmesa_context
);
1027 /* I do not understand this contributed code */
1028 /* Support memory and device contexts */
1029 if(WindowFromDC(hDC
) != NULL
) {
1030 c
->hDC
= GetDC(WindowFromDC(hDC
)); /* huh ???? */
1039 /* Get data for visual */
1040 /* Dealing with this is actually a bit of overkill because Mesa will end
1041 * up treating all color component size requests less than 8 by using
1042 * a single byte per channel. In addition, the interface to the span
1043 * routines passes colors as an entire byte per channel anyway, so there
1044 * is nothing to be saved by telling the visual to be 16 bits if the device
1045 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
1047 * But we go through the motions here anyway.
1049 switch (GetDeviceCaps(c
->hDC
, BITSPIXEL
)) {
1051 red_bits
= green_bits
= blue_bits
= 5;
1055 red_bits
= green_bits
= blue_bits
= 8;
1059 /* Create visual based on flags */
1060 visual
= _mesa_create_visual(db_flag
, /* db_flag */
1061 GL_FALSE
, /* stereo */
1062 red_bits
, green_bits
, blue_bits
, /* color RGB */
1063 alpha_flag
? alpha_bits
: 0, /* color A */
1064 DEFAULT_SOFTWARE_DEPTH_BITS
, /* depth_bits */
1065 8, /* stencil_bits */
1066 16,16,16, /* accum RGB */
1067 alpha_flag
? 16 : 0, /* accum A */
1068 1); /* num samples */
1075 /* Set up driver functions */
1076 _mesa_init_driver_functions(&functions
);
1077 functions
.GetString
= wmesa_get_string
;
1078 functions
.UpdateState
= wmesa_update_state
;
1079 functions
.GetBufferSize
= wmesa_get_buffer_size
;
1080 functions
.Flush
= wmesa_flush
;
1081 functions
.Clear
= clear
;
1082 functions
.ResizeBuffers
= wmesa_resize_buffers
;
1083 functions
.Viewport
= wmesa_viewport
;
1085 /* initialize the Mesa context data */
1087 _mesa_initialize_context(ctx
, API_OPENGL
, visual
,
1088 NULL
, &functions
, (void *)c
);
1090 /* visual no longer needed - it was copied by _mesa_initialize_context() */
1091 _mesa_destroy_visual(visual
);
1093 _mesa_enable_sw_extensions(ctx
);
1094 _mesa_enable_1_3_extensions(ctx
);
1095 _mesa_enable_1_4_extensions(ctx
);
1096 _mesa_enable_1_5_extensions(ctx
);
1097 _mesa_enable_2_0_extensions(ctx
);
1098 _mesa_enable_2_1_extensions(ctx
);
1100 _mesa_meta_init(ctx
);
1102 /* Initialize the software rasterizer and helper modules. */
1103 if (!_swrast_CreateContext(ctx
) ||
1104 !_vbo_CreateContext(ctx
) ||
1105 !_tnl_CreateContext(ctx
) ||
1106 !_swsetup_CreateContext(ctx
)) {
1107 _mesa_free_context_data(ctx
);
1111 _swsetup_Wakeup(ctx
);
1112 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
1118 void WMesaDestroyContext( WMesaContext pwc
)
1120 struct gl_context
*ctx
= &pwc
->gl_ctx
;
1121 WMesaFramebuffer pwfb
;
1122 GET_CURRENT_CONTEXT(cur_ctx
);
1124 if (cur_ctx
== ctx
) {
1125 /* unbind current if deleting current context */
1126 WMesaMakeCurrent(NULL
, NULL
);
1129 /* clean up frame buffer resources */
1130 pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
1132 if (ctx
->Visual
.doubleBufferMode
== 1)
1133 wmDeleteBackingStore(pwfb
);
1134 wmesa_free_framebuffer(pwc
->hDC
);
1137 /* Release for device, not memory contexts */
1138 if (WindowFromDC(pwc
->hDC
) != NULL
)
1140 ReleaseDC(WindowFromDC(pwc
->hDC
), pwc
->hDC
);
1142 DeleteObject(pwc
->clearPen
);
1143 DeleteObject(pwc
->clearBrush
);
1145 _mesa_meta_free(ctx
);
1147 _swsetup_DestroyContext(ctx
);
1148 _tnl_DestroyContext(ctx
);
1149 _vbo_DestroyContext(ctx
);
1150 _swrast_DestroyContext(ctx
);
1152 _mesa_free_context_data(ctx
);
1158 * Create a new color renderbuffer.
1160 static struct gl_renderbuffer
*
1161 wmesa_new_renderbuffer(void)
1163 struct gl_renderbuffer
*rb
= CALLOC_STRUCT(gl_renderbuffer
);
1167 _mesa_init_renderbuffer(rb
, (GLuint
)0);
1169 rb
->_BaseFormat
= GL_RGBA
;
1170 rb
->InternalFormat
= GL_RGBA
;
1171 rb
->Delete
= wmesa_delete_renderbuffer
;
1172 rb
->AllocStorage
= wmesa_renderbuffer_storage
;
1177 void WMesaMakeCurrent(WMesaContext c
, HDC hdc
)
1179 WMesaFramebuffer pwfb
;
1182 /* return if already current */
1183 GET_CURRENT_CONTEXT(ctx
);
1184 WMesaContext pwc
= wmesa_context(ctx
);
1185 if (pwc
&& c
== pwc
&& pwc
->hDC
== hdc
)
1189 pwfb
= wmesa_lookup_framebuffer(hdc
);
1191 /* Lazy creation of framebuffers */
1192 if (c
&& !pwfb
&& hdc
) {
1193 struct gl_renderbuffer
*rb
;
1194 struct gl_config
*visual
= &c
->gl_ctx
.Visual
;
1195 GLuint width
, height
;
1197 get_window_size(hdc
, &width
, &height
);
1199 c
->clearPen
= CreatePen(PS_SOLID
, 1, 0);
1200 c
->clearBrush
= CreateSolidBrush(0);
1202 pwfb
= wmesa_new_framebuffer(hdc
, visual
);
1204 /* Create back buffer if double buffered */
1205 if (visual
->doubleBufferMode
== 1) {
1206 wmCreateBackingStore(pwfb
, width
, height
);
1209 /* make render buffers */
1210 if (visual
->doubleBufferMode
== 1) {
1211 rb
= wmesa_new_renderbuffer();
1212 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_BACK_LEFT
, rb
);
1214 rb
= wmesa_new_renderbuffer();
1215 _mesa_add_renderbuffer(&pwfb
->Base
, BUFFER_FRONT_LEFT
, rb
);
1217 /* Let Mesa own the Depth, Stencil, and Accum buffers */
1218 _swrast_add_soft_renderbuffers(&pwfb
->Base
,
1219 GL_FALSE
, /* color */
1220 visual
->depthBits
> 0,
1221 visual
->stencilBits
> 0,
1222 visual
->accumRedBits
> 0,
1223 visual
->alphaBits
>0,
1228 _mesa_make_current(&c
->gl_ctx
, &pwfb
->Base
, &pwfb
->Base
);
1230 _mesa_make_current(NULL
, NULL
, NULL
);
1234 void WMesaSwapBuffers( HDC hdc
)
1236 GET_CURRENT_CONTEXT(ctx
);
1237 WMesaContext pwc
= wmesa_context(ctx
);
1238 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(hdc
);
1241 _mesa_problem(NULL
, "wmesa: swapbuffers on unknown hdc");
1245 /* If we're swapping the buffer associated with the current context
1246 * we have to flush any pending rendering commands first.
1248 if (pwc
->hDC
== hdc
) {
1249 _mesa_notifySwapBuffers(ctx
);
1251 BitBlt(pwfb
->hDC
, 0, 0, pwfb
->Base
.Width
, pwfb
->Base
.Height
,
1252 pwfb
->dib_hDC
, 0, 0, SRCCOPY
);
1255 /* XXX for now only allow swapping current window */
1256 _mesa_problem(NULL
, "wmesa: can't swap non-current window");
1260 void WMesaShareLists(WMesaContext ctx_to_share
, WMesaContext ctx
)
1262 _mesa_share_state(&ctx
->gl_ctx
, &ctx_to_share
->gl_ctx
);