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_setup/swrast_setup.h"
21 #include "tnl/t_context.h"
22 #include "tnl/t_pipeline.h"
25 /* linked list of our Framebuffers (windows) */
26 static WMesaFramebuffer FirstFramebuffer = NULL;
30 * Create a new WMesaFramebuffer object which will correspond to the
31 * given HDC (Window handle).
33 static WMesaFramebuffer
34 wmesa_new_framebuffer(HDC hdc, struct gl_config *visual)
37 = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer));
39 _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
41 /* insert at head of list */
42 pwfb->next = FirstFramebuffer;
43 FirstFramebuffer = pwfb;
49 * Given an hdc, free the corresponding WMesaFramebuffer
52 wmesa_free_framebuffer(HDC hdc)
54 WMesaFramebuffer pwfb, prev;
55 for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
61 struct gl_framebuffer *fb;
62 if (pwfb == FirstFramebuffer)
63 FirstFramebuffer = pwfb->next;
65 prev->next = pwfb->next;
67 _mesa_reference_framebuffer(&fb, NULL);
72 * Given an hdc, return the corresponding WMesaFramebuffer
74 static WMesaFramebuffer
75 wmesa_lookup_framebuffer(HDC hdc)
77 WMesaFramebuffer pwfb;
78 for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
87 * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
89 static WMesaFramebuffer wmesa_framebuffer(struct gl_framebuffer *fb)
91 return (WMesaFramebuffer) fb;
96 * Given a struct gl_context, return the corresponding WMesaContext.
98 static WMesaContext wmesa_context(const struct gl_context *ctx)
100 return (WMesaContext) ctx;
105 * Every driver should implement a GetString function in order to
106 * return a meaningful GL_RENDERER string.
108 static const GLubyte *wmesa_get_string(struct gl_context *ctx, GLenum name)
110 return (name == GL_RENDERER) ?
111 (GLubyte *) "Mesa Windows GDI Driver" : NULL;
116 * Determine the pixel format based on the pixel size.
118 static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
120 pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
122 /* Only 16 and 32 bit targets are supported now */
123 assert(pwfb->cColorBits == 0 ||
124 pwfb->cColorBits == 16 ||
125 pwfb->cColorBits == 24 ||
126 pwfb->cColorBits == 32);
128 switch(pwfb->cColorBits){
130 pwfb->pixelformat = PF_INDEX8;
133 pwfb->pixelformat = PF_5R6G5B;
137 pwfb->pixelformat = PF_8R8G8B;
140 pwfb->pixelformat = PF_BADFORMAT;
146 * Create DIB for back buffer.
147 * We write into this memory with the span routines and then blit it
148 * to the window on a buffer swap.
150 static BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
152 LPBITMAPINFO pbmi = &(pwfb->bmi);
155 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
156 pbmi->bmiHeader.biWidth = lxSize;
157 pbmi->bmiHeader.biHeight= -lySize;
158 pbmi->bmiHeader.biPlanes = 1;
159 pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
160 pbmi->bmiHeader.biCompression = BI_RGB;
161 pbmi->bmiHeader.biSizeImage = 0;
162 pbmi->bmiHeader.biXPelsPerMeter = 0;
163 pbmi->bmiHeader.biYPelsPerMeter = 0;
164 pbmi->bmiHeader.biClrUsed = 0;
165 pbmi->bmiHeader.biClrImportant = 0;
167 pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
168 pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
170 hic = CreateIC("display", NULL, NULL, NULL);
171 pwfb->dib_hDC = CreateCompatibleDC(hic);
173 pwfb->hbmDIB = CreateDIBSection(hic,
176 (void **)&(pwfb->pbPixels),
179 pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
183 wmSetPixelFormat(pwfb, pwfb->hDC);
188 static void wmDeleteBackingStore(WMesaFramebuffer pwfb)
191 SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
192 DeleteDC(pwfb->dib_hDC);
193 DeleteObject(pwfb->hbmDIB);
199 * Find the width and height of the window named by hdc.
202 get_window_size(HDC hdc, GLuint *width, GLuint *height)
204 if (WindowFromDC(hdc)) {
206 GetClientRect(WindowFromDC(hdc), &rect);
207 *width = rect.right - rect.left;
208 *height = rect.bottom - rect.top;
210 else { /* Memory context */
211 /* From contributed code - use the size of the desktop
212 * for the size of a memory context (?) */
213 *width = GetDeviceCaps(hdc, HORZRES);
214 *height = GetDeviceCaps(hdc, VERTRES);
220 wmesa_get_buffer_size(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
222 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
223 get_window_size(pwfb->hDC, width, height);
227 static void wmesa_flush(struct gl_context *ctx)
229 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
231 if (ctx->Visual.doubleBufferMode == 1) {
232 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
233 pwfb->dib_hDC, 0, 0, SRCCOPY);
236 /* Do nothing for single buffer */
241 /**********************************************************************/
242 /***** CLEAR Functions *****/
243 /**********************************************************************/
245 /* If we do not implement these, Mesa clears the buffers via the pixel
246 * span writing interface, which is very slow for a clear operation.
250 * Set the color used to clear the color buffer.
252 static void clear_color(struct gl_context *ctx, const GLfloat color[4])
254 WMesaContext pwc = wmesa_context(ctx);
257 CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
258 CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
259 CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
260 pwc->clearColorRef = RGB(col[0], col[1], col[2]);
261 DeleteObject(pwc->clearPen);
262 DeleteObject(pwc->clearBrush);
263 pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
264 pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
269 * Clear the specified region of the color buffer using the clear color
270 * or index as specified by one of the two functions above.
272 * This procedure clears either the front and/or the back COLOR buffers.
273 * Only the "left" buffer is cleared since we are not stereo.
274 * Clearing of the other non-color buffers is left to the swrast.
277 static void clear(struct gl_context *ctx, GLbitfield mask)
279 #define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1)
280 const GLint x = ctx->DrawBuffer->_Xmin;
281 const GLint y = ctx->DrawBuffer->_Ymin;
282 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
283 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
285 WMesaContext pwc = wmesa_context(ctx);
286 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
289 /* Let swrast do all the work if the masks are not set to
290 * clear all channels. */
291 if (!ctx->Color.ColorMask[0][0] ||
292 !ctx->Color.ColorMask[0][1] ||
293 !ctx->Color.ColorMask[0][2] ||
294 !ctx->Color.ColorMask[0][3]) {
295 _swrast_Clear(ctx, mask);
300 if (mask & BUFFER_BIT_BACK_LEFT) {
303 UINT bytesPerPixel = pwfb->cColorBits / 8;
304 LPBYTE lpb, clearRow;
312 /* Try for a fast clear - clearing entire buffer with a single
314 if (width == ctx->DrawBuffer->Width &&
315 height == ctx->DrawBuffer->Height) { /* entire buffer */
316 /* Now check for an easy clear value */
317 switch (bytesPerPixel) {
319 bColor = BGR8(GetRValue(pwc->clearColorRef),
320 GetGValue(pwc->clearColorRef),
321 GetBValue(pwc->clearColorRef));
322 memset(pwfb->pbPixels, bColor,
323 pwfb->ScanWidth * height);
327 wColor = BGR16(GetRValue(pwc->clearColorRef),
328 GetGValue(pwc->clearColorRef),
329 GetBValue(pwc->clearColorRef));
330 if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
331 memset(pwfb->pbPixels, wColor & 0xff,
332 pwfb->ScanWidth * height);
339 if (GetRValue(pwc->clearColorRef) ==
340 GetGValue(pwc->clearColorRef) &&
341 GetRValue(pwc->clearColorRef) ==
342 GetBValue(pwc->clearColorRef)) {
343 memset(pwfb->pbPixels,
344 GetRValue(pwc->clearColorRef),
345 pwfb->ScanWidth * height);
355 /* Need to clear a row at a time. Begin by setting the first
356 * row in the area to be cleared to the clear color. */
358 clearRow = pwfb->pbPixels +
359 pwfb->ScanWidth * FLIP(y) +
361 switch (bytesPerPixel) {
364 bColor = BGR8(GetRValue(pwc->clearColorRef),
365 GetGValue(pwc->clearColorRef),
366 GetBValue(pwc->clearColorRef));
367 memset(lpb, bColor, width);
370 lpw = (LPWORD)clearRow;
371 wColor = BGR16(GetRValue(pwc->clearColorRef),
372 GetGValue(pwc->clearColorRef),
373 GetBValue(pwc->clearColorRef));
374 for (i=0; i<width; i++)
379 r = GetRValue(pwc->clearColorRef);
380 g = GetGValue(pwc->clearColorRef);
381 b = GetBValue(pwc->clearColorRef);
382 for (i=0; i<width; i++) {
389 lpdw = (LPDWORD)clearRow;
390 dwColor = BGR32(GetRValue(pwc->clearColorRef),
391 GetGValue(pwc->clearColorRef),
392 GetBValue(pwc->clearColorRef));
393 for (i=0; i<width; i++)
400 /* copy cleared row to other rows in buffer */
401 lpb = clearRow - pwfb->ScanWidth;
402 rowSize = width * bytesPerPixel;
403 for (i=1; i<height; i++) {
404 memcpy(lpb, clearRow, rowSize);
405 lpb -= pwfb->ScanWidth;
408 mask &= ~BUFFER_BIT_BACK_LEFT;
412 if (mask & BUFFER_BIT_FRONT_LEFT) {
414 HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
415 HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
420 FLIP(y) - height + 1);
421 SelectObject(DC, Old_Pen);
422 SelectObject(DC, Old_Brush);
423 mask &= ~BUFFER_BIT_FRONT_LEFT;
426 /* Call swrast if there is anything left to clear (like DEPTH) */
428 _swrast_Clear(ctx, mask);
434 /**********************************************************************/
435 /***** PIXEL Functions *****/
436 /**********************************************************************/
438 #define FLIP(Y) (rb->Height - (Y) - 1)
442 ** Front Buffer reading/writing
443 ** These are slow, but work with all non-indexed visual types.
446 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
447 static void write_rgba_span_front(struct gl_context *ctx,
448 struct gl_renderbuffer *rb,
449 GLuint n, GLint x, GLint y,
453 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
454 WMesaContext pwc = wmesa_context(ctx);
455 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC);
462 unsigned b:8, g:8, r:8, a:8;
468 if (n < 16) { // the value 16 is just guessed
473 SetPixel(pwc->hDC, x+i, y,
474 RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
478 SetPixel(pwc->hDC, x+i, y,
479 RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
484 _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc");
487 bgra=malloc(n*sizeof(BGRA));
489 _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory");
494 for (i=0; i<n; i++) {
507 for (i=0; i<n; i++) {
515 bmp=CreateBitmap(n, 1, 1, 32, bgra);
516 mdc=CreateCompatibleDC(pwfb->hDC);
517 SelectObject(mdc, bmp);
519 BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY);
520 SelectObject(mdc, 0);
527 /* Write a horizontal span of RGB color pixels with a boolean mask. */
528 static void write_rgb_span_front(struct gl_context *ctx,
529 struct gl_renderbuffer *rb,
530 GLuint n, GLint x, GLint y,
534 const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values;
535 WMesaContext pwc = wmesa_context(ctx);
543 SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
548 SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
555 * Write a horizontal span of pixels with a boolean mask. The current color
556 * is used for all pixels.
558 static void write_mono_rgba_span_front(struct gl_context *ctx,
559 struct gl_renderbuffer *rb,
560 GLuint n, GLint x, GLint y,
564 const GLchan *color = (const GLchan *)value;
566 WMesaContext pwc = wmesa_context(ctx);
570 colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
575 SetPixel(pwc->hDC, x+i, y, colorref);
579 SetPixel(pwc->hDC, x+i, y, colorref);
583 /* Write an array of RGBA pixels with a boolean mask. */
584 static void write_rgba_pixels_front(struct gl_context *ctx,
585 struct gl_renderbuffer *rb,
587 const GLint x[], const GLint y[],
591 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
593 WMesaContext pwc = wmesa_context(ctx);
597 SetPixel(pwc->hDC, x[i], FLIP(y[i]),
598 RGB(rgba[i][RCOMP], rgba[i][GCOMP],
605 * Write an array of pixels with a boolean mask. The current color
606 * is used for all pixels.
608 static void write_mono_rgba_pixels_front(struct gl_context *ctx,
609 struct gl_renderbuffer *rb,
611 const GLint x[], const GLint y[],
615 const GLchan *color = (const GLchan *)value;
617 WMesaContext pwc = wmesa_context(ctx);
620 colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
623 SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
626 /* Read a horizontal span of color pixels. */
627 static void read_rgba_span_front(struct gl_context *ctx,
628 struct gl_renderbuffer *rb,
629 GLuint n, GLint x, GLint y,
632 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
633 WMesaContext pwc = wmesa_context(ctx);
637 for (i=0; i<n; i++) {
638 Color = GetPixel(pwc->hDC, x+i, y);
639 rgba[i][RCOMP] = GetRValue(Color);
640 rgba[i][GCOMP] = GetGValue(Color);
641 rgba[i][BCOMP] = GetBValue(Color);
642 rgba[i][ACOMP] = 255;
647 /* Read an array of color pixels. */
648 static void read_rgba_pixels_front(struct gl_context *ctx,
649 struct gl_renderbuffer *rb,
650 GLuint n, const GLint x[], const GLint y[],
653 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
654 WMesaContext pwc = wmesa_context(ctx);
657 for (i=0; i<n; i++) {
658 GLint y2 = FLIP(y[i]);
659 Color = GetPixel(pwc->hDC, x[i], y2);
660 rgba[i][RCOMP] = GetRValue(Color);
661 rgba[i][GCOMP] = GetGValue(Color);
662 rgba[i][BCOMP] = GetBValue(Color);
663 rgba[i][ACOMP] = 255;
667 /*********************************************************************/
669 /* DOUBLE BUFFER 32-bit */
671 #define WMSETPIXEL32(pwc, y, x, r, g, b) { \
672 LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
673 *lpdw = BGR32((r),(g),(b)); }
677 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
678 static void write_rgba_span_32(struct gl_context *ctx,
679 struct gl_renderbuffer *rb,
680 GLuint n, GLint x, GLint y,
684 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
685 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
692 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
696 lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
701 *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
707 /* Write a horizontal span of RGB color pixels with a boolean mask. */
708 static void write_rgb_span_32(struct gl_context *ctx,
709 struct gl_renderbuffer *rb,
710 GLuint n, GLint x, GLint y,
714 const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values;
715 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
722 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
726 lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
731 *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
737 * Write a horizontal span of pixels with a boolean mask. The current color
738 * is used for all pixels.
740 static void write_mono_rgba_span_32(struct gl_context *ctx,
741 struct gl_renderbuffer *rb,
742 GLuint n, GLint x, GLint y,
746 const GLchan *color = (const GLchan *)value;
750 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
751 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
753 pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
765 /* Write an array of RGBA pixels with a boolean mask. */
766 static void write_rgba_pixels_32(struct gl_context *ctx,
767 struct gl_renderbuffer *rb,
768 GLuint n, const GLint x[], const GLint y[],
772 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
774 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
777 WMSETPIXEL32(pwfb, FLIP(y[i]), x[i],
778 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
782 * Write an array of pixels with a boolean mask. The current color
783 * is used for all pixels.
785 static void write_mono_rgba_pixels_32(struct gl_context *ctx,
786 struct gl_renderbuffer *rb,
788 const GLint x[], const GLint y[],
792 const GLchan *color = (const GLchan *)value;
794 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
797 WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP],
798 color[GCOMP], color[BCOMP]);
801 /* Read a horizontal span of color pixels. */
802 static void read_rgba_span_32(struct gl_context *ctx,
803 struct gl_renderbuffer *rb,
804 GLuint n, GLint x, GLint y,
807 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
811 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
814 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
815 for (i=0; i<n; i++) {
817 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
818 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
819 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
820 rgba[i][ACOMP] = 255;
825 /* Read an array of color pixels. */
826 static void read_rgba_pixels_32(struct gl_context *ctx,
827 struct gl_renderbuffer *rb,
828 GLuint n, const GLint x[], const GLint y[],
831 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
835 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
837 for (i=0; i<n; i++) {
838 GLint y2 = FLIP(y[i]);
839 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
841 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16);
842 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8);
843 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff);
844 rgba[i][ACOMP] = 255;
849 /*********************************************************************/
851 /* DOUBLE BUFFER 24-bit */
853 #define WMSETPIXEL24(pwc, y, x, r, g, b) { \
854 LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \
859 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
860 static void write_rgba_span_24(struct gl_context *ctx,
861 struct gl_renderbuffer *rb,
862 GLuint n, GLint x, GLint y,
866 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
867 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
874 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
878 lpb[3*i] = rgba[i][BCOMP];
879 lpb[3*i+1] = rgba[i][GCOMP];
880 lpb[3*i+2] = rgba[i][RCOMP];
884 for (i=0; i<n; i++) {
885 *lpb++ = rgba[i][BCOMP];
886 *lpb++ = rgba[i][GCOMP];
887 *lpb++ = rgba[i][RCOMP];
893 /* Write a horizontal span of RGB color pixels with a boolean mask. */
894 static void write_rgb_span_24(struct gl_context *ctx,
895 struct gl_renderbuffer *rb,
896 GLuint n, GLint x, GLint y,
900 const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values;
901 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
908 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
912 lpb[3*i] = rgb[i][BCOMP];
913 lpb[3*i+1] = rgb[i][GCOMP];
914 lpb[3*i+2] = rgb[i][RCOMP];
918 for (i=0; i<n; i++) {
919 *lpb++ = rgb[i][BCOMP];
920 *lpb++ = rgb[i][GCOMP];
921 *lpb++ = rgb[i][RCOMP];
927 * Write a horizontal span of pixels with a boolean mask. The current color
928 * is used for all pixels.
930 static void write_mono_rgba_span_24(struct gl_context *ctx,
931 struct gl_renderbuffer *rb,
932 GLuint n, GLint x, GLint y,
936 const GLchan *color = (const GLchan *)value;
939 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
940 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
945 lpb[3*i] = color[BCOMP];
946 lpb[3*i+1] = color[GCOMP];
947 lpb[3*i+2] = color[RCOMP];
951 for (i=0; i<n; i++) {
952 *lpb++ = color[BCOMP];
953 *lpb++ = color[GCOMP];
954 *lpb++ = color[RCOMP];
958 /* Write an array of RGBA pixels with a boolean mask. */
959 static void write_rgba_pixels_24(struct gl_context *ctx,
960 struct gl_renderbuffer *rb,
961 GLuint n, const GLint x[], const GLint y[],
965 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
967 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
970 WMSETPIXEL24(pwfb, FLIP(y[i]), x[i],
971 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
975 * Write an array of pixels with a boolean mask. The current color
976 * is used for all pixels.
978 static void write_mono_rgba_pixels_24(struct gl_context *ctx,
979 struct gl_renderbuffer *rb,
981 const GLint x[], const GLint y[],
985 const GLchan *color = (const GLchan *)value;
987 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
990 WMSETPIXEL24(pwfb, FLIP(y[i]),x[i],color[RCOMP],
991 color[GCOMP], color[BCOMP]);
994 /* Read a horizontal span of color pixels. */
995 static void read_rgba_span_24(struct gl_context *ctx,
996 struct gl_renderbuffer *rb,
997 GLuint n, GLint x, GLint y,
1000 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
1003 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1006 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x);
1007 for (i=0; i<n; i++) {
1008 rgba[i][RCOMP] = lpb[3*i+2];
1009 rgba[i][GCOMP] = lpb[3*i+1];
1010 rgba[i][BCOMP] = lpb[3*i];
1011 rgba[i][ACOMP] = 255;
1016 /* Read an array of color pixels. */
1017 static void read_rgba_pixels_24(struct gl_context *ctx,
1018 struct gl_renderbuffer *rb,
1019 GLuint n, const GLint x[], const GLint y[],
1022 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
1025 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1027 for (i=0; i<n; i++) {
1028 GLint y2 = FLIP(y[i]);
1029 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]);
1030 rgba[i][RCOMP] = lpb[3*i+2];
1031 rgba[i][GCOMP] = lpb[3*i+1];
1032 rgba[i][BCOMP] = lpb[3*i];
1033 rgba[i][ACOMP] = 255;
1038 /*********************************************************************/
1040 /* DOUBLE BUFFER 16-bit */
1042 #define WMSETPIXEL16(pwc, y, x, r, g, b) { \
1043 LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
1044 *lpw = BGR16((r),(g),(b)); }
1048 /* Write a horizontal span of RGBA color pixels with a boolean mask. */
1049 static void write_rgba_span_16(struct gl_context *ctx,
1050 struct gl_renderbuffer *rb,
1051 GLuint n, GLint x, GLint y,
1053 const GLubyte *mask)
1055 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
1056 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1063 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1067 lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
1072 *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
1078 /* Write a horizontal span of RGB color pixels with a boolean mask. */
1079 static void write_rgb_span_16(struct gl_context *ctx,
1080 struct gl_renderbuffer *rb,
1081 GLuint n, GLint x, GLint y,
1083 const GLubyte *mask)
1085 const GLubyte (*rgb)[3] = (const GLubyte (*)[3])values;
1086 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1093 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1097 lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
1102 *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
1108 * Write a horizontal span of pixels with a boolean mask. The current color
1109 * is used for all pixels.
1111 static void write_mono_rgba_span_16(struct gl_context *ctx,
1112 struct gl_renderbuffer *rb,
1113 GLuint n, GLint x, GLint y,
1115 const GLubyte *mask)
1117 const GLchan *color = (const GLchan *)value;
1121 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1123 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1125 pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
1137 /* Write an array of RGBA pixels with a boolean mask. */
1138 static void write_rgba_pixels_16(struct gl_context *ctx,
1139 struct gl_renderbuffer *rb,
1140 GLuint n, const GLint x[], const GLint y[],
1142 const GLubyte *mask)
1144 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values;
1146 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1150 WMSETPIXEL16(pwfb, FLIP(y[i]), x[i],
1151 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1155 * Write an array of pixels with a boolean mask. The current color
1156 * is used for all pixels.
1158 static void write_mono_rgba_pixels_16(struct gl_context *ctx,
1159 struct gl_renderbuffer *rb,
1161 const GLint x[], const GLint y[],
1163 const GLubyte *mask)
1165 const GLchan *color = (const GLchan *)value;
1167 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1171 WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP],
1172 color[GCOMP], color[BCOMP]);
1175 /* Read a horizontal span of color pixels. */
1176 static void read_rgba_span_16(struct gl_context *ctx,
1177 struct gl_renderbuffer *rb,
1178 GLuint n, GLint x, GLint y,
1181 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
1184 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1187 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x;
1188 for (i=0; i<n; i++) {
1190 /* Windows uses 5,5,5 for 16-bit */
1191 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1192 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1193 rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1194 rgba[i][ACOMP] = 255;
1199 /* Read an array of color pixels. */
1200 static void read_rgba_pixels_16(struct gl_context *ctx,
1201 struct gl_renderbuffer *rb,
1202 GLuint n, const GLint x[], const GLint y[],
1205 GLubyte (*rgba)[4] = (GLubyte (*)[4])values;
1208 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
1210 for (i=0; i<n; i++) {
1211 GLint y2 = FLIP(y[i]);
1212 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
1214 /* Windows uses 5,5,5 for 16-bit */
1215 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
1216 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
1217 rgba[i][BCOMP] = (pixel & 0x001f) << 3;
1218 rgba[i][ACOMP] = 255;
1225 /**********************************************************************/
1226 /***** BUFFER Functions *****/
1227 /**********************************************************************/
1233 wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
1240 * This is called by Mesa whenever it determines that the window size
1241 * has changed. Do whatever's needed to cope with that.
1244 wmesa_renderbuffer_storage(struct gl_context *ctx,
1245 struct gl_renderbuffer *rb,
1246 GLenum internalFormat,
1251 rb->Height = height;
1257 * Plug in the Get/PutRow/Values functions for a renderbuffer depending
1258 * on if we're drawing to the front or back color buffer.
1261 wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
1262 int cColorBits, int double_buffer)
1264 if (double_buffer) {
1266 /* Picking the correct span functions is important because
1267 * the DIB was allocated with the indicated depth. */
1268 switch(pixelformat) {
1270 rb->PutRow = write_rgba_span_16;
1271 rb->PutRowRGB = write_rgb_span_16;
1272 rb->PutMonoRow = write_mono_rgba_span_16;
1273 rb->PutValues = write_rgba_pixels_16;
1274 rb->PutMonoValues = write_mono_rgba_pixels_16;
1275 rb->GetRow = read_rgba_span_16;
1276 rb->GetValues = read_rgba_pixels_16;
1279 if (cColorBits == 24)
1281 rb->PutRow = write_rgba_span_24;
1282 rb->PutRowRGB = write_rgb_span_24;
1283 rb->PutMonoRow = write_mono_rgba_span_24;
1284 rb->PutValues = write_rgba_pixels_24;
1285 rb->PutMonoValues = write_mono_rgba_pixels_24;
1286 rb->GetRow = read_rgba_span_24;
1287 rb->GetValues = read_rgba_pixels_24;
1291 rb->PutRow = write_rgba_span_32;
1292 rb->PutRowRGB = write_rgb_span_32;
1293 rb->PutMonoRow = write_mono_rgba_span_32;
1294 rb->PutValues = write_rgba_pixels_32;
1295 rb->PutMonoValues = write_mono_rgba_pixels_32;
1296 rb->GetRow = read_rgba_span_32;
1297 rb->GetValues = read_rgba_pixels_32;
1305 /* front buffer (actual Windows window) */
1306 rb->PutRow = write_rgba_span_front;
1307 rb->PutRowRGB = write_rgb_span_front;
1308 rb->PutMonoRow = write_mono_rgba_span_front;
1309 rb->PutValues = write_rgba_pixels_front;
1310 rb->PutMonoValues = write_mono_rgba_pixels_front;
1311 rb->GetRow = read_rgba_span_front;
1312 rb->GetValues = read_rgba_pixels_front;
1317 * Called by ctx->Driver.ResizeBuffers()
1318 * Resize the front/back colorbuffers to match the latest window size.
1321 wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
1322 GLuint width, GLuint height)
1324 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
1326 if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
1327 /* Realloc back buffer */
1328 if (ctx->Visual.doubleBufferMode == 1) {
1329 wmDeleteBackingStore(pwfb);
1330 wmCreateBackingStore(pwfb, width, height);
1333 _mesa_resize_framebuffer(ctx, buffer, width, height);
1338 * Called by glViewport.
1339 * This is a good time for us to poll the current window size and adjust
1340 * our renderbuffers to match the current window size.
1341 * Remember, we have no opportunity to respond to conventional
1342 * resize events since the driver has no event loop.
1344 * MakeCurrent also ends up making a call here, so that ensures
1345 * we get the viewport set correctly, even if the app does not call
1346 * glViewport and relies on the defaults.
1348 static void wmesa_viewport(struct gl_context *ctx,
1350 GLsizei width, GLsizei height)
1352 GLuint new_width, new_height;
1354 wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
1357 * Resize buffers if the window size changed.
1359 wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
1360 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
1367 * Called when the driver should update it's state, based on the new_state
1370 static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
1372 _swrast_InvalidateState(ctx, new_state);
1373 _swsetup_InvalidateState(ctx, new_state);
1374 _vbo_InvalidateState(ctx, new_state);
1375 _tnl_InvalidateState(ctx, new_state);
1377 /* TODO - This code is not complete yet because I
1378 * don't know what to do for all state updates.
1381 if (new_state & _NEW_BUFFERS) {
1389 /**********************************************************************/
1390 /***** WMESA Functions *****/
1391 /**********************************************************************/
1393 WMesaContext WMesaCreateContext(HDC hDC,
1397 GLboolean alpha_flag)
1400 struct dd_function_table functions;
1401 GLint red_bits, green_bits, blue_bits, alpha_bits;
1402 struct gl_context *ctx;
1403 struct gl_config *visual;
1407 /* Indexed mode not supported */
1411 /* Allocate wmesa context */
1412 c = CALLOC_STRUCT(wmesa_context);
1417 /* I do not understand this contributed code */
1418 /* Support memory and device contexts */
1419 if(WindowFromDC(hDC) != NULL) {
1420 c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
1429 /* Get data for visual */
1430 /* Dealing with this is actually a bit of overkill because Mesa will end
1431 * up treating all color component size requests less than 8 by using
1432 * a single byte per channel. In addition, the interface to the span
1433 * routines passes colors as an entire byte per channel anyway, so there
1434 * is nothing to be saved by telling the visual to be 16 bits if the device
1435 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
1437 * But we go through the motions here anyway.
1439 switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
1441 red_bits = green_bits = blue_bits = 5;
1445 red_bits = green_bits = blue_bits = 8;
1449 /* Create visual based on flags */
1450 visual = _mesa_create_visual(db_flag, /* db_flag */
1451 GL_FALSE, /* stereo */
1452 red_bits, green_bits, blue_bits, /* color RGB */
1453 alpha_flag ? alpha_bits : 0, /* color A */
1454 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
1455 8, /* stencil_bits */
1456 16,16,16, /* accum RGB */
1457 alpha_flag ? 16 : 0, /* accum A */
1458 1); /* num samples */
1465 /* Set up driver functions */
1466 _mesa_init_driver_functions(&functions);
1467 functions.GetString = wmesa_get_string;
1468 functions.UpdateState = wmesa_update_state;
1469 functions.GetBufferSize = wmesa_get_buffer_size;
1470 functions.Flush = wmesa_flush;
1471 functions.Clear = clear;
1472 functions.ClearColor = clear_color;
1473 functions.ResizeBuffers = wmesa_resize_buffers;
1474 functions.Viewport = wmesa_viewport;
1476 /* initialize the Mesa context data */
1478 _mesa_initialize_context(ctx, API_OPENGL, visual,
1479 NULL, &functions, (void *)c);
1481 /* visual no longer needed - it was copied by _mesa_initialize_context() */
1482 _mesa_destroy_visual(visual);
1484 _mesa_enable_sw_extensions(ctx);
1485 _mesa_enable_1_3_extensions(ctx);
1486 _mesa_enable_1_4_extensions(ctx);
1487 _mesa_enable_1_5_extensions(ctx);
1488 _mesa_enable_2_0_extensions(ctx);
1489 _mesa_enable_2_1_extensions(ctx);
1491 _mesa_meta_init(ctx);
1493 /* Initialize the software rasterizer and helper modules. */
1494 if (!_swrast_CreateContext(ctx) ||
1495 !_vbo_CreateContext(ctx) ||
1496 !_tnl_CreateContext(ctx) ||
1497 !_swsetup_CreateContext(ctx)) {
1498 _mesa_free_context_data(ctx);
1502 _swsetup_Wakeup(ctx);
1503 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1509 void WMesaDestroyContext( WMesaContext pwc )
1511 struct gl_context *ctx = &pwc->gl_ctx;
1512 WMesaFramebuffer pwfb;
1513 GET_CURRENT_CONTEXT(cur_ctx);
1515 if (cur_ctx == ctx) {
1516 /* unbind current if deleting current context */
1517 WMesaMakeCurrent(NULL, NULL);
1520 /* clean up frame buffer resources */
1521 pwfb = wmesa_lookup_framebuffer(pwc->hDC);
1523 if (ctx->Visual.doubleBufferMode == 1)
1524 wmDeleteBackingStore(pwfb);
1525 wmesa_free_framebuffer(pwc->hDC);
1528 /* Release for device, not memory contexts */
1529 if (WindowFromDC(pwc->hDC) != NULL)
1531 ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
1533 DeleteObject(pwc->clearPen);
1534 DeleteObject(pwc->clearBrush);
1536 _mesa_meta_free(ctx);
1538 _swsetup_DestroyContext(ctx);
1539 _tnl_DestroyContext(ctx);
1540 _vbo_DestroyContext(ctx);
1541 _swrast_DestroyContext(ctx);
1543 _mesa_free_context_data(ctx);
1549 * Create a new color renderbuffer.
1551 static struct gl_renderbuffer *
1552 wmesa_new_renderbuffer(void)
1554 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
1558 _mesa_init_renderbuffer(rb, (GLuint)0);
1560 rb->_BaseFormat = GL_RGBA;
1561 rb->InternalFormat = GL_RGBA;
1562 rb->DataType = CHAN_TYPE;
1563 rb->Delete = wmesa_delete_renderbuffer;
1564 rb->AllocStorage = wmesa_renderbuffer_storage;
1569 void WMesaMakeCurrent(WMesaContext c, HDC hdc)
1571 WMesaFramebuffer pwfb;
1574 /* return if already current */
1575 GET_CURRENT_CONTEXT(ctx);
1576 WMesaContext pwc = wmesa_context(ctx);
1577 if (pwc && c == pwc && pwc->hDC == hdc)
1581 pwfb = wmesa_lookup_framebuffer(hdc);
1583 /* Lazy creation of framebuffers */
1584 if (c && !pwfb && hdc) {
1585 struct gl_renderbuffer *rb;
1586 struct gl_config *visual = &c->gl_ctx.Visual;
1587 GLuint width, height;
1589 get_window_size(hdc, &width, &height);
1591 c->clearPen = CreatePen(PS_SOLID, 1, 0);
1592 c->clearBrush = CreateSolidBrush(0);
1594 pwfb = wmesa_new_framebuffer(hdc, visual);
1596 /* Create back buffer if double buffered */
1597 if (visual->doubleBufferMode == 1) {
1598 wmCreateBackingStore(pwfb, width, height);
1601 /* make render buffers */
1602 if (visual->doubleBufferMode == 1) {
1603 rb = wmesa_new_renderbuffer();
1604 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
1605 wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 1);
1607 rb = wmesa_new_renderbuffer();
1608 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
1609 wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, pwfb->cColorBits, 0);
1611 /* Let Mesa own the Depth, Stencil, and Accum buffers */
1612 _mesa_add_soft_renderbuffers(&pwfb->Base,
1613 GL_FALSE, /* color */
1614 visual->depthBits > 0,
1615 visual->stencilBits > 0,
1616 visual->accumRedBits > 0,
1617 visual->alphaBits >0,
1622 _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
1624 _mesa_make_current(NULL, NULL, NULL);
1628 void WMesaSwapBuffers( HDC hdc )
1630 GET_CURRENT_CONTEXT(ctx);
1631 WMesaContext pwc = wmesa_context(ctx);
1632 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
1635 _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
1639 /* If we're swapping the buffer associated with the current context
1640 * we have to flush any pending rendering commands first.
1642 if (pwc->hDC == hdc) {
1643 _mesa_notifySwapBuffers(ctx);
1645 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
1646 pwfb->dib_hDC, 0, 0, SRCCOPY);
1649 /* XXX for now only allow swapping current window */
1650 _mesa_problem(NULL, "wmesa: can't swap non-current window");
1654 void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
1656 _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);