wmesa.c revision 24d55a1145d52d221c7aa7066e033ca34e3ddef5
1/*
2 * Windows (Win32) 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    // TEMP - 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),
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
885/**
886 * Called by ctx->Driver.ResizeBuffers()
887 * Resize the front/back colorbuffers to match the latest window size.
888 */
889static void
890wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
891                     GLuint width, GLuint height)
892{
893    RECT CR;
894    if (Current->width != width || Current->height != height) {
895	Current->width = width;
896	Current->height = height;
897	/* Realloc back buffer */
898	if (Current->db_flag) {
899	    wmDeleteBackingStore(Current);
900	    wmCreateBackingStore(Current, width, height);
901	}
902	GetClientRect(Current->Window, &CR);
903	Current->width = CR.right;
904	Current->height = CR.bottom;
905    }
906    _mesa_resize_framebuffer(ctx, buffer, width, height);
907}
908
909
910/**
911 * Called by glViewport.
912 * This is a good time for us to poll the current window size and adjust
913 * our renderbuffers to match the current window size.
914 * Remember, we have no opportunity to respond to conventional
915 * resize events since the driver has no event loop.
916 * Thus, we poll.
917 * Note that this trick isn't fool-proof.  If the application never calls
918 * glViewport, our notion of the current window size may be incorrect.
919 */
920static void wmesa_viewport(GLcontext *ctx,
921			   GLint x, GLint y,
922			   GLsizei width, GLsizei height)
923{
924   if (Current->width != width || Current->height != height) {
925       wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, width, height);
926       ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
927   }
928}
929
930
931
932
933/**
934 * Called when the driver should update it's state, based on the new_state
935 * flags.
936 */
937static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
938{
939    _swrast_InvalidateState(ctx, new_state);
940    _swsetup_InvalidateState(ctx, new_state);
941    _ac_InvalidateState(ctx, new_state);
942    _tnl_InvalidateState(ctx, new_state);
943
944    /* TODO - need code to update the span functions in case the
945     * renderer changes the target buffer (like a DB app writing to
946     * the front buffer). */
947}
948
949
950
951
952
953/**********************************************************************/
954/*****                   WMESA Functions                          *****/
955/**********************************************************************/
956
957WMesaContext WMesaCreateContext(HWND hWnd,
958				HPALETTE* Pal,
959				GLboolean rgb_flag,
960				GLboolean db_flag,
961				GLboolean alpha_flag)
962{
963    RECT CR;
964    WMesaContext c;
965    struct dd_function_table functions;
966    struct gl_renderbuffer *rb;
967
968    (void) Pal;
969
970    /* Indexed mode not supported */
971    if (!rgb_flag)
972	return NULL;
973
974    c = CALLOC_STRUCT(wmesa_context);
975    if (!c)
976	return NULL;
977
978    c->Window = hWnd;
979    c->hDC = GetDC(hWnd);
980    GetClientRect(c->Window, &CR);
981    c->width = CR.right;
982    c->height = CR.bottom;
983
984    c->clearPen = CreatePen(PS_SOLID, 1, 0);
985    c->clearBrush = CreateSolidBrush(0);
986
987    /* Create back buffer if double buffered */
988    if (db_flag) {
989	c->db_flag = 1;
990	wmCreateBackingStore(c, c->width, c->height);
991
992    }
993
994    c->gl_visual = _mesa_create_visual(rgb_flag,
995				       db_flag,    /* db_flag */
996				       GL_FALSE,   /* stereo */
997				       8,8,8,      /* color RGB */
998				       alpha_flag ? 8 : 0, /* color A */
999				       0,          /* index bits */
1000				       16,         /* depth_bits */
1001				       8,          /* stencil_bits */
1002				       16,16,16,   /* accum RGB */
1003				       alpha_flag ? 16 : 0, /* accum A */
1004				       1);
1005
1006    if (!c->gl_visual) {
1007	_mesa_free(c);
1008	return NULL;
1009    }
1010
1011    /* Set up driver functions */
1012    _mesa_init_driver_functions(&functions);
1013    /* Fill in required functions */
1014    functions.GetString = wmesa_get_string;
1015    functions.UpdateState = wmesa_update_state;
1016    functions.GetBufferSize = wmesa_get_buffer_size;
1017    functions.Flush = wmesa_flush;
1018
1019    functions.Clear = clear;
1020    functions.ClearIndex = clear_index;
1021    functions.ClearColor = clear_color;
1022
1023    functions.ResizeBuffers = wmesa_resize_buffers;
1024    functions.Viewport = wmesa_viewport;
1025
1026    /* allocate a new Mesa context */
1027    c->gl_ctx = _mesa_create_context(c->gl_visual, NULL,
1028				     &functions, (void *)c);
1029    if (!c->gl_ctx) {
1030	_mesa_destroy_visual( c->gl_visual );
1031	_mesa_free(c);
1032	return NULL;
1033    }
1034
1035    _mesa_enable_sw_extensions(c->gl_ctx);
1036    _mesa_enable_1_3_extensions(c->gl_ctx);
1037    _mesa_enable_1_4_extensions(c->gl_ctx);
1038    _mesa_enable_1_5_extensions(c->gl_ctx);
1039    _mesa_enable_2_0_extensions(c->gl_ctx);
1040
1041    c->gl_buffer = _mesa_create_framebuffer(c->gl_visual);
1042    if (!c->gl_buffer) {
1043	_mesa_destroy_visual(c->gl_visual);
1044	_mesa_free_context_data(c->gl_ctx);
1045	_mesa_free(c);
1046	return NULL;
1047    }
1048
1049    rb = CALLOC_STRUCT(gl_renderbuffer);
1050
1051    if (!rb) {
1052	_mesa_destroy_visual(c->gl_visual);
1053	_mesa_destroy_framebuffer(c->gl_buffer);
1054	_mesa_free_context_data(c->gl_ctx);
1055	_mesa_free(c);
1056	return NULL;
1057    }
1058
1059    _mesa_init_renderbuffer(rb, (GLuint)0);
1060
1061    rb->_BaseFormat = GL_RGBA;
1062    rb->InternalFormat = GL_RGBA;
1063    rb->DataType = CHAN_TYPE;
1064    rb->Delete = wmesa_delete_renderbuffer;
1065    rb->AllocStorage = wmesa_renderbuffer_storage;
1066
1067    if (db_flag) {
1068	switch(c->cColorBits) {
1069	case 16:
1070	    rb->PutRow = write_rgba_span_16;
1071	    rb->PutRowRGB = write_rgb_span_16;
1072	    rb->PutMonoRow = write_mono_rgba_span_16;
1073	    rb->PutValues = write_rgba_pixels_16;
1074	    rb->PutMonoValues = write_mono_rgba_pixels_16;
1075	    rb->GetRow = read_rgba_span_16;
1076	    rb->GetValues = read_rgba_pixels_16;
1077	    break;
1078	case 32:
1079	    rb->PutRow = write_rgba_span_32;
1080	    rb->PutRowRGB = write_rgb_span_32;
1081	    rb->PutMonoRow = write_mono_rgba_span_32;
1082	    rb->PutValues = write_rgba_pixels_32;
1083	    rb->PutMonoValues = write_mono_rgba_pixels_32;
1084	    rb->GetRow = read_rgba_span_32;
1085	    rb->GetValues = read_rgba_pixels_32;
1086	    break;
1087	default:
1088	    break;
1089	}
1090	_mesa_add_renderbuffer(c->gl_buffer, BUFFER_BACK_LEFT, rb);
1091    }
1092    else { /* single buffer */
1093	rb->PutRow = write_rgba_span_single;
1094	rb->PutRowRGB = write_rgb_span_single;
1095	rb->PutMonoRow = write_mono_rgba_span_single;
1096	rb->PutValues = write_rgba_pixels_single;
1097	rb->PutMonoValues = write_mono_rgba_pixels_single;
1098	rb->GetRow = read_rgba_span_single;
1099	rb->GetValues = read_rgba_pixels_single;
1100	_mesa_add_renderbuffer(c->gl_buffer, BUFFER_FRONT_LEFT, rb);
1101    }
1102
1103    _mesa_add_soft_renderbuffers(c->gl_buffer,
1104				 GL_FALSE, /* color */
1105				 c->gl_visual->depthBits > 0,
1106				 c->gl_visual->stencilBits > 0,
1107				 c->gl_visual->accumRedBits > 0,
1108				 alpha_flag,
1109				 GL_FALSE);
1110
1111    /* Initialize the software rasterizer and helper modules. */
1112    if (!_swrast_CreateContext(c->gl_ctx) ||
1113        !_ac_CreateContext(c->gl_ctx) ||
1114        !_tnl_CreateContext(c->gl_ctx) ||
1115	!_swsetup_CreateContext(c->gl_ctx)) {
1116	_mesa_destroy_visual(c->gl_visual);
1117	_mesa_destroy_framebuffer(c->gl_buffer);
1118	_mesa_free_context_data(c->gl_ctx);
1119	_mesa_free(c);
1120	return NULL;
1121    }
1122
1123    _swsetup_Wakeup(c->gl_ctx);
1124
1125    TNL_CONTEXT(c->gl_ctx)->Driver.RunPipeline = _tnl_run_pipeline;
1126
1127    return c;
1128}
1129
1130void WMesaDestroyContext( void )
1131{
1132    WMesaContext c = Current;
1133
1134    WMesaMakeCurrent(NULL);
1135
1136    ReleaseDC(c->Window, c->hDC);
1137    DeleteObject(c->clearPen);
1138    DeleteObject(c->clearBrush);
1139
1140    if (c->db_flag)
1141	wmDeleteBackingStore(c);
1142
1143    _swsetup_DestroyContext(c->gl_ctx);
1144    _tnl_DestroyContext(c->gl_ctx);
1145    _ac_DestroyContext(c->gl_ctx);
1146    _swrast_DestroyContext(c->gl_ctx);
1147
1148    _mesa_destroy_visual(c->gl_visual);
1149    _mesa_destroy_framebuffer(c->gl_buffer);
1150    _mesa_free_context_data(c->gl_ctx);
1151    _mesa_free(c->gl_ctx);
1152    _mesa_free(c);
1153}
1154
1155
1156void WMesaMakeCurrent(WMesaContext c)
1157{
1158    /* return if already current */
1159    if (Current == c)
1160	return;
1161
1162    if (Current = c)
1163	_mesa_make_current(c->gl_ctx, c->gl_buffer, c->gl_buffer);
1164}
1165
1166
1167void WMesaSwapBuffers( void )
1168{
1169    GET_CURRENT_CONTEXT(ctx);
1170
1171    /* If we're swapping the buffer associated with the current context
1172     * we have to flush any pending rendering commands first.
1173     */
1174    if (Current && Current->gl_ctx == ctx)
1175	_mesa_notifySwapBuffers(ctx);
1176
1177    if (Current->db_flag)
1178	wmesa_flush(ctx);
1179}
1180
1181/**********************************************************************/
1182/*****                        END                                 *****/
1183/**********************************************************************/
1184