aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c')
-rw-r--r--nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c1184
1 files changed, 1184 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c b/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c
new file mode 100644
index 000000000..0265d80c0
--- /dev/null
+++ b/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/windows/gdi/wmesa.c
@@ -0,0 +1,1184 @@
+/*
+ * Windows (Win32/Win64) device driver for Mesa
+ *
+ */
+
+#include "wmesadef.h"
+#include "colors.h"
+#include <GL/wmesa.h>
+#include "extensions.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+#include "drivers/common/driverfuncs.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#define FLIP(Y) (Current->height-(Y)-1)
+
+/* Static Data */
+
+static PWMC Current = NULL;
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name)
+{
+ return (name == GL_RENDERER) ?
+ (GLubyte *) "Mesa Windows GDI Driver" : NULL;
+}
+
+/*
+ * Determine the pixel format based on the pixel size.
+ */
+static void wmSetPixelFormat(PWMC pwc, HDC hDC)
+{
+ pwc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+
+ // TEMP - only 16 and 32 bit targets are supported now
+ assert(pwc->cColorBits == 16 ||
+ pwc->cColorBits == 32);
+
+ switch(pwc->cColorBits){
+ case 8:
+ pwc->pixelformat = PF_INDEX8;
+ break;
+ case 16:
+ pwc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ pwc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ pwc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+/*
+ * Create DIB for back buffer.
+ * We write into this memory with the span routines and then blit it
+ * to the window on a buffer swap.
+ */
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ HDC hic;
+
+ assert(pwc->db_flag == GL_TRUE);
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = (lxSize * (pwc->cColorBits / 8) + 3) & ~3;
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &pwc->bmi,
+ DIB_RGB_COLORS,
+ (void **)&(pwc->pbPixels),
+ 0,
+ 0);
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return TRUE;
+}
+
+static wmDeleteBackingStore(PWMC pwc)
+{
+ if (pwc->hbmDIB) {
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ }
+}
+
+static void wmesa_get_buffer_size(GLframebuffer *buffer,
+ GLuint *width,
+ GLuint *height )
+{
+ *width = Current->width;
+ *height = Current->height;
+}
+
+
+static void wmesa_flush(GLcontext* ctx)
+{
+ if (Current->db_flag) {
+ BitBlt(Current->hDC, 0, 0, Current->width, Current->height,
+ Current->dib.hDC, 0, 0, SRCCOPY);
+ }
+ else {
+ /* Do nothing for single buffer */
+ }
+}
+
+
+/**********************************************************************/
+/***** CLEAR Functions *****/
+/**********************************************************************/
+
+/* If we do not implement these, Mesa clears the buffers via the pixel
+ * span writing interface, which is very slow for a clear operation.
+ */
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ /* Note that indexed mode is not supported yet */
+ Current->clearColorRef = RGB(0,0,0);
+}
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color(GLcontext* ctx, const GLfloat color[4])
+{
+ GLubyte col[3];
+ UINT bytesPerPixel = Current->cColorBits / 8;
+
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ Current->clearColorRef = RGB(col[0], col[1], col[2]);
+ DeleteObject(Current->clearPen);
+ DeleteObject(Current->clearBrush);
+ Current->clearPen = CreatePen(PS_SOLID, 1, Current->clearColorRef);
+ Current->clearBrush = CreateSolidBrush(Current->clearColorRef);
+}
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ */
+
+static void clear(GLcontext* ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x, GLint y,
+ GLint width, GLint height)
+{
+ int done = 0;
+
+ /* Let swrast do all the work if the masks are not set to
+ * clear all channels. */
+ if (ctx->Color.ColorMask[0] != 0xff ||
+ ctx->Color.ColorMask[1] != 0xff ||
+ ctx->Color.ColorMask[2] != 0xff ||
+ ctx->Color.ColorMask[3] != 0xff) {
+ _swrast_Clear(ctx, mask, all, x, y, width, height);
+ return;
+ }
+
+ /* 'all' means clear the entire window */
+ if (all) {
+ x = y = 0;
+ width = Current->width;
+ height = Current->height;
+ }
+
+ /* Back buffer */
+ if (mask & BUFFER_BIT_BACK_LEFT) {
+
+ int i, rowSize;
+ UINT bytesPerPixel = Current->cColorBits / 8;
+ LPBYTE lpb, clearRow;
+ LPWORD lpw;
+ BYTE bColor;
+ WORD wColor;
+ BYTE r, g, b;
+ DWORD dwColor;
+ LPDWORD lpdw;
+
+ /* Try for a fast clear - clearing entire buffer with a single
+ * byte value. */
+ if (all) { /* entire buffer */
+ /* Now check for an easy clear value */
+ switch (bytesPerPixel) {
+ case 1:
+ bColor = BGR8(GetRValue(Current->clearColorRef),
+ GetGValue(Current->clearColorRef),
+ GetBValue(Current->clearColorRef));
+ memset(Current->pbPixels, bColor,
+ Current->ScanWidth * height);
+ done = 1;
+ break;
+ case 2:
+ wColor = BGR16(GetRValue(Current->clearColorRef),
+ GetGValue(Current->clearColorRef),
+ GetBValue(Current->clearColorRef));
+ if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
+ memset(Current->pbPixels, wColor & 0xff,
+ Current->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ case 3:
+ /* fall through */
+ case 4:
+ if (GetRValue(Current->clearColorRef) ==
+ GetGValue(Current->clearColorRef) &&
+ GetRValue(Current->clearColorRef) ==
+ GetBValue(Current->clearColorRef)) {
+ memset(Current->pbPixels,
+ GetRValue(Current->clearColorRef),
+ Current->ScanWidth * height);
+ done = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ } /* all */
+
+ if (!done) {
+ /* Need to clear a row at a time. Begin by setting the first
+ * row in the area to be cleared to the clear color. */
+
+ clearRow = Current->pbPixels +
+ Current->ScanWidth * FLIP(y) +
+ bytesPerPixel * x;
+ switch (bytesPerPixel) {
+ case 1:
+ lpb = clearRow;
+ bColor = BGR8(GetRValue(Current->clearColorRef),
+ GetGValue(Current->clearColorRef),
+ GetBValue(Current->clearColorRef));
+ memset(lpb, bColor, width);
+ break;
+ case 2:
+ lpw = (LPWORD)clearRow;
+ wColor = BGR16(GetRValue(Current->clearColorRef),
+ GetGValue(Current->clearColorRef),
+ GetBValue(Current->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpw++ = wColor;
+ break;
+ case 3:
+ lpb = clearRow;
+ r = GetRValue(Current->clearColorRef);
+ g = GetGValue(Current->clearColorRef);
+ b = GetBValue(Current->clearColorRef);
+ for (i=0; i<width; i++) {
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb++ = r;
+ }
+ break;
+ case 4:
+ lpdw = (LPDWORD)clearRow;
+ dwColor = BGR32(GetRValue(Current->clearColorRef),
+ GetGValue(Current->clearColorRef),
+ GetBValue(Current->clearColorRef));
+ for (i=0; i<width; i++)
+ *lpdw++ = dwColor;
+ break;
+ default:
+ break;
+ } /* switch */
+
+ /* copy cleared row to other rows in buffer */
+ lpb = clearRow - Current->ScanWidth;
+ rowSize = width * bytesPerPixel;
+ for (i=1; i<height; i++) {
+ memcpy(lpb, clearRow, rowSize);
+ lpb -= Current->ScanWidth;
+ }
+ } /* not done */
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ } /* back buffer */
+
+ /* front buffer */
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
+ HDC DC = Current->hDC;
+ HPEN Old_Pen = SelectObject(DC, Current->clearPen);
+ HBRUSH Old_Brush = SelectObject(DC, Current->clearBrush);
+ Rectangle(DC,
+ x,
+ FLIP(y),
+ x + width + 1,
+ FLIP(y) - height + 1);
+ SelectObject(DC, Old_Pen);
+ SelectObject(DC, Old_Brush);
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ } /* front buffer */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear(ctx, mask, all, x, y, width, height);
+
+}
+
+
+/**********************************************************************/
+/***** PIXEL Functions *****/
+/**********************************************************************/
+
+/* SINGLE BUFFER */
+
+/* These are slow, but work with all non-indexed visual types */
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+
+ (void) ctx;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+
+ (void) ctx;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ COLORREF colorref;
+
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x+i, y, colorref);
+ }
+ else
+ for (i=0; i<n; i++)
+ SetPixel(pwc->hDC, x+i, y, colorref);
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ PWMC pwc = Current;
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]),
+ RGB(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLuint i;
+ PWMC pwc = Current;
+ COLORREF colorref;
+ (void) ctx;
+ colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ COLORREF Color;
+ y = FLIP(y);
+ for (i=0; i<n; i++) {
+ Color = GetPixel(Current->hDC, x+i, y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_single(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ COLORREF Color;
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ Color = GetPixel(Current->hDC, x[i], y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 32-bit */
+
+#define WMSETPIXEL32(pwc, y, x, r, g, b) { \
+LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpdw = BGR32((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][4],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+ LPDWORD lpdw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPDWORD lpdw;
+ DWORD pixel;
+ GLuint i;
+ PWMC pwc = Current;
+ lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpdw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpdw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwc, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL32(pwc, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ PWMC pwc = Current;
+
+ y = FLIP(y);
+ lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpdw[i];
+ rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
+ rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
+ rgba[i][BCOMP] = (pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_32(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i;
+ DWORD pixel;
+ LPDWORD lpdw;
+ PWMC pwc = Current;
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * y2)) + x[i];
+ pixel = lpdw[i];
+ rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
+ rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
+ rgba[i][BCOMP] = (pixel & 0x000000ff);
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/*********************************************************************/
+
+/* DOUBLE BUFFER 16-bit */
+
+#define WMSETPIXEL16(pwc, y, x, r, g, b) { \
+LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \
+*lpw = BGR16((r),(g),(b)); }
+
+
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+}
+
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][4],
+ const GLubyte mask[] )
+{
+ PWMC pwc = Current;
+ GLuint i;
+ LPWORD lpw;
+
+ (void) ctx;
+
+ y=FLIP(y);
+ lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP],
+ rgb[i][BCOMP]);
+ }
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ LPWORD lpw;
+ WORD pixel;
+ GLuint i;
+ PWMC pwc = Current;
+ (void) ctx;
+ lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ y=FLIP(y);
+ pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ lpw[i] = pixel;
+ }
+ else
+ for (i=0; i<n; i++)
+ *lpw++ = pixel;
+
+}
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwc, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+}
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ (void) ctx;
+ for (i=0; i<n; i++)
+ if (mask[i])
+ WMSETPIXEL16(pwc, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+}
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ PWMC pwc = Current;
+
+ y = FLIP(y);
+ lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y)) + x;
+ for (i=0; i<n; i++) {
+ pixel = lpw[i];
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels_16(const GLcontext* ctx,
+ struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4])
+{
+ GLuint i, pixel;
+ LPWORD lpw;
+ PWMC pwc = Current;
+
+ for (i=0; i<n; i++) {
+ GLint y2 = FLIP(y[i]);
+ lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * y2)) + x[i];
+ pixel = lpw[i];
+ /* Windows uses 5,5,5 for 16-bit */
+ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
+ rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
+ rgba[i][BCOMP] = (pixel & 0x001f) << 3;
+ rgba[i][ACOMP] = 255;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** BUFFER Functions *****/
+/**********************************************************************/
+
+
+
+
+static void
+wmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
+{
+ _mesa_free(rb);
+}
+
+static GLboolean
+wmesa_renderbuffer_storage(GLcontext *ctx,
+ struct gl_renderbuffer *rb,
+ GLenum internalFormat,
+ GLuint width,
+ GLuint height)
+{
+ return GL_TRUE;
+}
+
+/**
+ * Called by ctx->Driver.ResizeBuffers()
+ * Resize the front/back colorbuffers to match the latest window size.
+ */
+static void
+wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer,
+ GLuint width, GLuint height)
+{
+ if (Current->width != width || Current->height != height) {
+ Current->width = width;
+ Current->height = height;
+ /* Realloc back buffer */
+ if (Current->db_flag) {
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, width, height);
+ }
+ }
+ _mesa_resize_framebuffer(ctx, buffer, width, height);
+}
+
+
+/**
+ * Called by glViewport.
+ * This is a good time for us to poll the current window size and adjust
+ * our renderbuffers to match the current window size.
+ * Remember, we have no opportunity to respond to conventional
+ * resize events since the driver has no event loop.
+ * Thus, we poll.
+ * Note that this trick isn't fool-proof. If the application never calls
+ * glViewport, our notion of the current window size may be incorrect.
+ */
+static void wmesa_viewport(GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height)
+{
+ if (Current->width != width || Current->height != height) {
+ wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, width, height);
+ ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */
+ }
+}
+
+
+
+
+/**
+ * Called when the driver should update it's state, based on the new_state
+ * flags.
+ */
+static void wmesa_update_state(GLcontext *ctx, GLuint new_state)
+{
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _ac_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /* TODO - need code to update the span functions in case the
+ * renderer changes the target buffer (like a DB app writing to
+ * the front buffer). */
+}
+
+
+
+
+
+/**********************************************************************/
+/***** WMESA Functions *****/
+/**********************************************************************/
+
+WMesaContext WMesaCreateContext(HDC hDC,
+ HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag,
+ GLboolean alpha_flag)
+{
+ WMesaContext c;
+ struct dd_function_table functions;
+ struct gl_renderbuffer *rb;
+
+ (void) Pal;
+
+ /* Indexed mode not supported */
+ if (!rgb_flag)
+ return NULL;
+
+ c = CALLOC_STRUCT(wmesa_context);
+ if (!c)
+ return NULL;
+
+ /* Support memory and device contexts */
+ if(WindowFromDC(hDC) != NULL) {
+ c->hDC = GetDC(WindowFromDC(hDC));
+ }
+ else {
+ c->hDC = hDC;
+ }
+ c->width = GetDeviceCaps(c->hDC, HORZRES);
+ c->height = GetDeviceCaps(c->hDC, VERTRES);
+ c->clearPen = CreatePen(PS_SOLID, 1, 0);
+ c->clearBrush = CreateSolidBrush(0);
+
+ /* Create back buffer if double buffered */
+ if (db_flag) {
+ c->db_flag = 1;
+ wmCreateBackingStore(c, c->width, c->height);
+
+ }
+
+ c->gl_visual = _mesa_create_visual(rgb_flag,
+ db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8, /* color RGB */
+ alpha_flag ? 8 : 0, /* color A */
+ 0, /* index bits */
+ DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16, /* accum RGB */
+ alpha_flag ? 16 : 0, /* accum A */
+ 1);
+
+ if (!c->gl_visual) {
+ _mesa_free(c);
+ return NULL;
+ }
+
+ /* Set up driver functions */
+ _mesa_init_driver_functions(&functions);
+ /* Fill in required functions */
+ functions.GetString = wmesa_get_string;
+ functions.UpdateState = wmesa_update_state;
+ functions.GetBufferSize = wmesa_get_buffer_size;
+ functions.Flush = wmesa_flush;
+
+ functions.Clear = clear;
+ functions.ClearIndex = clear_index;
+ functions.ClearColor = clear_color;
+
+ functions.ResizeBuffers = wmesa_resize_buffers;
+ functions.Viewport = wmesa_viewport;
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = _mesa_create_context(c->gl_visual, NULL,
+ &functions, (void *)c);
+ if (!c->gl_ctx) {
+ _mesa_destroy_visual( c->gl_visual );
+ _mesa_free(c);
+ return NULL;
+ }
+
+ _mesa_enable_sw_extensions(c->gl_ctx);
+ _mesa_enable_1_3_extensions(c->gl_ctx);
+ _mesa_enable_1_4_extensions(c->gl_ctx);
+ _mesa_enable_1_5_extensions(c->gl_ctx);
+ _mesa_enable_2_0_extensions(c->gl_ctx);
+
+ c->gl_buffer = _mesa_create_framebuffer(c->gl_visual);
+ if (!c->gl_buffer) {
+ _mesa_destroy_visual(c->gl_visual);
+ _mesa_free_context_data(c->gl_ctx);
+ _mesa_free(c);
+ return NULL;
+ }
+
+ rb = CALLOC_STRUCT(gl_renderbuffer);
+
+ if (!rb) {
+ _mesa_destroy_visual(c->gl_visual);
+ _mesa_destroy_framebuffer(c->gl_buffer);
+ _mesa_free_context_data(c->gl_ctx);
+ _mesa_free(c);
+ return NULL;
+ }
+
+ _mesa_init_renderbuffer(rb, (GLuint)0);
+
+ rb->_BaseFormat = GL_RGBA;
+ rb->InternalFormat = GL_RGBA;
+ rb->DataType = CHAN_TYPE;
+ rb->Delete = wmesa_delete_renderbuffer;
+ rb->AllocStorage = wmesa_renderbuffer_storage;
+
+ if (db_flag) {
+ switch(c->cColorBits) {
+ case 16:
+ rb->PutRow = write_rgba_span_16;
+ rb->PutRowRGB = write_rgb_span_16;
+ rb->PutMonoRow = write_mono_rgba_span_16;
+ rb->PutValues = write_rgba_pixels_16;
+ rb->PutMonoValues = write_mono_rgba_pixels_16;
+ rb->GetRow = read_rgba_span_16;
+ rb->GetValues = read_rgba_pixels_16;
+ break;
+ case 32:
+ rb->PutRow = write_rgba_span_32;
+ rb->PutRowRGB = write_rgb_span_32;
+ rb->PutMonoRow = write_mono_rgba_span_32;
+ rb->PutValues = write_rgba_pixels_32;
+ rb->PutMonoValues = write_mono_rgba_pixels_32;
+ rb->GetRow = read_rgba_span_32;
+ rb->GetValues = read_rgba_pixels_32;
+ break;
+ default:
+ break;
+ }
+ _mesa_add_renderbuffer(c->gl_buffer, BUFFER_BACK_LEFT, rb);
+ }
+ else { /* single buffer */
+ rb->PutRow = write_rgba_span_single;
+ rb->PutRowRGB = write_rgb_span_single;
+ rb->PutMonoRow = write_mono_rgba_span_single;
+ rb->PutValues = write_rgba_pixels_single;
+ rb->PutMonoValues = write_mono_rgba_pixels_single;
+ rb->GetRow = read_rgba_span_single;
+ rb->GetValues = read_rgba_pixels_single;
+ _mesa_add_renderbuffer(c->gl_buffer, BUFFER_FRONT_LEFT, rb);
+ }
+
+ _mesa_add_soft_renderbuffers(c->gl_buffer,
+ GL_FALSE, /* color */
+ c->gl_visual->depthBits > 0,
+ c->gl_visual->stencilBits > 0,
+ c->gl_visual->accumRedBits > 0,
+ alpha_flag,
+ GL_FALSE);
+
+ /* Initialize the software rasterizer and helper modules. */
+ if (!_swrast_CreateContext(c->gl_ctx) ||
+ !_ac_CreateContext(c->gl_ctx) ||
+ !_tnl_CreateContext(c->gl_ctx) ||
+ !_swsetup_CreateContext(c->gl_ctx)) {
+ _mesa_destroy_visual(c->gl_visual);
+ _mesa_destroy_framebuffer(c->gl_buffer);
+ _mesa_free_context_data(c->gl_ctx);
+ _mesa_free(c);
+ return NULL;
+ }
+
+ _swsetup_Wakeup(c->gl_ctx);
+
+ TNL_CONTEXT(c->gl_ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+
+ return c;
+}
+
+void WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+
+ WMesaMakeCurrent(NULL);
+
+ /* Release for device, not memory contexts */
+ if(WindowFromDC(c->hDC) != NULL) {
+ ReleaseDC(WindowFromDC(c->hDC), c->hDC);
+ }
+ DeleteObject(c->clearPen);
+ DeleteObject(c->clearBrush);
+
+ if (c->db_flag)
+ wmDeleteBackingStore(c);
+
+ _swsetup_DestroyContext(c->gl_ctx);
+ _tnl_DestroyContext(c->gl_ctx);
+ _ac_DestroyContext(c->gl_ctx);
+ _swrast_DestroyContext(c->gl_ctx);
+
+ _mesa_destroy_visual(c->gl_visual);
+ _mesa_destroy_framebuffer(c->gl_buffer);
+ _mesa_free_context_data(c->gl_ctx);
+ _mesa_free(c->gl_ctx);
+ _mesa_free(c);
+}
+
+
+void WMesaMakeCurrent(WMesaContext c)
+{
+ /* return if already current */
+ if (Current == c)
+ return;
+
+ if (Current = c)
+ _mesa_make_current(c->gl_ctx, c->gl_buffer, c->gl_buffer);
+}
+
+
+void WMesaSwapBuffers( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (Current && Current->gl_ctx == ctx)
+ _mesa_notifySwapBuffers(ctx);
+
+ if (Current->db_flag)
+ wmesa_flush(ctx);
+}
+
+/**********************************************************************/
+/***** END *****/
+/**********************************************************************/