wmesa.c revision 782291ab916dcb3f11fe8b7c934b1fd164c46020
1/*
2 * Windows (Win32/Win64) device driver for Mesa
3 *
4 */
5
6#include "wmesadef.h"
7#include "colors.h"
8#include <GL/wmesa.h>
9#include "extensions.h"
10#include "framebuffer.h"
11#include "renderbuffer.h"
12#include "drivers/common/driverfuncs.h"
13#include "array_cache/acache.h"
14#include "swrast/swrast.h"
15#include "swrast_setup/swrast_setup.h"
16#include "tnl/tnl.h"
17#include "tnl/t_context.h"
18#include "tnl/t_pipeline.h"
19
20#define FLIP(Y)  (Current->height-(Y)-1)
21
22/* Static Data */
23
24static PWMC Current = NULL;
25
26/*
27 * Every driver should implement a GetString function in order to
28 * return a meaningful GL_RENDERER string.
29 */
30static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
31{
32    return (name == GL_RENDERER) ?
33	(GLubyte *) "Mesa Windows GDI Driver" : NULL;
34}
35
36/*
37 * Determine the pixel format based on the pixel size.
38 */
39static void wmSetPixelFormat(PWMC pwc, HDC hDC)
40{
41    pwc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
42
43    // Only 16 and 32 bit targets are supported now
44    assert(pwc->cColorBits == 16 ||
45	   pwc->cColorBits == 32);
46
47    switch(pwc->cColorBits){
48    case 8:
49	pwc->pixelformat = PF_INDEX8;
50	break;
51    case 16:
52	pwc->pixelformat = PF_5R6G5B;
53	break;
54    case 32:
55	pwc->pixelformat = PF_8R8G8B;
56	break;
57    default:
58	pwc->pixelformat = PF_BADFORMAT;
59    }
60}
61
62/*
63 * Create DIB for back buffer.
64 * We write into this memory with the span routines and then blit it
65 * to the window on a buffer swap.
66 */
67
68BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
69{
70    HDC          hdc = pwc->hDC;
71    LPBITMAPINFO pbmi = &(pwc->bmi);
72    HDC          hic;
73
74    assert(pwc->db_flag == GL_TRUE);
75
76    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
77    pbmi->bmiHeader.biWidth = lxSize;
78    pbmi->bmiHeader.biHeight= -lySize;
79    pbmi->bmiHeader.biPlanes = 1;
80    pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
81    pbmi->bmiHeader.biCompression = BI_RGB;
82    pbmi->bmiHeader.biSizeImage = 0;
83    pbmi->bmiHeader.biXPelsPerMeter = 0;
84    pbmi->bmiHeader.biYPelsPerMeter = 0;
85    pbmi->bmiHeader.biClrUsed = 0;
86    pbmi->bmiHeader.biClrImportant = 0;
87
88    pwc->cColorBits = pbmi->bmiHeader.biBitCount;
89    pwc->ScanWidth = (lxSize * (pwc->cColorBits / 8) + 3) & ~3;
90
91    hic = CreateIC("display", NULL, NULL, NULL);
92    pwc->dib.hDC = CreateCompatibleDC(hic);
93
94    pwc->hbmDIB = CreateDIBSection(hic,
95				   &pwc->bmi,
96				   DIB_RGB_COLORS,
97				   (void **)&(pwc->pbPixels),
98				   0,
99				   0);
100    pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
101
102    DeleteDC(hic);
103
104    wmSetPixelFormat(pwc, pwc->hDC);
105    return TRUE;
106}
107
108static wmDeleteBackingStore(PWMC pwc)
109{
110    if (pwc->hbmDIB) {
111	SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
112	DeleteDC(pwc->dib.hDC);
113	DeleteObject(pwc->hbmDIB);
114    }
115}
116
117static void wmesa_get_buffer_size(GLframebuffer *buffer,
118				  GLuint *width,
119				  GLuint *height )
120{
121    *width = Current->width;
122    *height = Current->height;
123}
124
125
126static void wmesa_flush(GLcontext* ctx)
127{
128    if (Current->db_flag) {
129	BitBlt(Current->hDC, 0, 0, Current->width, Current->height,
130	       Current->dib.hDC, 0, 0, SRCCOPY);
131    }
132    else {
133	/* Do nothing for single buffer */
134    }
135}
136
137
138/**********************************************************************/
139/*****                   CLEAR Functions                          *****/
140/**********************************************************************/
141
142/* If we do not implement these, Mesa clears the buffers via the pixel
143 * span writing interface, which is very slow for a clear operation.
144 */
145
146/*
147 * Set the color index used to clear the color buffer.
148 */
149static void clear_index(GLcontext* ctx, GLuint index)
150{
151    /* Note that indexed mode is not supported yet */
152    Current->clearColorRef = RGB(0,0,0);
153}
154
155/*
156 * Set the color used to clear the color buffer.
157 */
158static void clear_color(GLcontext* ctx, const GLfloat color[4])
159{
160    GLubyte col[3];
161    UINT    bytesPerPixel = Current->cColorBits / 8;
162
163    CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
164    CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
165    CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
166    Current->clearColorRef = RGB(col[0], col[1], col[2]);
167    DeleteObject(Current->clearPen);
168    DeleteObject(Current->clearBrush);
169    Current->clearPen = CreatePen(PS_SOLID, 1, Current->clearColorRef);
170    Current->clearBrush = CreateSolidBrush(Current->clearColorRef);
171}
172
173
174/*
175 * Clear the specified region of the color buffer using the clear color
176 * or index as specified by one of the two functions above.
177 *
178 * This procedure clears either the front and/or the back COLOR buffers.
179 * Only the "left" buffer is cleared since we are not stereo.
180 * Clearing of the other non-color buffers is left to the swrast.
181 */
182
183static void clear(GLcontext* ctx,
184		  GLbitfield mask,
185		  GLboolean all,
186		  GLint x, GLint y,
187		  GLint width, GLint height)
188{
189    int done = 0;
190
191    /* Let swrast do all the work if the masks are not set to
192     * clear all channels. */
193    if (ctx->Color.ColorMask[0] != 0xff ||
194	ctx->Color.ColorMask[1] != 0xff ||
195	ctx->Color.ColorMask[2] != 0xff ||
196	ctx->Color.ColorMask[3] != 0xff) {
197	_swrast_Clear(ctx, mask, all, x, y, width, height);
198	return;
199    }
200
201    /* 'all' means clear the entire window */
202    if (all) {
203	x = y = 0;
204	width = Current->width;
205	height = Current->height;
206    }
207
208    /* Back buffer */
209    if (mask & BUFFER_BIT_BACK_LEFT) {
210
211	int     i, rowSize;
212	UINT    bytesPerPixel = Current->cColorBits / 8;
213	LPBYTE  lpb, clearRow;
214	LPWORD  lpw;
215	BYTE    bColor;
216	WORD    wColor;
217	BYTE    r, g, b;
218	DWORD   dwColor;
219	LPDWORD lpdw;
220
221	/* Try for a fast clear - clearing entire buffer with a single
222	 * byte value. */
223	if (all) { /* entire buffer */
224	    /* Now check for an easy clear value */
225	    switch (bytesPerPixel) {
226	    case 1:
227		bColor = BGR8(GetRValue(Current->clearColorRef),
228			      GetGValue(Current->clearColorRef),
229			      GetBValue(Current->clearColorRef));
230		memset(Current->pbPixels, bColor,
231		       Current->ScanWidth * height);
232		done = 1;
233		break;
234	    case 2:
235		wColor = BGR16(GetRValue(Current->clearColorRef),
236			       GetGValue(Current->clearColorRef),
237			       GetBValue(Current->clearColorRef));
238		if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
239		    memset(Current->pbPixels, wColor & 0xff,
240			   Current->ScanWidth * height);
241		    done = 1;
242		}
243		break;
244	    case 3:
245		/* fall through */
246	    case 4:
247		if (GetRValue(Current->clearColorRef) ==
248		    GetGValue(Current->clearColorRef) &&
249		    GetRValue(Current->clearColorRef) ==
250		    GetBValue(Current->clearColorRef)) {
251		    memset(Current->pbPixels,
252			   GetRValue(Current->clearColorRef),
253			   Current->ScanWidth * height);
254		    done = 1;
255		}
256		break;
257	    default:
258		break;
259	    }
260	} /* all */
261
262	if (!done) {
263	    /* Need to clear a row at a time.  Begin by setting the first
264	     * row in the area to be cleared to the clear color. */
265
266	    clearRow = Current->pbPixels +
267		Current->ScanWidth * FLIP(y) +
268		bytesPerPixel * x;
269	    switch (bytesPerPixel) {
270	    case 1:
271		lpb = clearRow;
272		bColor = BGR8(GetRValue(Current->clearColorRef),
273			      GetGValue(Current->clearColorRef),
274			      GetBValue(Current->clearColorRef));
275		memset(lpb, bColor, width);
276		break;
277	    case 2:
278		lpw = (LPWORD)clearRow;
279		wColor = BGR16(GetRValue(Current->clearColorRef),
280			       GetGValue(Current->clearColorRef),
281			       GetBValue(Current->clearColorRef));
282		for (i=0; i<width; i++)
283		    *lpw++ = wColor;
284		break;
285	    case 3:
286		lpb = clearRow;
287		r = GetRValue(Current->clearColorRef);
288		g = GetGValue(Current->clearColorRef);
289		b = GetBValue(Current->clearColorRef);
290		for (i=0; i<width; i++) {
291		    *lpb++ = b;
292		    *lpb++ = g;
293		    *lpb++ = r;
294		}
295		break;
296	    case 4:
297		lpdw = (LPDWORD)clearRow;
298		dwColor = BGR32(GetRValue(Current->clearColorRef),
299				GetGValue(Current->clearColorRef),
300				GetBValue(Current->clearColorRef));
301		for (i=0; i<width; i++)
302		    *lpdw++ = dwColor;
303		break;
304	    default:
305		break;
306	    } /* switch */
307
308	    /* copy cleared row to other rows in buffer */
309	    lpb = clearRow - Current->ScanWidth;
310	    rowSize = width * bytesPerPixel;
311	    for (i=1; i<height; i++) {
312		memcpy(lpb, clearRow, rowSize);
313		lpb -= Current->ScanWidth;
314	    }
315	} /* not done */
316	mask &= ~BUFFER_BIT_BACK_LEFT;
317    } /* back buffer */
318
319    /* front buffer */
320    if (mask & BUFFER_BIT_FRONT_LEFT) {
321	HDC DC = Current->hDC;
322	HPEN Old_Pen = SelectObject(DC, Current->clearPen);
323	HBRUSH Old_Brush = SelectObject(DC, Current->clearBrush);
324	Rectangle(DC,
325		  x,
326		  FLIP(y) + 1,
327		  x + width + 1,
328		  FLIP(y) - height + 1);
329	SelectObject(DC, Old_Pen);
330	SelectObject(DC, Old_Brush);
331	mask &= ~BUFFER_BIT_FRONT_LEFT;
332    } /* front buffer */
333
334    /* Call swrast if there is anything left to clear (like DEPTH) */
335    if (mask)
336	_swrast_Clear(ctx, mask, all, x, y, width, height);
337
338}
339
340
341/**********************************************************************/
342/*****                   PIXEL Functions                          *****/
343/**********************************************************************/
344
345/* SINGLE BUFFER */
346
347/* These are slow, but work with all non-indexed visual types */
348
349/* Write a horizontal span of RGBA color pixels with a boolean mask. */
350static void write_rgba_span_single(const GLcontext* ctx,
351				   struct gl_renderbuffer *rb,
352				   GLuint n, GLint x, GLint y,
353				   const GLubyte rgba[][4],
354				   const GLubyte mask[] )
355{
356    PWMC    pwc = Current;
357    GLuint i;
358
359    (void) ctx;
360    y=FLIP(y);
361    if (mask) {
362	for (i=0; i<n; i++)
363	    if (mask[i])
364		SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
365					       rgba[i][BCOMP]));
366    }
367    else {
368	for (i=0; i<n; i++)
369	    SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
370					   rgba[i][BCOMP]));
371    }
372
373}
374
375/* Write a horizontal span of RGB color pixels with a boolean mask. */
376static void write_rgb_span_single(const GLcontext* ctx,
377				  struct gl_renderbuffer *rb,
378				  GLuint n, GLint x, GLint y,
379				  const GLubyte rgb[][3],
380				  const GLubyte mask[] )
381{
382    PWMC    pwc = Current;
383    GLuint i;
384
385    (void) ctx;
386    y=FLIP(y);
387    if (mask) {
388	for (i=0; i<n; i++)
389	    if (mask[i])
390		SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
391					       rgb[i][BCOMP]));
392    }
393    else {
394	for (i=0; i<n; i++)
395	    SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
396					   rgb[i][BCOMP]));
397    }
398
399}
400
401/*
402 * Write a horizontal span of pixels with a boolean mask.  The current color
403 * is used for all pixels.
404 */
405static void write_mono_rgba_span_single(const GLcontext* ctx,
406					struct gl_renderbuffer *rb,
407					GLuint n, GLint x, GLint y,
408					const GLchan color[4],
409					const GLubyte mask[])
410{
411    GLuint i;
412    PWMC pwc = Current;
413    COLORREF colorref;
414
415    (void) ctx;
416    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
417    y=FLIP(y);
418    if (mask) {
419	for (i=0; i<n; i++)
420	    if (mask[i])
421		SetPixel(pwc->hDC, x+i, y, colorref);
422    }
423    else
424	for (i=0; i<n; i++)
425	    SetPixel(pwc->hDC, x+i, y, colorref);
426
427}
428
429/* Write an array of RGBA pixels with a boolean mask. */
430static void write_rgba_pixels_single(const GLcontext* ctx,
431				     struct gl_renderbuffer *rb,
432				     GLuint n,
433				     const GLint x[], const GLint y[],
434				     const GLubyte rgba[][4],
435				     const GLubyte mask[] )
436{
437    GLuint i;
438    PWMC    pwc = Current;
439    (void) ctx;
440    for (i=0; i<n; i++)
441	if (mask[i])
442	    SetPixel(pwc->hDC, x[i], FLIP(y[i]),
443		     RGB(rgba[i][RCOMP], rgba[i][GCOMP],
444			 rgba[i][BCOMP]));
445}
446
447
448
449/*
450 * Write an array of pixels with a boolean mask.  The current color
451 * is used for all pixels.
452 */
453static void write_mono_rgba_pixels_single(const GLcontext* ctx,
454					  struct gl_renderbuffer *rb,
455					  GLuint n,
456					  const GLint x[], const GLint y[],
457					  const GLchan color[4],
458					  const GLubyte mask[] )
459{
460    GLuint i;
461    PWMC    pwc = Current;
462    COLORREF colorref;
463    (void) ctx;
464    colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
465    for (i=0; i<n; i++)
466	if (mask[i])
467	    SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
468}
469
470/* Read a horizontal span of color pixels. */
471static void read_rgba_span_single(const GLcontext* ctx,
472				  struct gl_renderbuffer *rb,
473				  GLuint n, GLint x, GLint y,
474				  GLubyte rgba[][4] )
475{
476    GLuint i;
477    COLORREF Color;
478    y = FLIP(y);
479    for (i=0; i<n; i++) {
480	Color = GetPixel(Current->hDC, x+i, y);
481	rgba[i][RCOMP] = GetRValue(Color);
482	rgba[i][GCOMP] = GetGValue(Color);
483	rgba[i][BCOMP] = GetBValue(Color);
484	rgba[i][ACOMP] = 255;
485    }
486}
487
488
489/* Read an array of color pixels. */
490static void read_rgba_pixels_single(const GLcontext* ctx,
491				    struct gl_renderbuffer *rb,
492				    GLuint n, const GLint x[], const GLint y[],
493				    GLubyte rgba[][4])
494{
495  GLuint i;
496  COLORREF Color;
497  for (i=0; i<n; i++) {
498      GLint y2 = FLIP(y[i]);
499      Color = GetPixel(Current->hDC, x[i], y2);
500      rgba[i][RCOMP] = GetRValue(Color);
501      rgba[i][GCOMP] = GetGValue(Color);
502      rgba[i][BCOMP] = GetBValue(Color);
503      rgba[i][ACOMP] = 255;
504  }
505}
506
507/*********************************************************************/
508
509/* DOUBLE BUFFER 32-bit */
510
511#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
512LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
513*lpdw = BGR32((r),(g),(b)); }
514
515
516
517/* Write a horizontal span of RGBA color pixels with a boolean mask. */
518static void write_rgba_span_32(const GLcontext* ctx,
519			       struct gl_renderbuffer *rb,
520			       GLuint n, GLint x, GLint y,
521			       const GLubyte rgba[][4],
522			       const GLubyte mask[] )
523{
524    PWMC    pwc = Current;
525    GLuint i;
526    LPDWORD lpdw;
527
528    (void) ctx;
529
530    y=FLIP(y);
531    lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
532    if (mask) {
533	for (i=0; i<n; i++)
534	    if (mask[i])
535                lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
536				rgba[i][BCOMP]);
537    }
538    else {
539	for (i=0; i<n; i++)
540                *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
541				rgba[i][BCOMP]);
542    }
543}
544
545
546/* Write a horizontal span of RGB color pixels with a boolean mask. */
547static void write_rgb_span_32(const GLcontext* ctx,
548			      struct gl_renderbuffer *rb,
549			      GLuint n, GLint x, GLint y,
550			      const GLubyte rgb[][4],
551			      const GLubyte mask[] )
552{
553    PWMC    pwc = Current;
554    GLuint i;
555    LPDWORD lpdw;
556
557    (void) ctx;
558
559    y=FLIP(y);
560    lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
561    if (mask) {
562	for (i=0; i<n; i++)
563	    if (mask[i])
564                lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
565				rgb[i][BCOMP]);
566    }
567    else {
568	for (i=0; i<n; i++)
569                *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
570				rgb[i][BCOMP]);
571    }
572}
573
574/*
575 * Write a horizontal span of pixels with a boolean mask.  The current color
576 * is used for all pixels.
577 */
578static void write_mono_rgba_span_32(const GLcontext* ctx,
579				    struct gl_renderbuffer *rb,
580				    GLuint n, GLint x, GLint y,
581				    const GLchan color[4],
582				    const GLubyte mask[])
583{
584    LPDWORD lpdw;
585    DWORD pixel;
586    GLuint i;
587    PWMC pwc = Current;
588    lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
589    y=FLIP(y);
590    pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
591    if (mask) {
592	for (i=0; i<n; i++)
593	    if (mask[i])
594                lpdw[i] = pixel;
595    }
596    else
597	for (i=0; i<n; i++)
598                *lpdw++ = pixel;
599
600}
601
602/* Write an array of RGBA pixels with a boolean mask. */
603static void write_rgba_pixels_32(const GLcontext* ctx,
604				 struct gl_renderbuffer *rb,
605				 GLuint n, const GLint x[], const GLint y[],
606				 const GLubyte rgba[][4],
607				 const GLubyte mask[])
608{
609    GLuint i;
610    PWMC    pwc = Current;
611    for (i=0; i<n; i++)
612	if (mask[i])
613	    WMSETPIXEL32(pwc, FLIP(y[i]), x[i],
614			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
615}
616
617/*
618 * Write an array of pixels with a boolean mask.  The current color
619 * is used for all pixels.
620 */
621static void write_mono_rgba_pixels_32(const GLcontext* ctx,
622				      struct gl_renderbuffer *rb,
623				      GLuint n,
624				      const GLint x[], const GLint y[],
625				      const GLchan color[4],
626				      const GLubyte mask[])
627{
628    GLuint i;
629    PWMC pwc = Current;
630    for (i=0; i<n; i++)
631	if (mask[i])
632	    WMSETPIXEL32(pwc, FLIP(y[i]),x[i],color[RCOMP],
633			 color[GCOMP], color[BCOMP]);
634}
635
636/* Read a horizontal span of color pixels. */
637static void read_rgba_span_32(const GLcontext* ctx,
638			      struct gl_renderbuffer *rb,
639			      GLuint n, GLint x, GLint y,
640			      GLubyte rgba[][4] )
641{
642    GLuint i;
643    DWORD pixel;
644    LPDWORD lpdw;
645    PWMC pwc = Current;
646
647    y = FLIP(y);
648    lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
649    for (i=0; i<n; i++) {
650	pixel = lpdw[i];
651	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
652	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
653	rgba[i][BCOMP] = (pixel & 0x000000ff);
654	rgba[i][ACOMP] = 255;
655    }
656}
657
658
659/* Read an array of color pixels. */
660static void read_rgba_pixels_32(const GLcontext* ctx,
661				struct gl_renderbuffer *rb,
662				GLuint n, const GLint x[], const GLint y[],
663				GLubyte rgba[][4])
664{
665    GLuint i;
666    DWORD pixel;
667    LPDWORD lpdw;
668    PWMC pwc = Current;
669
670    for (i=0; i<n; i++) {
671	GLint y2 = FLIP(y[i]);
672	lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y2)) + x[i];
673	pixel = lpdw[i];
674	rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
675	rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
676	rgba[i][BCOMP] = (pixel & 0x000000ff);
677	rgba[i][ACOMP] = 255;
678  }
679}
680
681
682/*********************************************************************/
683
684/* DOUBLE BUFFER 16-bit */
685
686#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
687LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
688*lpw = BGR16((r),(g),(b)); }
689
690
691
692/* Write a horizontal span of RGBA color pixels with a boolean mask. */
693static void write_rgba_span_16(const GLcontext* ctx,
694			       struct gl_renderbuffer *rb,
695			       GLuint n, GLint x, GLint y,
696			       const GLubyte rgba[][4],
697			       const GLubyte mask[] )
698{
699    PWMC    pwc = Current;
700    GLuint i;
701    LPWORD lpw;
702
703    (void) ctx;
704
705    y=FLIP(y);
706    lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
707    if (mask) {
708	for (i=0; i<n; i++)
709	    if (mask[i])
710                lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
711			       rgba[i][BCOMP]);
712    }
713    else {
714	for (i=0; i<n; i++)
715                *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
716			       rgba[i][BCOMP]);
717    }
718}
719
720
721/* Write a horizontal span of RGB color pixels with a boolean mask. */
722static void write_rgb_span_16(const GLcontext* ctx,
723			      struct gl_renderbuffer *rb,
724			      GLuint n, GLint x, GLint y,
725			      const GLubyte rgb[][4],
726			      const GLubyte mask[] )
727{
728    PWMC    pwc = Current;
729    GLuint i;
730    LPWORD lpw;
731
732    (void) ctx;
733
734    y=FLIP(y);
735    lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
736    if (mask) {
737	for (i=0; i<n; i++)
738	    if (mask[i])
739                lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
740			       rgb[i][BCOMP]);
741    }
742    else {
743	for (i=0; i<n; i++)
744                *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
745			       rgb[i][BCOMP]);
746    }
747}
748
749/*
750 * Write a horizontal span of pixels with a boolean mask.  The current color
751 * is used for all pixels.
752 */
753static void write_mono_rgba_span_16(const GLcontext* ctx,
754				    struct gl_renderbuffer *rb,
755				    GLuint n, GLint x, GLint y,
756				    const GLchan color[4],
757				    const GLubyte mask[])
758{
759    LPWORD lpw;
760    WORD pixel;
761    GLuint i;
762    PWMC pwc = Current;
763    (void) ctx;
764    lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
765    y=FLIP(y);
766    pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
767    if (mask) {
768	for (i=0; i<n; i++)
769	    if (mask[i])
770                lpw[i] = pixel;
771    }
772    else
773	for (i=0; i<n; i++)
774                *lpw++ = pixel;
775
776}
777
778/* Write an array of RGBA pixels with a boolean mask. */
779static void write_rgba_pixels_16(const GLcontext* ctx,
780				 struct gl_renderbuffer *rb,
781				 GLuint n, const GLint x[], const GLint y[],
782				 const GLubyte rgba[][4],
783				 const GLubyte mask[])
784{
785    GLuint i;
786    PWMC    pwc = Current;
787    (void) ctx;
788    for (i=0; i<n; i++)
789	if (mask[i])
790	    WMSETPIXEL16(pwc, FLIP(y[i]), x[i],
791			 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
792}
793
794/*
795 * Write an array of pixels with a boolean mask.  The current color
796 * is used for all pixels.
797 */
798static void write_mono_rgba_pixels_16(const GLcontext* ctx,
799				      struct gl_renderbuffer *rb,
800				      GLuint n,
801				      const GLint x[], const GLint y[],
802				      const GLchan color[4],
803				      const GLubyte mask[])
804{
805    GLuint i;
806    PWMC    pwc = Current;
807    (void) ctx;
808    for (i=0; i<n; i++)
809	if (mask[i])
810	    WMSETPIXEL16(pwc, FLIP(y[i]),x[i],color[RCOMP],
811			 color[GCOMP], color[BCOMP]);
812}
813
814/* Read a horizontal span of color pixels. */
815static void read_rgba_span_16(const GLcontext* ctx,
816			      struct gl_renderbuffer *rb,
817			      GLuint n, GLint x, GLint y,
818			      GLubyte rgba[][4] )
819{
820    GLuint i, pixel;
821    LPWORD lpw;
822    PWMC pwc = Current;
823
824    y = FLIP(y);
825    lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
826    for (i=0; i<n; i++) {
827	pixel = lpw[i];
828	/* Windows uses 5,5,5 for 16-bit */
829	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
830	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
831	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
832	rgba[i][ACOMP] = 255;
833    }
834}
835
836
837/* Read an array of color pixels. */
838static void read_rgba_pixels_16(const GLcontext* ctx,
839				struct gl_renderbuffer *rb,
840				GLuint n, const GLint x[], const GLint y[],
841				GLubyte rgba[][4])
842{
843    GLuint i, pixel;
844    LPWORD lpw;
845    PWMC pwc = Current;
846
847    for (i=0; i<n; i++) {
848	GLint y2 = FLIP(y[i]);
849	lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y2)) + x[i];
850	pixel = lpw[i];
851	/* Windows uses 5,5,5 for 16-bit */
852	rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
853	rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
854	rgba[i][BCOMP] = (pixel & 0x001f) << 3;
855	rgba[i][ACOMP] = 255;
856  }
857}
858
859
860
861
862/**********************************************************************/
863/*****                   BUFFER Functions                         *****/
864/**********************************************************************/
865
866
867
868
869static void
870wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
871{
872    _mesa_free(rb);
873}
874
875static GLboolean
876wmesa_renderbuffer_storage(GLcontext *ctx,
877			   struct gl_renderbuffer *rb,
878			   GLenum internalFormat,
879			   GLuint width,
880			   GLuint height)
881{
882    return GL_TRUE;
883}
884
885void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat,
886                                  int double_buffer)
887{
888    if (double_buffer) {
889	/* Picking the correct span functions is important because
890	 * the DIB was allocated with the indicated depth. */
891	switch(pixelformat) {
892	case PF_5R6G5B:
893	    rb->PutRow = write_rgba_span_16;
894	    rb->PutRowRGB = write_rgb_span_16;
895	    rb->PutMonoRow = write_mono_rgba_span_16;
896	    rb->PutValues = write_rgba_pixels_16;
897	    rb->PutMonoValues = write_mono_rgba_pixels_16;
898	    rb->GetRow = read_rgba_span_16;
899	    rb->GetValues = read_rgba_pixels_16;
900	    break;
901	case PF_8R8G8B:
902	    rb->PutRow = write_rgba_span_32;
903	    rb->PutRowRGB = write_rgb_span_32;
904	    rb->PutMonoRow = write_mono_rgba_span_32;
905	    rb->PutValues = write_rgba_pixels_32;
906	    rb->PutMonoValues = write_mono_rgba_pixels_32;
907	    rb->GetRow = read_rgba_span_32;
908	    rb->GetValues = read_rgba_pixels_32;
909	    break;
910	default:
911	    break;
912	}
913    }
914    else { /* single buffer */
915	rb->PutRow = write_rgba_span_single;
916	rb->PutRowRGB = write_rgb_span_single;
917	rb->PutMonoRow = write_mono_rgba_span_single;
918	rb->PutValues = write_rgba_pixels_single;
919	rb->PutMonoValues = write_mono_rgba_pixels_single;
920	rb->GetRow = read_rgba_span_single;
921	rb->GetValues = read_rgba_pixels_single;
922    }
923}
924
925/**
926 * Called by ctx->Driver.ResizeBuffers()
927 * Resize the front/back colorbuffers to match the latest window size.
928 */
929static void
930wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
931                     GLuint width, GLuint height)
932{
933    if (Current->width != width || Current->height != height) {
934	Current->width = width;
935	Current->height = height;
936	/* Realloc back buffer */
937	if (Current->db_flag) {
938	    wmDeleteBackingStore(Current);
939	    wmCreateBackingStore(Current, width, height);
940	}
941    }
942    _mesa_resize_framebuffer(ctx, buffer, width, height);
943}
944
945
946/**
947 * Called by glViewport.
948 * This is a good time for us to poll the current window size and adjust
949 * our renderbuffers to match the current window size.
950 * Remember, we have no opportunity to respond to conventional
951 * resize events since the driver has no event loop.
952 * Thus, we poll.
953 * Note that this trick isn't fool-proof.  If the application never calls
954 * glViewport, our notion of the current window size may be incorrect.
955 */
956static void wmesa_viewport(GLcontext *ctx,
957			   GLint x, GLint y,
958			   GLsizei width, GLsizei height)
959{
960   if (Current->width != width || Current->height != height) {
961       wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, width, height);
962       ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
963   }
964}
965
966
967
968
969/**
970 * Called when the driver should update it's state, based on the new_state
971 * flags.
972 */
973static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
974{
975    _swrast_InvalidateState(ctx, new_state);
976    _swsetup_InvalidateState(ctx, new_state);
977    _ac_InvalidateState(ctx, new_state);
978    _tnl_InvalidateState(ctx, new_state);
979
980    /* TODO - need code to update the span functions in case the
981     * renderer changes the target buffer (like a DB app writing to
982     * the front buffer). */
983
984#if 0
985    {  /* could check _NEW_BUFFERS bit flag here  in new_state */
986	/* In progress - Need to make the wmesa context inherit (by containment)
987	the gl_context, so I can get access to the pixel format */
988	struct gl_renderbuffer *rb;
989	int pixelformat, double_buffer;
990
991	rb = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
992	pixelformat = PF_5R6G5B;  // hard code for now - see note above
993        double_buffer = ctx->DrawBuffer->ColorDrawBuffer[0] == GL_BACK ? 1 : 0;
994	if (rb)
995        wmesa_set_renderbuffer_funcs(rb, pixelformat, double_buffer);
996    }
997#endif
998}
999
1000
1001
1002
1003
1004/**********************************************************************/
1005/*****                   WMESA Functions                          *****/
1006/**********************************************************************/
1007
1008WMesaContext WMesaCreateContext(HDC hDC,
1009				HPALETTE* Pal,
1010				GLboolean rgb_flag,
1011				GLboolean db_flag,
1012				GLboolean alpha_flag)
1013{
1014    WMesaContext c;
1015    struct dd_function_table functions;
1016    GLint red_bits, green_bits, blue_bits, alpha_bits;
1017
1018    (void) Pal;
1019
1020    /* Indexed mode not supported */
1021    if (!rgb_flag)
1022	return NULL;
1023
1024    /* Allocate wmesa context */
1025    c = CALLOC_STRUCT(wmesa_context);
1026    if (!c)
1027	return NULL;
1028
1029#if 0
1030    /* I do not understand this contributed code */
1031    /* Support memory and device contexts */
1032    if(WindowFromDC(hDC) != NULL) {
1033	c->hDC = GetDC(WindowFromDC(hDC)); // huh ????
1034    }
1035    else {
1036	c->hDC = hDC;
1037    }
1038#else
1039    c->hDC = hDC;
1040#endif
1041
1042    /* rememember DC and flag settings */
1043    c->rgb_flag = rgb_flag;
1044    c->db_flag = db_flag;
1045    c->alpha_flag = alpha_flag;
1046
1047    /* Get data for visual */
1048    /* Dealing with this is actually a bit of overkill because Mesa will end
1049     * up treating all color component size requests less than 8 by using
1050     * a single byte per channel.  In addition, the interface to the span
1051     * routines passes colors as an entire byte per channel anyway, so there
1052     * is nothing to be saved by telling the visual to be 16 bits if the device
1053     * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
1054     * channel anyway.
1055     * But we go through the motions here anyway.
1056     */
1057    switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
1058    case 16:
1059	red_bits = green_bits = blue_bits = 5;
1060	alpha_bits = 0;
1061	break;
1062    default:
1063	red_bits = green_bits = blue_bits = 8;
1064	alpha_bits = 8;
1065	break;
1066    }
1067    /* Create visual based on flags */
1068    c->gl_visual = _mesa_create_visual(rgb_flag,
1069				       db_flag,    /* db_flag */
1070				       GL_FALSE,   /* stereo */
1071				       red_bits, green_bits, blue_bits, /* color RGB */
1072				       alpha_flag ? alpha_bits : 0, /* color A */
1073				       0,          /* index bits */
1074				       DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
1075				       8,          /* stencil_bits */
1076				       16,16,16,   /* accum RGB */
1077				       alpha_flag ? 16 : 0, /* accum A */
1078				       1);         /* num samples */
1079
1080    if (!c->gl_visual) {
1081	_mesa_free(c);
1082	return NULL;
1083    }
1084
1085    /* Set up driver functions */
1086    _mesa_init_driver_functions(&functions);
1087    functions.GetString = wmesa_get_string;
1088    functions.UpdateState = wmesa_update_state;
1089    functions.GetBufferSize = wmesa_get_buffer_size;
1090    functions.Flush = wmesa_flush;
1091    functions.Clear = clear;
1092    functions.ClearIndex = clear_index;
1093    functions.ClearColor = clear_color;
1094    functions.ResizeBuffers = wmesa_resize_buffers;
1095    functions.Viewport = wmesa_viewport;
1096
1097    /* allocate a new Mesa context */
1098    c->gl_ctx = _mesa_create_context(c->gl_visual, NULL,
1099				     &functions, (void *)c);
1100    if (!c->gl_ctx) {
1101	_mesa_destroy_visual( c->gl_visual );
1102	_mesa_free(c);
1103	return NULL;
1104    }
1105
1106    _mesa_enable_sw_extensions(c->gl_ctx);
1107    _mesa_enable_1_3_extensions(c->gl_ctx);
1108    _mesa_enable_1_4_extensions(c->gl_ctx);
1109    _mesa_enable_1_5_extensions(c->gl_ctx);
1110    _mesa_enable_2_0_extensions(c->gl_ctx);
1111
1112    /* Initialize the software rasterizer and helper modules. */
1113    if (!_swrast_CreateContext(c->gl_ctx) ||
1114        !_ac_CreateContext(c->gl_ctx) ||
1115        !_tnl_CreateContext(c->gl_ctx) ||
1116	!_swsetup_CreateContext(c->gl_ctx)) {
1117	_mesa_destroy_visual(c->gl_visual);
1118	_mesa_destroy_framebuffer(c->gl_buffer);
1119	_mesa_free_context_data(c->gl_ctx);
1120	_mesa_free(c);
1121	return NULL;
1122    }
1123    _swsetup_Wakeup(c->gl_ctx);
1124    TNL_CONTEXT(c->gl_ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1125
1126    return c;
1127}
1128
1129void WMesaDestroyContext( void )
1130{
1131    WMesaContext c = Current;
1132
1133    WMesaMakeCurrent(NULL);
1134
1135    /* Release for device, not memory contexts */
1136    if(WindowFromDC(c->hDC) != NULL)
1137    {
1138      ReleaseDC(WindowFromDC(c->hDC), c->hDC);
1139    }
1140    DeleteObject(c->clearPen);
1141    DeleteObject(c->clearBrush);
1142
1143    if (c->db_flag)
1144	wmDeleteBackingStore(c);
1145
1146    _swsetup_DestroyContext(c->gl_ctx);
1147    _tnl_DestroyContext(c->gl_ctx);
1148    _ac_DestroyContext(c->gl_ctx);
1149    _swrast_DestroyContext(c->gl_ctx);
1150
1151    _mesa_destroy_visual(c->gl_visual);
1152    _mesa_destroy_framebuffer(c->gl_buffer);
1153    _mesa_free_context_data(c->gl_ctx);
1154    _mesa_free(c->gl_ctx);
1155    _mesa_free(c);
1156}
1157
1158
1159void WMesaMakeCurrent(WMesaContext c)
1160{
1161    /* return if already current */
1162    if (Current == c || c == NULL)
1163	return;
1164
1165    /* Lazy creation of buffers */
1166    if (!c->gl_buffer) {
1167        struct gl_renderbuffer *rb;
1168        RECT rect;
1169
1170	/* Determine window size */
1171	if (WindowFromDC(c->hDC)) {
1172	    GetClientRect(WindowFromDC(c->hDC), &rect);
1173	    c->width = rect.right - rect.left;
1174	    c->height = rect.bottom - rect.top;
1175	}
1176	else { /* Memory context */
1177	    /* From contributed code - use the size of the desktop
1178	     * for the size of a memory context (?) */
1179	    c->width = GetDeviceCaps(c->hDC, HORZRES);
1180	    c->height = GetDeviceCaps(c->hDC, VERTRES);
1181	}
1182	c->clearPen = CreatePen(PS_SOLID, 1, 0);
1183	c->clearBrush = CreateSolidBrush(0);
1184
1185	/* Create back buffer if double buffered */
1186	if (c->db_flag) {
1187	    wmCreateBackingStore(c, c->width, c->height);
1188
1189	}
1190
1191	c->gl_buffer = _mesa_create_framebuffer(c->gl_visual);
1192	if (!c->gl_buffer)
1193	    return;
1194
1195	rb = CALLOC_STRUCT(gl_renderbuffer);
1196
1197	if (!rb)
1198	    return;
1199
1200	_mesa_init_renderbuffer(rb, (GLuint)0);
1201
1202	rb->_BaseFormat = GL_RGBA;
1203	rb->InternalFormat = GL_RGBA;
1204	rb->DataType = CHAN_TYPE;
1205	rb->Delete = wmesa_delete_renderbuffer;
1206	rb->AllocStorage = wmesa_renderbuffer_storage;
1207
1208	if (c->db_flag)
1209	    _mesa_add_renderbuffer(c->gl_buffer, BUFFER_BACK_LEFT, rb);
1210	else
1211	    _mesa_add_renderbuffer(c->gl_buffer, BUFFER_FRONT_LEFT, rb);
1212	wmesa_set_renderbuffer_funcs(rb, c->pixelformat, c->db_flag);
1213
1214	/* Let Mesa own the Depth, Stencil, and Accum buffers */
1215	_mesa_add_soft_renderbuffers(c->gl_buffer,
1216				     GL_FALSE, /* color */
1217				     c->gl_visual->depthBits > 0,
1218				     c->gl_visual->stencilBits > 0,
1219				     c->gl_visual->accumRedBits > 0,
1220				     c->alpha_flag,
1221				     GL_FALSE);
1222    }
1223
1224
1225
1226
1227    if (Current = c)
1228	_mesa_make_current(c->gl_ctx, c->gl_buffer, c->gl_buffer);
1229}
1230
1231
1232void WMesaSwapBuffers( void )
1233{
1234    GET_CURRENT_CONTEXT(ctx);
1235
1236    /* If we're swapping the buffer associated with the current context
1237     * we have to flush any pending rendering commands first.
1238     */
1239    if (Current && Current->gl_ctx == ctx)
1240	_mesa_notifySwapBuffers(ctx);
1241
1242    if (Current->db_flag)
1243	wmesa_flush(ctx);
1244}
1245
1246/**********************************************************************/
1247/*****                        END                                 *****/
1248/**********************************************************************/
1249