diff options
author | David Nusinow <[email protected]> | 2006-09-24 21:11:46 +0000 |
---|---|---|
committer | David Nusinow <[email protected]> | 2006-09-24 21:11:46 +0000 |
commit | eadb76b3f8e0e9b82da762bd29e53895bf9e6351 (patch) | |
tree | b9f68fc763f9ea055287c366e61de84191b200ce /src/mesa/drivers | |
parent | b3f7313ae4f4cd418522595e90e7d06ef6992f0a (diff) |
Bump to latest mesa in Debian
Diffstat (limited to 'src/mesa/drivers')
180 files changed, 42657 insertions, 1133 deletions
diff --git a/src/mesa/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c new file mode 100644 index 00000000000..cb46efa56ac --- /dev/null +++ b/src/mesa/drivers/allegro/amesa.c @@ -0,0 +1,404 @@ +/*
+ * Mesa 3-D graphics library
+ * Version: 3.0
+ * Copyright (C) 1995-1998 Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <allegro.h>
+#include "buffers.h"
+#include "context.h"
+#include "imports.h"
+#include "matrix.h"
+#include "mtypes.h" +#include "GL/amesa.h"
+
+
+struct amesa_visual
+ {
+ GLvisual *GLVisual; /* inherit from GLvisual */
+ GLboolean DBFlag; /* double buffered? */
+ GLuint Depth; /* bits per pixel ( >= 15 ) */
+ };
+
+
+struct amesa_buffer
+ {
+ GLframebuffer *GLBuffer; /* inherit from GLframebuffer */
+ GLuint Width, Height;
+ BITMAP *Screen;
+ BITMAP *Background;
+ BITMAP *Active;
+ };
+
+
+struct amesa_context
+ {
+ GLcontext *GLContext; /* inherit from GLcontext */
+ AMesaVisual Visual;
+ AMesaBuffer Buffer;
+ GLuint ClearColor;
+ GLuint CurrentColor;
+ };
+
+
+static void setup_dd_pointers(GLcontext *ctx);
+
+
+/**********************************************************************/
+/***** drawing functions *****/
+/**********************************************************************/
+
+#define FLIP(context, y) (context->Buffer->Height - (y) - 1)
+
+#include "allegro/generic.h"
+#include "allegro/direct.h"
+
+
+/**********************************************************************/
+/***** 15-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_RGB_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_READ_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_RGBA_PIXELS(15, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(15, unsigned short)
+IMPLEMENT_READ_RGBA_PIXELS(15, unsigned short)
+
+
+/**********************************************************************/
+/***** 16-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_RGB_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_READ_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_RGBA_PIXELS(16, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(16, unsigned short)
+IMPLEMENT_READ_RGBA_PIXELS(16, unsigned short)
+
+
+/**********************************************************************/
+/***** 32-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_RGB_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_READ_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_RGBA_PIXELS(32, unsigned long)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(32, unsigned long)
+IMPLEMENT_READ_RGBA_PIXELS(32, unsigned long)
+
+
+/**********************************************************************/
+/***** Miscellaneous device driver funcs *****/
+/**********************************************************************/
+
+static GLboolean set_buffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bit)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ GLboolean ok = GL_TRUE;
+
+ if (bit == DD_FRONT_LEFT_BIT)
+ context->Buffer->Active = context->Buffer->Screen;
+
+ else if (bit == DD_BACK_LEFT)
+ {
+ if (context->Buffer->Background)
+ context->Buffer->Active = context->Buffer->Background;
+ else
+ ok = GL_FALSE;
+ }
+
+ else
+ ok = GL_FALSE;
+
+ return ok;
+ }
+
+
+static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ *width = context->Buffer->Width;
+ *height = context->Buffer->Height;
+ }
+
+
+static void viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ /* poll for window size change and realloc software Z/stencil/etc if needed */
+ _mesa_ResizeBuffersMESA();
+}
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+static void setup_dd_pointers(GLcontext *ctx)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ /* Initialize all the pointers in the driver struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+
+ ctx->Driver.UpdateState = setup_dd_pointers;
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = get_buffer_size;
+ ctx->Driver.Viewport = viewport;
+
+ ctx->Driver.Color = set_color_generic;
+ ctx->Driver.ClearColor = clear_color_generic;
+ ctx->Driver.Clear = clear_generic;
+ ctx->Driver.WriteRGBASpan = write_rgba_span_generic;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_generic;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_generic;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_generic;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_generic;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_generic;
+
+ if (context->Buffer->Active != screen)
+ {
+ switch (context->Visual->Depth)
+ {
+ case 15:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_15;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_15;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_15;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_15;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_15;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_15;
+ break;
+
+ case 16:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_16;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_16;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_16;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_16;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_16;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_16;
+ break;
+
+ case 32:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_32;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_32;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_32;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_32;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_32;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_32;
+ break;
+ }
+ }
+ }
+
+
+/**********************************************************************/
+/***** AMesa Public API Functions *****/
+/**********************************************************************/
+
+
+AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
+ GLint depthSize, GLint stencilSize, GLint accumSize)
+ {
+ AMesaVisual visual;
+ GLbyte redBits, greenBits, blueBits;
+
+ visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
+ if (!visual)
+ return NULL;
+
+ switch (depth)
+ {
+ case 15:
+ redBits = 5;
+ greenBits = 5;
+ blueBits = 5;
+ break;
+
+ case 16:
+ redBits = 5;
+ greenBits = 6;
+ blueBits = 5;
+ break;
+
+ case 24: case 32:
+ redBits = 8;
+ greenBits = 8;
+ blueBits = 8;
+ break;
+
+ default:
+ free(visual);
+ return NULL;
+ }
+
+ visual->DBFlag = dbFlag;
+ visual->Depth = depth;
+ visual->GLVisual = _mesa_create_visual(GL_TRUE, /* rgb mode */
+ dbFlag, /* db_flag */
+ GL_FALSE, /* stereo */
+ redBits, greenBits, blueBits, 8,
+ 0, /* index bits */
+ depthSize, /* depth bits */
+ stencilSize,/* stencil bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ 1 );
+ if (!visual->GLVisual)
+ {
+ free(visual);
+ return NULL;
+ }
+
+ return visual;
+ }
+
+
+void AMesaDestroyVisual(AMesaVisual visual)
+ {
+ _mesa_destroy_visual(visual->GLVisual);
+ free(visual);
+ }
+
+
+AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
+ GLint width, GLint height)
+ {
+ AMesaBuffer buffer;
+
+ buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
+ if (!buffer)
+ return NULL;
+
+ buffer->Screen = NULL;
+ buffer->Background = NULL;
+ buffer->Active = NULL;
+ buffer->Width = width;
+ buffer->Height = height;
+
+ if (visual->DBFlag)
+ {
+ buffer->Background = create_bitmap_ex(visual->Depth, width, height);
+ if (!buffer->Background)
+ {
+ free(buffer);
+ return NULL;
+ }
+ }
+
+ buffer->GLBuffer = _mesa_create_framebuffer(visual->GLVisual);
+ if (!buffer->GLBuffer)
+ {
+ if (buffer->Background) destroy_bitmap(buffer->Background);
+ free(buffer);
+ return NULL;
+ }
+
+ return buffer;
+ }
+
+
+void AMesaDestroyBuffer(AMesaBuffer buffer)
+{
+ if (buffer->Screen) destroy_bitmap(buffer->Screen);
+ if (buffer->Background) destroy_bitmap(buffer->Background);
+ _mesa_destroy_framebuffer(buffer->GLBuffer);
+ free(buffer);
+}
+
+
+AMesaContext AMesaCreateContext(AMesaVisual visual,
+ AMesaContext share)
+{
+ AMesaContext context;
+ GLboolean direct = GL_FALSE;
+
+ context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
+ if (!context)
+ return NULL;
+
+ context->Visual = visual;
+ context->Buffer = NULL;
+ context->ClearColor = 0;
+ context->CurrentColor = 0;
+ context->GLContext = _mesa_create_context(visual->GLVisual,
+ share ? share->GLContext : NULL,
+ (void *) context, GL_FALSE );
+ if (!context->GLContext)
+ {
+ free(context);
+ return NULL;
+ }
+
+ return context;
+}
+
+
+void AMesaDestroyContext(AMesaContext context)
+{
+ _mesa_destroy_context(context->GLContext);
+ free(context);
+}
+
+
+GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
+{
+ if (context && buffer) {
+ set_color_depth(context->Visual->Depth);
+ if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
+ return GL_FALSE;
+
+ context->Buffer = buffer;
+ buffer->Screen = screen;
+ buffer->Active = buffer->Background ? buffer->Background : screen;
+
+ setup_dd_pointers(context->GLContext);
+ _mesa_make_current(context->GLContext, buffer->GLBuffer);
+ }
+ else {
+ /* XXX I don't think you want to destroy anything here! */ + destroy_bitmap(context->Buffer->Screen);
+ context->Buffer->Screen = NULL;
+ context->Buffer->Active = NULL;
+ context->Buffer = NULL;
+ _mesa_make_current(NULL, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+
+void AMesaSwapBuffers(AMesaBuffer buffer)
+{
+ if (buffer->Background) {
+ blit(buffer->Background, buffer->Screen,
+ 0, 0, 0, 0,
+ buffer->Width, buffer->Height);
+ }
+}
diff --git a/src/mesa/drivers/allegro/direct.h b/src/mesa/drivers/allegro/direct.h new file mode 100644 index 00000000000..3998fc19d7b --- /dev/null +++ b/src/mesa/drivers/allegro/direct.h @@ -0,0 +1,189 @@ +/*
+ * Mesa 3-D graphics library
+ * Version: 3.0
+ * Copyright (C) 1995-1998 Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#define DESTINATION(BMP, X, Y, TYPE) \
+ ({ \
+ BITMAP *_bmp = BMP; \
+ \
+ (TYPE*)(_bmp->line[_bmp->h - (Y) - 1]) + (X); \
+ })
+
+
+#define IMPLEMENT_WRITE_RGBA_SPAN(DEPTH, TYPE) \
+static void write_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ if (mask) \
+ { \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ d++; rgba++; mask++; \
+ } \
+ } \
+ else \
+ { \
+ while (n--) \
+ { \
+ d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ d++; rgba++; \
+ } \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_RGB_SPAN(DEPTH, TYPE) \
+static void write_rgb_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte rgb[][3], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ if (mask) \
+ { \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \
+ d++; rgb++; mask++; \
+ } \
+ } \
+ else \
+ { \
+ while (n--) \
+ { \
+ d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \
+ d++; rgb++; \
+ } \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_MONO_RGBA_SPAN(DEPTH, TYPE) \
+static void write_mono_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE color = context->CurrentColor; \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = color; \
+ d++; mask++; \
+ } \
+ }
+
+
+#define IMPLEMENT_READ_RGBA_SPAN(DEPTH, TYPE) \
+static void read_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ GLubyte rgba[][4]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ TYPE *d = DESTINATION(bmp, x, y, TYPE); \
+ \
+ while (n--) \
+ { \
+ rgba[0][RCOMP] = getr##DEPTH(d[0]); \
+ rgba[0][GCOMP] = getg##DEPTH(d[0]); \
+ rgba[0][BCOMP] = getb##DEPTH(d[0]); \
+ rgba[0][ACOMP] = 255; \
+ \
+ d++; rgba++; \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_RGBA_PIXELS(DEPTH, TYPE) \
+static void write_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ const GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ rgba++; x++; y++; mask++; \
+ } \
+ }
+
+
+
+#define IMPLEMENT_WRITE_MONO_RGBA_PIXELS(DEPTH, TYPE) \
+static void write_mono_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE color = context->CurrentColor; \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = color; \
+ x++; y++; mask++; \
+ } \
+ }
+
+
+#define IMPLEMENT_READ_RGBA_PIXELS(DEPTH, TYPE) \
+static void read_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) \
+ { \
+ int color = *DESTINATION(bmp, x[0], y[0], TYPE); \
+ \
+ rgba[0][RCOMP] = getr##DEPTH(color); \
+ rgba[0][GCOMP] = getg##DEPTH(color); \
+ rgba[0][BCOMP] = getb##DEPTH(color); \
+ rgba[0][ACOMP] = 255; \
+ } \
+ \
+ x++; y++; rgba++; mask++; \
+ } \
+ }
+
diff --git a/src/mesa/drivers/allegro/generic.h b/src/mesa/drivers/allegro/generic.h new file mode 100644 index 00000000000..cbdf5ff2b3a --- /dev/null +++ b/src/mesa/drivers/allegro/generic.h @@ -0,0 +1,234 @@ +/*
+ * Mesa 3-D graphics library
+ * Version: 3.0
+ * Copyright (C) 1995-1998 Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+static void clear_color_generic(GLcontext *ctx, const GLfloat color[4])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ GLubyte r, g, b;
+ CLAMPED_FLOAT_TO_UBYTE(r, color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(g, color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(b, color[2]);
+ context->ClearColor = makecol(r, g, b);
+ }
+
+
+static void set_color_generic(GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ context->CurrentColor = makecol(red, green, blue);
+ }
+
+
+static GLbitfield clear_generic(GLcontext *ctx,
+ GLbitfield mask, GLboolean all,
+ GLint x, GLint y,
+ GLint width, GLint height)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (all)
+ clear_to_color(context->Buffer->Active, context->ClearColor);
+ else
+ rect(context->Buffer->Active,
+ x, y, x+width-1, y+height-1,
+ context->ClearColor);
+ }
+
+ return mask & (~GL_COLOR_BUFFER_BIT);
+ }
+
+
+static void write_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; mask++; rgba++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; rgba++;
+ }
+ }
+ }
+
+
+static void write_rgb_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while(n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
+ x++; mask++; rgb++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
+ x++; rgb++;
+ }
+ }
+ }
+
+
+static void write_mono_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+ int color = context->CurrentColor;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while(n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, color);
+ x++; mask++;
+ }
+ }
+ else
+ {
+ while(n--)
+ {
+ putpixel(bmp, x, y, color);
+ x++;
+ }
+ }
+ }
+
+
+static void read_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ while (n--)
+ {
+ int color = getpixel(bmp, x, y);
+
+ rgba[0][RCOMP] = getr(color);
+ rgba[0][GCOMP] = getg(color);
+ rgba[0][BCOMP] = getb(color);
+ rgba[0][ACOMP] = 255;
+
+ x++; rgba++;
+ }
+ }
+
+
+static void write_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; y++; mask++;
+ }
+ }
+
+
+static void write_mono_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+ int color = context->CurrentColor;
+
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), color);
+ x++; y++; mask++;
+ }
+ }
+
+
+static void read_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ while (n--)
+ {
+ if (mask[0])
+ {
+ int color = getpixel(bmp, x[0], FLIP(context, y[0]));
+
+ rgba[0][RCOMP] = getr(color);
+ rgba[0][GCOMP] = getg(color);
+ rgba[0][BCOMP] = getb(color);
+ rgba[0][ACOMP] = 255;
+ }
+
+ x++; y++; mask++; rgba++;
+ }
+ }
+
diff --git a/src/mesa/drivers/d3d/D3DCAPS.CPP b/src/mesa/drivers/d3d/D3DCAPS.CPP new file mode 100644 index 00000000000..cd95ef0f1ee --- /dev/null +++ b/src/mesa/drivers/d3d/D3DCAPS.CPP @@ -0,0 +1,250 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver Build 5 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Macros. */
+/*===========================================================================*/
+#define SRCBLEND_MAP(gl,d3d,fall) if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwSrcBlendCaps & d3d ) \
+ { \
+ sprintf( buffer, "SRC Blend: %s -> %s", # gl, # d3d ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwSrcBlendCaps[index] = d3d; \
+ } \
+ else \
+ { \
+ sprintf( buffer, "SRC Blend: %s -> %s", # gl, # fall ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwSrcBlendCaps[index] = fall; \
+ }
+#define DSTBLEND_MAP(gl,d3d,fall) if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwDestBlendCaps & d3d ) \
+ { \
+ sprintf( buffer, "DST Blend: %s -> %s", # gl, # d3d ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwDestBlendCaps[index] = d3d; \
+ } \
+ else \
+ { \
+ sprintf( buffer, "DST Blend: %s -> %s", # gl, # fall ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwDestBlendCaps[index] = fall; \
+ }
+
+/*===========================================================================*/
+/* I use this function to handle the fact that the D3D texture blending and */
+/* OpenGL texture blending functions don't map one to one. Also there is the*/
+/* problem with cards not supporting all the D3D functions. So I use the CAPS*/
+/* of the card to make a table of functions that will have defaults for the */
+/* unsupported functions. */
+/* So first I fill the table with the fallback function then I check to see */
+/* if the card supports the requested function. If it does I replace the */
+/* default thats already in the array. Now order does matter as I used an */
+/* enum type in D3DShared.h so that the mapping would be a little easier. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void AlphaBlendTableHAL( PMESAD3DHAL pHAL )
+{
+ PMESAD3DSHARED pShared = &pHAL->shared;
+ int index;
+ char buffer[128];
+
+ DPF(( DBG_FUNC, "AlphaBlendTableHAL();" ));
+
+ /* Make the fallback for the Source blend. */
+ for( index = 0; index < 14; index++ )
+ {
+ switch( index )
+ {
+ case s_zero:
+ SRCBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
+ break;
+ case s_one:
+ SRCBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
+ break;
+ case s_dst_color:
+ SRCBLEND_MAP( GL_DST_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
+ break;
+ case s_one_minus_dst_color:
+ SRCBLEND_MAP( GL_ONE_MINUS_DST_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
+ break;
+ case s_src_alpha:
+ SRCBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_src_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_dst_alpha:
+ SRCBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_dst_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
+ break;
+ case s_src_alpha_saturate:
+ SRCBLEND_MAP( GL_SRC_ALPHA_SATURATE, D3DBLEND_SRCALPHASAT, D3DBLEND_ONE );
+ break;
+ case s_constant_color:
+ SRCBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
+ break;
+ case s_one_minus_constant_color:
+ SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
+ break;
+ case s_constant_alpha:
+ SRCBLEND_MAP( GL_CONSTANT_ALPHA, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_constant_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
+ break;
+ }
+ }
+
+ /* Make the fallback for the Destination blend. */
+ for( index = 0; index < 14; index++ )
+ {
+ switch( index )
+ {
+ case d_zero:
+ DSTBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
+ break;
+ case d_one:
+ DSTBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
+ break;
+ case d_src_color:
+ DSTBLEND_MAP( GL_SRC_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
+ break;
+ case d_one_minus_src_color:
+ DSTBLEND_MAP( GL_ONE_MINUS_SRC_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
+ break;
+ case d_src_alpha:
+ DSTBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_src_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_dst_alpha:
+ DSTBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_dst_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
+ break;
+ case d_constant_color:
+ DSTBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
+ break;
+ case d_one_minus_constant_color:
+ DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
+ break;
+ case d_constant_alpha:
+ DSTBLEND_MAP( GL_CONSTANT_ALPHAR, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_constant_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
+ break;
+ }
+ }
+
+ /* Make the fallbacks for the texture functions. */
+ for( index = 0; index < 4; index++ )
+ {
+ switch( index )
+ {
+ case d3dtblend_decal:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_decalalpha:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECALALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_DECALALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECALALPHA;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPA -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_modulate:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATEALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA;
+ }
+ else if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_modulatealpha:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATEALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_DECALE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ }
+ }
+}
+
diff --git a/src/mesa/drivers/d3d/D3DHAL.H b/src/mesa/drivers/d3d/D3DHAL.H new file mode 100644 index 00000000000..5295520d7be --- /dev/null +++ b/src/mesa/drivers/d3d/D3DHAL.H @@ -0,0 +1,68 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _D3D_HAL_INC
+#define _D3D_HAL_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <time.h>
+#include "D3DShared.h"
+#include "D3DTextureMgr.h"
+#include "Debug.h"
+/*===========================================================================*/
+/* Defines. */
+/*===========================================================================*/
+#define DX_RESTORE(ps) if ( (ps) && (ps)->IsLost() ) (ps)->Restore();
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _d3d_hal_struct
+{
+ MESAD3DSHARED shared;
+
+ GUID guid;
+ LPDIRECTDRAW lpDD;
+ LPDIRECTDRAW4 lpDD4;
+ LPDIRECT3D3 lpD3D3;
+ LPDIRECT3DDEVICE3 lpD3DDevice;
+ D3DDEVICEDESC D3DHWDevDesc;
+ LPDIRECTDRAWSURFACE4 lpDDSPrimary,
+ lpDDSRender,
+ lpDDSZbuffer;
+ LPDIRECT3DVIEWPORT3 lpViewport;
+ LPDIRECTDRAWCLIPPER lpClipper;
+ DDPIXELFORMAT ddpf,
+ ddpfZBuffer;
+ PTM_OBJECT pTMList;
+
+} MESAD3DHAL, *PMESAD3DHAL;
+/*===========================================================================*/
+/* External function prototypes. */
+/*===========================================================================*/
+extern BOOL InitTMgrHAL( PMESAD3DHAL pHAL );
+extern void TermTMgrHAL( PMESAD3DHAL pHAL );
+extern void AlphaBlendTableHAL( PMESAD3DHAL pHAL );
+
+extern void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel );
+extern char *ErrorStringD3D( HRESULT hr );
+extern void FatalShutDown( PMESAD3DHAL pHAL );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern char *errorMsg;
+
+#endif
+
diff --git a/src/mesa/drivers/d3d/D3DInit.cpp b/src/mesa/drivers/d3d/D3DInit.cpp new file mode 100644 index 00000000000..ba7891612e4 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DInit.cpp @@ -0,0 +1,891 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver Build 5 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local function prototypes. */
+/*===========================================================================*/
+static void DestroyAllSurfaces( PMESAD3DHAL pHAL );
+static void DestroyDevice( PMESAD3DHAL pHAL );
+static void DestroyInterfaces( PMESAD3DHAL pHAL );
+
+HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid );
+HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid );
+HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc, void *pVoid );
+/*===========================================================================*/
+/* Globals. */
+/*===========================================================================*/
+//char *errorMsg;
+/*===========================================================================*/
+/* This function is responable for allocating the actual MESAD3DHAL struct. */
+/* Each Mesa context will have its own MESAD3DHAL struct so its like a mini */
+/* context to some extent. All one time allocations/operations get done here.*/
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" PMESAD3DSHARED InitHAL( HWND hwnd )
+{
+ PMESAD3DHAL pHAL;
+ ULONG rc;
+
+ DPF(( DBG_FUNC, "InitHAL();" ));
+ DPF(( DBG_CNTX_INFO, "hwnd: %d", hwnd ));
+
+ /* Allocate the structure and zero it out. */
+ pHAL = (PMESAD3DHAL)ALLOC( sizeof(MESAD3DHAL) );
+ if ( pHAL == NULL )
+ {
+ RIP( pHAL, "InitHAL->", "Memory Allocation" );
+ return (PMESAD3DSHARED)NULL;
+ }
+ memset( pHAL, 0, sizeof(MESAD3DHAL) );
+
+ /* Get the texture manager going. */
+ rc = InitTMgrHAL( pHAL );
+ if ( rc == FALSE )
+ {
+ RIP( pHAL, "InitTMgrHAL->", "Failed" );
+ return (PMESAD3DSHARED)NULL;
+ }
+
+ /* Fill in the window parameters if we can. */
+ pHAL->shared.hwnd = hwnd;
+
+ /* Parse the user's enviroment variables to generate a debug mask. */
+ ReadDBGEnv();
+
+ return (PMESAD3DSHARED)pHAL;
+}
+/*===========================================================================*/
+/* This function will unload all the resources that the MESAD3DHAL struct */
+/* has bound to it. The actual structure itself will be freed. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void TermHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+ DPF(( DBG_FUNC, "TermHAL();" ));
+
+ /* Check for an empty wrapper structure. */
+ if ( pHAL == NULL )
+ return;
+
+ /* Kill this texture manager. */
+ TermTMgrHAL( pHAL );
+
+ /* Kill any DDraw stuff if exists. */
+ DestroyDevice( pHAL );
+ DestroyAllSurfaces( pHAL );
+ DestroyInterfaces( pHAL );
+
+ FREE( pHAL );
+}
+/*===========================================================================*/
+/* This function is used to init and resize the rendering surface as the two*/
+/* are almost the same. First the device and all the surfaces are destoryed */
+/* if they already exist. Next we create a OffScreen rendering surface and */
+/* save some pixelformat info to do color convertions. Next we start to take */
+/* care of getting the most out of the hardware. I use bHardware to determine*/
+/* the state of the device we found in the device enumeration. The enum proc*/
+/* will try for hardware first. I next use a bForceSW to make the enum proc */
+/* choose a software device. So I will try some combinations with HW first */
+/* until I feel I have to set the bForceSW and call this function again. If */
+/* this function is called with no width or height then use the internals. */
+/* NOTE: The worst case is that all will be in SW (RGBDevice) and really */
+/* I should forget the whole thing and fall back to a DDraw span type*/
+/* rendering but what is the point. This way I always know I have a */
+/* D3DDevice and that makes things easier. I do impliment the span */
+/* rendering function for stuff that I haven't done support for such */
+/* as points and lines. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE */
+/*===========================================================================*/
+extern "C" BOOL CreateHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ DDSURFACEDESC2 ddsd2;
+ D3DDEVICEDESC D3DSWDevDesc;
+ DDSCAPS2 ddscaps;
+ DWORD dwCoopFlags,
+ dwWidth,
+ dwHeight;
+ ULONG rc;
+
+ DPF(( DBG_FUNC, "CreateHAL();" ));
+
+#define InitDDSD2(f) memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); \
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 ); \
+ ddsd2.dwFlags = f;
+
+ if ( pHAL == NULL )
+ return FALSE;
+
+ /* Use the internal rectangle struct. */
+ dwWidth = pShared->rectW.right - pShared->rectW.left;
+ dwHeight = pShared->rectW.bottom - pShared->rectW.top;
+
+ DPF(( DBG_CNTX_INFO, "Width: %d Height: %d", dwWidth, dwHeight ));
+
+ /* The dimensions might still be the same so just leave. */
+ if ( (dwWidth == pShared->dwWidth) && (dwHeight == pShared->dwHeight) )
+ {
+ DPF(( DBG_CNTX_WARN, "Context size hasn't changed" ));
+ return TRUE;
+ }
+
+ /* If one of the dimensions are zero then leave. WM_SIZE should get us back here. */
+ if ( (dwWidth == 0) || (dwHeight == 0) )
+ return TRUE;
+
+ /* Save the renders dimensions. */
+ pShared->dwWidth = dwWidth;
+ pShared->dwHeight = dwHeight;
+
+ DPF(( DBG_CNTX_INFO, "Creating Context:\n cx:%d cy:%d", pShared->dwWidth, pShared->dwHeight ));
+
+ /*=================================*/
+ /* Create all required interfaces. */
+ /*=================================*/
+
+ /* Kill any DDraw stuff if exists. */
+ DestroyDevice( pHAL );
+ DestroyAllSurfaces( pHAL );
+ DestroyInterfaces( pHAL );
+
+ /* Create a instance of DDraw using the Primary display driver. */
+ rc = DirectDrawCreate( NULL, &pHAL->lpDD, NULL );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "DirectDrawCreate->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the DDraw4 interface. */
+ rc = pHAL->lpDD->QueryInterface( IID_IDirectDraw4, (void **)&pHAL->lpDD4 );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "QueryInterface (IID_IDirectDraw4) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the Direct3D3 interface. */
+ rc = pHAL->lpDD4->QueryInterface( IID_IDirect3D3, (void **)&pHAL->lpD3D3 );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "QueryInterface (IID_IDirect3D3) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Set the Cooperative level. NOTE: we need to know if we are FS at this point.*/
+ dwCoopFlags = (pShared->bWindow == TRUE) ? DDSCL_NORMAL : (DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ rc = pHAL->lpDD4->SetCooperativeLevel( pShared->hwnd, dwCoopFlags );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "SetCooperativeLevel->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /*==================================================================*/
+ /* Get the best device we can and note whether its hardware or not. */
+ /*==================================================================*/
+ pShared->bForceSW = FALSE;
+ pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
+ pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
+ DPF(( DBG_CNTX_INFO, "bHardware: %s", (pShared->bHardware) ? "TRUE" : "FALSE" ));
+ DPF(( DBG_CNTX_INFO, "bWindowed: %s", (pShared->bWindow) ? "TRUE" : "FALSE" ));
+
+ /*========================================================================*/
+ /* HARDWARE was found. */
+ /*========================================================================*/
+ if ( pShared->bHardware == TRUE )
+ {
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER. */
+ /*===================================*/
+
+ /* Get a Z-Buffer pixelformat. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ rc = pHAL->lpD3D3->EnumZBufferFormats( pHAL->guid, EnumZBufferHook, (VOID*)&ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumZBufferFormatsl->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Setup our request structure for the Z-buffer surface. */
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSZbuffer, NULL );
+ if ( !FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_INFO, "HW ZBuffer" ));
+
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER -> FLIPABLE */
+ /*===================================*/
+ if ( pShared->bWindow == FALSE )
+ {
+ InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
+ ddsd2.dwBackBufferCount = 1;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* Make sure we try the next fall back. */
+ DPF(( DBG_CNTX_WARN, "HW Flip/Complex not available" ));
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* Get the back buffer that was created. */
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> HW Flip/Complex" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* I have had problems when a complex surface comes back */
+ /* with the back buffer being created in SW. Not sure why */
+ /* or how this is possable but I'm checking for it here. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* If the surface is in VID then we are happy with are Flipable. */
+ if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
+ {
+ pShared->bFlipable = TRUE;
+ DPF(( DBG_CNTX_INFO, "HW Flip/Complex!" ));
+ }
+ else
+ {
+ /* Kill this setup. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ }
+ }
+ }
+
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER -> BLT */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary == NULL )
+ {
+ pShared->bFlipable = FALSE;
+
+ /* Create the Primary (front buffer). */
+ InitDDSD2( DDSD_CAPS );
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* This is an error as we should be able to do this at minimum. */
+ RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the Render (back buffer). */
+ InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed HW Offscreen surface" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* Might as well check here too see if this surface is in */
+ /* hardware. If nothing else just to be consistant. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* If the surface is in VID then we are happy. */
+ if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
+ {
+ /* Create a clipper object so that DDraw will be able to blt windows that */
+ /* have been clipped by the screen or other windows. */
+ pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
+ pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
+ pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
+ pHAL->lpClipper->Release();
+ DPF(( DBG_CNTX_INFO, "HW RENDER surface" ));
+ }
+ else
+ {
+ /* Kill this setup. */
+ pHAL->lpDDSRender->Release();
+ pHAL->lpDDSRender = NULL;
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ }
+ }
+
+ /*===================================*/
+ /* Create D3DDEVICE -> HARDWARE. */
+ /*===================================*/
+ if ( pHAL->lpDDSZbuffer && pHAL->lpDDSPrimary && pHAL->lpDDSRender )
+ {
+ DX_RESTORE( pHAL->lpDDSRender );
+ DX_RESTORE( pHAL->lpDDSZbuffer );
+
+ rc = pHAL->lpDDSRender->AddAttachedSurface( pHAL->lpDDSZbuffer );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "AddAttachedSurface (ZBUFFER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DHALDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
+ if ( rc != D3D_OK )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed HW Device" ));
+ pHAL->lpD3DDevice = NULL;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "HW Device" ));
+ }
+ }
+ }
+ }
+
+ /*========================================================================*/
+ /* SOFTWARE fallback. */
+ /*========================================================================*/
+ if ( pHAL->lpD3DDevice == NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "SW fallback :(" ));
+
+ /* Make sure we have no surfaces allocated. Just incase. */
+ DestroyAllSurfaces( pHAL );
+
+ /* Get a software device. */
+ pShared->bFlipable = FALSE;
+ pShared->bForceSW = TRUE;
+ pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
+ pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER. */
+ /*===================================*/
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER -> FLIPABLE */
+ /*===================================*/
+ if ( pShared->bWindow == FALSE )
+ {
+ InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
+ ddsd2.dwBackBufferCount = 1;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed SW Flip/Complex" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
+ if ( FAILED(rc) )
+ {
+ /* Make sure we try the next fall back. */
+ DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> SW Flip/Complex" ));
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "SW Flip/Complex" ));
+ pShared->bFlipable = TRUE;
+ }
+ }
+ }
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER -> BLT */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary == NULL )
+ {
+ /* Create the Primary (front buffer). */
+ InitDDSD2( DDSD_CAPS );
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* This is an error as we should be able to do this at minimum. */
+ RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the Render (back buffer). */
+ InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
+ if ( FAILED(rc) )
+ {
+ /* That was our last hope. */
+ RIP( pHAL, "CreateSurface (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "SW RENDER surface" ));
+
+ /* Create a clipper object so that DDraw will be able to blt windows that */
+ /* have been clipped by the screen or other windows. */
+ pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
+ pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
+ pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
+ pHAL->lpClipper->Release();
+ }
+ }
+
+ /*===================================*/
+ /* Create D3DDEVICE -> SOFTWARE. */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary && pHAL->lpDDSRender )
+ {
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DRGBDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
+ if ( rc != D3D_OK )
+ {
+ /* That was our last hope. */
+ RIP( pHAL, "CreateDevice (IID_IDirect3DRGBDevice) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ DPF(( DBG_CNTX_INFO, "SW Device" ));
+ }
+ }
+
+ /*==============================================================================*/
+ /* Get a copy of the render pixelformat so that wgl.c can call GetPixelInfoD3D. */
+ /*==============================================================================*/
+ memset( &pHAL->ddpf, 0, sizeof(DDPIXELFORMAT) );
+ pHAL->ddpf.dwSize = sizeof( DDPIXELFORMAT );
+ rc = pHAL->lpDDSRender->GetPixelFormat( &pHAL->ddpf );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetPixelFormat ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+ DebugPixelFormat( "Using OFFSCREEN", &pHAL->ddpf );
+ DebugPixelFormat( "Using ZBUFFER", &ddsd2.ddpfPixelFormat );
+
+ /* Get a copy of what the D3DDevice supports for later use. */
+ memset( &D3DSWDevDesc, 0, sizeof(D3DDEVICEDESC) );
+ memset( &pHAL->D3DHWDevDesc, 0, sizeof(D3DDEVICEDESC) );
+ D3DSWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
+ pHAL->D3DHWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
+ rc = pHAL->lpD3DDevice->GetCaps( &pHAL->D3DHWDevDesc, &D3DSWDevDesc );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetCaps ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get a copy of the pixel convertion stuff for direct buffer access. */
+ Solve8BitChannelPixelFormat( &pHAL->ddpf, &pShared->pixel );
+ AlphaBlendTableHAL( pHAL );
+
+ /* We must prime the Begin/End scene for SwapBuffers to work. */
+ rc = pHAL->lpD3DDevice->BeginScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+#undef InitDDSD2
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will make sure a viewport is created and set for the device*/
+/* in the supplied structure. If a rect is supplied then it will be used for*/
+/* the viewport otherwise the current setting in the strucute will be used. */
+/* Note that the rect is relative to the window. So left/top must be 0,0 to */
+/* use the whole window else there is scissoring going down. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ D3DVIEWPORT2 vdData;
+ ULONG rc;
+ POINT pt;
+
+ DPF(( DBG_FUNC, "SetViewportHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( !pHAL || !pHAL->lpDDSPrimary || !pHAL->lpD3DDevice )
+ {
+ DPF(( DBG_CNTX_WARN, "SetViewport() -> NULL Pointer" ));
+ return FALSE;
+ }
+
+ /* TODO: this is just a temp fix to stop redundant changes. */
+ if ( pRect &&
+ (pShared->rectV.left == pRect->left) &&
+ (pShared->rectV.right == pRect->right) &&
+ (pShared->rectV.top == pRect->top) &&
+ (pShared->rectV.bottom == pRect->bottom) )
+ {
+ DPF(( DBG_CNTX_WARN, "Redundant viewport" ));
+ return TRUE;
+ }
+
+ DPF(( DBG_CNTX_INFO, "Current Viewport:" ));
+ DPF(( DBG_CNTX_INFO, "x: %d y: %d", pShared->rectV.left, pShared->rectV.top ));
+ DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pShared->rectV.right-pShared->rectV.left), (pShared->rectV.bottom-pShared->rectV.top) ));
+ DPF(( DBG_CNTX_INFO, "New Viewport:" ));
+ DPF(( DBG_CNTX_INFO, "x: %d y: %d", pRect->left, pRect->top ));
+ DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pRect->right-pRect->left), (pRect->bottom-pRect->top) ));
+
+ /* Update the current viewport rect if one is supplied. */
+ if ( pRect )
+ memcpy( &pShared->rectV, pRect, sizeof(RECT) );
+
+ /* Build the request structure. */
+ memset( &vdData, 0, sizeof(D3DVIEWPORT2) );
+ vdData.dwSize = sizeof(D3DVIEWPORT2);
+ vdData.dwX = pShared->rectV.left;
+ vdData.dwY = pShared->rectV.top;
+ vdData.dwWidth = (pShared->rectV.right - pShared->rectV.left);
+ vdData.dwHeight = (pShared->rectV.bottom - pShared->rectV.top);
+
+ if ( !vdData.dwWidth || !vdData.dwHeight )
+ {
+ GetClientRect( pShared->hwnd, &pShared->rectW );
+ pt.x = pt.y = 0;
+ ClientToScreen( pShared->hwnd, &pt );
+ OffsetRect( &pShared->rectW, pt.x, pt.y);
+ vdData.dwX = pShared->rectW.left;
+ vdData.dwY = pShared->rectW.top;
+ vdData.dwWidth = (pShared->rectW.right - pShared->rectW.left);
+ vdData.dwHeight = (pShared->rectW.bottom - pShared->rectW.top);
+ memcpy( &pShared->rectV, &pShared->rectW, sizeof(RECT) );
+ }
+
+ // The dvClipX, dvClipY, dvClipWidth, dvClipHeight, dvMinZ,
+ // and dvMaxZ members define the non-normalized post-perspective
+ // 3-D view volume which is visible to the viewer. In most cases,
+ // dvClipX is set to -1.0 and dvClipY is set to the inverse of
+ // the viewport's aspect ratio on the target surface, which can be
+ // calculated by dividing the dwHeight member by dwWidth. Similarly,
+ // the dvClipWidth member is typically 2.0 and dvClipHeight is set
+ // to twice the aspect ratio set in dwClipY. The dvMinZ and dvMaxZ
+ // are usually set to 0.0 and 1.0.
+ vdData.dvClipX = -1.0f;
+ vdData.dvClipWidth = 2.0f;
+ vdData.dvClipY = 1.0f;
+ vdData.dvClipHeight = 2.0f;
+ vdData.dvMaxZ = maxZ;
+ vdData.dvMinZ = minZ;
+
+ DPF(( DBG_CNTX_INFO, "zMin: %f zMax: %f", minZ, maxZ ));
+
+ /* I'm going to destroy the viewport everytime as when we size we will */
+ /* have a new D3DDevice. As this area doesn't need to be fast... */
+ if ( pHAL->lpViewport )
+ {
+ DPF(( DBG_CNTX_INFO, "DeleteViewport" ));
+
+ pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
+ rc = pHAL->lpViewport->Release();
+ pHAL->lpViewport = NULL;
+ }
+
+ rc = pHAL->lpD3D3->CreateViewport( &pHAL->lpViewport, NULL );
+ if ( rc != D3D_OK )
+ {
+ DPF(( DBG_CNTX_ERROR, "CreateViewport Failed" ));
+ return FALSE;
+ }
+
+ /* Update the device with the new viewport. */
+ pHAL->lpD3DDevice->AddViewport( pHAL->lpViewport );
+ pHAL->lpViewport->SetViewport2( &vdData );
+ pHAL->lpD3DDevice->SetCurrentViewport( pHAL->lpViewport );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid )
+{
+ DDSURFACEDESC2 *pddsd2 = (DDSURFACEDESC2 *)pVoid;
+
+ DPF(( DBG_FUNC, "EnumSurfacesHook();" ));
+
+ if ( (lpDDSDesc->ddpfPixelFormat.dwFlags == pddsd2->ddpfPixelFormat.dwFlags) && (lpDDSDesc->ddsCaps.dwCaps == pddsd2->ddsCaps.dwCaps) )
+ {
+ /* Save the pixelformat now so that we know we have one. */
+ memcpy( pddsd2, lpDDSDesc, sizeof(DDSURFACEDESC2) );
+
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This is the callback proc to get a Z-Buffer. Thats it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid )
+{
+ DDPIXELFORMAT *pddpfChoice = (DDPIXELFORMAT *)pVoid;
+
+ DPF(( DBG_FUNC, "EnumZBufferHook();" ));
+
+ /* If this is ANY type of depth-buffer, stop. */
+ if( pddpf->dwFlags == DDPF_ZBUFFER )
+ {
+ /* Save the pixelformat now so that we know we have one. */
+ memcpy( pddpfChoice, pddpf, sizeof(DDPIXELFORMAT) );
+
+ /* I feel if the hardware supports this low then lets use it. Could get ugly. */
+ if( pddpf->dwZBufferBitDepth >= 8 )
+ {
+ return D3DENUMRET_CANCEL;
+ }
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This function handles the callback for the D3DDevice enumeration. Good */
+/* god who's idea was this? The D3D wrapper has two variable related to what*/
+/* kind of device we want and have. First we have a Bool that is set if we */
+/* have allocated a HW device. We always look for the HW device first. The */
+/* other variable is used to force SW. If we have run into a case that we */
+/* want to fallback to SW then we set this. We will fallback if we cannot */
+/* texture in video memory (among others). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc, void *pVoid )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pVoid;
+ LPD3DDEVICEDESC pChoice = lpD3DHWDesc;
+
+ DPF(( DBG_FUNC, "EnumDeviceHook();" ));
+
+ /* Determine if which device description is valid. */
+ if ( pChoice->dcmColorModel == 0 )
+ pChoice = lpD3DHELDesc;
+
+ /* Make sure we always have a GUID. */
+ memcpy( &pHAL->guid, lpGuid, sizeof(GUID) );
+
+ /* This controls whether we will except HW or not. */
+ if ( pHAL->shared.bForceSW == TRUE )
+ {
+ return (pChoice == lpD3DHELDesc) ? D3DENUMRET_CANCEL : D3DENUMRET_OK;
+ }
+
+ /* Always try for hardware. */
+ if ( pChoice == lpD3DHWDesc )
+ {
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This function will destroy any and all surfaces that this context has */
+/* allocated. If there is a clipper object then it will also be destoryed as*/
+/* it is part of the Primary Surface. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyAllSurfaces( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyAllSurfaces();" ));
+
+ DX_RESTORE( pHAL->lpDDSPrimary );
+ DX_RESTORE( pHAL->lpDDSRender );
+ DX_RESTORE( pHAL->lpDDSZbuffer);
+
+ if ( pHAL->lpDDSRender )
+ {
+ pHAL->lpDDSRender->Unlock( NULL );
+
+ /* If this isn't a Flipable surface then we must clean up the render. */
+ if ( pHAL->shared.bFlipable == FALSE)
+ {
+ if ( pHAL->lpDDSZbuffer )
+ {
+ DPF(( DBG_CNTX_INFO, "Remove attached surfaces from RENDER" ));
+ pHAL->lpDDSRender->DeleteAttachedSurface( 0, NULL );
+ }
+
+ DPF(( DBG_CNTX_INFO, "Release RENDER" ));
+ refCount = pHAL->lpDDSRender->Release();
+ pHAL->lpDDSRender = NULL;
+ }
+ }
+
+ if ( pHAL->lpDDSZbuffer )
+ {
+ DPF(( DBG_CNTX_INFO, "Release ZBuffer" ));
+ pHAL->lpDDSZbuffer->Unlock( NULL );
+ refCount = pHAL->lpDDSZbuffer->Release();
+ pHAL->lpDDSZbuffer = NULL;
+ }
+
+ if ( pHAL->lpClipper )
+ {
+ DPF(( DBG_CNTX_INFO, "Release Clipper" ));
+ refCount = pHAL->lpClipper->Release();
+ pHAL->lpClipper = NULL;
+ }
+
+ if ( pHAL->lpDDSPrimary )
+ {
+ pHAL->lpDDSPrimary->Unlock( NULL );
+
+ DPF(( DBG_CNTX_INFO, "Release PRIMARY" ));
+ refCount = pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will destroy the current D3DDevice and any resources that */
+/* belong to it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyDevice( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyDevice();" ));
+
+ /* Kill the D3D stuff if exists. */
+ if ( pHAL->lpViewport )
+ {
+ DPF(( DBG_CNTX_INFO, "Delete Viewport" ));
+ pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
+
+ DPF(( DBG_CNTX_INFO, "Release Viewport" ));
+ refCount = pHAL->lpViewport->Release();
+ pHAL->lpViewport = NULL;
+ }
+
+ if ( pHAL->lpD3DDevice != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release D3DDevice" ));
+ refCount = pHAL->lpD3DDevice->EndScene();
+ refCount = pHAL->lpD3DDevice->Release();
+ pHAL->lpD3DDevice = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will destroy the current D3DDevice and any resources that */
+/* belong to it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyInterfaces( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyInterfaces();" ));
+
+ if ( pHAL->lpD3D3 != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release Direct3D3" ));
+ refCount = pHAL->lpD3D3->Release();
+ pHAL->lpD3D3 = NULL;
+ }
+
+ if ( pHAL->lpDD4 != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release DDraw4" ));
+ refCount = pHAL->lpDD4->Release();
+ pHAL->lpDD4 = NULL;
+ }
+
+ if ( pHAL->lpDD != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release DDraw" ));
+ refCount = pHAL->lpDD->Release();
+ pHAL->lpDD = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will first send (not post) a message to the client window */
+/* that this context is using. The client will respond by unbinding itself */
+/* and binding the 'default' context. This allows the API to be supported */
+/* until the window can be destroyed. Finally we post the quit message to */
+/* the client in hopes to end the application. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void FatalShutDown( PMESAD3DHAL pHAL )
+{
+ /* Whip this baby in too try and support the API until we die... */
+ if ( pHAL )
+ SendMessage( pHAL->shared.hwnd, UM_FATALSHUTDOWN, 0L, 0L );
+
+ /* Close the client application down. */
+ PostQuitMessage( 0 );
+}
+
diff --git a/src/mesa/drivers/d3d/D3DMESA.H b/src/mesa/drivers/d3d/D3DMESA.H new file mode 100644 index 00000000000..074ceca816a --- /dev/null +++ b/src/mesa/drivers/d3d/D3DMESA.H @@ -0,0 +1,84 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef D3D_MESA_H
+#define D3D_MESA_H
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "matrix.h"
+#include "context.h"
+#include "mtypes.h" +#include "vb.h"
+#include "D3DShared.h"
+#include "Debug.h"
+#include "NULLProcs.h"
+/*===========================================================================*/
+/* Macros. */
+/*===========================================================================*/
+#define FLIP(h,y) (h-y)
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+struct __extensions__
+{
+ PROC proc;
+ char *name;
+};
+
+typedef GLbitfield (*ClearPROC)( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+typedef void (*WSpanRGBPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
+typedef void (*WSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+typedef void (*WSpanRGBAMonoPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
+typedef void (*WPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+typedef void (*WPixelsRGBAMonoPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
+typedef void (*RSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+typedef void (*RPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+typedef struct D3D_mesa_context
+{
+ PMESAD3DSHARED pShared;
+
+ GLcontext *gl_ctx; /* The core GL/Mesa context */
+ GLvisual *gl_visual; /* Describes the buffers */
+ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
+
+ HDC hdc;
+ WNDPROC hOldProc;
+
+ UCHAR rClear, /* Current clear colors. */
+ gClear,
+ bClear,
+ aClear,
+ rCurrent, /* Current rendering colors. */
+ gCurrent,
+ bCurrent,
+ aCurrent;
+
+ struct D3D_mesa_context *next;
+
+} D3DMESACONTEXT, *PD3DMESACONTEXT;
+/*===========================================================================*/
+/* Extern function prototypes. */
+/*===========================================================================*/
+extern void gl_Viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern D3DTLVERTEX D3DTLVertices[(VB_MAX*6)];
+
+#endif
+
diff --git a/src/mesa/drivers/d3d/D3DRaster.cpp b/src/mesa/drivers/d3d/D3DRaster.cpp new file mode 100644 index 00000000000..004bb773603 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DRaster.cpp @@ -0,0 +1,213 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* This function clears the context bound to the supplied shared context. */
+/* The function takes the D3D flags D3DCLEAR_TARGET, D3DCLEAR_STENCIL and */
+/* D3DCLEAR_ZBUFFER. Set bAll to TRUE for a full clear else supply the coord*/
+/* of the rect to be cleared relative to the window. The color is always a */
+/* 32bit value (RGBA). Fill in the z-value and stencil if needed. */
+/* */
+/* TODO: this can be redone to be called by Mesa directly. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ D3DRECT d3dRect;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "CleaHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpViewport == NULL) )
+ return;
+#endif
+
+ if ( bAll )
+ {
+ /* I assume my viewport is valid. */
+ d3dRect.lX1 = pShared->rectV.left;
+ d3dRect.lY1 = pShared->rectV.top;
+ d3dRect.lX2 = pShared->rectV.right;
+ d3dRect.lY2 = pShared->rectV.bottom;
+ }
+ else
+ {
+ d3dRect.lX1 = pShared->rectV.left + x;
+ d3dRect.lY1 = pShared->rectV.top + y;
+ d3dRect.lX2 = d3dRect.lX1 + cx;
+ d3dRect.lY2 = d3dRect.lY1 + cy;
+ }
+
+#ifdef D3D_DEBUG
+ rc = pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Clear2 ->", ErrorStringD3D(rc) );
+ }
+#else
+ pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
+#endif
+}
+/*===========================================================================*/
+/* Well this is the guts of it all. Here we rasterize the primitives that */
+/* are in their final form. OpenGL has done all the lighting, transfomations*/
+/* and clipping at this point. */
+/* */
+/* TODO: I'm not sure if I want to bother to check for errors on this call. */
+/* The overhead kills me... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "DrawPrimitveHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ DPF(( DBG_PRIM_INFO, "DP( %d )", dwCount ));
+
+ rc = pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
+ D3DFVF_TLVERTEX,
+ (LPVOID)pVertices,
+ dwCount,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "DrawPrimitive ->", ErrorStringD3D(rc) );
+ }
+#else
+ pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
+ D3DFVF_TLVERTEX,
+ (LPVOID)pVertices,
+ dwCount,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+#endif
+}
+/*===========================================================================*/
+/* This call will handle the swapping of the buffers. Now I didn't bother */
+/* to support single buffered so this will be used for glFlush() as its all */
+/* the same. So first we do an EndScene as we are always considered to be in*/
+/* a BeginScene because when we leave we do a BeginScene. Now note that when*/
+/* the context is created in the first place we do a BeginScene also just to */
+/* get things going. The call will use either Flip/blt based on the type of */
+/* surface was created for rendering. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void SwapBuffersHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "SwapBuffersHAL();" ));
+ DPF(( DBG_ALL_PROFILE, "=================SWAP===================" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ /* Make sure we have enough info. */
+ if ( pHAL->lpDDSPrimary != NULL )
+ {
+ rc = pHAL->lpD3DDevice->EndScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EndScene ->", ErrorStringD3D(rc) );
+ }
+
+ if ( pShared->bFlipable )
+ {
+ DPF(( DBG_CNTX_PROFILE, "Swap->FLIP" ));
+ rc = pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
+ }
+ else
+ {
+ DPF(( DBG_CNTX_PROFILE, "Swap->Blt" ));
+ rc = pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
+ }
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Blt (RENDER/PRIMARY) ->", ErrorStringD3D(rc) );
+ }
+
+ rc = pHAL->lpD3DDevice->BeginScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
+ }
+ }
+#else
+ pHAL->lpD3DDevice->EndScene();
+
+ if ( pShared->bFlipable )
+ pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
+ else
+ pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
+
+ pHAL->lpD3DDevice->BeginScene();
+
+#endif
+}
+/*===========================================================================*/
+/* This function is a very thin wrapper for the D3D call 'SetRenderState'. */
+/* Using this function requires all the types to be defined by including the */
+/* D3D header file. */
+/* */
+/* TODO: would be much better to get ride of all these calls per VBRender. */
+/* I feel I should get this call into SetRenderStates() the RenderVB. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "SetStateHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ rc = pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "SetRenderState ->", ErrorStringD3D(rc) );
+ }
+
+#else
+ pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
+#endif
+}
+
+
+
+
+
+
+
+
diff --git a/src/mesa/drivers/d3d/D3DShared.h b/src/mesa/drivers/d3d/D3DShared.h new file mode 100644 index 00000000000..cc629e21111 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DShared.h @@ -0,0 +1,154 @@ +/*===========================================================================*/ +/* */ +/* Mesa-3.0 DirectX 6 Driver */ +/* */ +/* By Leigh McRae */ +/* */ +/* http://www.altsoftware.com/ */ +/* */ +/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */ +/*===========================================================================*/ +#ifndef D3D_MESA_ALL_H +#define D3D_MESA_ALL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ +/* Includes. */ +/*===========================================================================*/ +#include <stdio.h> +#include <string.h> +/*===========================================================================*/ +/* Magic numbers. */ +/*===========================================================================*/ +#define TM_ACTION_LOAD 0x01 +#define TM_ACTION_BIND 0x02 +#define TM_ACTION_UPDATE 0x04 + +#define UM_FATALSHUTDOWN (WM_USER+42) +/*===========================================================================*/ +/* Macros defines. */ +/*===========================================================================*/ +#define ALLOC(cb) malloc( (cb) ) +#define FREE(p) { free( (p) ); (p) = NULL; } +/*===========================================================================*/ +/* Type defines. */ +/*===========================================================================*/ +typedef struct _pixel_convert +{ + int cb, /* Count in bytes of one pixel. */ + rShift, /* Shift count that postions each componet. */ + gShift, + bShift, + aShift; + float rScale, /* Value that scales a color that ranges 0.0 -> 1.0 */ + gScale, /* to this pixel format. */ + bScale, + aScale; + DWORD dwRMask, /* Color mask per component. */ + dwGMask, + dwBMask, + dwAMask; + +} PIXELINFO, *PPIXELINFO; + + +typedef struct _d3d_shared_info +{ + HWND hwnd; + BOOL bWindow, + bFlipable, + bForceSW, + bHardware; + RECT rectW, /* Window size and postion in screen space. */ + rectV; /* Viewport size and postion. */ + DWORD dwWidth, /* Current render size for quick checks. */ + dwHeight; + + PIXELINFO pixel; + DWORD dwSrcBlendCaps[14], /* See D3DCAPS.CPP */ + dwDestBlendCaps[14], + dwTexFunc[4]; + +} MESAD3DSHARED, *PMESAD3DSHARED; + +typedef struct _render_options +{ + BOOL bForceSoftware, /* TODO: Add user switches. */ + bStretchtoPrimary; + +} USER_CTRL, *PUSER_CRTL; + +enum { s_zero = 0, + s_one, + s_dst_color, + s_one_minus_dst_color, + s_src_alpha, + s_one_minus_src_alpha, + s_dst_alpha, + s_one_minus_dst_alpha, + s_src_alpha_saturate, + s_constant_color, + s_one_minus_constant_color, + s_constant_alpha, + s_one_minus_constant_alpha }; + +enum { d_zero = 0, + d_one, + d_src_color, + d_one_minus_src_color, + d_src_alpha, + d_one_minus_src_alpha, + d_dst_alpha, + d_one_minus_dst_alpha, + d_constant_color, + d_one_minus_constant_color, + d_constant_alpha, + d_one_minus_constant_alpha }; + +enum { d3dtblend_decal = 0, + d3dtblend_decalalpha, + d3dtblend_modulate, + d3dtblend_modulatealpha }; + +/*===========================================================================*/ +/* Function prototypes. */ +/*===========================================================================*/ +PMESAD3DSHARED InitHAL( HWND hwnd ); +void TermHAL( PMESAD3DSHARED pShared ); +BOOL CreateHAL( PMESAD3DSHARED pShared ); +BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ ); + +void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil ); +void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState ); +void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount ); + +void SwapBuffersHAL( PMESAD3DSHARED pShared ); +DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack ); +void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack ); +void UpdateScreenPosHAL( PMESAD3DSHARED pShared ); +void GetPixelInfoHAL( PMESAD3DSHARED pShared, PPIXELINFO pPixel ); +BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels ); +void DisableTMgrHAL( PMESAD3DSHARED pShared ); + + +int SaveDIBitmap( char *filename, BITMAPINFO *info, void *bits ); +int ARGB_SaveBitmap( char *filename, int width, int height, unsigned char *pARGB ); +int BGRA_SaveBitmap( char *filename, int width, int height, unsigned char *pBGRA ); +int BGR_SaveBitmap( char *filename, int width, int height, unsigned char *pBGR ); +/*===========================================================================*/ +/* Global variables. */ +/*===========================================================================*/ +extern float g_DepthScale, /* Mesa needs to scale Z in SW. The HAL */ + g_MaxDepth; /* doesn't but I wanted SW still to work.*/ + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/src/mesa/drivers/d3d/D3DTEXT.CPP b/src/mesa/drivers/d3d/D3DTEXT.CPP new file mode 100644 index 00000000000..e6ff8645611 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTEXT.CPP @@ -0,0 +1,576 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "d3dText.h"
+
+/*=============================================================================
+
+ 1
+ ------
+ | |
+ 6 | | 2
+ | 7 |
+ ------
+ | |
+ 5 | | 3
+ | |
+ ------
+ 4
+
+ TL_0 TR_0
+TLL TL_1 TR_1 TRR
+
+MLL_0 ML_0 MR_0 MRR_0
+MLL_1 ML_1 MR_1 MRR_1
+
+BLL BL_0 BR_0 BRR
+ BL_1 BR_1
+
+=============================================================================*/
+
+#define TLL 0
+#define TRR 1
+#define TL_0 2
+#define TL_1 3
+#define TR_0 4
+#define TR_1 5
+
+#define MLL_0 6
+#define MLL_1 7
+#define MRR_0 8
+#define MRR_1 9
+
+#define ML_0 10
+#define ML_1 11
+#define MR_0 12
+#define MR_1 13
+
+#define BL_0 14
+#define BL_1 15
+#define BR_0 16
+#define BR_1 17
+#define BLL 18
+#define BRR 19
+
+#define BIT1 0x00000001
+#define BIT2 0x00000002
+#define BIT3 0x00000004
+#define BIT4 0x00000008
+#define BIT5 0x00000010
+#define BIT6 0x00000020
+#define BIT7 0x00000040
+
+#define TOP BIT4
+#define MIDDLE BIT7
+#define BOTTOM BIT1
+#define TLEFT BIT5
+#define BLEFT BIT6
+#define LEFT (TLEFT|BLEFT)
+#define TRIGHT BIT3
+#define BRIGHT BIT2
+#define RIGHT (TRIGHT|BRIGHT)
+#define ALL 0xFFFFFFFF
+
+/*===========================================================================*/
+/* This is the static array that will map the ASCII value of the character */
+/* being draw to the bit mask that will be scan converted to the LED display.*/
+/*===========================================================================*/
+DWORD textBitMasks[] =
+{
+ 0xFFFFFFFF, // 000
+ 0xFFFFFFFF, // 001
+ 0xFFFFFFFF, // 002
+ 0xFFFFFFFF, // 003
+ 0xFFFFFFFF, // 004
+ 0xFFFFFFFF, // 005
+ 0xFFFFFFFF, // 006
+ 0xFFFFFFFF, // 007
+ 0xFFFFFFFF, // 008
+ 0xFFFFFFFF, // 009
+ 0xFFFFFFFF, // 010
+ 0xFFFFFFFF, // 011
+ 0xFFFFFFFF, // 012
+ 0xFFFFFFFF, // 013
+ 0xFFFFFFFF, // 014
+ 0xFFFFFFFF, // 015
+ 0xFFFFFFFF, // 016
+ 0xFFFFFFFF, // 017
+ 0xFFFFFFFF, // 018
+ 0xFFFFFFFF, // 019
+ 0xFFFFFFFF, // 020
+ 0xFFFFFFFF, // 021
+ 0xFFFFFFFF, // 022
+ 0xFFFFFFFF, // 023
+ 0xFFFFFFFF, // 024
+ 0xFFFFFFFF, // 025
+ 0xFFFFFFFF, // 026
+ 0xFFFFFFFF, // 027
+ 0xFFFFFFFF, // 028
+ 0xFFFFFFFF, // 029
+ 0xFFFFFFFF, // 030
+ 0XFFFFFFFF, // 031
+ 0x00000000, // 032 'SPC'
+ 0xFFFFFFFF, // 033
+ 0xFFFFFFFF, // 034
+ 0xFFFFFFFF, // 035
+ 0xFFFFFFFF, // 036
+ 0xFFFFFFFF, // 037
+ 0xFFFFFFFF, // 038
+ 0xFFFFFFFF, // 039
+ 0xFFFFFFFF, // 040
+ 0xFFFFFFFF, // 041
+ 0xFFFFFFFF, // 042
+ 0xFFFFFFFF, // 043
+ 0xFFFFFFFF, // 044
+ 0xFFFFFFFF, // 045
+ 0xFFFFFFFF, // 046
+ 0xFFFFFFFF, // 047
+ (ALL &~ MIDDLE), // 048 '0'
+ (RIGHT), // 049 '1'
+ (ALL &~ TLEFT &~ BRIGHT), // 050 '2'
+ (ALL &~ LEFT), // 051 '3'
+ (TLEFT | MIDDLE | RIGHT), // 052 '4'
+ (ALL &~ TRIGHT &~ BLEFT), // 053 '5'
+ (ALL &~ TRIGHT), // 054 '6'
+ (TOP | RIGHT), // 055 '7'
+ (ALL), // 056 '8'
+ (ALL &~ BOTTOM &~ BLEFT), // 057 '9'
+ 0xFFFFFFFF, // 058
+ 0xFFFFFFFF, // 059
+ 0xFFFFFFFF, // 060
+ 0XFFFFFFFF, // 061
+ 0xFFFFFFFF, // 062
+ 0xFFFFFFFF, // 063
+ 0xFFFFFFFF, // 064
+ (ALL &~ BOTTOM), // 065 'A'
+ (ALL), // 066 'B'
+ (TOP | LEFT | BOTTOM), // 067 'C'
+ (ALL &~ MIDDLE), // 068 'D'
+ (ALL &~ RIGHT), // 069 'E'
+ (LEFT | TOP | MIDDLE), // 070 'F'
+ 0x00000000, // 071 'G'
+ (ALL &~ TOP &~ BOTTOM), // 072 'H'
+ (RIGHT), // 073 'I'
+ (RIGHT | BOTTOM), // 074 'J'
+ 0x00000000, // 075 'K'
+ (LEFT | BOTTOM), // 076 'L'
+ 0x00000000, // 088 'M'
+ 0x00000000, // 089 'N'
+ (ALL &~ MIDDLE), // 090 'O'
+ (ALL &~ BRIGHT &~ BOTTOM),// 091 'P'
+ 0x00000000, // 092 'Q'
+ 0x00000000, // 093 'R'
+ (ALL &~ TRIGHT &~ BLEFT), // 094 'S'
+ 0X00000000, // 095 'T'
+ (LEFT | RIGHT | BOTTOM), // 096 'U'
+ 0x00000000, // 097 'V'
+ 0x00000000, // 098 'W'
+ 0x00000000, // 099 'X'
+ 0x00000000, // 1000 'Z'
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 100
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 104
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 108
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 112
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 116
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 120
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF // 124
+};
+
+#define CT 1.0f
+#define CX 7.0f
+#define CY 13.0f
+#define CM ((CY-(CT*3.0f))/2.0f)
+
+float lCoords[][2] =
+{
+ /* Top outsides. */
+ { 0, (CY-CT) },
+ { CX, (CY-CT) },
+
+ /* Top Line. */
+ { CT, CY },
+ { CT, (CY-CT) },
+ { (CX-CT), CY },
+ { (CX-CT), (CY-CT) },
+
+ /* Middle outsides. */
+ { 0.0f, (CT+CM+CT) },
+ { 0.0f, (CT+CM) },
+ { CX, (CT+CM+CT) },
+ { CX, (CT+CM) },
+
+ /* Middle Line. */
+ { CT, (CT+CM+CT) },
+ { CT, (CT+CM) },
+ { (CX-CT), (CT+CM+CT) },
+ { (CX-CT), (CT+CM) },
+
+ /* Bottom line. */
+ { CT, CT },
+ { CT, 0.0f },
+ { (CX-CT), CT },
+ { (CX-CT), 0.0f },
+
+ /* Bottom outsides. */
+ { 0.0f, CT},
+ { CX, CT }
+};
+
+static int ConvertCharacter( char *c, int cIndex, PD3DFONTMETRICS pfntMetrics );
+
+D3DTLVERTEX TextVertices[MAX_VERTICES];
+/*===========================================================================*/
+/* When we attach I will zero out the whole D3D vertex buffer I'm using for */
+/* the text. This way I don't need to set all the redundant values. I also */
+/* set all the oow values to 1 as I will be doing direct rendering. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL InitD3DText( void )
+{
+ int index;
+
+ /* Set the D3D Vertex Buffer up once so we don't do redundant changes. */
+ memset( &TextVertices[0], 0, sizeof(TextVertices) );
+ for( index = 0; index < MAX_VERTICES; index++ )
+ TextVertices[index].rhw = D3DVAL( 1.0 );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it using the supplied */
+/* fontmetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics )
+{
+ int cIndex,
+ nIndex,
+ index;
+ float cWidth = CX,
+ cHeight = CY;
+
+ /* Find the max width/height of a character and add the spacing so */
+ /* that we can use this value to calculate the x,y of the character.*/
+ cWidth = (cWidth * pfntMetrics->fntXScale) + pfntMetrics->fntXSpacing;
+ cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
+
+ /* Walk the string. This must be NULL terminated. */
+ for( cIndex = 0, nIndex = 0; *pszString; pszString++, cIndex = nIndex, x++ )
+ {
+ /* Convert the character and get the index into the text vertex buffer. */
+ nIndex = ConvertCharacter( &pszString[0], cIndex, pfntMetrics );
+ if ( (nIndex - cIndex) > 2 )
+ {
+ /* Modify the text vertex buffer based on the fntMetrics structure. */
+ for( index = cIndex; index < nIndex; index++ )
+ {
+ /* Scale the character. */
+ TextVertices[index].sx *= pfntMetrics->fntXScale;
+ TextVertices[index].sy *= pfntMetrics->fntYScale;
+
+ /* Move the character. */
+ TextVertices[index].sx += (cWidth*x);
+ TextVertices[index].sy += (cHeight*y);
+
+ /* Set the color. */
+ TextVertices[index].color = pfntMetrics->dwColor;
+ }
+ }
+ }
+
+ if ( nIndex < 3 )
+ return;
+
+ /* Set the states that slim things down. */
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
+
+ /* Blast them baby... */
+ pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
+ D3DFVF_TLVERTEX,
+ (LPVOID)&TextVertices[0],
+ nIndex,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it directly to the screen*/
+/* unsing the supplied fntMetrics structure. The character will be drawn at */
+/* the supplied x,y. The x,y position is relative to the top left and uses */
+/* the spacing in the fntMetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics )
+{
+ int cIndex = 0,
+ index;
+ float cWidth = CX,
+ cHeight = CY;
+
+ /* Convert the character and get the index into the text vertex buffer. */
+ cIndex = ConvertCharacter( c, 0, pfntMetrics );
+ if ( cIndex < 3 )
+ return;
+
+ /* Find the max width/height of a character and add the spacing so */
+ /* that we can use this value to calculate the x,y of the character.*/
+ cWidth = (cWidth * pfntMetrics->fntXScale) + pfntMetrics->fntXSpacing;
+ cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
+
+ /* Modify the text vertex buffer based on the fntMetrics structure. */
+ for( index = 0; index < cIndex; index++ )
+ {
+ /* Scale the character. */
+ TextVertices[index].sx *= pfntMetrics->fntXScale;
+ TextVertices[index].sy *= pfntMetrics->fntYScale;
+
+ /* Move the character. */
+ TextVertices[index].sx += (cWidth*x);
+ TextVertices[index].sy += (cHeight*y);
+
+ /* Set the color. */
+ TextVertices[index].color = pfntMetrics->dwColor;
+ }
+
+
+ /* Set the states that slim things down. */
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
+
+ /* Blast them baby... */
+ pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
+ D3DFVF_TLVERTEX,
+ (LPVOID)&TextVertices[0],
+ cIndex,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it using the supplied */
+/* fontmetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static int ConvertCharacter( char *c, int cIndex, PD3DFONTMETRICS pfntMetrics )
+{
+ DWORD asciiChar = (int)(*c);
+
+ /* Handle the TOP line. */
+ if ( textBitMasks[asciiChar] & BIT1 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
+ }
+
+ /* Handle the TOP/BOTTOM RIGHT lines. */
+ // if ( textBitMasks[index] & (BIT2|BIT3) )
+ if ( 1 == 0 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ }
+ else
+ {
+ if ( textBitMasks[asciiChar] & BIT2 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TR_1][1] );
+ }
+ if ( textBitMasks[asciiChar] & BIT3 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_1][1] );
+ }
+ }
+
+ /* Handle the TOP/BOTTOM LEFT lines. */
+ // if ( textBitMasks[asciiChar] & (BIT5|BIT6) )
+ if ( 1 == 0 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
+ }
+ else
+ {
+ if ( textBitMasks[asciiChar] & BIT5 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_1][1] );
+ }
+ if ( textBitMasks[asciiChar] & BIT6 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TLL][1] );
+ }
+ }
+
+ /* Handle the MIDDLE line. */
+ if ( textBitMasks[asciiChar] & BIT7 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
+ }
+
+ /* Handle the BOTTOM line. */
+ if ( textBitMasks[asciiChar] & BIT4 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ }
+
+ return cIndex;
+}
+
+#undef CM
+#undef CY
+#undef CX
+#undef CT
+
+#undef TLL
+#undef TRR
+#undef TL_0
+#undef TL_1
+#undef TR_0
+#undef TR_1
+
+#undef MLL_0
+#undef MLL_1
+#undef MRR_0
+#undef MRR_1
+
+#undef ML_0
+#undef ML_1
+#undef MR_0
+#undef MR_1
+
+#undef BL_0
+#undef BL_1
+#undef BR_0
+#undef BR_1
+#undef BLL
+#undef BRR
+
+#undef BIT1
+#undef BIT2
+#undef BIT3
+#undef BIT4
+#undef BIT5
+#undef BIT6
+#undef BIT7
+
+#undef TOP
+#undef MIDDLE
+#undef BOTTOM
+#undef TLEFT
+#undef BLEFT
+#undef LEFT
+#undef TRIGHT
+#undef BRIGHT
+#undef RIGHT
+#undef ALL
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.cpp b/src/mesa/drivers/d3d/D3DTextureMgr.cpp new file mode 100644 index 00000000000..ac9d2621fcc --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTextureMgr.cpp @@ -0,0 +1,947 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local function prototypes. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels );
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj );
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext );
+/*===========================================================================*/
+/* This function will simply set the top of stack to NULL. I only used it */
+/* just incase I want to add something later. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL InitTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "InitTMgrHAL();" ));
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will walk the Texture Managers linked list and destroy all */
+/* surfaces (SYSTEM/VIDEO). The texture objects themselves also will be */
+/* freed. */
+/* NOTE: this is per/context. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void TermTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "TermTMgrHAL();" ));
+
+ if ( pHAL && pHAL->pTMList )
+ {
+ /* Destroy the surface and remove the TMO from the stack. */
+ while( DestroyTextureObject(pHAL,NULL) );
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function is a HACK as I don't know how I can disable a texture with-*/
+/* out booting it out. Is there know state change? */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+ DPF(( DBG_FUNC, "DisableTMgrHAL();" ));
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return;
+ }
+
+ // TODO: This is a hack to shut off textures.
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+}
+/*===========================================================================*/
+/* This function is the only entry into the TextureManager that Mesa/wgl */
+/* will see. It uses a dwAction to specify what we are doing. I did this as*/
+/* depending on the cards resources the action taken can change. */
+/* When this function is called we will always search the Texture Managers */
+/* linked list (per context remember) and try and find a structure that has */
+/* the same dwName. If we have a match we pull it out of the list and put it*/
+/* at the top of the list (TOL). If we don't find one then we create a struc*/
+/* and put it a TOL. This TOL idea makes for some caching as we will always */
+/* destroy Texture Surfaces from the bottom up... */
+/* All texture objects at this point will create a texture surface in System*/
+/* memory (SMEM). Then we will copy the Mesa texture into the surface using */
+/* the 'pixel' struc to get the translation info. So now this means that all*/
+/* textures that Mesa gives me I will have a Surface with a copy. If Mesa */
+/* changes the texture the I update the surface in (SMEM). */
+/* Now we have a texture struc and a Texture Surface in SMEM. At this point*/
+/* we create another surface on the card (VMEM). Finally we blt from the */
+/* SMEM to the VMEM and set the texture as current. Why do I need two? First*/
+/* this solves square textures. If the cards CAPS is square textures only */
+/* then I change the dimensions of the VMEM surface and the blt solves it for*/
+/* me. Second it saves me from filling D3D textures over and over if the */
+/* card needs to be creating and destroying surfaces because of low memory. */
+/* The surface in SMEM is expected to work always. When a surface has to be*/
+/* created in VMEM then we put it in a loop that tries to create the surface.*/
+/* If we create the surface ok then we brake from the loop. If we fail then */
+/* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/
+/* memory was freed. If memory was freed then we can try again. If no memory*/
+/* was freed then it just can't fit. */
+/* 'FreeTextureMemory' will find the end of the list and start freeing VMEM */
+/* (never SMEM) surfaces that are not locked. */
+/* BIND - when we bind and there is a texture struct with a texture surface */
+/* in VMEM then we just make it current. If we have a struct and a surface */
+/* in SMEM but no VMEM surface then we create the surface in VMEM and blt */
+/* from the SMEM surface. If we have nothing its just like a creation... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags,
+ RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ PTM_OBJECT pTMObj,
+ pTemp;
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+
+ DPF(( DBG_FUNC, "CreateTMgrHAL();" ));
+
+ DPF(( DBG_TXT_INFO, "Texture:" ));
+ DPF(( DBG_TXT_INFO, "cx: %d cy: %d", dwWidth, dwHeight ));
+ DPF(( DBG_TXT_INFO, "Rect:" ));
+ if ( rectDirty )
+ {
+ DPF(( DBG_TXT_INFO, "x0: %d y0: %d", rectDirty->left, rectDirty->top ));
+ DPF(( DBG_TXT_INFO, "x1: %d y1: %d", rectDirty->right, rectDirty->bottom ));
+ }
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return FALSE;
+ }
+
+ /*=================================================*/
+ /* See if we can find this texture object by name. */
+ /*=================================================*/
+ for( pTMObj = pHAL->pTMList; pTMObj && (pTMObj->dwName != dwName); pTMObj = pTMObj->next );
+
+ /*=========================================================*/
+ /* Allocate a new object if we didn't get a matching name. */
+ /*=========================================================*/
+ if ( pTMObj == NULL )
+ {
+ pTMObj = (PTM_OBJECT)ALLOC( sizeof(TM_OBJECT) );
+ if ( pTMObj == NULL )
+ return FALSE;
+ memset( pTMObj, 0, sizeof(TM_OBJECT) );
+
+ /* Put the object at the beginning of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ else
+ {
+ /*===============================================================*/
+ /* Make some caching happen by pulling this object to the front. */
+ /*===============================================================*/
+ if ( pHAL->pTMList != pTMObj )
+ {
+ /* Pull the object out of the list. */
+ if ( pTMObj->prev )
+ {
+ pTemp = pTMObj->prev;
+ pTemp->next = pTMObj->next;
+ }
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj->prev;
+ }
+
+ pTMObj->prev = NULL;
+ pTMObj->next = NULL;
+
+ /* Put the object at the front of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ }
+
+ /*========================================================*/
+ /* If we are doing BIND and the texture is in VID memory. */
+ /*========================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache HIT (%d)", dwName ));
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=================================================================*/
+ /* If we are doing BIND and the texture is at least in SYS memory. */
+ /*=================================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache MISS (%d)", dwName ));
+
+ /* Create the texture on the card. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=========================================================*/
+ /* If we are doing UPDATE then try in VID first for speed. */
+ /*=========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_Video &&
+ !(pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture on the card. */
+ UpdateTexture( pTMObj, TRUE, rectDirty, (UCHAR *)pPixels );
+
+ /* We updated the texture in VID so kill the SYS so we know its dirty. */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*===========================================================*/
+ /* If we are doing UPDATE then try in SYS still gives speed. */
+ /*===========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture in SYS. */
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /* We updated the SYS texture only so now blt to the VID. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /* At this point we have a valid Texture Manager Object with updated */
+ /* links. We now need to create or update a texture surface that is */
+ /* in system memory. Every texture has a copy in system so we can use*/
+ /* blt to solve problems with textures allocated on the card (square */
+ /* only textures, pixelformats...). */
+
+ // TODO: make support for update also. Dirty rectangle basicly...
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the system surface. TODO: should try to get the SubIMage going again */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /*================================================================*/
+ /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */
+ /*================================================================*/
+ switch( dwRequestFlags )
+ {
+ case GL_ALPHA:
+ dwRequestFlags = DDPF_ALPHA;
+ DPF(( DBG_TXT_WARN, "GL_ALPHA not supported!)" ));
+ return FALSE;
+
+ case GL_INTENSITY:
+ case GL_LUMINANCE:
+ DPF(( DBG_TXT_WARN, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE;
+ return FALSE;
+
+ case GL_LUMINANCE_ALPHA:
+ DPF(( DBG_TXT_WARN, "GL_LUMINANCE_ALPHA not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS;
+ return FALSE;
+
+ case GL_RGB:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGB" ));
+ dwRequestFlags = DDPF_RGB;
+ break;
+
+ case GL_RGBA:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGBA" ));
+ dwRequestFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
+ break;
+ }
+
+ /*==============================*/
+ /* Populate the texture object. */
+ /*==============================*/
+ pTMObj->dwName = dwName;
+ pTMObj->lpD3DDevice = pHAL->lpD3DDevice;
+ pTMObj->dwFlags = dwRequestFlags;
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
+ {
+ DPF(( DBG_TXT_INFO, "Convert to Square..." ));
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+
+ /* Shrink non-square textures. */
+ pTMObj->dwVHeight = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ pTMObj->dwVWidth = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ }
+ else
+ {
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+ pTMObj->dwVHeight = dwHeight;
+ pTMObj->dwVWidth = dwWidth;
+ }
+
+ /*========================*/
+ /* Create SYSTEM surface. */
+ /*========================*/
+
+ /* Request a surface in system memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwSWidth;
+ ddsd2.dwHeight = pTMObj->dwSHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = dwRequestFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the surface using the enumerated pixelformat. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_System, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Solve the pixel mapping info using the surface pixelformat. */
+ Solve8BitChannelPixelFormat( &ddsd2.ddpfPixelFormat, &pTMObj->pixel );
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /*=======================*/
+ /* Create VIDEO surface. */
+ /*=======================*/
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will handle the creation and destruction of the texture */
+/* surfaces on the card. Using the dw'V'Width/Height dimensions the call */
+/* try and create the texture on the card and keep using FreeTextureMemory */
+/* until the surace can be created. Once the surface is created we get the */
+/* interface that we will use to make it the current texture. I didn't put */
+/* the code to make the texture current in this function as BIND needs to */
+/* use the same code and this function doesn't always get called when we do a*/
+/* bind. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj )
+{
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LoadTextureInVideo();" ));
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /* Request a surface in Video memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwVWidth;
+ ddsd2.dwHeight = pTMObj->dwVHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = pTMObj->dwFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Make sure we lock so we don't nuke this texture trying to free memory for it. */
+ pTMObj->bLock = TRUE;
+
+ /* Start a loop that will free all textures until we have created the texture */
+ /* surface or we can't free up more memory. */
+ do
+ {
+ /* Try to create the texture surface. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_Video, NULL );
+ if ( !FAILED(rc) )
+ break;
+
+ DPF(( DBG_TXT_INFO, "Free Texture Memory" ));
+
+ /* DestroyTexture will return TRUE if a surface was freed. */
+ } while( FreeTextureMemory(pHAL,NULL) );
+
+ /* Make sure we unlock or we won't be able to nuke the TMO later. */
+ pTMObj->bLock = FALSE;
+
+ /* Did we create a valid texture surface? */
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed to load texture" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ DX_RESTORE( pTMObj->lpDDS_System );
+ DX_RESTORE( pTMObj->lpDDS_Video );
+
+ DPF(( DBG_TXT_INFO, "Texture Blt SYSTEM -> VID" ));
+
+ /* Now blt the texture in system memory to the card. */
+ rc = pTMObj->lpDDS_Video->Blt( NULL, pTMObj->lpDDS_System, NULL, DDBLT_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Blt (TEXTURE) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the Texture interface that is used to render with. */
+ pTMObj->lpDDS_Video->QueryInterface( IID_IDirect3DTexture2, (void **)&pTMObj->lpD3DTexture2 );
+ if ( pTMObj->lpD3DTexture2 == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "Failed QueryTextureInterface" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* If this function gets a texture object struc then we will try and free */
+/* it. If we get a NULL then we will search from the bottom up and free one */
+/* VMEM surface. I can only free when the surface isn't locked and of course*/
+/* there must be a VMEM surface. We never free SMEM surfaces as that isn't */
+/* the point. */
+/* TODO: should have a pointer to the bottom of the stack really. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+ BOOL bFreed = FALSE;
+
+ DPF(( DBG_FUNC, "FreeTextureMemory();" ));
+ DPF(( DBG_TXT_WARN, "FREE TEXTURE!" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Free Last texture in cache" ));
+
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+
+ /* Now backup until we find a texture on the card. */
+ while( pCurrent && (pCurrent->lpDDS_Video == NULL) && (pCurrent->bLock == FALSE) )
+ pCurrent = pCurrent->prev;
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "No texture memory freed" ));
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Requested texture to be freed NOT FOUND" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ bFreed = TRUE;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ DPF(( DBG_TXT_INFO, "dwName: %d", pCurrent->dwName ));
+ DPF(( DBG_TXT_INFO, "cx: %d, cy: %d", pCurrent->dwVWidth, pCurrent->dwVHeight ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ bFreed = TRUE;
+ }
+
+ return bFreed;
+}
+/*===========================================================================*/
+/* This function searches the linked list of texture objects in the supplied*/
+/* D3Dwrapper structure. If it finds a match it will free it and pull it out*/
+/* of the linked list. The function works on the bases of a matching pointer*/
+/* to the object (not matching content). */
+/* If the function gets passed a NULL then we want to free the last texture */
+/* object in the list. Used in a loop to destory all. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+
+ DPF(( DBG_FUNC, "DestoryTextureObject();" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "No textures to be freed" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture to be freed LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ }
+ if ( pCurrent->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS):" ));
+ pCurrent->lpDDS_System->Release();
+ pCurrent->lpDDS_System = NULL;
+ }
+
+ /* Pull this texture out of the list. */
+ if ( pCurrent == pHAL->pTMList )
+ pHAL->pTMList = NULL;
+ if ( pCurrent->prev )
+ (pCurrent->prev)->next = pCurrent->next;
+ if ( pCurrent->next )
+ (pCurrent->next)->prev = pCurrent->prev;
+ FREE( pCurrent );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels )
+{
+ LPDIRECTDRAWSURFACE4 lpDDS;
+ DDSURFACEDESC2 ddsd2;
+ DWORD srcPitch,
+ dwHeight,
+ dwWidth,
+ dwCol,
+ dwColor;
+ UCHAR *pSrc,
+ *pSrcRow,
+ *pDest,
+ *pDestRow;
+ int rc;
+
+ // TODO: Do I need to pass the h/w when its in the object!
+ DPF(( DBG_FUNC, "UpdateTexture();" ));
+
+ /* Get the surface pointer we are looking for. */
+ lpDDS = (bVideo) ? pTMObj->lpDDS_Video : pTMObj->lpDDS_System;
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+
+ /* Get the surface pointer. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+ rc = lpDDS->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return;
+ }
+
+ /* For now we are only updating the system surface so use its dimensions. */
+ dwWidth = (bVideo) ? pTMObj->dwVWidth : pTMObj->dwSWidth;
+ dwHeight = (bVideo) ? pTMObj->dwVHeight : pTMObj->dwSHeight;
+
+ /* If we are updating the whole surface then the pDest/pSrc will */
+ /* always be the same. */
+ if ( pRect == NULL )
+ {
+ pDest = (UCHAR *)ddsd2.lpSurface;
+ pSrc = pixels;
+ }
+
+ /* Fill the texture surface based on the pixelformat flags. */
+ if ( pTMObj->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 4;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 4) + (pRect->left * 4);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+3) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+3) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 4;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_RGB )
+ {
+ srcPitch = dwWidth * 3;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 3) + (pRect->left * 3);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 3;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 2;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 2) + (pRect->left * 2);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+1) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 2;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_LUMINANCE )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_ALPHAPIXELS )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor = ( (*pSrc & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+
+ /* Unlock the surface. */
+ rc = lpDDS->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ }
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
+{
+ LPDDPIXELFORMAT lpDDPixFmtRequest = (LPDDPIXELFORMAT)lpContext;
+ PIXELINFO pixel;
+
+ DPF(( DBG_FUNC, "EnumPFHook();" ));
+
+ if ( lpDDPixFmt->dwFlags == lpDDPixFmtRequest->dwFlags )
+ {
+ /* Are we looking for an alpha channel? */
+ if ( lpDDPixFmtRequest->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ /* Try for something that has more then 1bits of Alpha. */
+ Solve8BitChannelPixelFormat( lpDDPixFmt, &pixel );
+ if ( pixel.aScale == -1.0 )
+ {
+ /* Save this format no matter what as its a match of sorts. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+ return D3DENUMRET_OK;
+ }
+ }
+
+ /* Save this format as its a good match. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+
+ /* We are happy at this point so lets leave. */
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.h b/src/mesa/drivers/d3d/D3DTextureMgr.h new file mode 100644 index 00000000000..f4a4154917a --- /dev/null +++ b/src/mesa/drivers/d3d/D3DTextureMgr.h @@ -0,0 +1,62 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _TEXTURE_MGR_INC
+#define _TEXTURE_MGR_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include "GL/gl.h"
+/*========================================================================*/
+/* Defines. */
+/*========================================================================*/
+/*========================================================================*/
+/* Type defines. */
+/*========================================================================*/
+typedef struct _local_texture_object
+{
+ DWORD dwName,
+ dwPriority,
+ dwFlags,
+ dwSWidth,
+ dwSHeight,
+ dwVWidth,
+ dwVHeight;
+ BOOL bLock,
+ bDirty; /* I only update VID on SubImage calls so the system */
+ /* texture can get invalid. */
+
+ LPDIRECT3DDEVICE3 lpD3DDevice; /* If the device changes we must get new handles... */
+ LPDIRECTDRAWSURFACE4 lpDDS_System,
+ lpDDS_Video;
+ LPDIRECT3DTEXTURE2 lpD3DTexture2;
+
+ PIXELINFO pixel;
+
+ struct _local_texture_object *next;
+ struct _local_texture_object *prev;
+
+} TM_OBJECT, *PTM_OBJECT;
+/*========================================================================*/
+/* Function prototypes. */
+/*========================================================================*/
+void APIENTRY InitTMD3D( void *pVoid );
+void APIENTRY TermTMD3D( void *pVoid );
+/*========================================================================*/
+/* Global variables declaration. */
+/*========================================================================*/
+
+#endif
diff --git a/src/mesa/drivers/d3d/D3DUTILS.CPP b/src/mesa/drivers/d3d/D3DUTILS.CPP new file mode 100644 index 00000000000..c13d89cd711 --- /dev/null +++ b/src/mesa/drivers/d3d/D3DUTILS.CPP @@ -0,0 +1,638 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local only functions. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask );
+/*===========================================================================*/
+/* This function is used to get the pointer to the surface and the pitch for*/
+/* the scanline rendering functions. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ static DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LockHAL();" ));
+
+ /* Set the request structure up first. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Lock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+
+ return &ddsd2;
+}
+/*===========================================================================*/
+/* This is just a simple wrapper. I probably don't need to do any error */
+/* checking as the Lock must have worked inorder to get here... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "UnlockHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Unlock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+}
+/*===========================================================================*/
+/* This function will track the main/Primary window that will be used as the*/
+/* target for the Blt in SwapBuffers. As a side effect the call will check */
+/* to see if the primary surface is the same size and position as the screen.*/
+/* If they are the same size we will call it fullscreen... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UpdateScreenPosHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ POINT pt;
+ DWORD dwWidth, dwHeight;
+
+ DPF(( DBG_FUNC, "UpdateScreenPosHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL != NULL )
+ {
+ /* Update the windows screen position. */
+ GetClientRect( pShared->hwnd, &pShared->rectW );
+ pt.x = pt.y = 0;
+ ClientToScreen( pShared->hwnd, &pt );
+ OffsetRect( &pShared->rectW, pt.x, pt.y);
+
+ /* Compare the primary to the screen. */
+ dwWidth = GetSystemMetrics( SM_CXSCREEN );
+ dwHeight = GetSystemMetrics( SM_CYSCREEN );
+ if ( (pShared->rectW.left > 0) || (pShared->rectW.top > 0) ||
+ (pShared->rectW.right > dwWidth) || (pShared->rectW.bottom > dwHeight) )
+ pShared->bWindow = TRUE;
+ else
+ pShared->bWindow = FALSE;
+ }
+}
+/*===========================================================================*/
+/* This function will fill in the pixel info structure defined in D3Dshared.*/
+/* Basicly it will take a DirectDraw pixelformat structure and make scaling */
+/* values that will convert from 8bit channels to whatever the supplied ddpf */
+/* uses. Also we will generate shift values that will be used to get move */
+/* each component of the pixel into place. */
+/* I have now added a special case for a 1bit alpha channel. If I find a 1b*/
+/* alpha then I will set the scale to -1.0 which should be unique. Later I */
+/* can check the alpha scale value too see if its -1.0 and thus handle it. I*/
+/* was finding that the case was not working tom my advantage so this is my */
+/* HACK for the day. As a TODO I should work on this... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel )
+{
+ DPF(( DBG_FUNC, "Solve8BitChannelPixelFromat();" ));
+
+ memset( pPixel, 0, sizeof(PPIXELINFO) );
+
+ /* Check too see if the color space is valid in the PF. */
+ if ( pddpf->dwFlags & DDPF_RGB )
+ {
+ /* Solve the red stuff. */
+ pPixel->dwRMask = pddpf->dwRBitMask;
+ pPixel->rShift = CountTrailingZeros( pPixel->dwRMask );
+ pPixel->rScale = (float)0.00392156 * (float)(pPixel->dwRMask >> pPixel->rShift);
+
+ /* Solve the green thingy's. */
+ pPixel->dwGMask = pddpf->dwGBitMask;
+ pPixel->gShift = CountTrailingZeros( pPixel->dwGMask );
+ pPixel->gScale = (float)0.00392156 * (float)(pPixel->dwGMask >> pPixel->gShift);
+
+ /* Solve the blues. */
+ pPixel->dwBMask = pddpf->dwBBitMask;
+ pPixel->bShift = CountTrailingZeros( pddpf->dwBBitMask );
+ pPixel->bScale = (float)0.00392156 * (float)(pddpf->dwBBitMask >> pPixel->bShift);
+ }
+
+ /* Do the alpha channel if there is one. */
+ if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ pPixel->dwAMask = pddpf->dwRGBAlphaBitMask;
+ pPixel->aShift = CountTrailingZeros( pPixel->dwAMask );
+
+ /* Special case a 1bit alpha. */
+ if ( (pPixel->dwAMask >> pPixel->aShift) == 1 )
+ pPixel->aScale = -1.0;
+ else
+ pPixel->aScale = (float)0.00392156 * (float)(pPixel->dwAMask >> pPixel->aShift);
+ }
+
+ /* Get the size of the pixel in bytes. Should work as dwRGBBitCount is in a union. */
+ pPixel->cb = pddpf->dwRGBBitCount / 8;
+}
+/*===========================================================================*/
+/* See RETURN :) */
+/*===========================================================================*/
+/* RETURN: number of contiguous zeros starting from the right. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask )
+{
+ DWORD Mask;
+
+ if ( dwMask == 0 )
+ return 32;
+
+ /* Can't take credit for this one! */
+ Mask = dwMask & -(int)dwMask;
+ return ((Mask & 0xFFFF0000)!=0) << 4
+ | ((Mask & 0xFF00FF00)!=0) << 3
+ | ((Mask & 0xF0F0F0F0)!=0) << 2
+ | ((Mask & 0xCCCCCCCC)!=0) << 1
+ | ((Mask & 0xAAAAAAAA)!=0);
+}
+/*===========================================================================*/
+/* This function will convert the DDraw error code to its macro string. The*/
+/* returned pointer is static so you need not worry about memory managemnet */
+/* but the error message gets written over from call to call... */
+/*===========================================================================*/
+/* RETURN: pointer to the single static buffer that hold the error message. */
+/*===========================================================================*/
+char *ErrorStringD3D( HRESULT hr )
+{
+ static char errorString[128];
+
+ switch( hr )
+ {
+ case DDERR_ALREADYINITIALIZED:
+ strcpy( errorString, "DDERR_ALREADYINITIALIZED" );
+ break;
+
+ case DDERR_CANNOTATTACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTATTACHSURFACE" );
+ break;
+
+ case DDERR_CANNOTDETACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTDETACHSURFACE" );
+ break;
+
+ case DDERR_CURRENTLYNOTAVAIL:
+ strcpy( errorString, "DDERR_CURRENTLYNOTAVAIL" );
+ break;
+
+ case DDERR_EXCEPTION:
+ strcpy( errorString, "DDERR_EXCEPTION" );
+ break;
+
+ case DDERR_GENERIC:
+ strcpy( errorString, "DDERR_GENERIC" );
+ break;
+
+ case DDERR_HEIGHTALIGN:
+ strcpy( errorString, "DDERR_HEIGHTALIGN" );
+ break;
+
+ case DDERR_INCOMPATIBLEPRIMARY:
+ strcpy( errorString, "DDERR_INCOMPATIBLEPRIMARY" );
+ break;
+
+ case DDERR_INVALIDCAPS:
+ strcpy( errorString, "DDERR_INVALIDCAPS" );
+ break;
+
+ case DDERR_INVALIDCLIPLIST:
+ strcpy( errorString, "DDERR_INVALIDCLIPLIST" );
+ break;
+
+ case DDERR_INVALIDMODE:
+ strcpy( errorString, "DDERR_INVALIDMODE" );
+ break;
+
+ case DDERR_INVALIDOBJECT:
+ strcpy( errorString, "DDERR_INVALIDOBJECT" );
+ break;
+
+ case DDERR_INVALIDPARAMS:
+ strcpy( errorString, "DDERR_INVALIDPARAMS" );
+ break;
+
+ case DDERR_INVALIDPIXELFORMAT:
+ strcpy( errorString, "DDERR_INVALIDPIXELFORMAT" );
+ break;
+
+ case DDERR_INVALIDRECT:
+ strcpy( errorString, "DDERR_INVALIDRECT" );
+ break;
+
+ case DDERR_LOCKEDSURFACES:
+ strcpy( errorString, "DDERR_LOCKEDSURFACES" );
+ break;
+
+ case DDERR_NO3D:
+ strcpy( errorString, "DDERR_NO3D" );
+ break;
+
+ case DDERR_NOALPHAHW:
+ strcpy( errorString, "DDERR_NOALPHAHW" );
+ break;
+
+ case DDERR_NOCLIPLIST:
+ strcpy( errorString, "DDERR_NOCLIPLIST" );
+ break;
+
+ case DDERR_NOCOLORCONVHW:
+ strcpy( errorString, "DDERR_NOCOLORCONVHW" );
+ break;
+
+ case DDERR_NOCOOPERATIVELEVELSET:
+ strcpy( errorString, "DDERR_NOCOOPERATIVELEVELSET" );
+ break;
+
+ case DDERR_NOCOLORKEY:
+ strcpy( errorString, "DDERR_NOCOLORKEY" );
+ break;
+
+ case DDERR_NOCOLORKEYHW:
+ strcpy( errorString, "DDERR_NOCOLORKEYHW" );
+ break;
+
+ case DDERR_NODIRECTDRAWSUPPORT:
+ strcpy( errorString, "DDERR_NODIRECTDRAWSUPPORT" );
+ break;
+
+ case DDERR_NOEXCLUSIVEMODE:
+ strcpy( errorString, "DDERR_NOEXCLUSIVEMODE" );
+ break;
+
+ case DDERR_NOFLIPHW:
+ strcpy( errorString, "DDERR_NOFLIPHW" );
+ break;
+
+ case DDERR_NOGDI:
+ strcpy( errorString, "DDERR_NOGDI" );
+ break;
+
+ case DDERR_NOMIRRORHW:
+ strcpy( errorString, "DDERR_NOMIRRORHW" );
+ break;
+
+ case DDERR_NOTFOUND:
+ strcpy( errorString, "DDERR_NOTFOUND" );
+ break;
+
+ case DDERR_NOOVERLAYHW:
+ strcpy( errorString, "DDERR_NOOVERLAYHW" );
+ break;
+
+ case DDERR_OVERLAPPINGRECTS:
+ strcpy( errorString, "DDERR_OVERLAPPINGRECTS" );
+ break;
+
+ case DDERR_NORASTEROPHW:
+ strcpy( errorString, "DDERR_NORASTEROPHW" );
+ break;
+
+ case DDERR_NOROTATIONHW:
+ strcpy( errorString, "DDERR_NOROTATIONHW" );
+ break;
+
+ case DDERR_NOSTRETCHHW:
+ strcpy( errorString, "DDERR_NOSTRETCHHW" );
+ break;
+
+ case DDERR_NOT4BITCOLOR:
+ strcpy( errorString, "DDERR_NOT4BITCOLOR" );
+ break;
+
+ case DDERR_NOT4BITCOLORINDEX:
+ strcpy( errorString, "DDERR_NOT4BITCOLORINDEX" );
+ break;
+
+ case DDERR_NOT8BITCOLOR:
+ strcpy( errorString, "DDERR_NOT8BITCOLOR" );
+ break;
+
+ case DDERR_NOTEXTUREHW:
+ strcpy( errorString, "DDERR_NOTEXTUREHW" );
+ break;
+
+ case DDERR_NOVSYNCHW:
+ strcpy( errorString, "DDERR_NOVSYNCHW" );
+ break;
+
+ case DDERR_NOZBUFFERHW:
+ strcpy( errorString, "DDERR_NOZBUFFERHW" );
+ break;
+
+ case DDERR_NOZOVERLAYHW:
+ strcpy( errorString, "DDERR_NOZOVERLAYHW" );
+ break;
+
+ case DDERR_OUTOFCAPS:
+ strcpy( errorString, "DDERR_OUTOFCAPS" );
+ break;
+
+ case DDERR_OUTOFMEMORY:
+ strcpy( errorString, "DDERR_OUTOFMEMORY" );
+ break;
+
+ case DDERR_OUTOFVIDEOMEMORY:
+ strcpy( errorString, "DDERR_OUTOFVIDEOMEMORY" );
+ break;
+
+ case DDERR_OVERLAYCANTCLIP:
+ strcpy( errorString, "DDERR_OVERLAYCANTCLIP" );
+ break;
+
+ case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
+ strcpy( errorString, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE" );
+ break;
+
+ case DDERR_PALETTEBUSY:
+ strcpy( errorString, "DDERR_PALETTEBUSY" );
+ break;
+
+ case DDERR_COLORKEYNOTSET:
+ strcpy( errorString, "DDERR_COLORKEYNOTSET" );
+ break;
+
+ case DDERR_SURFACEALREADYATTACHED:
+ strcpy( errorString, "DDERR_SURFACEALREADYATTACHED" );
+ break;
+
+ case DDERR_SURFACEALREADYDEPENDENT:
+ strcpy( errorString, "DDERR_SURFACEALREADYDEPENDENT" );
+ break;
+
+ case DDERR_SURFACEBUSY:
+ strcpy( errorString, "DDERR_SURFACEBUSY" );
+ break;
+
+ case DDERR_CANTLOCKSURFACE:
+ strcpy( errorString, "DDERR_CANTLOCKSURFACE" );
+ break;
+
+ case DDERR_SURFACEISOBSCURED:
+ strcpy( errorString, "DDERR_SURFACEISOBSCURED" );
+ break;
+
+ case DDERR_SURFACELOST:
+ strcpy( errorString, "DDERR_SURFACELOST" );
+ break;
+
+ case DDERR_SURFACENOTATTACHED:
+ strcpy( errorString, "DDERR_SURFACENOTATTACHED" );
+ break;
+
+ case DDERR_TOOBIGHEIGHT:
+ strcpy( errorString, "DDERR_TOOBIGHEIGHT" );
+ break;
+
+ case DDERR_TOOBIGSIZE:
+ strcpy( errorString, "DDERR_TOOBIGSIZE" );
+ break;
+
+ case DDERR_TOOBIGWIDTH:
+ strcpy( errorString, "DDERR_TOOBIGWIDTH" );
+ break;
+
+ case DDERR_UNSUPPORTED:
+ strcpy( errorString, "DDERR_UNSUPPORTED" );
+ break;
+
+ case DDERR_UNSUPPORTEDFORMAT:
+ strcpy( errorString, "DDERR_UNSUPPORTEDFORMAT" );
+ break;
+
+ case DDERR_UNSUPPORTEDMASK:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMASK" );
+ break;
+
+ case DDERR_INVALIDSTREAM:
+ strcpy( errorString, "DDERR_INVALIDSTREAM" );
+ break;
+
+ case DDERR_VERTICALBLANKINPROGRESS:
+ strcpy( errorString, "DDERR_VERTICALBLANKINPROGRESS" );
+ break;
+
+ case DDERR_WASSTILLDRAWING:
+ strcpy( errorString, "DDERR_WASSTILLDRAWING" );
+ break;
+
+ case DDERR_XALIGN:
+ strcpy( errorString, "DDERR_XALIGN" );
+ break;
+
+ case DDERR_INVALIDDIRECTDRAWGUID:
+ strcpy( errorString, "DDERR_INVALIDDIRECTDRAWGUID" );
+ break;
+
+ case DDERR_DIRECTDRAWALREADYCREATED:
+ strcpy( errorString, "DDERR_DIRECTDRAWALREADYCREATED" );
+ break;
+
+ case DDERR_NODIRECTDRAWHW:
+ strcpy( errorString, "DDERR_NODIRECTDRAWHW" );
+ break;
+
+ case DDERR_PRIMARYSURFACEALREADYEXISTS:
+ strcpy( errorString, "DDERR_PRIMARYSURFACEALREADYEXISTS" );
+ break;
+
+ case DDERR_NOEMULATION:
+ strcpy( errorString, "DDERR_NOEMULATION" );
+ break;
+
+ case DDERR_REGIONTOOSMALL:
+ strcpy( errorString, "DDERR_REGIONTOOSMALL" );
+ break;
+
+ case DDERR_CLIPPERISUSINGHWND:
+ strcpy( errorString, "DDERR_CLIPPERISUSINGHWND" );
+ break;
+
+ case DDERR_NOCLIPPERATTACHED:
+ strcpy( errorString, "DDERR_NOCLIPPERATTACHED" );
+ break;
+
+ case DDERR_NOHWND:
+ strcpy( errorString, "DDERR_NOHWND" );
+ break;
+
+ case DDERR_HWNDSUBCLASSED:
+ strcpy( errorString, "DDERR_HWNDSUBCLASSED" );
+ break;
+
+ case DDERR_HWNDALREADYSET:
+ strcpy( errorString, "DDERR_HWNDALREADYSET" );
+ break;
+
+ case DDERR_NOPALETTEATTACHED:
+ strcpy( errorString, "DDERR_NOPALETTEATTACHED" );
+ break;
+
+ case DDERR_NOPALETTEHW:
+ strcpy( errorString, "DDERR_NOPALETTEHW" );
+ break;
+
+ case DDERR_BLTFASTCANTCLIP:
+ strcpy( errorString, "DDERR_BLTFASTCANTCLIP" );
+ break;
+
+ case DDERR_NOBLTHW:
+ strcpy( errorString, "DDERR_NOBLTHW" );
+ break;
+
+ case DDERR_NODDROPSHW:
+ strcpy( errorString, "DDERR_NODDROPSHW" );
+ break;
+
+ case DDERR_OVERLAYNOTVISIBLE:
+ strcpy( errorString, "DDERR_OVERLAYNOTVISIBLE" );
+ break;
+
+ case DDERR_NOOVERLAYDEST:
+ strcpy( errorString, "DDERR_NOOVERLAYDEST" );
+ break;
+
+ case DDERR_INVALIDPOSITION:
+ strcpy( errorString, "DDERR_INVALIDPOSITION" );
+ break;
+
+ case DDERR_NOTAOVERLAYSURFACE:
+ strcpy( errorString, "DDERR_NOTAOVERLAYSURFACE" );
+ break;
+
+ case DDERR_EXCLUSIVEMODEALREADYSET:
+ strcpy( errorString, "DDERR_EXCLUSIVEMODEALREADYSET" );
+ break;
+
+ case DDERR_NOTFLIPPABLE:
+ strcpy( errorString, "DDERR_NOTFLIPPABLE" );
+ break;
+
+ case DDERR_CANTDUPLICATE:
+ strcpy( errorString, "DDERR_CANTDUPLICATE" );
+ break;
+
+ case DDERR_NOTLOCKED:
+ strcpy( errorString, "DDERR_NOTLOCKED" );
+ break;
+
+ case DDERR_CANTCREATEDC:
+ strcpy( errorString, "DDERR_CANTCREATEDC" );
+ break;
+
+ case DDERR_NODC:
+ strcpy( errorString, "DDERR_NODC" );
+ break;
+
+ case DDERR_WRONGMODE:
+ strcpy( errorString, "DDERR_WRONGMODE" );
+ break;
+
+ case DDERR_IMPLICITLYCREATED:
+ strcpy( errorString, "DDERR_IMPLICITLYCREATED" );
+ break;
+
+ case DDERR_NOTPALETTIZED:
+ strcpy( errorString, "DDERR_NOTPALETTIZED" );
+ break;
+
+ case DDERR_UNSUPPORTEDMODE:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMODE" );
+ break;
+
+ case DDERR_NOMIPMAPHW:
+ strcpy( errorString, "DDERR_NOMIPMAPHW" );
+ break;
+
+ case DDERR_INVALIDSURFACETYPE:
+ strcpy( errorString, "DDERR_INVALIDSURFACETYPE" );
+ break;
+
+ case DDERR_NOOPTIMIZEHW:
+ strcpy( errorString, "DDERR_NOOPTIMIZEHW" );
+ break;
+
+ case DDERR_NOTLOADED:
+ strcpy( errorString, "DDERR_NOTLOADED" );
+ break;
+
+ case DDERR_NOFOCUSWINDOW:
+ strcpy( errorString, "DDERR_NOFOCUSWINDOW" );
+ break;
+
+ case DDERR_DCALREADYCREATED:
+ strcpy( errorString, "DDERR_DCALREADYCREATED" );
+ break;
+
+ case DDERR_NONONLOCALVIDMEM:
+ strcpy( errorString, "DDERR_NONONLOCALVIDMEM" );
+ break;
+
+ case DDERR_CANTPAGELOCK:
+ strcpy( errorString, "DDERR_CANTPAGELOCK" );
+ break;
+
+ case DDERR_CANTPAGEUNLOCK:
+ strcpy( errorString, "DDERR_CANTPAGEUNLOCK" );
+ break;
+
+ case DDERR_NOTPAGELOCKED:
+ strcpy( errorString, "DDERR_NOTPAGELOCKED" );
+ break;
+
+ case DDERR_MOREDATA:
+ strcpy( errorString, "DDERR_MOREDATA" );
+ break;
+
+ case DDERR_EXPIRED:
+ strcpy( errorString, "DDERR_EXPIRED" );
+ break;
+
+ case DDERR_VIDEONOTACTIVE:
+ strcpy( errorString, "DDERR_VIDEONOTACTIVE" );
+ break;
+
+ case DDERR_DEVICEDOESNTOWNSURFACE:
+ strcpy( errorString, "DDERR_DEVICEDOESNTOWNSURFACE" );
+ break;
+
+ case DDERR_NOTINITIALIZED:
+ strcpy( errorString, "DDERR_NOTINITIALIZED" );
+ break;
+
+ default:
+ strcpy( errorString, "<unknown error code>" );
+ break;
+ }
+
+ return &errorString[0];
+}
diff --git a/src/mesa/drivers/d3d/D3Dvbrender.c b/src/mesa/drivers/d3d/D3Dvbrender.c new file mode 100644 index 00000000000..09857f1dc8d --- /dev/null +++ b/src/mesa/drivers/d3d/D3Dvbrender.c @@ -0,0 +1,2149 @@ +/*===========================================================================*/ +/* */ +/* Mesa-3.0 DirectX 6 Driver */ +/* */ +/* By Leigh McRae */ +/* */ +/* http://www.altsoftware.com/ */ +/* */ +/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */ +/*===========================================================================*/ +#include <stdio.h> +#include "clip.h" +#include "context.h" +#include "light.h" +#include "lines.h" +#include "macros.h" +#include "matrix.h" +#include "pb.h" +#include "points.h" +#include "mtypes.h" +#include "vb.h" +#include "vbrender.h" +#include "xform.h" +#include "D3DMesa.h" + +static void SetRenderStates( GLcontext *ctx ); +static void DebugRenderStates( GLcontext *ctx, BOOL bForce ); + +static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end ); +static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv ); +void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv ); +void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ); + +/* I went with a D3D vertex buffer that is 6 times that of the Mesa one */ +/* instead of having the D3D one flush when its full. This way Mesa will*/ +/* handle all the flushing. I need x6 as points can use 4 vertex each. */ +D3DTLVERTEX D3DTLVertices[ (VB_MAX*6) ]; +GLuint VList[VB_SIZE]; +/*===========================================================================*/ +/* Compute Z offsets for a polygon with plane defined by (A,B,C,D) */ +/* D is not needed. TODO: Currently we are calculating this but not using it.*/ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void OffsetPolygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c ) +{ + GLfloat ac, + bc, + m, + offset; + + DPF(( DBG_FUNC, "OffsetPolygon();" )); + + if ( (c < 0.001F) && (c > - 0.001F) ) + { + /* Prevents underflow problems. */ + ctx->PointZoffset = 0.0F; + ctx->LineZoffset = 0.0F; + ctx->PolygonZoffset = 0.0F; + } + else + { + ac = a / c; + bc = b / c; + if ( ac < 0.0F ) + ac = -ac; + if ( bc<0.0F ) + bc = -bc; + m = MAX2( ac, bc ); /* m = sqrt( ac*ac + bc*bc ); */ + + offset = (m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits); + ctx->PointZoffset = ctx->Polygon.OffsetPoint ? offset : 0.0F; + ctx->LineZoffset = ctx->Polygon.OffsetLine ? offset : 0.0F; + ctx->PolygonZoffset = ctx->Polygon.OffsetFill ? offset : 0.0F; + } + + DPF(( DBG_PRIM_INFO, "OffsetPolygon: %f", offset )); +} +/*===========================================================================*/ +/* Compute signed area of the n-sided polgyon specified by vertices */ +/* vb->Win[] and vertex list vlist[]. */ +/* A clockwise polygon will return a negative area. A counter-clockwise */ +/* polygon will return a positive area. I have changed this function to */ +/* actually calculate twice the area as its faster and still gives the sign. */ +/*===========================================================================*/ +/* RETURN: signed area of the polgon. */ +/*===========================================================================*/ +static GLfloat PolygonArea( const struct vertex_buffer *vb, GLuint n, const GLuint vlist[] ) +{ + GLfloat area; + GLuint i; + + DPF(( DBG_FUNC, "PolygonArea();" )); + +#define j0 vlist[i] +#define j1 vlist[(i+1)%n] +#define x0 vb->Win[j0][0] +#define y0 vb->Win[j0][1] +#define x1 vb->Win[j1][0] +#define y1 vb->Win[j1][1] + + /* area = sum of trapezoids */ + for( i = 0, area = 0.0; i < n; i++ ) + area += ((x0 - x1) * (y0 + y1)); /* Note: no divide by two here! */ + +#undef x0 +#undef y0 +#undef x1 +#undef y1 +#undef j1 +#undef j0 + + // TODO: I don't see the point or * 0.5 as we just want the sign... + return area; +} +/*===========================================================================*/ +/* Render a polygon that needs clipping on at least one vertex. The function*/ +/* will first clip the polygon to any user clipping planes then clip to the */ +/* viewing volume. The final polygon will be draw as single triangles that */ +/* first need minor proccessing (culling, offset, etc) before we draw the */ +/* polygon as a fan. NOTE: the fan is draw as single triangles as its not */ +/* formed sequentaly in the VB but is in the vlist[]. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderClippedPolygon( GLcontext *ctx, GLuint n, GLuint vlist[] ) +{ + struct vertex_buffer *VB = ctx->VB; + GLfloat (*win)[3] = VB->Win, + *proj = ctx->ProjectionMatrix, + ex, ey, + fx, fy, c, + wInv; + GLuint index, + pv, + facing; + + DPF(( DBG_FUNC, "RenderClippedPolygon();" )); + + DPF(( DBG_PRIM_INFO, "RenderClippedtPolygon( %d )", n )); + + /* Which vertex dictates the color when flat shading. */ + pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1]; + + /* Clipping may introduce new vertices. New vertices will be stored in */ + /* the vertex buffer arrays starting with location VB->Free. After we've*/ + /* rendered the polygon, these extra vertices can be overwritten. */ + VB->Free = VB_MAX; + + /* Clip against user clipping planes in eye coord space. */ + if ( ctx->Transform.AnyClip ) + { + n = gl_userclip_polygon( ctx, n, vlist ); + if ( n < 3 ) + return; + + /* Transform vertices from eye to clip coordinates: clip = Proj * eye */ + for( index = 0; index < n; index++ ) + { + TRANSFORM_POINT( VB->Clip[vlist[index]], proj, VB->Eye[vlist[index]] ); + } + } + + /* Clip against view volume in clip coord space */ + n = gl_viewclip_polygon( ctx, n, vlist ); + if ( n < 3 ) + return; + + /* Transform new vertices from clip to ndc to window coords. */ + /* ndc = clip / W window = viewport_mapping(ndc) */ + /* Note that window Z values are scaled to the range of integer */ + /* depth buffer values. */ + + /* Only need to compute window coords for new vertices */ + for( index = VB_MAX; index < VB->Free; index++ ) + { + if ( VB->Clip[index][3] != 0.0F ) + { + wInv = 1.0F / VB->Clip[index][3]; + + win[index][0] = VB->Clip[index][0] * wInv * ctx->Viewport.Sx + ctx->Viewport.Tx; + win[index][1] = VB->Clip[index][1] * wInv * ctx->Viewport.Sy + ctx->Viewport.Ty; + win[index][2] = VB->Clip[index][2] * wInv * ctx->Viewport.Sz + ctx->Viewport.Tz; + } + else + { + /* Can't divide by zero, so... */ + win[index][0] = win[index][1] = win[index][2] = 0.0F; + } + } + + /* Draw filled polygon as a triangle fan */ + for( index = 2; index < n; index++ ) + { + /* Compute orientation of triangle */ + ex = win[vlist[index-1]][0] - win[vlist[0]][0]; + ey = win[vlist[index-1]][1] - win[vlist[0]][1]; + fx = win[vlist[index]][0] - win[vlist[0]][0]; + fy = win[vlist[index]][1] - win[vlist[0]][1]; + c = (ex * fy) - (ey * fx); + + /* polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + continue; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + continue; + + if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE ) + { + if ( facing == 1 ) + { + /* use back color */ + VB->Color = VB->Bcolor; + VB->Specular= VB->Bspec; + } + else + { + /* use front color */ + VB->Color = VB->Fcolor; + VB->Specular= VB->Fspec; + } + } + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* finish computing plane equation of polygon, compute offset */ + GLfloat fz = win[vlist[index]][2] - win[vlist[0]][2]; + GLfloat ez = win[vlist[index-1]][2] - win[vlist[0]][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + RenderOneTriangle( ctx, vlist[0], vlist[index-1], vlist[index], pv ); + } +} +/*===========================================================================*/ +/* This function gets called when either the vertex buffer is full or glEnd */ +/* has been called. If the we aren't in rendering mode (FEEDBACK) then I */ +/* pass the vertex buffer back to Mesa to deal with by returning FALSE. */ +/* If I can render the primitive types in the buffer directly then I will */ +/* return TRUE after I render the vertex buffer and reset the vertex buffer. */ +/* */ +/* TODO: I don't handle the special case of when the vertex buffer is full */ +/* and we have a primitive that bounds this buffer and the next one to */ +/* come. I'm not sure right now if Mesa handles this for me... */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE. */ +/*===========================================================================*/ +GLboolean RenderVertexBuffer( GLcontext *ctx, GLboolean allDone ) +{ + struct vertex_buffer *VB = ctx->VB; + GLuint index, + vlist[VB_SIZE]; + + DPF(( DBG_FUNC, "RenderVertexBuffer();" )); + + /* We only need to hook actual tri's that need rendering. */ + if ( ctx->RenderMode != GL_RENDER ) + { + // (ctx->Visual->AccumBits > 0) ) + // (ctx->Visual->StencilBits > 0) ) + DPF(( DBG_PRIM_INFO, "Passing VB back to Mesa" )); + return FALSE; + } + + /* I'm going to set the states here so that all functions will */ + /* be assured to have the right states. If Mesa's vertex bufefr */ + /* function calls one of my primitive functions (TRI,POINT,LINE) */ + /* it will need the right states. So instead of doing it in the */ + /* primitive function I will always do it here at risk of some */ + /* slow down to some cases... */ + SetRenderStates( ctx ); + + switch( ctx->Primitive ) + { + case GL_POINTS: + DPF(( DBG_PRIM_INFO, "GL_POINTS( %d )", VB->Count )); + RenderPointsVB( ctx, 0, VB->Count ); + break; + + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + /* Not supported functions yet so pass back that we failed to */ + /* render the vertex buffer and Mesa will have to do it. */ + DPF(( DBG_PRIM_INFO, "GL_LINE_?( %d )", VB->Count )); + return FALSE; + + case GL_TRIANGLES: + if ( VB->Count < 3 ) + { + DPF(( DBG_PRIM_WARN, "GL_TRIANGLES( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_TRIANGLES( %d )", VB->Count )); + RenderTriangleVB( ctx, 0, VB->Count ); + break; + + case GL_TRIANGLE_STRIP: + if ( VB->Count < 3 ) + { + DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_STRIP( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_STRIP( %d )", VB->Count )); + RenderTriangleStripVB( ctx, 0, VB->Count ); + break; + + case GL_TRIANGLE_FAN: + if ( VB->Count < 3 ) + { + DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_FAN( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_FAN( %d )", VB->Count )); + RenderTriangleFanVB( ctx, 0, VB->Count ); + break; + + case GL_QUADS: + if ( VB->Count < 4 ) + { + DPF(( DBG_PRIM_WARN, "GL_QUADS( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_QUADS( %d )", VB->Count )); + RenderQuadVB( ctx, 0, VB->Count ); + break; + + case GL_QUAD_STRIP: + if ( VB->Count < 4 ) + { + DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_QUAD_STRIP( %d )", VB->Count )); + + if ( VB->ClipOrMask ) + { + for( index = 3; index < VB->Count; index += 2 ) + { + if ( VB->ClipMask[index-3] & VB->ClipMask[index-2] & VB->ClipMask[index-1] & VB->ClipMask[index] & CLIP_ALL_BITS ) + { + /* All points clipped by common plane */ + DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count )); + continue; + } + else if ( VB->ClipMask[index-3] | VB->ClipMask[index-2] | VB->ClipMask[index-1] | VB->ClipMask[index] ) + { + vlist[0] = index - 3; + vlist[1] = index - 2; + vlist[2] = index; + vlist[3] = index - 1; + RenderClippedPolygon( ctx, 4, vlist ); + } + else + { + RenderQuad( ctx, (index-3), (index-2), index, (index-1), index ); + } + } + } + else + { + /* No clipping needed */ + for( index = 3; index < VB->Count; index += 2 ) + RenderQuad( ctx, (index-3), (index-2), index, (index-1), index ); + } + break; + + case GL_POLYGON: + if ( VB->Count < 3 ) + { + DPF(( DBG_PRIM_WARN, "GL_POLYGON( %d )", VB->Count )); + return FALSE; + } + + DPF(( DBG_PRIM_INFO, "GL_POLYGON( %d )", VB->Count )); + + /* All points clipped by common plane, draw nothing */ + if ( !(VB->ClipAndMask & CLIP_ALL_BITS) ) + RenderTriangleFanVB( ctx, 0, VB->Count ); + break; + + default: + /* should never get here */ + _mesa_problem( ctx, "invalid mode in gl_render_vb" ); + } + + DPF(( DBG_PRIM_INFO, "ResetVB" )); + + /* We return TRUE to indicate we rendered the VB. */ + gl_reset_vb( ctx, allDone ); + return TRUE; +} +/*===========================================================================*/ +/* This function will render the current vertex buffer as triangles. The */ +/* buffer has to be able to be rendered directly. This means that we are */ +/* filled, no offsets, no culling and one sided rendering. Also we must be */ +/* in render mode of course. */ +/* First I will fill the global D3D vertice buffer. Next I will set all the*/ +/* states for D3D based on the current OGL state. Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int index, + cVertex, + height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + GLfloat ex, ey, + fx, fy, c; + GLuint facing; + + DPF(( DBG_FUNC, "RenderTriangleVB" )); + + if ( !VB->ClipOrMask ) + { + DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) )); + for( index = start, cVertex = 0; index < end; ) + { + dwPVColor = (VB->Color[(index+2)][3]<<24) | (VB->Color[(index+2)][0]<<16) | (VB->Color[(index+2)][1]<<8) | VB->Color[(index+2)][2]; + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; + index++; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; + index++; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color= dwPVColor; + index++; + } + } + else + { +#define v1 index +#define v2 (index+1) +#define v3 (index+2) + + for( index = start, cVertex = 0; index < end; index += 3 ) + { + if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS ) + { + continue; + } + else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] ) + { + VList[0] = v1; + VList[1] = v2; + VList[2] = v3; + RenderClippedPolygon( ctx, 3, VList ); + continue; + } + + /* Compute orientation of triangle */ + ex = VB->Win[v2][0] - VB->Win[v1][0]; + ey = VB->Win[v2][1] - VB->Win[v1][1]; + fx = VB->Win[v3][0] - VB->Win[v1][0]; + fy = VB->Win[v3][1] - VB->Win[v1][1]; + c = (ex * fy) - (ey * fx); + + /* polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + continue; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + continue; + + if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE ) + { + if ( facing == 1 ) + { + /* use back color */ + VB->Color = VB->Bcolor; + VB->Specular= VB->Bspec; + } + else + { + /* use front color */ + VB->Color = VB->Fcolor; + VB->Specular= VB->Fspec; + } + } + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* Finish computing plane equation of polygon, compute offset */ + GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2]; + GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */ + dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= dwPVColor; + } +#undef v1 +#undef v2 +#undef v3 + } + + /* Render the converted vertex buffer. */ + if ( cVertex > 2 ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/* This function will render the current vertex buffer as a triangle fan. */ +/* The buffer has to be able to be rendered directly. This means that we are*/ +/* filled, no offsets, no culling and one sided rendering. Also we must be */ +/* in render mode of course. */ +/* First I will fill the global D3D vertice buffer. Next I will set all the*/ +/* states for D3D based on the current OGL state. Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int index, + cVertex, + height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + GLfloat ex, ey, + fx, fy, c; + GLuint facing; + DWORD dwPVColor; + + DPF(( DBG_FUNC, "RenderTriangleFanVB();" )); + + /* Special case that we can blast the fan without culling, offset, etc... */ + if ( !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) ) + { + DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) )); + + /* Seed the the fan. */ + D3DTLVertices[0].sx = D3DVAL( VB->Win[start][0] ); + D3DTLVertices[0].sy = D3DVAL( (height - VB->Win[start][1]) ); + D3DTLVertices[0].sz = D3DVAL( VB->Win[start][2] ); + D3DTLVertices[0].tu = D3DVAL( VB->TexCoord[start][0] ); + D3DTLVertices[0].tv = D3DVAL( VB->TexCoord[start][1] ); + D3DTLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[start][3]) ); + D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2]; + + /* Seed the the fan. */ + D3DTLVertices[1].sx = D3DVAL( VB->Win[(start+1)][0] ); + D3DTLVertices[1].sy = D3DVAL( (height - VB->Win[(start+1)][1]) ); + D3DTLVertices[1].sz = D3DVAL( VB->Win[(start+1)][2] ); + D3DTLVertices[1].tu = D3DVAL( VB->TexCoord[(start+1)][0] ); + D3DTLVertices[1].tv = D3DVAL( VB->TexCoord[(start+1)][1] ); + D3DTLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) ); + D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2]; + + for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ ) + { + /*=================================*/ + /* Add the next vertex to the fan. */ + /*=================================*/ + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex].color = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; + } + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLEFAN, &D3DTLVertices[0], cVertex ); + } + else + { +#define v1 start +#define v2 (index-1) +#define v3 index + + for( index = (start+2), cVertex = 0; index < end; index++ ) + { + if ( VB->ClipOrMask ) + { + /* All points clipped by common plane */ + if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS ) + { + continue; + } + else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] ) + { + VList[0] = v1; + VList[1] = v2; + VList[2] = v3; + RenderClippedPolygon( ctx, 3, VList ); + continue; + } + } + + /* Compute orientation of triangle */ + ex = VB->Win[v2][0] - VB->Win[v1][0]; + ey = VB->Win[v2][1] - VB->Win[v1][1]; + fx = VB->Win[v3][0] - VB->Win[v1][0]; + fy = VB->Win[v3][1] - VB->Win[v1][1]; + c = (ex * fy) - (ey * fx); + + /* polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + continue; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + continue; + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* Finish computing plane equation of polygon, compute offset */ + GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2]; + GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= dwPVColor; + } + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +#undef v1 +#undef v2 +#undef v3 + } +} +/*===========================================================================*/ +/* This function will render the current vertex buffer as a triangle strip. */ +/* The buffer has to be able to be rendered directly. This means that we are*/ +/* filled, no offsets, no culling and one sided rendering. Also we must be */ +/* in render mode of course. */ +/* First I will fill the global D3D vertice buffer. Next I will set all the*/ +/* states for D3D based on the current OGL state. Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int index, + cVertex = 0, + v1, v2, v3, + height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + GLfloat ex, ey, + fx, fy, c; + GLuint facing; + DWORD dwPVColor; + + DPF(( DBG_FUNC, "RenderTriangleStripVB();" )); + + /* Special case that we can blast the fan without culling, offset, etc... */ + if ( !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) ) + { + DPF(( DBG_PRIM_PROFILE, "DirectTriangles" )); + + /* Seed the the strip. */ + D3DTLVertices[0].sx = D3DVAL( VB->Win[start][0] ); + D3DTLVertices[0].sy = D3DVAL( (height - VB->Win[start][1]) ); + D3DTLVertices[0].sz = D3DVAL( VB->Win[start][2] ); + D3DTLVertices[0].tu = D3DVAL( VB->TexCoord[start][0] ); + D3DTLVertices[0].tv = D3DVAL( VB->TexCoord[start][1] ); + D3DTLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[start][3]) ); + D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2]; + + /* Seed the the strip. */ + D3DTLVertices[1].sx = D3DVAL( VB->Win[(start+1)][0] ); + D3DTLVertices[1].sy = D3DVAL( (height - VB->Win[(start+1)][1]) ); + D3DTLVertices[1].sz = D3DVAL( VB->Win[(start+1)][2] ); + D3DTLVertices[1].tu = D3DVAL( VB->TexCoord[(start+1)][0] ); + D3DTLVertices[1].tv = D3DVAL( VB->TexCoord[(start+1)][1] ); + D3DTLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) ); + D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2]; + + for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ ) + { + /*===================================*/ + /* Add the next vertex to the strip. */ + /*===================================*/ + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex].color = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2]; + } + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLESTRIP, &D3DTLVertices[0], cVertex ); + } + else + { + for( index = (start+2); index < end; index++ ) + { + /* We need to switch order so that winding won't be a problem. */ + if ( index & 1 ) + { + v1 = index - 1; + v2 = index - 2; + v3 = index - 0; + } + else + { + v1 = index - 2; + v2 = index - 1; + v3 = index - 0; + } + + /* All vertices clipped by common plane */ + if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS ) + continue; + + /* Check if any vertices need clipping. */ + if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] ) + { + VList[0] = v1; + VList[1] = v2; + VList[2] = v3; + RenderClippedPolygon( ctx, 3, VList ); + } + else + { + /* Compute orientation of triangle */ + ex = VB->Win[v2][0] - VB->Win[v1][0]; + ey = VB->Win[v2][1] - VB->Win[v1][1]; + fx = VB->Win[v3][0] - VB->Win[v1][0]; + fy = VB->Win[v3][1] - VB->Win[v1][1]; + c = (ex * fy) - (ey * fx); + + /* Polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + continue; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + continue; + + /* Need right color if we have two sided lighting. */ + if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE ) + { + if ( facing == 1 ) + { + /* use back color */ + VB->Color = VB->Bcolor; + VB->Specular= VB->Bspec; + } + else + { + /* use front color */ + VB->Color = VB->Fcolor; + VB->Specular= VB->Fspec; + } + } + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* Finish computing plane equation of polygon, compute offset */ + GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2]; + GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + + /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */ + dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= dwPVColor; + } + } + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); + } +} +/*===========================================================================*/ +/* This function will render the current vertex buffer as Quads. The buffer*/ +/* has to be able to be rendered directly. This means that we are filled, no*/ +/* offsets, no culling and one sided rendering. Also we must be in render */ +/* mode of cource. */ +/* First I will fill the global D3D vertice buffer. Next I will set all the*/ +/* states for D3D based on the current OGL state. Finally I pass the D3D VB */ +/* to the wrapper that call DrawPrimitives. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int index, + cVertex, + height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + GLfloat ex, ey, + fx, fy, c; + GLuint facing; /* 0=front, 1=back */ + + DPF(( DBG_FUNC, "RenderQuadVB();" )); + +#define v1 (index) +#define v2 (index+1) +#define v3 (index+2) +#define v4 (index+3) + + if ( !VB->ClipOrMask ) + { + DPF(( DBG_PRIM_PROFILE, "DirectTriangles" )); + + for( cVertex = 0, index = start; index < end; index += 4 ) + { + if ( ctx->Light.ShadeModel == GL_FLAT ) + dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v1][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v2][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v3][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v1][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v3][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v4][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v4][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v4][2] ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v4][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v4][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + } + } + else + { + for( cVertex = 0, index = start; index < end; index += 4 ) + { + if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & VB->ClipMask[v4] & CLIP_ALL_BITS ) + { + continue; + } + else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] | VB->ClipMask[v4] ) + { + VList[0] = v1; + VList[1] = v2; + VList[2] = v3; + VList[3] = v4; + RenderClippedPolygon( ctx, 4, VList ); + continue; + } + + /* Compute orientation of triangle */ + ex = VB->Win[v2][0] - VB->Win[v1][0]; + ey = VB->Win[v2][1] - VB->Win[v1][1]; + fx = VB->Win[v3][0] - VB->Win[v1][0]; + fy = VB->Win[v3][1] - VB->Win[v1][1]; + c = (ex * fy) - (ey * fx); + + /* polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + continue; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + continue; + + if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE ) + { + if ( facing == 1 ) + { + /* use back color */ + VB->Color = VB->Bcolor; + VB->Specular= VB->Bspec; + } + else + { + /* use front color */ + VB->Color = VB->Fcolor; + VB->Specular= VB->Fspec; + } + } + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* Finish computing plane equation of polygon, compute offset */ + GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2]; + GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + + if ( ctx->Light.ShadeModel == GL_FLAT ) + dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v4][0] ); + D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v4][1]) ); + D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) ); + D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v4][0] ); + D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v4][1] ); + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) ); + D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? + dwPVColor : + (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + } + } + +#undef v4 +#undef v3 +#undef v2 +#undef v1 + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/* */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE. */ +/*===========================================================================*/ +static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + GLfloat ex, ey, + fx, fy, c; + GLuint facing; /* 0=front, 1=back */ + static D3DTLVERTEX TLVertices[6]; + + DPF(( DBG_FUNC, "RenderQuad" )); + DPF(( DBG_PRIM_INFO, "RenderQuad( 1 )" )); + + /* Compute orientation of triangle */ + ex = VB->Win[v2][0] - VB->Win[v1][0]; + ey = VB->Win[v2][1] - VB->Win[v1][1]; + fx = VB->Win[v3][0] - VB->Win[v1][0]; + fy = VB->Win[v3][1] - VB->Win[v1][1]; + c = (ex * fy) - (ey * fx); + + /* polygon is perpindicular to view plane, don't draw it */ + if ( (c == 0.0F) && !ctx->Polygon.Unfilled ) + return; + + /* Backface culling. */ + facing = (c < 0.0F) ^ ctx->Polygon.FrontBit; + if ( (facing + 1) & ctx->Polygon.CullBits ) + return; + + if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE ) + { + if ( facing == 1 ) + { + /* use back color */ + VB->Color = VB->Bcolor; + VB->Specular= VB->Bspec; + } + else + { + /* use front color */ + VB->Color = VB->Fcolor; + VB->Specular= VB->Fspec; + } + } + + if ( ctx->IndirectTriangles & DD_TRI_OFFSET ) + { + /* Finish computing plane equation of polygon, compute offset */ + GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2]; + GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2]; + GLfloat a = (ey * fz) - (ez * fy); + GLfloat b = (ez * fx) - (ex * fz); + OffsetPolygon( ctx, a, b, c ); + } + + if ( ctx->Light.ShadeModel == GL_FLAT ) + dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + TLVertices[0].sx = D3DVAL( VB->Win[v1][0] ); + TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) ); + TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] ); + TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] ); + TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + TLVertices[1].sx = D3DVAL( VB->Win[v2][0] ); + TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) ); + TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] ); + TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] ); + TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + TLVertices[2].sx = D3DVAL( VB->Win[v3][0] ); + TLVertices[2].sy = D3DVAL( (height - VB->Win[v3][1]) ); + TLVertices[2].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + TLVertices[2].tu = D3DVAL( VB->TexCoord[v3][0] ); + TLVertices[2].tv = D3DVAL( VB->TexCoord[v3][1] ); + TLVertices[2].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + TLVertices[2].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + TLVertices[3].sx = D3DVAL( VB->Win[v3][0] ); + TLVertices[3].sy = D3DVAL( (height - VB->Win[v3][1]) ); + TLVertices[3].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + TLVertices[3].tu = D3DVAL( VB->TexCoord[v3][0] ); + TLVertices[3].tv = D3DVAL( VB->TexCoord[v3][1] ); + TLVertices[3].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + TLVertices[3].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + + TLVertices[4].sx = D3DVAL( VB->Win[v4][0] ); + TLVertices[4].sy = D3DVAL( (height - VB->Win[v4][1]) ); + TLVertices[4].sz = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) ); + TLVertices[4].tu = D3DVAL( VB->TexCoord[v4][0] ); + TLVertices[4].tv = D3DVAL( VB->TexCoord[v4][1] ); + TLVertices[4].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) ); + TLVertices[4].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2]; + + TLVertices[5].sx = D3DVAL( VB->Win[v1][0] ); + TLVertices[5].sy = D3DVAL( (height - VB->Win[v1][1]) ); + TLVertices[5].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + TLVertices[5].tu = D3DVAL( VB->TexCoord[v1][0] ); + TLVertices[5].tv = D3DVAL( VB->TexCoord[v1][1] ); + TLVertices[5].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + TLVertices[5].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + /* Draw the two triangles. */ + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 6 ); +} +/*===========================================================================*/ +/* */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE. */ +/*===========================================================================*/ +void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + static D3DTLVERTEX TLVertices[3]; + + DPF(( DBG_FUNC, "RenderOneTriangle" )); + DPF(( DBG_PRIM_INFO, "RenderTriangle( 1 )" )); + + /*=====================================*/ + /* Populate the the triangle vertices. */ + /*=====================================*/ + if ( ctx->Light.ShadeModel == GL_FLAT ) + dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + + TLVertices[0].sx = D3DVAL( VB->Win[v1][0] ); + TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) ); + TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) ); + TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] ); + TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] ); + TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + DPF(( DBG_PRIM_INFO, "V1 -> x:%f y:%f z:%f c:%x", + TLVertices[0].sx, + TLVertices[0].sy, + TLVertices[0].sz, + TLVertices[0].color )); + + TLVertices[1].sx = D3DVAL( VB->Win[v2][0] ); + TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) ); + TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) ); + TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] ); + TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] ); + TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + DPF(( DBG_PRIM_INFO, "V2 -> x:%f y:%f z:%f c:%x", + TLVertices[1].sx, + TLVertices[1].sy, + TLVertices[1].sz, + TLVertices[1].color )); + + TLVertices[2].sx = D3DVAL( VB->Win[v3][0] ); + TLVertices[2].sy = D3DVAL( (height - VB->Win[v3][1]) ); + TLVertices[2].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) ); + TLVertices[2].tu = D3DVAL( VB->TexCoord[v3][0] ); + TLVertices[2].tv = D3DVAL( VB->TexCoord[v3][1] ); + TLVertices[2].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) ); + TLVertices[2].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2]; + DPF(( DBG_PRIM_INFO, "V3 -> x:%f y:%f z:%f c:%x", + TLVertices[2].sx, + TLVertices[2].sy, + TLVertices[2].sz, + TLVertices[2].color )); + + /* Draw the triangle. */ + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 3 ); +} +/*===========================================================================*/ +/* */ +/*===========================================================================*/ +/* RETURN: TRUE, FALSE. */ +/*===========================================================================*/ +void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + static D3DTLVERTEX TLVertices[2]; + + DPF(( DBG_FUNC, "RenderOneLine" )); + DPF(( DBG_PRIM_INFO, "RenderLine( 1 )" )); + + if ( VB->MonoColor ) + dwPVColor = (pContext->aCurrent<<24) | (pContext->rCurrent<<16) | (pContext->gCurrent<<8) | pContext->bCurrent; + else + dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2]; + + TLVertices[0].sx = D3DVAL( VB->Win[v1][0] ); + TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) ); + TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->LineZoffset) ); + TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] ); + TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] ); + TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) ); + TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2]; + + TLVertices[1].sx = D3DVAL( VB->Win[v2][0] ); + TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) ); + TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->LineZoffset) ); + TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] ); + TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] ); + TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) ); + TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor : + (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2]; + + /* Draw line from (x0,y0) to (x1,y1) with current pixel color/index */ + DrawPrimitiveHAL( pContext->pShared, D3DPT_LINELIST, &TLVertices[0], 2 ); +} +/*===========================================================================*/ +/* This function was written to convert points into triangles. I did this */ +/* as all card accelerate triangles and most drivers do this anyway. In hind*/ +/* thought this might be a bad idea as some cards do better. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + struct vertex_buffer *VB = ctx->VB; + struct pixel_buffer *PB = ctx->PB; + GLuint index; + GLfloat radius, z, + xmin, ymin, + xmax, ymax; + GLint cVertex, + height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top); + DWORD dwPVColor; + + DPF(( DBG_FUNC, "RenderPointsVB();" )); + + radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F; + + for( index = start, cVertex = 0; index <= end; index++ ) + { + if ( VB->ClipMask[index] == 0 ) + { + xmin = D3DVAL( VB->Win[index][0] - radius ); + xmax = D3DVAL( VB->Win[index][0] + radius ); + ymin = D3DVAL( height - VB->Win[index][1] - radius ); + ymax = D3DVAL( height - VB->Win[index][1] + radius ); + z = D3DVAL( (VB->Win[index][2] + ctx->PointZoffset) ); + + dwPVColor = (VB->Color[index][3]<<24) | + (VB->Color[index][0]<<16) | + (VB->Color[index][1]<<8) | + VB->Color[index][2]; + + D3DTLVertices[cVertex].sx = xmin; + D3DTLVertices[cVertex].sy = ymax; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + + D3DTLVertices[cVertex].sx = xmin; + D3DTLVertices[cVertex].sy = ymin; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + + D3DTLVertices[cVertex].sx = xmax; + D3DTLVertices[cVertex].sy = ymin; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + + D3DTLVertices[cVertex].sx = xmax; + D3DTLVertices[cVertex].sy = ymin; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + + D3DTLVertices[cVertex].sx = xmax; + D3DTLVertices[cVertex].sy = ymax; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + + D3DTLVertices[cVertex].sx = xmin; + D3DTLVertices[cVertex].sy = ymax; + D3DTLVertices[cVertex].sz = z; + D3DTLVertices[cVertex].tu = 0.0; + D3DTLVertices[cVertex].tv = 0.0; + D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) ); + D3DTLVertices[cVertex++].color = dwPVColor; + } + } + + /* Render the converted vertex buffer. */ + if ( cVertex ) + DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex ); +} +/*===========================================================================*/ +/* This gets call before we render any primitives so that the current OGL */ +/* states will be mapped the D3D context. I'm still not sure how D3D works */ +/* but I'm finding that it doesn't act like a state machine as OGL is. It */ +/* looks like the state gets set back to the defaults after a DrawPrimitives */ +/* or an EndScene. Also I set states that are the default even though this */ +/* is redundant as the defaults seem screwed up. */ +/* TODO: make a batch call. */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void SetRenderStates( GLcontext *ctx ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + DWORD dwFunc; + static BOOL bTexture = FALSE; + static int texName = -1; + + DPF(( DBG_FUNC, "SetRenderStates();" )); + + if ( g_DBGMask & DBG_STATES ) + DebugRenderStates( ctx, FALSE ); + + SetStateHAL( pContext->pShared, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE ); + SetStateHAL( pContext->pShared, D3DRENDERSTATE_DITHERENABLE, (ctx->Color.DitherFlag) ? TRUE : FALSE ); + + /*================================================*/ + /* Check too see if there are new TEXTURE states. */ + /*================================================*/ + if ( ctx->Texture._EnabledUnits ) + { + switch( ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode ) + { + case GL_MODULATE: + if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Format == GL_RGBA ) + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulatealpha]; + else + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulate]; + break; + + case GL_BLEND: + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha]; + break; + + case GL_REPLACE: + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal]; + break; + + case GL_DECAL: + if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Format == GL_RGBA ) + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha]; + else + dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal]; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAPBLEND, dwFunc ); + + switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter ) + { + case GL_NEAREST: + dwFunc = D3DFILTER_NEAREST; + break; + case GL_LINEAR: + dwFunc = D3DFILTER_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + dwFunc = D3DFILTER_MIPNEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + dwFunc = D3DFILTER_LINEARMIPNEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + dwFunc = D3DFILTER_MIPLINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + dwFunc = D3DFILTER_LINEARMIPLINEAR; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAG, dwFunc ); + + switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter ) + { + case GL_NEAREST: + dwFunc = D3DFILTER_NEAREST; + break; + case GL_LINEAR: + dwFunc = D3DFILTER_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + dwFunc = D3DFILTER_MIPNEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + dwFunc = D3DFILTER_LINEARMIPNEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + dwFunc = D3DFILTER_MIPLINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + dwFunc = D3DFILTER_LINEARMIPLINEAR; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMIN, dwFunc ); + + /* Another hack to cut down on redundant texture binding. */ + // if ( texName != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name ) + // { + texName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name; + CreateTMgrHAL( pContext->pShared, + texName, + 0, + ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Format, + (RECT *)NULL, + ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Width, + ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Height, + TM_ACTION_BIND, + (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Data ); + // } + bTexture = TRUE; + } + else + { + /* This is nasty but should cut down on the number of redundant calls. */ + if ( bTexture == TRUE ) + { + DisableTMgrHAL( pContext->pShared ); + bTexture = FALSE; + } + } + + /*===============================================*/ + /* Check too see if there are new RASTER states. */ + /*===============================================*/ + + // TODO: no concept of front & back. + switch( ctx->Polygon.FrontMode ) + { + case GL_POINT: + SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_POINT ); + break; + case GL_LINE: + SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME ); + break; + case GL_FILL: + SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID ); + break; + } + + /*************/ + /* Z-Buffer. */ + /*************/ + if ( ctx->Depth.Test == GL_TRUE ) + { + switch( ctx->Depth.Func ) + { + case GL_NEVER: + dwFunc = D3DCMP_NEVER; + break; + case GL_LESS: + dwFunc = D3DCMP_LESS; + break; + case GL_GEQUAL: + dwFunc = D3DCMP_GREATEREQUAL; + break; + case GL_LEQUAL: + dwFunc = D3DCMP_LESSEQUAL; + break; + case GL_GREATER: + dwFunc = D3DCMP_GREATER; + break; + case GL_NOTEQUAL: + dwFunc = D3DCMP_NOTEQUAL; + break; + case GL_EQUAL: + dwFunc = D3DCMP_EQUAL; + break; + case GL_ALWAYS: + dwFunc = D3DCMP_ALWAYS; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZFUNC, dwFunc ); + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, TRUE ); + } + else + { + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, FALSE ); + } + + /*******************/ + /* Z-Write Enable. */ + /*******************/ + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZWRITEENABLE , (ctx->Depth.Mask == GL_TRUE) ? TRUE : FALSE ); + + /***************/ + /* Alpha test. */ + /***************/ + if ( ctx->Color.AlphaEnabled == GL_TRUE ) + { + switch( ctx->Color.AlphaFunc ) + { + case GL_NEVER: + dwFunc = D3DCMP_NEVER; + break; + case GL_LESS: + dwFunc = D3DCMP_LESS; + break; + case GL_GEQUAL: + dwFunc = D3DCMP_GREATEREQUAL; + break; + case GL_LEQUAL: + dwFunc = D3DCMP_LESSEQUAL; + break; + case GL_GREATER: + dwFunc = D3DCMP_GREATER; + break; + case GL_NOTEQUAL: + dwFunc = D3DCMP_NOTEQUAL; + break; + case GL_EQUAL: + dwFunc = D3DCMP_EQUAL; + break; + case GL_ALWAYS: + dwFunc = D3DCMP_ALWAYS; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHAFUNC , dwFunc ); + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); + } + else + { + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); + } + + /****************/ + /* Alpha blend. */ + /****************/ + if ( ctx->Color.BlendEnabled == GL_TRUE ) + { + switch( ctx->Color.BlendSrc ) + { + case GL_ZERO: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_zero]; + break; + case GL_ONE: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one]; + break; + case GL_DST_COLOR: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_color]; + break; + case GL_ONE_MINUS_DST_COLOR: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_color]; + break; + case GL_SRC_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_src_alpha]; + break; + case GL_DST_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_alpha]; + break; + case GL_ONE_MINUS_DST_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_alpha]; + break; + case GL_SRC_ALPHA_SATURATE: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha_saturate]; + break; + case GL_CONSTANT_COLOR: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_color]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_color]; + break; + case GL_CONSTANT_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_alpha]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_alpha]; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_SRCBLEND, dwFunc ); + + switch( ctx->Color.BlendDst ) + { + case GL_ZERO: + dwFunc = pContext->pShared->dwDestBlendCaps[d_zero]; + break; + case GL_ONE: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one]; + break; + case GL_SRC_COLOR: + dwFunc = pContext->pShared->dwDestBlendCaps[d_src_color]; + break; + case GL_ONE_MINUS_SRC_COLOR: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_color]; + break; + case GL_SRC_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_src_alpha]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_alpha]; + break; + case GL_DST_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_dst_alpha]; + break; + case GL_ONE_MINUS_DST_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_dst_alpha]; + break; + case GL_CONSTANT_COLOR: + dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_color]; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_color]; + break; + case GL_CONSTANT_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_alpha]; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_alpha]; + break; + } + SetStateHAL( pContext->pShared, D3DRENDERSTATE_DESTBLEND, dwFunc ); + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE ); + } + else + { + SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE ); + } +} +/*===========================================================================*/ +/* If this function is called it will track the changes to the current */ +/* states that I'm setting in Direct3D. I did this so that the DPF's would */ +/* be under control! */ +/*===========================================================================*/ +/* RETURN: */ +/*===========================================================================*/ +static void DebugRenderStates( GLcontext *ctx, BOOL bForce ) +{ + D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx; + DWORD dwFunc; + static int dither = -1, + texture = -1, + textName = -1, + textEnv = -1, + textMin = -1, + textMag = -1, + polyMode = -1, + depthTest = -1, + depthFunc = -1, + depthMask = -1, + alphaTest = -1, + alphaFunc = -1, + blend = -1, + blendSrc = -1, + blendDest = -1; + + /* Force a displayed update of all current states. */ + if ( bForce ) + { + dither = texture = textName = textEnv = textMin = textMag = -1; + polyMode = depthTest = depthFunc = depthMask = -1; + alphaTest = alphaFunc = blend = blendSrc = blendDest = -1; + } + + if ( dither != ctx->Color.DitherFlag ) + { + dither = ctx->Color.DitherFlag; + DPF(( 0, "\tDither\t\t%s", (dither) ? "ENABLED" : "--------" )); + } + if ( depthTest != ctx->Depth.Test ) + { + depthTest = ctx->Depth.Test; + DPF(( 0, "\tDepth Test\t%s", (depthTest) ? "ENABLED" : "--------" )); + } + if ( alphaTest != ctx->Color.AlphaEnabled ) + { + alphaTest = ctx->Color.AlphaEnabled; + + DPF(( 0, "\tAlpha Test\t%s", (alphaTest) ? "ENABLED" : "--------" )); + } + if ( blend != ctx->Color.BlendEnabled ) + { + blend = ctx->Color.BlendEnabled; + + DPF(( 0, "\tBlending\t%s", (blend) ? "ENABLED" : "--------" )); + } + + /*================================================*/ + /* Check too see if there are new TEXTURE states. */ + /*================================================*/ + if ( texture != ctx->Texture._EnabledUnits ) + { + texture = ctx->Texture._EnabledUnits; + DPF(( 0, "\tTexture\t\t%s", (texture) ? "ENABLED" : "--------" )); + } + + if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current ) + { + if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name != textName ) + { + textName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name; + DPF(( 0, "\tTexture Name:\t%d", textName )); + DPF(( 0, "\tTexture Format:\t%s", + (ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Format == GL_RGBA) ? + "GL_RGBA" : "GLRGB" )); + } + + if ( textEnv != ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode ) + { + textEnv = ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode; + + switch( textEnv ) + { + case GL_MODULATE: + DPF(( 0, "\tTexture\tMode\tGL_MODULATE" )); + break; + case GL_BLEND: + DPF(( 0, "\tTexture\tMode\tGL_BLEND" )); + break; + case GL_REPLACE: + DPF(( 0, "\tTexture\tMode\tGL_REPLACE" )); + break; + case GL_DECAL: + DPF(( 0, "\tTexture\tMode\tGL_DECAL" )); + break; + } + } + + if ( textMag != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter ) + { + textMag = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter; + + switch( textMag ) + { + case GL_NEAREST: + DPF(( 0, "\tTexture MAG\tGL_NEAREST" )); + break; + case GL_LINEAR: + DPF(( 0, "\tTexture MAG\tGL_LINEAR" )); + break; + case GL_NEAREST_MIPMAP_NEAREST: + DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_NEAREST" )); + break; + case GL_LINEAR_MIPMAP_NEAREST: + DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_NEAREST" )); + break; + case GL_NEAREST_MIPMAP_LINEAR: + DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_LINEAR" )); + break; + case GL_LINEAR_MIPMAP_LINEAR: + DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_LINEAR" )); + break; + } + } + + if ( textMin != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter ) + { + textMin = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter; + + switch( textMin ) + { + case GL_NEAREST: + DPF(( 0, "\tTexture MIN\tGL_NEAREST" )); + break; + case GL_LINEAR: + DPF(( 0, "\tTexture MIN\tGL_LINEAR" )); + break; + case GL_NEAREST_MIPMAP_NEAREST: + DPF(( 0, "\tTexture MIN\tGL_NEAREST_MIPMAP_NEAREST" )); + break; + case GL_LINEAR_MIPMAP_NEAREST: + DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_NEAREST" )); + break; + case GL_NEAREST_MIPMAP_LINEAR: + DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" )); + break; + case GL_LINEAR_MIPMAP_LINEAR: + DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" )); + break; + } + } + } + + if ( ctx->Polygon.FrontMode != polyMode ) + { + polyMode = ctx->Polygon.FrontMode; + + switch( polyMode ) + { + case GL_POINT: + DPF(( 0, "\tMode\t\tGL_POINT" )); + break; + case GL_LINE: + DPF(( 0, "\tMode\t\tGL_LINE" )); + break; + case GL_FILL: + DPF(( 0, "\tMode\t\tGL_FILL" )); + break; + } + } + + if ( depthFunc != ctx->Depth.Func ) + { + depthFunc = ctx->Depth.Func; + + switch( depthFunc ) + { + case GL_NEVER: + DPF(( 0, "\tDepth Func\tGL_NEVER" )); + break; + case GL_LESS: + DPF(( 0, "\tDepth Func\tGL_LESS" )); + break; + case GL_GEQUAL: + DPF(( 0, "\tDepth Func\tGL_GEQUAL" )); + break; + case GL_LEQUAL: + DPF(( 0, "\tDepth Func\tGL_LEQUAL" )); + break; + case GL_GREATER: + DPF(( 0, "\tDepth Func\tGL_GREATER" )); + break; + case GL_NOTEQUAL: + DPF(( 0, "\tDepth Func\tGL_NOTEQUAL" )); + break; + case GL_EQUAL: + DPF(( 0, "\tDepth Func\tGL_EQUAL" )); + break; + case GL_ALWAYS: + DPF(( 0, "\tDepth Func\tGL_ALWAYS" )); + break; + } + } + + if ( depthMask != ctx->Depth.Mask ) + { + depthMask = ctx->Depth.Mask; + DPF(( 0, "\tZWrite\t\t%s", (depthMask) ? "ENABLED" : "--------" )); + } + + if ( alphaFunc != ctx->Color.AlphaFunc ) + { + alphaFunc = ctx->Color.AlphaFunc; + + switch( alphaFunc ) + { + case GL_NEVER: + DPF(( 0, "\tAlpha Func\tGL_NEVER" )); + break; + case GL_LESS: + DPF(( 0, "\tAlpha Func\tGL_LESS" )); + break; + case GL_GEQUAL: + DPF(( 0, "\tAlpha Func\tGL_GEQUAL" )); + break; + case GL_LEQUAL: + DPF(( 0, "\tAlpha Func\tGL_LEQUAL" )); + break; + case GL_GREATER: + DPF(( 0, "\tAlpha Func\tGL_GREATER" )); + break; + case GL_NOTEQUAL: + DPF(( 0, "\tAlpha Func\tGL_NOTEQUAL" )); + break; + case GL_EQUAL: + DPF(( 0, "\tAlpha Func\tGL_EQUAL" )); + break; + case GL_ALWAYS: + DPF(( 0, "\tAlpha Func\tGL_ALWAYS" )); + break; + } + } + + if ( blendSrc != ctx->Color.BlendSrc ) + { + blendSrc = ctx->Color.BlendSrc; + + switch( blendSrc ) + { + case GL_ZERO: + DPF(( 0, "\tSRC Blend\tGL_ZERO" )); + break; + case GL_ONE: + DPF(( 0, "\tSRC Blend\tGL_ONE" )); + break; + case GL_DST_COLOR: + DPF(( 0, "\tSRC Blend\tGL_DST_COLOR" )); + break; + case GL_ONE_MINUS_DST_COLOR: + DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_COLOR" )); + break; + case GL_SRC_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA" )); + break; + case GL_ONE_MINUS_SRC_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_MINUS_SRC_ALPHA" )); + break; + case GL_DST_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_DST_ALPHA" )); + break; + case GL_ONE_MINUS_DST_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_ALPHA" )); + break; + case GL_SRC_ALPHA_SATURATE: + DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA_SATURATE" )); + break; + case GL_CONSTANT_COLOR: + DPF(( 0, "\tSRC Blend\tGL_CONSTANT_COLOR" )); + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_COLOR" )); + break; + case GL_CONSTANT_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_CONSTANT_ALPHA" )); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" )); + break; + } + } + + if ( blendDest != ctx->Color.BlendDst ) + { + blendDest = ctx->Color.BlendDst; + + switch( blendDest ) + { + case GL_ZERO: + DPF(( 0, "\tDST Blend\tGL_ZERO" )); + break; + case GL_ONE: + DPF(( 0, "\tDST Blend\tGL_ONE" )); + break; + case GL_SRC_COLOR: + DPF(( 0, "\tDST Blend\tGL_SRC_COLOR" )); + break; + case GL_ONE_MINUS_SRC_COLOR: + DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_COLOR" )); + break; + case GL_SRC_ALPHA: + DPF(( 0, "\tDST Blend\tGL_SRC_ALPHA" )); + break; + case GL_ONE_MINUS_SRC_ALPHA: + DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_ALPHA" )); + break; + case GL_DST_ALPHA: + DPF(( 0, "\tDST Blend\tGL_DST_ALPHA" )); + break; + case GL_ONE_MINUS_DST_ALPHA: + DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_DST_ALPHA" )); + break; + case GL_CONSTANT_COLOR: + DPF(( 0, "\tDST Blend\tGL_CONSTANT_COLOR" )); + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_COLOR" )); + break; + case GL_CONSTANT_ALPHA: + DPF(( 0, "\tDST Blend\tGL_CONSTANT_ALPHA" )); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" )); + break; + } + } +} diff --git a/src/mesa/drivers/d3d/DDrawPROCS.c b/src/mesa/drivers/d3d/DDrawPROCS.c new file mode 100644 index 00000000000..a02a89debbb --- /dev/null +++ b/src/mesa/drivers/d3d/DDrawPROCS.c @@ -0,0 +1,399 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DMesa.h"
+/*===========================================================================*/
+/* This call will clear the render surface using the pixel info built from */
+/* the surface at creation time. The call uses Lock/Unlock to access the */
+/* surface. The call also special cases a full clear or a dirty rectangle. */
+/* Finally the call returns the new clear mask that reflects that the color */
+/* buffer was cleared. */
+/*===========================================================================*/
+/* RETURN: the original mask with the bits cleared that represents the buffer*/
+/* or buffers we just cleared. */
+/*===========================================================================*/
+GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer,
+ *pScanLine;
+ int index,
+ index2;
+ DWORD dwColor;
+
+ if ( mask & GL_COLOR_BUFFER_BIT )
+ {
+ /* Lock the surface to get the surface pointer. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. */
+ dwColor = ( ((DWORD)((float)pContext->rClear * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gClear * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bClear * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ if ( all )
+ {
+ for( index = 0, pScanLine = (UCHAR *)pddsd2->lpSurface; index < pContext->pShared->dwHeight; index++, pScanLine += pddsd2->lPitch )
+ for( pBuffer = pScanLine, index2 = 0; index2 < pContext->pShared->dwWidth; index2++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ else
+ {
+ pScanLine = ((UCHAR *)pddsd2->lpSurface) +
+ ( (FLIP( pContext->pShared->dwHeight, (y+height)) * pddsd2->lPitch) + (x * pContext->pShared->pixel.cb) );
+
+ for( index = 0; index < height; index++, pScanLine += pddsd2->lPitch )
+ {
+ for( index2 = 0, pBuffer = pScanLine; index2 < width; index2++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ UnlockHAL( pContext->pShared, TRUE );
+ }
+
+ return (mask & ~GL_COLOR_BUFFER_BIT);
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The color is solved once from the current */
+/* color components. The alpha is ignored as Mesa is doing it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Lock the surface to get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. (no alpha) */
+ dwColor = ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ if ( mask[index] )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++ )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The color is solved once from the current */
+/* color components. The alpha is ignored as Mesa is doing it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. I don't uses the alpha. */
+ dwColor = ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ if ( mask )
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc isn't written for speed rather its to handle the general case. */
+/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
+/* structure that was generated from the OffScreen surface pixelformat. The */
+/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
+/* own alpha channel when the context was created. I did this as I didn't */
+/* feel that it was worth the effort to try and get HW to work (bus bound). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD *pdwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface +
+ (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) +
+ (x*pContext->pShared->pixel.cb);
+
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ pdwColor = (DWORD *)pBuffer;
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc isn't written for speed rather its to handle the general case. */
+/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
+/* structure that was generated from the OffScreen surface pixelformat. The */
+/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
+/* own alpha channel when the context was created. I did this as I didn't */
+/* feel that it was worth the effort to try and get HW to work (bus bound). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ int index;
+ DWORD *pdwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ if ( mask )
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Find the start of the pixel. Invert y for Windows. */
+ pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+ }
+ }
+ else
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ /* Find the start of the pixel. Invert y for Windows. */
+ pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
diff --git a/src/mesa/drivers/d3d/DEBUG.C b/src/mesa/drivers/d3d/DEBUG.C new file mode 100644 index 00000000000..dfa524bf314 --- /dev/null +++ b/src/mesa/drivers/d3d/DEBUG.C @@ -0,0 +1,143 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "Debug.h"
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+DWORD g_DBGMask = DBG_ALL_ERROR;
+/*===========================================================================*/
+/* This is your basic DPF function with printf like support. The function */
+/* also works with a global debug mask variable. I have written support that*/
+/* allows for the user's enviroment variable space to be read and set the */
+/* masks. This is done when the dll starts and is only in the debug version.*/
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void _cdecl DebugPrint( int mask, char *pszFormat, ... )
+{
+ char buffer[512];
+ va_list args;
+
+ /* A mask of 0 will always pass. Easy to remeber. */
+ if ( (mask == 0) || (mask & g_DBGMask) )
+ {
+ va_start( args, pszFormat );
+
+ if ( mask & DBG_ALL_ERROR )
+ OutputDebugString( "MesaD3D: (ERROR)" );
+ else
+ OutputDebugString( "MesaD3D: " );
+
+ vsprintf( buffer, pszFormat, args );
+ strcat( buffer, "\n" );
+ OutputDebugString( buffer );
+
+ va_end( args );
+ }
+}
+/*===========================================================================*/
+/* This call reads the users enviroment variables and sets any debug mask */
+/* that they have set to TRUE. Now the value must be "TRUE". */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void ReadDBGEnv( void )
+{
+ g_DBGMask = DBG_ALL_ERROR;
+
+#define IS_VAR_SET(v) if ( getenv( # v ) && !strcmp(getenv( # v ),"TRUE") ) g_DBGMask |= v;
+
+ IS_VAR_SET( DBG_FUNC );
+ IS_VAR_SET( DBG_STATES );
+
+ IS_VAR_SET( DBG_CNTX_INFO );
+ IS_VAR_SET( DBG_CNTX_WARN );
+ IS_VAR_SET( DBG_CNTX_PROFILE );
+ IS_VAR_SET( DBG_CNTX_ERROR );
+ IS_VAR_SET( DBG_CNTX_ALL );
+
+ IS_VAR_SET( DBG_PRIM_INFO );
+ IS_VAR_SET( DBG_PRIM_WARN );
+ IS_VAR_SET( DBG_PRIM_PROFILE );
+ IS_VAR_SET( DBG_PRIM_ERROR );
+ IS_VAR_SET( DBG_PRIM_ALL );
+
+ IS_VAR_SET( DBG_TXT_INFO );
+ IS_VAR_SET( DBG_TXT_WARN );
+ IS_VAR_SET( DBG_TXT_PROFILE );
+ IS_VAR_SET( DBG_TXT_ERROR );
+ IS_VAR_SET( DBG_TXT_ALL );
+
+ IS_VAR_SET( DBG_ALL_INFO );
+ IS_VAR_SET( DBG_ALL_WARN );
+ IS_VAR_SET( DBG_ALL_PROFILE );
+ IS_VAR_SET( DBG_ALL_ERROR );
+ IS_VAR_SET( DBG_ALL );
+
+#undef IS_VAR_SET
+}
+/*===========================================================================*/
+/* This function will take a pointer to a DDSURFACEDESC2 structure & display*/
+/* the parsed information using a DPF call. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf )
+{
+ char buffer[256];
+
+ /* Parse the flag type and write the string equivalent. */
+ if ( pddpf->dwFlags & DDPF_ALPHA )
+ strcat( buffer, "DDPF_ALPHA " );
+ if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
+ strcat( buffer, "DDPF_ALPHAPIXELS " );
+ if ( pddpf->dwFlags & DDPF_ALPHAPREMULT )
+ strcat( buffer, "DDPF_ALPHAPREMULT " );
+ if ( pddpf->dwFlags & DDPF_BUMPLUMINANCE )
+ strcat( buffer, "DDPF_BUMPLUMINANCE " );
+ if ( pddpf->dwFlags & DDPF_BUMPDUDV )
+ strcat( buffer, "DDPF_BUMPDUDV " );
+ if ( pddpf->dwFlags & DDPF_COMPRESSED )
+ strcat( buffer, "DDPF_COMPRESSED " );
+ if ( pddpf->dwFlags & DDPF_FOURCC )
+ strcat( buffer, "DDPF_FOURCC " );
+ if ( pddpf->dwFlags & DDPF_LUMINANCE )
+ strcat( buffer, "DDPF_LUMINANCE " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED1 )
+ strcat( buffer, "DDPF_PALETTEINDEXED1 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED2 )
+ strcat( buffer, "DDPF_PALETTEINDEXED2 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED4 )
+ strcat( buffer, "DDPF_PALETTEINDEXED4 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED8 )
+ strcat( buffer, "DDPF_PALETTEINDEXED8 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
+ strcat( buffer, "DDPF_PALETTEINDEXEDTO8 " );
+ if ( pddpf->dwFlags & DDPF_RGB )
+ strcat( buffer, "DDPF_RGB " );
+ if ( pddpf->dwFlags & DDPF_RGBTOYUV )
+ strcat( buffer, "DDPF_RGBTOYUV " );
+ if ( pddpf->dwFlags & DDPF_STENCILBUFFER )
+ strcat( buffer, "DDPF_STENCILBUFFER " );
+ if ( pddpf->dwFlags & DDPF_YUV )
+ strcat( buffer, "DDPF_YUV " );
+ if ( pddpf->dwFlags & DDPF_ZBUFFER )
+ strcat( buffer, "DDPF_ZBUFFER " );
+ if ( pddpf->dwFlags & DDPF_ZPIXELS )
+ strcat( buffer, "DDPF_ZPIXELS " );
+
+ DPF(( (DBG_TXT_INFO|DBG_CNTX_INFO),"%s", buffer ));
+}
+
+
+
+
+
diff --git a/src/mesa/drivers/d3d/DEBUG.H b/src/mesa/drivers/d3d/DEBUG.H new file mode 100644 index 00000000000..76122b91210 --- /dev/null +++ b/src/mesa/drivers/d3d/DEBUG.H @@ -0,0 +1,90 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <stdio.h>
+#include <string.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "D3DShared.h"
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+#define DBG_FUNC 0x00000001
+#define DBG_STATES 0x00000002
+
+#define DBG_CNTX_INFO 0x00000010
+#define DBG_CNTX_WARN 0x00000020
+#define DBG_CNTX_PROFILE 0x00000040
+#define DBG_CNTX_ERROR 0x00000080
+#define DBG_CNTX_ALL 0x000000F0
+
+#define DBG_PRIM_INFO 0x00000100
+#define DBG_PRIM_WARN 0x00000200
+#define DBG_PRIM_PROFILE 0x00000400
+#define DBG_PRIM_ERROR 0x00000800
+#define DBG_PRIM_ALL 0x00000F00
+
+#define DBG_TXT_INFO 0x00001000
+#define DBG_TXT_WARN 0x00002000
+#define DBG_TXT_PROFILE 0x00004000
+#define DBG_TXT_ERROR 0x00008000
+#define DBG_TXT_ALL 0x0000F000
+
+#define DBG_ALL_INFO 0x11111110
+#define DBG_ALL_WARN 0x22222220
+#define DBG_ALL_PROFILE 0x44444440
+#define DBG_ALL_ERROR 0x88888880
+#define DBG_ALL 0xFFFFFFFF
+
+#ifdef D3D_DEBUG
+# define DPF(arg) DebugPrint arg
+# define RIP(pH,msg,err) OutputDebugString(msg); \
+ OutputDebugString(err); \
+ OutputDebugString("\n"); \
+ FatalShutDown(pH)
+#else
+# define DPF(arg)
+# define RIP(pH,msg,err) FatalShutDown(pH)
+#endif
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+extern void ReadDBGEnv( void );
+extern void _cdecl DebugPrint( int mask, char *pszFormat, ... );
+extern void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern DWORD g_DBGMask;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/mesa/drivers/d3d/DbgEnv.bat b/src/mesa/drivers/d3d/DbgEnv.bat new file mode 100644 index 00000000000..40858e66844 --- /dev/null +++ b/src/mesa/drivers/d3d/DbgEnv.bat @@ -0,0 +1,25 @@ +SET DBG_FUNC=FALSE
+
+SET DBG_CNTX_INFO=TRUE
+SET DBG_CNTX_WARN=TRUE
+SET DBG_CNTX_PROFILE=FALSE
+SET DBG_CNTX_ERROR=TRUE
+SET DBG_CNTX_ALL=TRUE
+
+SET DBG_PRIM_INFO=FALSE
+SET DBG_PRIM_WARN=FALSE
+SET DBG_PRIM_PROFILE=FALSE
+SET DBG_PRIM_ERROR=TRUE
+SET DBG_PRIM_ALL=FALSE
+
+SET DBG_TXT_INFO=FALSE
+SET DBG_TXT_WARN=TRUE
+SET DBG_TXT_PROFILE=FALSE
+SET DBG_TXT_ERROR=TRUE
+SET DBG_TXT_ALL=FALSE
+
+SET DBG_ALL_INFO=FALSE
+SET DBG_ALL_WARN=TRUE
+SET DBG_ALL_PROFILE=FALSE
+SET DBG_ALL_ERROR=TRUE
+SET DBG_ALL=FALSE
diff --git a/src/mesa/drivers/d3d/MAKEFILE b/src/mesa/drivers/d3d/MAKEFILE new file mode 100644 index 00000000000..ad1d40dc27b --- /dev/null +++ b/src/mesa/drivers/d3d/MAKEFILE @@ -0,0 +1,101 @@ +##############################################################################
+#
+# Mesa-3.0 Makefile for DirectX 6 Driver
+#
+# By Leigh McRae
+#
+# http://www.altsoftware.com/
+#
+# Copyright (c) 1999-1998 alt.software inc. All Rights Reserved
+##############################################################################
+NAME=
+TARGET= WGL Driver (D3DHAL)
+
+D3D_DIR=$(MAKEDIR)\D3D
+TARGET_DIR=e:\WinNT\System32
+TEMP_DIR=c:\Temp
+
+SPACE=-
+LINKER=link.exe
+
+INCLUDE=$(SDKROOT)\include;$(INCLUDE)
+LIB=$(SDKROOT)\lib;$(LIB)
+##############################################################################
+CFLAGS = /c /nologo /W1 /G5 /I..\ /I..\..\Include \
+ /D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "MESAD3D"
+CPPFLAGS= /c /nologo /W1 /G5 /I..\ /I..\..\Include \
+ /D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "MESAD3D"
+
+!IF "$(DEBUG)" == "1"
+
+CFLAGS = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CFLAGS)
+CPPFLAGS = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CPPFLAGS)
+BUILD_TYPE=debug
+
+!ELSE
+
+CFLAGS = /MT /Ox /D "NDEBUG" $(CFLAGS)
+CPPFLAGS = /MT /Ox /D "NDEBUG" $(CPPFLAGS)
+BUILD_TYPE=release
+
+!ENDIF
+##############################################################################
+SRCS_WGL = wgl.c D3Dvbrender.c DDrawPROCS.c NULLProcs.c Debug.c
+SRCS_HAL = D3DInit.cpp D3DRaster.cpp D3DTextureMgr.cpp D3DUtils.cpp D3DCaps.cpp
+OBJS_WGL = $(SRCS_WGL:.c=.obj)
+OBJS_HAL = $(SRCS_HAL:.cpp=.obj)
+
+WINLIBS = kernel32.lib user32.lib gdi32.lib oldnames.lib
+DXLIBS =
+LIBS = $(WINLIBS) $(DXLIBS)
+###############################################################################
+# Primary Targets #
+###############################################################################
+
+default: header WGL HAL footer
+
+all: default
+
+WGL : $(OBJS_WGL)
+
+HAL : $(OBJS_HAL)
+
+install : forceit
+ @echo $(SPACE)
+ @echo ========================================
+ @echo Install files created.
+ @echo ========================================
+
+
+###############################################################################
+# Secondary Targets #
+###############################################################################
+
+clean:
+ @echo ========================================
+ @echo Cleaning $(TARGET)
+ @del *.obj
+ @del *.dep
+ @del *.exp
+ @del *.ncb
+ @del *.plg
+ @del *.lib
+ @echo ========================================
+
+header:
+ @echo ============================================================
+ @echo Building $(TARGET) ($(BUILD_TYPE) version)
+ @echo ============================================================
+ @echo $(SPACE)
+
+footer:
+ @echo $(SPACE)
+ @echo ============================================================
+ @echo DONE building $(TARGET) ($(BUILD_TYPE) version)
+ @echo ============================================================
+
+forceit:
+
+
+
+
diff --git a/src/mesa/drivers/d3d/NULLProcs.h b/src/mesa/drivers/d3d/NULLProcs.h new file mode 100644 index 00000000000..f0bbd2162dd --- /dev/null +++ b/src/mesa/drivers/d3d/NULLProcs.h @@ -0,0 +1,49 @@ +/*===========================================================================*/ +/* */ +/* Mesa-3.0 DirectX 6 Driver */ +/* */ +/* By Leigh McRae */ +/* */ +/* http://www.altsoftware.com/ */ +/* */ +/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */ +/*===========================================================================*/ +#ifndef NULL_MESA_PROCS_INC +#define NULL_MESA_PROCS_INC +/*===========================================================================*/ +/* Includes. */ +/*===========================================================================*/ +#include "matrix.h" +#include "context.h" +#include "types.h" +#include "vb.h" +/*===========================================================================*/ +/* Macros. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Magic numbers. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Type defines. */ +/*===========================================================================*/ +void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +GLboolean NULLSetBuffer( GLcontext *ctx, GLenum mode ); +void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height ); +GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h ); +void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] ); +void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] ); +void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] ); +void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] ); +void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] ); +void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] ); +void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] ); +/*===========================================================================*/ +/* Extern function prototypes. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Global variables. */ +/*===========================================================================*/ + +#endif + diff --git a/src/mesa/drivers/d3d/NullProcs.c b/src/mesa/drivers/d3d/NullProcs.c new file mode 100644 index 00000000000..d6fb598074b --- /dev/null +++ b/src/mesa/drivers/d3d/NullProcs.c @@ -0,0 +1,49 @@ +/*===========================================================================*/ +/* */ +/* Mesa-3.0 DirectX 6 Driver */ +/* */ +/* By Leigh McRae */ +/* */ +/* http://www.altsoftware.com/ */ +/* */ +/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */ +/*===========================================================================*/ +#ifndef NULL_MESA_PROCS_INC +#define NULL_MESA_PROCS_INC +/*===========================================================================*/ +/* Includes. */ +/*===========================================================================*/ +#include "matrix.h" +#include "context.h" +#include "mtypes.h" +#include "vb.h" +/*===========================================================================*/ +/* Macros. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Magic numbers. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Type defines. */ +/*===========================================================================*/ +void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ); +GLboolean NULLSetBuffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bit ); +void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height ); +GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h ); +void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] ); +void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] ); +void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] ); +void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] ); +void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] ); +void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] ); +void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] ); +/*===========================================================================*/ +/* Extern function prototypes. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Global variables. */ +/*===========================================================================*/ + +#endif + diff --git a/src/mesa/drivers/d3d/OPENGL32.DEF b/src/mesa/drivers/d3d/OPENGL32.DEF new file mode 100644 index 00000000000..b32bd1fef81 --- /dev/null +++ b/src/mesa/drivers/d3d/OPENGL32.DEF @@ -0,0 +1,442 @@ +;===========================================================================
+;
+; Mesa-3.0 DirectX 6 Driver
+;
+; By Leigh McRae
+;
+; http://www.altsoftware.com/
+;
+; Copyright (c) 1999-1998 alt.software inc. All Rights Reserved
+;===========================================================================
+NAME OpenGL32.DLL
+DESCRIPTION "Mesa-3.0 DX6 Driver Version 0.5"
+
+EXPORTS
+ DllMain
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glAreTexturesResidentEXT
+ glArrayElement
+ glArrayElementEXT
+ glBegin
+ glBindTexture
+ glBindTextureEXT
+ glBitmap
+ glBlendColorEXT
+ glBlendEquationEXT
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3bv
+ glColor3d
+ glColor3dv
+ glColor3f
+ glColor3fv
+ glColor3i
+ glColor3iv
+ glColor3s
+ glColor3sv
+ glColor3ub
+ glColor3ubv
+ glColor3ui
+ glColor3uiv
+ glColor3us
+ glColor3usv
+ glColor4b
+ glColor4bv
+ glColor4d
+ glColor4dv
+ glColor4f
+ glColor4fv
+ glColor4i
+ glColor4iv
+ glColor4s
+ glColor4sv
+ glColor4ub
+ glColor4ubv
+ glColor4ui
+ glColor4uiv
+ glColor4us
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorPointerEXT
+ glColorSubTableEXT
+ glColorTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCopyTexSubImage3DEXT
+ glCullFace
+ glDeleteLists
+ glDeleteTextures
+ glDeleteTexturesEXT
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawArraysEXT
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagPointerEXT
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGenTexturesEXT
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterfvEXT
+ glGetColorTableParameterivEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPointervEXT
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexMask
+ glIndexPointer
+ glIndexPointerEXT
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInterleavedArrays
+ glIsEnabled
+ glIsList
+ glIsTexture
+ glIsTextureEXT
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glNormalPointer
+ glNormalPointerEXT
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointParameterfEXT
+ glPointParameterfvEXT
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPrioritizeTexturesEXT
+ glPushAttrib
+ glPushClientAttrib
+ glPushMatrix
+ glPushName
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glRenderMode
+ glResizeBuffersMESA
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glScissor
+ glSelectBuffer
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1dv
+ glTexCoord1f
+ glTexCoord1fv
+ glTexCoord1i
+ glTexCoord1iv
+ glTexCoord1s
+ glTexCoord1sv
+ glTexCoord2d
+ glTexCoord2dv
+ glTexCoord2f
+ glTexCoord2fv
+ glTexCoord2i
+ glTexCoord2iv
+ glTexCoord2s
+ glTexCoord2sv
+ glTexCoord3d
+ glTexCoord3dv
+ glTexCoord3f
+ glTexCoord3fv
+ glTexCoord3i
+ glTexCoord3iv
+ glTexCoord3s
+ glTexCoord3sv
+ glTexCoord4d
+ glTexCoord4dv
+ glTexCoord4f
+ glTexCoord4fv
+ glTexCoord4i
+ glTexCoord4iv
+ glTexCoord4s
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexCoordPointerEXT
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexImage3DEXT
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTexSubImage3DEXT
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glVertexPointer
+ glVertexPointerEXT
+ glViewport
+ glWindowPos2dMESA
+ glWindowPos2dvMESA
+ glWindowPos2fMESA
+ glWindowPos2fvMESA
+ glWindowPos2iMESA
+ glWindowPos2ivMESA
+ glWindowPos2sMESA
+ glWindowPos2svMESA
+ glWindowPos3dMESA
+ glWindowPos3dvMESA
+ glWindowPos3fMESA
+ glWindowPos3fvMESA
+ glWindowPos3iMESA
+ glWindowPos3ivMESA
+ glWindowPos3sMESA
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+; WMesaCreateContext
+; WMesaDestroyContext
+; WMesaMakeCurrent
+; WMesaPaletteChange
+; WMesaSwapBuffers
+; OSMesaCreateContext
+; OSMesaDestroyContext
+; OSMesaMakeCurrent
+; OSMesaGetCurrentContext
+; OSMesaPixelStore
+; OSMesaGetIntegerv
+; OSMesaGetDepthBuffer
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+; wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+; wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+; wglRealizeLayerPalette
+; wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglChoosePixelFormat
+ wglDescribePixelFormat
+ wglGetPixelFormat
+ wglSetPixelFormat
+ wglSwapBuffers
+
+
+
diff --git a/src/mesa/drivers/d3d/WGL.C b/src/mesa/drivers/d3d/WGL.C new file mode 100644 index 00000000000..e3b95e1de72 --- /dev/null +++ b/src/mesa/drivers/d3d/WGL.C @@ -0,0 +1,1262 @@ +/*===========================================================================*/
+/* */
+/* Mesa-3.0 Makefile for DirectX 6 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1998-1997 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DMesa.h"
+/*===========================================================================*/
+/* Window managment. */
+/*===========================================================================*/
+static BOOL InitOpenGL( HINSTANCE hInst );
+static BOOL TermOpenGL( HINSTANCE hInst );
+static BOOL ResizeContext( GLcontext *ctx );
+static BOOL MakeCurrent( D3DMESACONTEXT *pContext );
+static void DestroyContext( D3DMESACONTEXT *pContext );
+static BOOL UnBindWindow( D3DMESACONTEXT *pContext );
+LONG APIENTRY wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam );
+/*===========================================================================*/
+/* Mesa hooks. */
+/*===========================================================================*/
+static void SetupDDPointers( GLcontext *ctx );
+static void SetupSWDDPointers( GLcontext *ctx );
+static void SetupHWDDPointers( GLcontext *ctx );
+static void SetupNULLDDPointers( GLcontext *ctx );
+static const char *RendererString( void );
+
+/* State Management hooks. */
+static void SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+static void ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer );
+
+/* Window Management hooks. */
+static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height );
+static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h );
+static void Flush( GLcontext *ctx );
+
+/* Span rendering hooks. */
+void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
+void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
+void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
+void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+
+/* Primitve rendering hooks. */
+GLboolean RenderVertexBuffer( GLcontext *ctx, GLboolean allDone );
+void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv );
+void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv );
+GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+
+/* Texture Management hooks. */
+static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj );
+static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image );
+static void TextureSubImage( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint internalFormat, const struct gl_texture_image *image );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+D3DMESACONTEXT *pD3DCurrent,
+ *pD3DDefault; /* Thin support context. */
+
+struct __extensions__ ext[] = {
+
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+};
+
+int qt_ext = sizeof(ext) / sizeof(ext[0]);
+float g_DepthScale,
+ g_MaxDepth;
+/*===========================================================================*/
+/* When a process loads this DLL we will setup the linked list for context */
+/* management and create a default context that will support the API until */
+/* the user creates and binds thier own. This THIN default context is useful*/
+/* to have around. */
+/* When the process terminates we will clean up all resources here. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY DllMain( HINSTANCE hInst, DWORD reason, LPVOID reserved )
+{
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ return InitOpenGL( hInst );
+
+ case DLL_PROCESS_DETACH:
+ return TermOpenGL( hInst );
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* The first thing we do when this dll is hit is connect to the dll that has*/
+/* handles all the DirectX 6 rendering. I decided to use another dll as DX6 */
+/* is all C++ and Mesa-3.0 is C (thats a good thing). This way I can write */
+/* the DX6 in C++ and Mesa-3.0 in C without having to worry about linkage. */
+/* I feel this is easy and better then using static wrappers as it is likely */
+/* faster and it allows me to just develope the one without compiling the */
+/* other. */
+/* NOTE that at this point we don't have much other than a very thin context*/
+/* that will support the API calls only to the point of not causing the app */
+/* to crash from the API table being empty. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL InitOpenGL( HINSTANCE hInst )
+{
+ /* Allocate and clear the default context. */
+ pD3DDefault = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
+ if ( pD3DDefault == NULL )
+ return FALSE;
+ memset( pD3DDefault, 0, sizeof(D3DMESACONTEXT) );
+
+ /* Clear the D3D vertex buffer so that values not used will be zero. This */
+ /* save me from some redundant work. */
+ memset( &D3DTLVertices, 0, sizeof(D3DTLVertices) );
+
+ /* Update the link. We uses a circular list so that it is easy to */
+ /* add and search. This context will also be used for head and tail.*/
+ pD3DDefault->next = pD3DDefault;
+
+ /*========================================================================*/
+ /* Do all core Mesa stuff. */
+ /*========================================================================*/
+ pD3DDefault->gl_visual = _mesa_create_visual( TRUE,
+ FALSE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8,8, /* r, g, b, a bits */
+ 0, /* index bits */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8,8,8,8, /* accum_bits */
+ 1 );
+
+ if ( pD3DDefault->gl_visual == NULL)
+ {
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa context */
+ pD3DDefault->gl_ctx = _mesa_create_context( pD3DDefault->gl_visual, NULL, pD3DDefault, GL_TRUE );
+ if ( pD3DDefault->gl_ctx == NULL )
+ {
+ _mesa_destroy_visual( pD3DDefault->gl_visual );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pD3DDefault->gl_buffer = _mesa_create_framebuffer( pD3DDefault->gl_visual );
+ if ( pD3DDefault->gl_buffer == NULL )
+ {
+ _mesa_destroy_visual( pD3DDefault->gl_visual );
+ _mesa_destroy_context( pD3DDefault->gl_ctx );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+ SetupDDPointers( pD3DDefault->gl_ctx );
+ _mesa_make_current( pD3DDefault->gl_ctx, pD3DDefault->gl_buffer );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will create a new D3D context but will not create the D3D */
+/* surfaces or even an instance of D3D (see at GetBufferSize). The only stuff*/
+/* done here is the internal Mesa stuff and some Win32 handles. */
+/*===========================================================================*/
+/* RETURN: casted pointer to the context, NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglCreateContext( HDC hdc )
+{
+ D3DMESACONTEXT *pNewContext;
+ DWORD dwCoopFlags = DDSCL_NORMAL;
+ RECT rectClient;
+ POINT pt;
+
+ /* ALLOC and clear the new context. */
+ pNewContext = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
+ if ( pNewContext == NULL )
+ {
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+ memset( pNewContext, 0, sizeof(D3DMESACONTEXT) );
+
+ /*========================================================================*/
+ /* Do all core Mesa stuff. */
+ /*========================================================================*/
+
+ /* TODO: support more then one visual. */
+ pNewContext->gl_visual = _mesa_create_visual( TRUE,
+ TRUE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8,8, /* r, g, b, a bits */
+ 0, /* index bits */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16,16,/* accum_bits */
+ 1 );
+ if ( pNewContext->gl_visual == NULL)
+ {
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa context */
+ pNewContext->gl_ctx = _mesa_create_context( pNewContext->gl_visual, NULL, pNewContext, GL_TRUE );
+ if ( pNewContext->gl_ctx == NULL )
+ {
+ _mesa_destroy_visual( pNewContext->gl_visual );
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pNewContext->gl_buffer = _mesa_create_framebuffer( pNewContext->gl_visual );
+ if ( pNewContext->gl_buffer == NULL )
+ {
+ _mesa_destroy_visual( pNewContext->gl_visual );
+ _mesa_destroy_context( pNewContext->gl_ctx );
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /*========================================================================*/
+ /* Do all the driver stuff. */
+ /*========================================================================*/
+ pNewContext->hdc = hdc;
+ pNewContext->next = pD3DDefault->next;
+ pD3DDefault->next = pNewContext; /* Add to circular list. */
+
+ /* Create the HAL for the new context. */
+ pNewContext->pShared = InitHAL( WindowFromDC(hdc) );
+
+ return (HGLRC)pNewContext;
+}
+/*===========================================================================*/
+/* This is a wrapper function that is supported by MakeCurrent. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglMakeCurrent( HDC hdc, HGLRC hglrc )
+{
+ return MakeCurrent((D3DMESACONTEXT *)hglrc);
+}
+/*===========================================================================*/
+/* MakeCurrent will unbind whatever context is current (if any) & then bind */
+/* the supplied context. A context that is bound has it's window proc hooked*/
+/* with the wglMonitorProc and the context pointer is saved in pD3DCurrent. */
+/* Once the context is bound we update the Mesa-3.0 hooks (SetDDPointers) and*/
+/* the viewport (Mesa-.30 and DX6). */
+/* */
+/* TODO: this function can't fail. */
+/*===========================================================================*/
+/* RETURN: TRUE */
+/*===========================================================================*/
+static BOOL MakeCurrent( D3DMESACONTEXT *pContext )
+{
+ D3DMESACONTEXT *pNext;
+
+ /*====================================================================*/
+ /* This is a special case that is a request to have no context bound. */
+ /*====================================================================*/
+ if ( pContext == NULL )
+ {
+ /* Walk the whole list. We start and end at the Default context. */
+ for( pNext = pD3DDefault->next; pNext != pD3DDefault; pNext = pNext->next )
+ UnBindWindow( pNext );
+
+ return TRUE;
+ }
+
+ /*=================================================*/
+ /* Make for a fast redundant use of this function. */
+ /*=================================================*/
+ if ( pD3DCurrent == pContext )
+ return TRUE;
+
+ /*=============================*/
+ /* Unbind the current context. */
+ /*=============================*/
+ UnBindWindow( pD3DCurrent );
+
+ /*=====================================*/
+ /* Let Mesa-3.0 we have a new context. */
+ /*=====================================*/
+ SetupDDPointers( pContext->gl_ctx );
+ _mesa_make_current( pContext->gl_ctx, pContext->gl_buffer );
+
+ /* We are done so set the internal current context. */
+ if ( pContext != pD3DDefault )
+ {
+ ResizeContext( pContext->gl_ctx );
+ pContext->hOldProc = (WNDPROC)GetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC );
+ SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)wglMonitorProc );
+ }
+ pD3DCurrent = pContext;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will only return the current window size. I have re-done */
+/* this function so that it doesn't check the current size and react to it as*/
+/* I should be able to have all the react code in the WM_SIZE message. The */
+/* old version would check the current window size and create/resize the HAL */
+/* surfaces if they have changed. I needed to delay the creation if the */
+/* surfaces because sometimes I wouldn't have a window size so this is where */
+/* I delayed it. If you are reading this then all went ok! */
+/* The default context will return a zero sized window and I'm not sure if */
+/* this is ok at this point (TODO). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pContext == pD3DDefault )
+ {
+ *width = 0;
+ *height = 0;
+ }
+ else
+ {
+ *width = pContext->pShared->dwWidth;
+ *height = pContext->pShared->dwHeight;
+ }
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static BOOL ResizeContext( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx,
+ *pCurrentTemp;
+ RECT rectClient;
+ POINT pt;
+ DWORD dwWidth,
+ dwHeight;
+ static BOOL bDDrawLock = FALSE;
+
+ /* Make sure we have some values. */
+ if ( (pContext->hdc == NULL ) ||
+ (pContext->pShared->hwnd != WindowFromDC(pContext->hdc)) ||
+ (pContext == pD3DDefault) )
+ return FALSE;
+
+ /* Having problems with DDraw sending resize messages before I was done. */
+ if( bDDrawLock == TRUE )
+ return FALSE;
+
+ // TODO: don't think I need this anymore.
+ pCurrentTemp = pD3DCurrent;
+ pD3DCurrent = pD3DDefault;
+ bDDrawLock = TRUE;
+
+ /* Get the current window dimentions. */
+ UpdateScreenPosHAL( pContext->pShared );
+ dwWidth = pContext->pShared->rectW.right - pContext->pShared->rectW.left;
+ dwHeight = pContext->pShared->rectW.bottom - pContext->pShared->rectW.top;
+
+ /* Is the size of the OffScreen Render different? */
+ if ( (dwWidth != pContext->pShared->dwWidth) || (dwHeight != pContext->pShared->dwHeight) )
+ {
+ /* Create all the D3D surfaces and device. */
+ CreateHAL( pContext->pShared );
+
+ /* I did this so that software rendering would still work as */
+ /* I don't need to scale the z values twice. */
+ g_DepthScale = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
+ g_MaxDepth = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
+ gl_DepthRange( pContext->gl_ctx, ctx->Viewport.Near, ctx->Viewport.Far );
+
+ /* Make sure we have a viewport. */
+ gl_Viewport( pContext->gl_ctx, 0, 0, dwWidth, dwHeight );
+
+ /* Update Mesa as we might have changed from SW <-> HW. */
+ SetupDDPointers( pContext->gl_ctx );
+ _mesa_make_current( pContext->gl_ctx, pContext->gl_buffer );
+
+ /* If we are in HW we need to load the current texture if there is one already. */
+ // if ( (ctx->Texture.Set[ctx->Texture.CurrentSet].Current != NULL) &&
+ // (pContext->pShared->bHardware == TRUE) )
+ // {
+ // CreateTMgrHAL( pContext->pShared,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name,
+ // 0,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format,
+ // (RECT *)NULL,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Width,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Height,
+ // TM_ACTION_BIND,
+ // (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Data );
+ // }
+ }
+
+ // TODO: don't think I need this anymore.
+ pD3DCurrent = pCurrentTemp;
+ bDDrawLock = FALSE;
+
+ return TRUE;
+}
+
+/*===========================================================================*
+/* This function will Blt the render buffer to the PRIMARY surface. I repeat*/
+/* this code for the other SwapBuffer like functions and the flush (didn't */
+/* want the function calling overhead). Thsi could have been a macro... */
+/* */
+/* TODO: there are some problems with viewport/scissoring. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSwapBuffers( HDC hdc )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return FALSE;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* Same as wglSwapBuffers. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY SwapBuffers( HDC hdc )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return FALSE;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This should be ok as none of the SwapBuffers will cause a redundant Blt */
+/* as none of my Swap functions will call flush. This should also allow */
+/* sinlge buffered applications to work (not really worried though). Some */
+/* applications may flush then swap but then this is there fault IMHO. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void Flush( GLcontext *ctx )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+}
+/*===========================================================================*/
+/* For now this function will ignore the supplied PF. If I'm going to allow */
+/* the user to choice the mode and device at startup I'm going to have to do */
+/* something different. */
+/* */
+/* TODO: use the linked list of modes to build a pixel format to be returned */
+/* to the caller. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return 1;
+}
+/*===========================================================================*/
+/* See wglChoosePixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY ChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return wglChoosePixelFormat(hdc,ppfd);
+}
+/*===========================================================================*/
+/* This function (for now) returns a static PF everytime. This is just to */
+/* allow things to continue. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglDescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_DOUBLEBUFFER, /* support double-buffering */
+ PFD_TYPE_RGBA, /* color type */
+ 16, /* prefered color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ 0, /* no alpha buffer */
+ 0, /* alpha bits (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 16, /* depth buffer */
+ 0, /* no stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0, /* no layer, visible, damage masks */
+ };
+
+ /* Return the address of this static PF if one was requested. */
+ if ( ppfd != NULL )
+ memcpy( ppfd, &pfd, sizeof(PIXELFORMATDESCRIPTOR) );
+
+ return 1;
+}
+/*===========================================================================*/
+/* See wglDescribePixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY DescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd);
+}
+/*===========================================================================*/
+/* This function will always return 1 for now. Just to allow for support. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglGetPixelFormat( HDC hdc )
+{
+ return 1;
+}
+/*===========================================================================*/
+/* See wglGetPixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY GetPixelFormat( HDC hdc )
+{
+ return wglGetPixelFormat(hdc);
+}
+/*===========================================================================*/
+/* This will aways work for now. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return TRUE;
+}
+/*===========================================================================*/
+/* See wglSetPixelFormat. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY SetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return wglSetPixelFormat(hdc,iPixelFormat,ppfd);
+}
+/*===========================================================================*/
+/* This is a wrapper function that is supported by my own internal function.*/
+/* that takes my own D3D Mesa context structure. This so I can reuse the */
+/* function (no need for speed). */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL APIENTRY wglDeleteContext( HGLRC hglrc )
+{
+ DestroyContext( (D3DMESACONTEXT *)hglrc );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* Simple getter function that uses a cast. */
+/*===========================================================================*/
+/* RETURN: casted pointer to the context, NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglGetCurrentContext( VOID )
+{
+ return (pD3DCurrent) ? (HGLRC)pD3DCurrent : (HGLRC)NULL;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglCreateLayerContext( HDC hdc,int iLayerPlane )
+{
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+}
+/*===========================================================================*/
+/* Simple getter function. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+HDC APIENTRY wglGetCurrentDC( VOID )
+{
+ return (pD3DCurrent) ? pD3DCurrent->hdc : (HDC)NULL;
+}
+/*===========================================================================*/
+/* Simply call that searches the supported extensions for a match & returns */
+/* the pointer to the function that lends support. */
+/*===========================================================================*/
+/* RETURN: pointer to API call, NULL. */
+/*===========================================================================*/
+PROC APIENTRY wglGetProcAddress( LPCSTR lpszProc )
+{
+ int index;
+
+ for( index = 0; index < qt_ext; index++ )
+ if( !strcmp(lpszProc,ext[index].name) )
+ return ext[index].proc;
+
+ SetLastError( 0 );
+ return NULL;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglShareLists( HGLRC hglrc1, HGLRC hglrc2 )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontBitmaps( HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontBitmapsW( HDC hdc,DWORD first,DWORD count,DWORD listBase )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontOutlinesA( HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontOutlinesW( HDC hdc,DWORD first,DWORD count, DWORD listBase,FLOAT deviation, FLOAT extrusion,int format, LPGLYPHMETRICSFLOAT lpgmf )
+{
+ SetLastError( 0 );
+ return FALSE ;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSwapLayerBuffers( HDC hdc, UINT fuPlanes )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* This function will be hooked into the window that has been bound. Right */
+/* now it is used to track the window size and position. Also the we clean */
+/* up the currrent context when the window is close/destroyed. */
+/* */
+/* TODO: there might be something wrong here as some games (Heretic II) don't*/
+/* track the window quit right. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+LONG APIENTRY wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam )
+{
+ WNDPROC hOldProc;
+ GLint width,
+ height;
+
+ switch( message )
+ {
+// case WM_PAINT:
+// break;
+// case WM_ACTIVATE:
+// break;
+// case WM_SHOWWINDOW:
+// break;
+
+ case UM_FATALSHUTDOWN:
+ /* Support the API until we die... */
+ MakeCurrent( pD3DDefault );
+ break;
+
+ case WM_MOVE:
+ case WM_DISPLAYCHANGE:
+ case WM_SIZE:
+ ResizeContext( pD3DCurrent->gl_ctx );
+ break;
+
+ case WM_CLOSE:
+ case WM_DESTROY:
+ /* Support the API until we die... */
+ hOldProc = pD3DCurrent->hOldProc;
+ DestroyContext( pD3DCurrent );
+ return (hOldProc)(hwnd,message,wParam,lParam);
+ }
+
+ return (pD3DCurrent->hOldProc)(hwnd,message,wParam,lParam);
+}
+
+/**********************************************************************/
+/***** Miscellaneous device driver funcs *****/
+/**********************************************************************/
+
+/*===========================================================================*/
+/* Not reacting to this as I'm only supporting drawing to the back buffer */
+/* right now. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer )
+{
+ if (buffer == GL_BACK_LEFT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+/*===========================================================================*/
+/* This proc will be called by Mesa when the viewport has been set. So if */
+/* we have a context and it isn't the default then we should let D3D know of */
+/* the change. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ RECT rect;
+
+ /* Make sure we can set a viewport. */
+ if ( pContext->pShared && (pContext != pD3DDefault) )
+ {
+ // TODO: might be needed.
+ UpdateScreenPosHAL( pContext->pShared );
+ rect.left = x;
+ rect.right = x + w;
+ rect.top = y;
+ rect.bottom = y + h;
+
+ // TODO: shared struct should make this call smaller
+ SetViewportHAL( pContext->pShared, &rect, 0.0F, 1.0F );
+ }
+}
+/*===========================================================================*/
+/* This function could be better I guess but I decided just to grab the four*/
+/* components and store then seperately. Makes it easier to use IMHO. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ pContext->aClear = a;
+ pContext->bClear = b;
+ pContext->gClear = g;
+ pContext->rClear = r;
+}
+/*===========================================================================*/
+/* This function could be better I guess but I decided just to grab the four*/
+/* components and store then seperately. Makes it easier to use IMHO. */
+/* (is there an echo in here?) */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ pContext->aCurrent = a;
+ pContext->bCurrent = b;
+ pContext->gCurrent = g;
+ pContext->rCurrent = r;
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static const char *RendererString( void )
+{
+ static char pszRender[64];
+
+ strcpy( pszRender, "altD3D " );
+
+ if ( pD3DCurrent->pShared->bHardware )
+ strcat( pszRender, "(HW)");
+ else
+ strcat( pszRender, "(SW)");
+
+ return (const char *)pszRender;
+}
+/*===========================================================================*/
+/* This function will choose which set of pointers Mesa will use based on */
+/* whether we hard using hardware or software. I have added another set of */
+/* pointers that will do nothing but stop the API from crashing. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetupDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ // TODO: write a generic NULL support for the span render.
+ if ( pContext->pShared && pContext->pShared->bHardware )
+ {
+ ctx->Driver.UpdateState = SetupHWDDPointers;
+ }
+ else if ( pContext == pD3DDefault )
+ {
+ ctx->Driver.UpdateState = SetupNULLDDPointers;
+ }
+ else
+ {
+ ctx->Driver.UpdateState = SetupSWDDPointers;
+ }
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. This version of */
+/* hooks will do nothing but support the API when we don't have a valid */
+/* context bound. This is mostly for applications that don't behave right */
+/* and also to help exit as clean as possable when we have a FatalError. */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupNULLDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupNULLDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = NULLSetColor;
+ ctx->Driver.ClearColor = NULLClearColor;
+ ctx->Driver.Clear = NULLClearBuffers;
+ ctx->Driver.SetBuffer = NULLSetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = NULLGetBufferSize;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = NULL;
+ ctx->Driver.RenderVB = NULL;
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = NULLWrSpRGBA;
+ ctx->Driver.WriteRGBSpan = NULLWrSpRGB;
+ ctx->Driver.WriteMonoRGBASpan = NULLWrSpRGBAMono;
+ ctx->Driver.WriteRGBAPixels = NULLWrPiRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = NULLWrPiRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = NULLReSpRGBA;
+ ctx->Driver.ReadRGBAPixels = NULLRePiRGBA;
+
+ /* Misc. hooks. */
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. There are two of */
+/* these functions. One if we have hardware support and one is there is only*/
+/* software. These functions will be called by Mesa and by the wgl.c when we*/
+/* have resized (or created) the buffers. The thing is that if a window gets*/
+/* resized we may loose hardware support or gain it... */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupSWDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupSWDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = SetColor;
+ ctx->Driver.ClearColor = ClearColor;
+ ctx->Driver.Clear = ClearBuffers;
+ ctx->Driver.SetBuffer = SetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = GetBufferSize;
+ ctx->Driver.Viewport = SetViewport;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = NULL;
+ ctx->Driver.RenderVB = NULL;
+
+ /* Texture management hooks. */
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = WSpanRGBA;
+ ctx->Driver.WriteRGBSpan = WSpanRGB;
+ ctx->Driver.WriteMonoRGBASpan = WSpanRGBAMono;
+ ctx->Driver.WriteRGBAPixels = WPixelsRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = WPixelsRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = RSpanRGBA;
+ ctx->Driver.ReadRGBAPixels = RPixelsRGBA;
+
+ /* Misc. hooks. */
+ ctx->Driver.Flush = Flush;
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. There are two of */
+/* these functions. One if we have hardware support and one is there is only*/
+/* software. These functions will be called by Mesa and by the wgl.c when we*/
+/* have resized (or created) the buffers. The thing is that if a window gets*/
+/* resized we may loose hardware support or gain it... */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupHWDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupHWDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = SetColor;
+ ctx->Driver.ClearColor = ClearColor;
+ ctx->Driver.Clear = ClearBuffersD3D;
+ ctx->Driver.SetBuffer = SetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = GetBufferSize;
+ ctx->Driver.Viewport = SetViewport;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = RenderOneTriangle;
+ ctx->Driver.LineFunc = RenderOneLine;
+ ctx->Driver.RenderVB = RenderVertexBuffer;
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = WSpanRGBA;
+ ctx->Driver.WriteRGBSpan = WSpanRGB;
+ ctx->Driver.WriteMonoRGBASpan = WSpanRGBAMono;
+ ctx->Driver.WriteRGBAPixels = WPixelsRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = WPixelsRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = RSpanRGBA;
+ ctx->Driver.ReadRGBAPixels = RPixelsRGBA;
+
+ /* Texture management hooks. */
+ // ctx->Driver.BindTexture = TextureBind;
+ ctx->Driver.TexImage = TextureLoad;
+ ctx->Driver.TexSubImage = TextureSubImage;
+
+ /* Misc. hooks. */
+ ctx->Driver.Flush = Flush;
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will release all resources used by the DLL. Every context */
+/* will be clobbered by releaseing all driver desources and then freeing the */
+/* context memory. Most all the work is done in DestroyContext. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+static BOOL TermOpenGL( HINSTANCE hInst )
+{
+ D3DMESACONTEXT *pTmp,
+ *pNext;
+
+ /* Just incase we are still getting paint msg. */
+ MakeCurrent( pD3DDefault );
+
+ /* Walk the list until we get back to the default context. */
+ for( pTmp = pD3DDefault->next; pTmp != pD3DDefault; pTmp = pNext )
+ {
+ pNext = pTmp->next;
+ DestroyContext( pTmp );
+ }
+ DestroyContext( pD3DDefault );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function is an internal function that will clean up all the Mesa */
+/* context bound to this D3D context. Also any D3D stuff that this context */
+/* uses will be unloaded. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static void DestroyContext( D3DMESACONTEXT *pContext )
+{
+ D3DMESACONTEXT *pTmp;
+
+ /* Walk the list until we find the context before this one. */
+ for( pTmp = pD3DDefault; pTmp && (pTmp->next != pContext); pTmp = pTmp->next )
+ if ( pTmp == pTmp->next )
+ break;
+
+ /* If we never found it it must already be deleted. */
+ if ( pTmp->next != pContext )
+ return;
+
+ /* Make sure we are not using this context. */
+ if ( pContext == pD3DCurrent )
+ MakeCurrent( pD3DDefault );
+
+ /* Free the Mesa stuff. */
+ if ( pContext->gl_visual )
+ {
+ _mesa_destroy_visual( pContext->gl_visual );
+ pContext->gl_visual = NULL;
+ }
+ if ( pContext->gl_buffer )
+ {
+ _mesa_destroy_framebuffer( pContext->gl_buffer );
+ pContext->gl_buffer = NULL;
+ }
+ if ( pContext->gl_ctx )
+ {
+ _mesa_destroy_context( pContext->gl_ctx );
+ pContext->gl_ctx = NULL;
+ }
+
+ /* Now dump the D3D. */
+ if ( pContext->pShared )
+ TermHAL( pContext->pShared );
+
+ /* Update the previous context's link. */
+ pTmp->next = pContext->next;
+
+ /* Gonzo. */
+ FREE( pContext );
+}
+/*===========================================================================*/
+/* This function will pull the supplied context away from Win32. Basicly it*/
+/* will remove the hook from the window Proc. */
+/* */
+/* TODO: might want to serialize this stuff... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL UnBindWindow( D3DMESACONTEXT *pContext )
+{
+ if ( pContext == NULL )
+ return FALSE;
+
+ if ( pContext == pD3DDefault )
+ return TRUE;
+
+ /* Make sure we always have a context bound. */
+ if ( pContext == pD3DCurrent )
+ pD3DCurrent = pD3DDefault;
+
+ SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)pContext->hOldProc );
+ pContext->hOldProc = NULL;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* There are two cases that allow for a faster clear when we know that the */
+/* whole buffer is cleared and that there is no clipping. */
+/*===========================================================================*/
+/* RETURN: the original mask with the bits cleared that represents the buffer*
+/* or buffers we just cleared. */
+/*===========================================================================*/
+GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DWORD dwFlags = 0;
+
+ if ( mask & GL_COLOR_BUFFER_BIT )
+ {
+ dwFlags |= D3DCLEAR_TARGET;
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+ if ( mask & GL_DEPTH_BUFFER_BIT )
+ {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+ if ( dwFlags == 0 )
+ return mask;
+
+ ClearHAL( pContext->pShared,
+ dwFlags,
+ all,
+ x, y,
+ width, height,
+ ((pContext->aClear<<24) | (pContext->rClear<<16) | (pContext->gClear<<8) | (pContext->bClear)),
+ ctx->Depth.Clear,
+ 0 );
+
+ return mask;
+}
+
+
+
+/*===========================================================================*/
+/* TEXTURE MANAGER: ok here is how I did textures. Mesa-3.0 will keep track*/
+/* of all the textures for us. So this means that at anytime we can go to */
+/* the Mesa context and get the current texture. With this in mind this is */
+/* what I did. I really don't care about what textures get or are loaded */
+/* until I actually have to draw a tri that is textured. At this point I */
+/* must have the texture so I demand the texture by destorying all other */
+/* texture surfaces if need be and load the current one. This allows for the*/
+/* best preformance on low memory cards as time is not wasted loading and */
+/* unload textures. */
+/*===========================================================================*/
+
+
+
+
+
+/*===========================================================================*/
+/* TextureLoad will try and create a D3D surface from the supplied texture */
+/* object if its level 0 (first). The surface will be fully filled with the */
+/* texture. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* TODO: only doing first LOD. */
+ if ( (ctx->DriverCtx == NULL) || (level != 0) )
+ return;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ level,
+ tObj->Image[level]->Format,
+ (RECT *)NULL,
+ tObj->Image[level]->Width,
+ tObj->Image[level]->Height,
+ TM_ACTION_LOAD,
+ (void *)tObj->Image[level]->Data );
+}
+/*===========================================================================*/
+/* TextureBind make sure that the texture is on the card. Thats it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* TODO: only doing first LOD. */
+ if ( (tObj->Image[0] == NULL) || (ctx->DriverCtx == NULL) )
+ return;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ 0,
+ tObj->Image[0]->Format,
+ (RECT *)NULL,
+ tObj->Image[0]->Width,
+ tObj->Image[0]->Height,
+ TM_ACTION_BIND,
+ (void *)tObj->Image[0]->Data );
+}
+/*===========================================================================*/
+/* TextureSubImage will make sure that the texture being updated is updated */
+/* if its on the card. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureSubImage( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint internalFormat, const struct gl_texture_image *image )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ RECT rect;
+
+ /* TODO: only doing first LOD. */
+ if ( (ctx->DriverCtx == NULL) || (level > 0) )
+ return;
+
+ /* Create a dirty rectangle structure. */
+ rect.left = xoffset;
+ rect.right = xoffset + width;
+ rect.top = yoffset;
+ rect.bottom = yoffset + height;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ 0,
+ tObj->Image[0]->Format,
+ &rect,
+ tObj->Image[0]->Width,
+ tObj->Image[0]->Height,
+ TM_ACTION_UPDATE,
+ (void *)tObj->Image[0]->Data );
+}
+
diff --git a/src/mesa/drivers/d3d/d3dText.h b/src/mesa/drivers/d3d/d3dText.h new file mode 100644 index 00000000000..9ff0650518b --- /dev/null +++ b/src/mesa/drivers/d3d/d3dText.h @@ -0,0 +1,53 @@ +#ifndef D3D_TEXT_H +#define D3D_TEXT_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/*===========================================================================*/ +/* Includes. */ +/*===========================================================================*/ +#include <windows.h> +#include <ddraw.h> +#include <d3d.h> +/*===========================================================================*/ +/* Magic numbers. */ +/*===========================================================================*/ +#define D3DLTEXT_BITSUSED 0xFFFFFFFF +#define MAX_VERTICES 700 // (14*40) 14 per character, 40 characters +/*===========================================================================*/ +/* Macros defines. */ +/*===========================================================================*/ +/*===========================================================================*/ +/* Type defines. */ +/*===========================================================================*/ +typedef struct _d3dText_metrics +{ + float fntYScale, + fntXScale; + + int fntXSpacing, + fntYSpacing; + + DWORD dwColor; + LPDIRECT3DDEVICE3 lpD3DDevice; + +} D3DFONTMETRICS, *PD3DFONTMETRICS; +/*===========================================================================*/ +/* Function prototypes. */ +/*===========================================================================*/ +extern BOOL InitD3DText( void ); +extern void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics ); +extern void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics ); +/*===========================================================================*/ +/* Global variables. */ +/*===========================================================================*/ + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/mesa/drivers/directfb/idirectfbgl_mesa.c b/src/mesa/drivers/directfb/idirectfbgl_mesa.c index e8ed192be3e..1c481af3f2a 100644 --- a/src/mesa/drivers/directfb/idirectfbgl_mesa.c +++ b/src/mesa/drivers/directfb/idirectfbgl_mesa.c @@ -310,6 +310,13 @@ set_viewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h ) _mesa_ResizeBuffersMESA(); } +/* required but not used */ +static void +set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) +{ + return; +} + static void delete_renderbuffer( struct gl_renderbuffer *render ) { @@ -555,6 +562,7 @@ dfb_mesa_create_context( GLcontext *context, _swsetup_Wakeup( context ); swdd = _swrast_GetDeviceDriverReference( context ); + swdd->SetBuffer = set_buffer; _mesa_init_renderbuffer( &data->render, 0 ); data->render.InternalFormat = GL_RGBA; diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 9e1b36252ff..4a7a6552ac0 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -14,8 +14,7 @@ COMMON_SOURCES = \ ifeq ($(WINDOW_SYSTEM),dri) WINOBJ= WINLIB= -INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) \ - `pkg-config --cflags libdrm` +INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) OBJECTS = $(C_SOURCES:.c=.o) \ $(ASM_SOURCES:.S=.o) @@ -25,8 +24,6 @@ WINOBJ= WINLIB=-L$(MESA)/src/glx/mini MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini INCLUDES = $(MINIGLX_INCLUDES) \ - -I$(DRM_SOURCE_PATH)/shared-core \ - -I$(DRM_SOURCE_PATH)/libdrm \ $(SHARED_INCLUDES) OBJECTS = $(C_SOURCES:.c=.o) \ @@ -40,7 +37,6 @@ SHARED_INCLUDES = \ -I. \ -I$(TOP)/src/mesa/drivers/dri/common \ -Iserver \ - -I$(DRM_SOURCE_PATH)/shared-core \ -I$(TOP)/include \ -I$(TOP)/include/GL/internal \ -I$(TOP)/src/mesa \ @@ -52,15 +48,16 @@ SHARED_INCLUDES = \ -I$(TOP)/src/mesa/swrast \ -I$(TOP)/src/mesa/swrast_setup \ -I$(TOP)/src/egl/main \ - -I$(TOP)/src/egl/drivers/dri + -I$(TOP)/src/egl/drivers/dri \ + `pkg-config --cflags libdrm` ##### RULES ##### .c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ .S.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@ ##### TARGETS ##### @@ -85,11 +82,10 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME) # Run 'make depend' to update the dependencies if you change # what's included by any source file. -.PHONY: depend depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \ - >& /dev/null + $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \ + $(ASM_SOURCES) > /dev/null # Emacs tags diff --git a/src/mesa/drivers/dri/common/glcontextmodes.c b/src/mesa/drivers/dri/common/glcontextmodes.c index d1297991497..edb04463f61 100644 --- a/src/mesa/drivers/dri/common/glcontextmodes.c +++ b/src/mesa/drivers/dri/common/glcontextmodes.c @@ -104,7 +104,7 @@ _gl_convert_to_x_visual_type( int visualType ) GrayScale, StaticGray }; - return ( (unsigned) (visualType - GLX_TRUE_COLOR) <= NUM_VISUAL_TYPES ) + return ( (unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES ) ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; } @@ -182,6 +182,15 @@ _gl_copy_visual_to_context_mode( __GLcontextModes * mode, mode->transparentIndex = config->transparentIndex; mode->swapMethod = GLX_SWAP_UNDEFINED_OML; + + mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE; + mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ? + GL_TRUE : GL_FALSE; + mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE; + mode->bindToTextureTargets = mode->rgbMode ? + GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT : 0; + mode->yInverted = GL_FALSE; } @@ -313,6 +322,21 @@ _gl_get_context_mode_data(const __GLcontextModes *mode, int attribute, case GLX_SAMPLES_SGIS: *value_return = mode->samples; return 0; + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value_return = mode->bindToTextureRgb; + return 0; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + *value_return = mode->bindToTextureRgba; + return 0; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value_return = mode->bindToMipmapTexture; + return 0; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value_return = mode->bindToTextureTargets; + return 0; + case GLX_Y_INVERTED_EXT: + *value_return = mode->yInverted; + return 0; /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX. * It is ONLY for communication between the GLX client and the GLX @@ -383,6 +407,11 @@ _gl_context_modes_create( unsigned count, size_t minimum_size ) (*next)->xRenderable = GLX_DONT_CARE; (*next)->fbconfigID = GLX_DONT_CARE; (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; + (*next)->bindToTextureRgb = GLX_DONT_CARE; + (*next)->bindToTextureRgba = GLX_DONT_CARE; + (*next)->bindToMipmapTexture = GLX_DONT_CARE; + (*next)->bindToTextureTargets = 0; + (*next)->yInverted = GLX_DONT_CARE; next = & ((*next)->next); } @@ -495,5 +524,10 @@ _gl_context_modes_are_same( const __GLcontextModes * a, (a->maxPbufferPixels == b->maxPbufferPixels) && (a->optimalPbufferWidth == b->optimalPbufferWidth) && (a->optimalPbufferHeight == b->optimalPbufferHeight) && - (a->swapMethod == b->swapMethod) ); + (a->swapMethod == b->swapMethod) && + (a->bindToTextureRgb == b->bindToTextureRgb) && + (a->bindToTextureRgba == b->bindToTextureRgba) && + (a->bindToMipmapTexture == b->bindToMipmapTexture) && + (a->bindToTextureTargets == b->bindToTextureTargets) && + (a->yInverted == b->yInverted) ); } diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c index 41316de1fc4..b0e8c4c1c28 100644 --- a/src/mesa/drivers/dri/common/texmem.c +++ b/src/mesa/drivers/dri/common/texmem.c @@ -410,6 +410,7 @@ static void driTexturesGone( driTexHeap * heap, int offset, int size, fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId, (int)size, (int)offset ); mmDumpMemInfo( heap->memory_heap ); + FREE(t); return; } t->heap = heap; diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c index fbe1991fa5d..e3eca86da1b 100644 --- a/src/mesa/drivers/dri/common/utils.c +++ b/src/mesa/drivers/dri/common/utils.c @@ -361,25 +361,26 @@ driCheckDriDdxDrmVersions3(const char * driver_name, const __DRIversion * drmExpected) { static const char format[] = "%s DRI driver expected %s version %d.%d.x " - "but got version %d.%d.%d"; + "but got version %d.%d.%d\n"; static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " - "but got version %d.%d.%d"; + "but got version %d.%d.%d\n"; /* Check the DRI version */ if ( (driActual->major != driExpected->major) || (driActual->minor < driExpected->minor) ) { - __driUtilMessage(format, driver_name, "DRI", + fprintf(stderr, format, driver_name, "DRI", driExpected->major, driExpected->minor, driActual->major, driActual->minor, driActual->patch); return GL_FALSE; } /* Check that the DDX driver version is compatible */ - if ( (ddxActual->major < ddxExpected->major_min) + /* for miniglx we pass in -1 so we can ignore the DDX version */ + if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min) || (ddxActual->major > ddxExpected->major_max) - || (ddxActual->minor < ddxExpected->minor) ) { - __driUtilMessage(format2, driver_name, "DDX", + || (ddxActual->minor < ddxExpected->minor)) ) { + fprintf(stderr, format2, driver_name, "DDX", ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, ddxActual->major, ddxActual->minor, ddxActual->patch); return GL_FALSE; @@ -388,7 +389,7 @@ driCheckDriDdxDrmVersions3(const char * driver_name, /* Check that the DRM driver version is compatible */ if ( (drmActual->major != drmExpected->major) || (drmActual->minor < drmExpected->minor) ) { - __driUtilMessage(format, driver_name, "DRM", + fprintf(stderr, format, driver_name, "DRM", drmExpected->major, drmExpected->minor, drmActual->major, drmActual->minor, drmActual->patch); return GL_FALSE; diff --git a/src/mesa/drivers/dri/common/xmlpool/Makefile b/src/mesa/drivers/dri/common/xmlpool/Makefile new file mode 100644 index 00000000000..ef94541c374 --- /dev/null +++ b/src/mesa/drivers/dri/common/xmlpool/Makefile @@ -0,0 +1,96 @@ +# Convenient makefile for managing translations. + +# Prerequisites: +# - GNU gettext +# - Python + +# Adding new translations +# ----------------------- + +# To start working on a new translation edit the POS=... line +# below. If you want to add for example a french translation, add +# fr.po. + +# Then run "make po" to generate a fresh .po file from translatable +# strings in t_options.h. Now you can edit the new .po file (fr.po in +# the example above) to translate the strings. Please make sure that +# your editor encodes the file in UTF-8. + +# Updating existing translations +# ------------------------------ + +# Run "make po" to update .po files with new translatable strings from +# t_options.h. Now you can edit the .po files you're interested +# in. Please make sure that your editor encodes the file in UTF-8. + +# Updating options.h +# ------------------ + +# Finally run "make" to generate options.h from t_options.h with all +# translations. Now you can rebuild the drivers. Any common options +# used by the drivers will have option descriptions with the latest +# translations. + +# Publishing translations +# ----------------------- + +# To get your translation(s) into Mesa CVS, please send me your +# <lang>.po file. + +# More information: +# - info gettext + +# The set of supported languages. Add languages as needed. +POS=de.po es.po nl.po fr.po + +# +# Don't change anything below, unless you know what you're doing. +# +LANGS=$(POS:%.po=%) +MOS=$(POS:%.po=%/LC_MESSAGES/options.mo) +POT=xmlpool.pot + +.PHONY: all clean pot po mo + +all: options.h + +# Only intermediate files are cleaned up. options.h is not deleted because +# it's in CVS. +clean: + rm -f $(POT) *~ + rm -rf $(LANGS) + +# Default target options.h +options.h: t_options.h mo + python gen_xmlpool.py $(LANGS) > options.h + +# Update .mo files from the corresponding .po files. +mo: + @for mo in $(MOS); do \ + lang=$${mo%%/*}; \ + echo "Updating $$mo from $$lang.po."; \ + mkdir -p $${mo%/*}; \ + msgfmt -o $$mo $$lang.po; \ + done + +# Use this target to create or update .po files with new messages in +# driconf.py. +po: $(POS) + +pot: $(POT) + +# Extract message catalog from driconf.py. +$(POT): t_options.h + xgettext -L C --from-code utf-8 -o $(POT) t_options.h + +# Create or update a .po file for a specific language. +%.po: $(POT) + @if [ -f $@ ]; then \ + echo "Merging new strings from $(POT) into $@."; \ + mv $@ $@~; \ + msgmerge -o $@ $@~ $(POT); \ + else \ + echo "Initializing $@ from $(POT)."; \ + msginit -i $(POT) -o $@~ --locale=$*; \ + sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $@~ > $@; \ + fi diff --git a/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py b/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py new file mode 100644 index 00000000000..7398c4cd0b2 --- /dev/null +++ b/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py @@ -0,0 +1,191 @@ +#!/usr/bin/python + +import sys +import gettext +import re + +# List of supported languages +languages = sys.argv[1:] + +# Escape special characters in C strings +def escapeCString (s): + escapeSeqs = {'\a' : '\\a', '\b' : '\\b', '\f' : '\\f', '\n' : '\\n', + '\r' : '\\r', '\t' : '\\t', '\v' : '\\v', '\\' : '\\\\'} + # " -> '' is a hack. Quotes (") aren't possible in XML attributes. + # Better use Unicode characters for typographic quotes in option + # descriptions and translations. + i = 0 + r = '' + while i < len(s): + # Special case: escape double quote with \u201c or \u201d, depending + # on whether it's an open or close quote. This is needed because plain + # double quotes are not possible in XML attributes. + if s[i] == '"': + if i == len(s)-1 or s[i+1].isspace(): + # close quote + q = u'\u201c' + else: + # open quote + q = u'\u201d' + r = r + q + elif escapeSeqs.has_key(s[i]): + r = r + escapeSeqs[s[i]] + else: + r = r + s[i] + i = i + 1 + return r + +# Expand escape sequences in C strings (needed for gettext lookup) +def expandCString (s): + escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n', + 'r' : '\r', 't' : '\t', 'v' : '\v', + '"' : '"', '\\' : '\\'} + i = 0 + escape = False + hexa = False + octa = False + num = 0 + digits = 0 + r = '' + while i < len(s): + if not escape: + if s[i] == '\\': + escape = True + else: + r = r + s[i] + elif hexa: + if (s[i] >= '0' and s[i] <= '9') or \ + (s[i] >= 'a' and s[i] <= 'f') or \ + (s[i] >= 'A' and s[i] <= 'F'): + num = num * 16 + int(s[i],16) + digits = digits + 1 + else: + digits = 2 + if digits >= 2: + hexa = False + escape = False + r = r + chr(num) + elif octa: + if s[i] >= '0' and s[i] <= '7': + num = num * 8 + int(s[i],8) + digits = digits + 1 + else: + digits = 3 + if digits >= 3: + octa = False + escape = False + r = r + chr(num) + else: + if escapeSeqs.has_key(s[i]): + r = r + escapeSeqs[s[i]] + escape = False + elif s[i] >= '0' and s[i] <= '7': + octa = True + num = int(s[i],8) + if num <= 3: + digits = 1 + else: + digits = 2 + elif s[i] == 'x' or s[i] == 'X': + hexa = True + num = 0 + digits = 0 + else: + r = r + s[i] + escape = False + i = i + 1 + return r + +# Expand matches. The first match is always a DESC or DESC_BEGIN match. +# Subsequent matches are ENUM matches. +# +# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7 +# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5 +def expandMatches (matches, translations, end=None): + assert len(matches) > 0 + nTranslations = len(translations) + i = 0 + # Expand the description+enums for all translations + for lang,trans in translations: + i = i + 1 + # Make sure that all but the last line of a simple description + # are extended with a backslash. + suffix = '' + if len(matches) == 1 and i < len(translations) and \ + not matches[0].expand (r'\7').endswith('\\'): + suffix = ' \\' + # Expand the description line. Need to use ugettext in order to allow + # non-ascii unicode chars in the original English descriptions. + text = escapeCString (trans.ugettext (unicode (expandCString ( + matches[0].expand (r'\5')), "utf-8"))).encode("utf-8") + print matches[0].expand (r'\1' + lang + r'\3"' + text + r'"\7') + suffix + # Expand any subsequent enum lines + for match in matches[1:]: + text = escapeCString (trans.ugettext (unicode (expandCString ( + match.expand (r'\3')), "utf-8"))).encode("utf-8") + print match.expand (r'\1"' + text + r'"\5') + + # Expand description end + if end: + print end, + +# Compile a list of translation classes to all supported languages. +# The first translation is always a NullTranslations. +translations = [("en", gettext.NullTranslations())] +for lang in languages: + try: + trans = gettext.translation ("options", ".", [lang]) + except IOError: + sys.stderr.write ("Warning: language '%s' not found.\n" % lang) + continue + translations.append ((lang, trans)) + +# Regular expressions: +reLibintl_h = re.compile (r'#\s*include\s*<libintl.h>') +reDESC = re.compile (r'(\s*DRI_CONF_DESC\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reDESC_BEGIN = re.compile (r'(\s*DRI_CONF_DESC_BEGIN\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reENUM = re.compile (r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reDESC_END = re.compile (r'\s*DRI_CONF_DESC_END') + +# Print a header +print \ +"/***********************************************************************\n" \ +" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \ +" ***********************************************************************/" + +# Process the options template and generate options.h with all +# translations. +template = file ("t_options.h", "r") +descMatches = [] +for line in template: + if len(descMatches) > 0: + matchENUM = reENUM .match (line) + matchDESC_END = reDESC_END.match (line) + if matchENUM: + descMatches.append (matchENUM) + elif matchDESC_END: + expandMatches (descMatches, translations, line) + descMatches = [] + else: + sys.stderr.write ( + "Warning: unexpected line inside description dropped:\n%s\n" \ + % line) + continue + if reLibintl_h.search (line): + # Ignore (comment out) #include <libintl.h> + print "/* %s * commented out by gen_xmlpool.py */" % line + continue + matchDESC = reDESC .match (line) + matchDESC_BEGIN = reDESC_BEGIN.match (line) + if matchDESC: + assert len(descMatches) == 0 + expandMatches ([matchDESC], translations) + elif matchDESC_BEGIN: + assert len(descMatches) == 0 + descMatches = [matchDESC_BEGIN] + else: + print line, + +if len(descMatches) > 0: + sys.stderr.write ("Warning: unterminated description at end of file.\n") + expandMatches (descMatches, translations) diff --git a/src/mesa/drivers/dri/dri_client/Makefile b/src/mesa/drivers/dri/dri_client/Makefile new file mode 100644 index 00000000000..9ab60cdaf80 --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/Makefile @@ -0,0 +1,60 @@ +# src/mesa/drivers/dri/gamma/Makefile + +TOP = ../../../../.. +include $(TOP)/configs/current + +# Get rid of this: +# +DEFINES += -DGLX_DIRECT_RENDERING + +C_SOURCES = \ + xf86drm.c \ + xf86drmHash.c \ + xf86drmRandom.c \ + xf86drmSL.c \ + + + +OBJECTS = $(C_SOURCES:.c=.o) + +INCLUDES = \ + -I$(TOP)/include \ + -I$(DRM_SOURCE_PATH)/shared-core \ + -I$(TOP)/include/GL/internal \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi \ + -Iimports + + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +default: depend dri.a + + +# Run 'make dep' to update the dependencies if you change +# what's included by any source file. +depend: $(C_SOURCES) $(ASM_SOURCES) + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) \ + $(C_SOURCES) $(ASM_SOURCES) + + +dri.a: $(OBJECTS) + rm -f $@ + ar rcv $@ $(OBJECTS) + ranlib $@ + +# Remove .o and backup files +clean: + -rm -f *.o */*.o *~ *.so *.a depend depend.bak + +install: + +include depend diff --git a/src/mesa/drivers/dri/dri_client/imports/xf86drm.h b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h new file mode 100644 index 00000000000..d3d78eb84e8 --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h @@ -0,0 +1,636 @@ +/** + * \file xf86drm.h + * OS-independent header for DRM user-level library interface. + * + * \author Rickard E. (Rik) Faith <[email protected]> + */ + +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.26 2003/08/16 19:26:37 dawes Exp $ */ + +#ifndef _XF86DRM_H_ +#define _XF86DRM_H_ + +#include <drm.h> + + /* Defaults, if nothing set in xf86config */ +#define DRM_DEV_UID 0 +#define DRM_DEV_GID 0 +/* Default /dev/dri directory permissions 0755 */ +#define DRM_DEV_DIRMODE \ + (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + +#define DRM_DIR_NAME "/dev/dri" +#define DRM_DEV_NAME "%s/card%d" +#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */ + +#define DRM_ERR_NO_DEVICE (-1001) +#define DRM_ERR_NO_ACCESS (-1002) +#define DRM_ERR_NOT_ROOT (-1003) +#define DRM_ERR_INVALID (-1004) +#define DRM_ERR_NO_FD (-1005) + +#define DRM_AGP_NO_HANDLE 0 + +typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */ +typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */ + +/** + * Driver version information. + * + * \sa drmGetVersion() and drmSetVersion(). + */ +typedef struct _drmVersion { + int version_major; /**< Major version */ + int version_minor; /**< Minor version */ + int version_patchlevel; /**< Patch level */ + int name_len; /**< Length of name buffer */ + char *name; /**< Name of driver */ + int date_len; /**< Length of date buffer */ + char *date; /**< User-space buffer to hold date */ + int desc_len; /**< Length of desc buffer */ + char *desc; /**< User-space buffer to hold desc */ +} drmVersion, *drmVersionPtr; + +typedef struct _drmStats { + unsigned long count; /**< Number of data */ + struct { + unsigned long value; /**< Value from kernel */ + const char *long_format; /**< Suggested format for long_name */ + const char *long_name; /**< Long name for value */ + const char *rate_format; /**< Suggested format for rate_name */ + const char *rate_name; /**< Short name for value per second */ + int isvalue; /**< True if value (vs. counter) */ + const char *mult_names; /**< Multiplier names (e.g., "KGM") */ + int mult; /**< Multiplier value (e.g., 1024) */ + int verbose; /**< Suggest only in verbose output */ + } data[15]; +} drmStatsT; + + + /* All of these enums *MUST* match with the + kernel implementation -- so do *NOT* + change them! (The drmlib implementation + will just copy the flags instead of + translating them.) */ +typedef enum { + DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */ + DRM_REGISTERS = 1, /**< no caching, no core dump */ + DRM_SHM = 2, /**< shared, cached */ + DRM_AGP = 3, /**< AGP/GART */ + DRM_SCATTER_GATHER = 4 /**< PCI scatter/gather */ +} drmMapType; + +typedef enum { + DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */ + DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */ + DRM_LOCKED = 0x0004, /**< Physical pages locked */ + DRM_KERNEL = 0x0008, /**< Kernel requires access */ + DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */ + DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */ + DRM_REMOVABLE = 0x0040 /**< Removable mapping */ +} drmMapFlags; + +/** + * \warning These values *MUST* match drm.h + */ +typedef enum { + /** \name Flags for DMA buffer dispatch */ + /*@{*/ + DRM_DMA_BLOCK = 0x01, /**< + * Block until buffer dispatched. + * + * \note the buffer may not yet have been + * processed by the hardware -- getting a + * hardware lock with the hardware quiescent + * will ensure that the buffer has been + * processed. + */ + DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */ + DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */ + /*@}*/ + + /** \name Flags for DMA buffer request */ + /*@{*/ + DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */ + DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */ + DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */ + /*@}*/ +} drmDMAFlags; + +typedef enum { + DRM_PAGE_ALIGN = 0x01, + DRM_AGP_BUFFER = 0x02, + DRM_SG_BUFFER = 0x04 +} drmBufDescFlags; + +typedef enum { + DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */ + DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */ + DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */ + DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */ + /* These *HALT* flags aren't supported yet + -- they will be used to support the + full-screen DGA-like mode. */ + DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */ + DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */ +} drmLockFlags; + +typedef enum { + DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and + never swapped. */ + DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */ +} drm_context_tFlags, *drm_context_tFlagsPtr; + +typedef struct _drmBufDesc { + int count; /**< Number of buffers of this size */ + int size; /**< Size in bytes */ + int low_mark; /**< Low water mark */ + int high_mark; /**< High water mark */ +} drmBufDesc, *drmBufDescPtr; + +typedef struct _drmBufInfo { + int count; /**< Number of buffers described in list */ + drmBufDescPtr list; /**< List of buffer descriptions */ +} drmBufInfo, *drmBufInfoPtr; + +typedef struct _drmBuf { + int idx; /**< Index into the master buffer list */ + int total; /**< Buffer size */ + int used; /**< Amount of buffer in use (for DMA) */ + drmAddress address; /**< Address */ +} drmBuf, *drmBufPtr; + +/** + * Buffer mapping information. + * + * Used by drmMapBufs() and drmUnmapBufs() to store information about the + * mapped buffers. + */ +typedef struct _drmBufMap { + int count; /**< Number of buffers mapped */ + drmBufPtr list; /**< Buffers */ +} drmBufMap, *drmBufMapPtr; + +typedef struct _drmLock { + volatile unsigned int lock; + char padding[60]; + /* This is big enough for most current (and future?) architectures: + DEC Alpha: 32 bytes + Intel Merced: ? + Intel P5/PPro/PII/PIII: 32 bytes + Intel StrongARM: 32 bytes + Intel i386/i486: 16 bytes + MIPS: 32 bytes (?) + Motorola 68k: 16 bytes + Motorola PowerPC: 32 bytes + Sun SPARC: 32 bytes + */ +} drmLock, *drmLockPtr; + +/** + * Indices here refer to the offset into + * list in drmBufInfo + */ +typedef struct _drmDMAReq { + drm_context_t context; /**< Context handle */ + int send_count; /**< Number of buffers to send */ + int *send_list; /**< List of handles to buffers */ + int *send_sizes; /**< Lengths of data to send, in bytes */ + drmDMAFlags flags; /**< Flags */ + int request_count; /**< Number of buffers requested */ + int request_size; /**< Desired size of buffers requested */ + int *request_list; /**< Buffer information */ + int *request_sizes; /**< Minimum acceptable sizes */ + int granted_count; /**< Number of buffers granted at this size */ +} drmDMAReq, *drmDMAReqPtr; + +typedef struct _drmRegion { + drm_handle_t handle; + unsigned int offset; + drmSize size; + drmAddress map; +} drmRegion, *drmRegionPtr; + +typedef struct _drmTextureRegion { + unsigned char next; + unsigned char prev; + unsigned char in_use; + unsigned char padding; /**< Explicitly pad this out */ + unsigned int age; +} drmTextureRegion, *drmTextureRegionPtr; + + +typedef enum { + DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ + DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ +} drmVBlankSeqType; + +typedef struct _drmVBlankReq { + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq, *drmVBlankReqPtr; + +typedef struct _drmVBlankReply { + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply, *drmVBlankReplyPtr; + +typedef union _drmVBlank { + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank, *drmVBlankPtr; + +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; + + +#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) + +#define DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */ +#define DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */ + +#if defined(__GNUC__) && (__GNUC__ >= 2) +# if defined(__i386) || defined(__amd64__) + /* Reflect changes here to drmP.h */ +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + int __dummy; /* Can't mark eax as clobbered */ \ + __asm__ __volatile__( \ + "lock ; cmpxchg %4,%1\n\t" \ + "setnz %0" \ + : "=d" (__ret), \ + "=m" (__drm_dummy_lock(lock)), \ + "=a" (__dummy) \ + : "2" (old), \ + "r" (new)); \ + } while (0) + +#elif defined(__alpha__) + +#define DRM_CAS(lock, old, new, ret) \ + do { \ + int old32; \ + int cur32; \ + __asm__ __volatile__( \ + " mb\n" \ + " zap %4, 0xF0, %0\n" \ + " ldl_l %1, %2\n" \ + " zap %1, 0xF0, %1\n" \ + " cmpeq %0, %1, %1\n" \ + " beq %1, 1f\n" \ + " bis %5, %5, %1\n" \ + " stl_c %1, %2\n" \ + "1: xor %1, 1, %1\n" \ + " stl %1, %3" \ + : "+r" (old32), \ + "+&r" (cur32), \ + "=m" (__drm_dummy_lock(lock)),\ + "=m" (ret) \ + : "r" (old), \ + "r" (new)); \ + } while(0) + +#elif defined(__sparc__) + +#define DRM_CAS(lock,old,new,__ret) \ +do { register unsigned int __old __asm("o0"); \ + register unsigned int __new __asm("o1"); \ + register volatile unsigned int *__lock __asm("o2"); \ + __old = old; \ + __new = new; \ + __lock = (volatile unsigned int *)lock; \ + __asm__ __volatile__( \ + /*"cas [%2], %3, %0"*/ \ + ".word 0xd3e29008\n\t" \ + /*"membar #StoreStore | #StoreLoad"*/ \ + ".word 0x8143e00a" \ + : "=&r" (__new) \ + : "0" (__new), \ + "r" (__lock), \ + "r" (__old) \ + : "memory"); \ + __ret = (__new != __old); \ +} while(0) + +#elif defined(__ia64__) + +#ifdef __INTEL_COMPILER +/* this currently generates bad code (missing stop bits)... */ +#include <ia64intrin.h> + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned long __result, __old = (old) & 0xffffffff; \ + __mf(); \ + __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\ + __ret = (__result) != (__old); \ +/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ + (old), (new)) \ + != (old)); */\ + } while (0) + +#else +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + unsigned int __result, __old = (old); \ + __asm__ __volatile__( \ + "mf\n" \ + "mov ar.ccv=%2\n" \ + ";;\n" \ + "cmpxchg4.acq %0=%1,%3,ar.ccv" \ + : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ + : "r" ((unsigned long)__old), "r" (new) \ + : "memory"); \ + __ret = (__result) != (__old); \ + } while (0) + +#endif + +#elif defined(__powerpc__) + +#define DRM_CAS(lock,old,new,__ret) \ + do { \ + __asm__ __volatile__( \ + "sync;" \ + "0: lwarx %0,0,%1;" \ + " xor. %0,%3,%0;" \ + " bne 1f;" \ + " stwcx. %2,0,%1;" \ + " bne- 0b;" \ + "1: " \ + "sync;" \ + : "=&r"(__ret) \ + : "r"(lock), "r"(new), "r"(old) \ + : "cr0", "memory"); \ + } while (0) + +#endif /* architecture */ +#endif /* __GNUC__ >= 2 */ + +#ifndef DRM_CAS +#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */ +#endif + +#if defined(__alpha__) || defined(__powerpc__) +#define DRM_CAS_RESULT(_result) int _result +#else +#define DRM_CAS_RESULT(_result) char _result +#endif + +#define DRM_LIGHT_LOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + } while(0) + + /* This one counts fast locks -- for + benchmarking only. */ +#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ + if (__ret) drmGetLock(fd,context,0); \ + else ++count; \ + } while(0) + +#define DRM_LOCK(fd,lock,context,flags) \ + do { \ + if (flags) drmGetLock(fd,context,flags); \ + else DRM_LIGHT_LOCK(fd,lock,context); \ + } while(0) + +#define DRM_UNLOCK(fd,lock,context) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \ + if (__ret) drmUnlock(fd,context); \ + } while(0) + + /* Simple spin locks */ +#define DRM_SPINLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + do { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) while ((spin)->lock); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_TAKE(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + int cur; \ + do { \ + cur = (*spin).lock; \ + DRM_CAS(spin,cur,val,__ret); \ + } while (__ret); \ + } while(0) + +#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ + do { \ + int __i; \ + __ret = 1; \ + for (__i = 0; __ret && __i < count; __i++) { \ + DRM_CAS(spin,0,val,__ret); \ + if (__ret) for (;__i < count && (spin)->lock; __i++); \ + } \ + } while(0) + +#define DRM_SPINUNLOCK(spin,val) \ + do { \ + DRM_CAS_RESULT(__ret); \ + if ((*spin).lock == val) { /* else server stole lock */ \ + do { \ + DRM_CAS(spin,val,0,__ret); \ + } while (__ret); \ + } \ + } while(0) + +/* General user-level programmer's API: unprivileged */ +extern int drmAvailable(void); +extern int drmOpen(const char *name, const char *busid); +extern int drmClose(int fd); +extern drmVersionPtr drmGetVersion(int fd); +extern drmVersionPtr drmGetLibVersion(int fd); +extern void drmFreeVersion(drmVersionPtr); +extern int drmGetMagic(int fd, drm_magic_t * magic); +extern char *drmGetBusid(int fd); +extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum, + int funcnum); +extern int drmGetMap(int fd, int idx, drm_handle_t *offset, + drmSize *size, drmMapType *type, + drmMapFlags *flags, drm_handle_t *handle, + int *mtrr); +extern int drmGetClient(int fd, int idx, int *auth, int *pid, + int *uid, unsigned long *magic, + unsigned long *iocs); +extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); +extern int drmCommandNone(int fd, unsigned long drmCommandIndex); +extern int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); +extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size); + +/* General user-level programmer's API: X server (root) only */ +extern void drmFreeBusid(const char *busid); +extern int drmSetBusid(int fd, const char *busid); +extern int drmAuthMagic(int fd, drm_magic_t magic); +extern int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle); +extern int drmRmMap(int fd, drm_handle_t handle); +extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t handle); + +extern int drmAddBufs(int fd, int count, int size, + drmBufDescFlags flags, + int agp_offset); +extern int drmMarkBufs(int fd, double low, double high); +extern int drmCreateContext(int fd, drm_context_t * handle); +extern int drmSetContextFlags(int fd, drm_context_t context, + drm_context_tFlags flags); +extern int drmGetContextFlags(int fd, drm_context_t context, + drm_context_tFlagsPtr flags); +extern int drmAddContextTag(int fd, drm_context_t context, void *tag); +extern int drmDelContextTag(int fd, drm_context_t context); +extern void *drmGetContextTag(int fd, drm_context_t context); +extern drm_context_t * drmGetReservedContextList(int fd, int *count); +extern void drmFreeReservedContextList(drm_context_t *); +extern int drmSwitchToContext(int fd, drm_context_t context); +extern int drmDestroyContext(int fd, drm_context_t handle); +extern int drmCreateDrawable(int fd, drm_drawable_t * handle); +extern int drmDestroyDrawable(int fd, drm_drawable_t handle); +extern int drmCtlInstHandler(int fd, int irq); +extern int drmCtlUninstHandler(int fd); +extern int drmInstallSIGIOHandler(int fd, + void (*f)(int fd, + void *oldctx, + void *newctx)); +extern int drmRemoveSIGIOHandler(int fd); + +/* General user-level programmer's API: authenticated client and/or X */ +extern int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address); +extern int drmUnmap(drmAddress address, drmSize size); +extern drmBufInfoPtr drmGetBufInfo(int fd); +extern drmBufMapPtr drmMapBufs(int fd); +extern int drmUnmapBufs(drmBufMapPtr bufs); +extern int drmDMA(int fd, drmDMAReqPtr request); +extern int drmFreeBufs(int fd, int count, int *list); +extern int drmGetLock(int fd, + drm_context_t context, + drmLockFlags flags); +extern int drmUnlock(int fd, drm_context_t context); +extern int drmFinish(int fd, int context, drmLockFlags flags); +extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, + drm_handle_t * handle); + +/* AGP/GART support: X server (root) only */ +extern int drmAgpAcquire(int fd); +extern int drmAgpRelease(int fd); +extern int drmAgpEnable(int fd, unsigned long mode); +extern int drmAgpAlloc(int fd, unsigned long size, + unsigned long type, unsigned long *address, + unsigned long *handle); +extern int drmAgpFree(int fd, unsigned long handle); +extern int drmAgpBind(int fd, unsigned long handle, + unsigned long offset); +extern int drmAgpUnbind(int fd, unsigned long handle); + +/* AGP/GART info: authenticated client and/or X */ +extern int drmAgpVersionMajor(int fd); +extern int drmAgpVersionMinor(int fd); +extern unsigned long drmAgpGetMode(int fd); +extern unsigned long drmAgpBase(int fd); /* Physical location */ +extern unsigned long drmAgpSize(int fd); /* Bytes */ +extern unsigned long drmAgpMemoryUsed(int fd); +extern unsigned long drmAgpMemoryAvail(int fd); +extern unsigned int drmAgpVendorId(int fd); +extern unsigned int drmAgpDeviceId(int fd); + +/* PCI scatter/gather support: X server (root) only */ +extern int drmScatterGatherAlloc(int fd, unsigned long size, + unsigned long *handle); +extern int drmScatterGatherFree(int fd, unsigned long handle); + +extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); + +/* Support routines */ +extern int drmError(int err, const char *label); +extern void *drmMalloc(int size); +extern void drmFree(void *pt); + +/* Hash table routines */ +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, void **value); +extern int drmHashInsert(void *t, unsigned long key, void *value); +extern int drmHashDelete(void *t, unsigned long key); +extern int drmHashFirst(void *t, unsigned long *key, void **value); +extern int drmHashNext(void *t, unsigned long *key, void **value); + +/* PRNG routines */ +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); + +/* Skip list routines */ + +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); + +#endif diff --git a/src/mesa/drivers/dri/dri_client/xf86drm.c b/src/mesa/drivers/dri/dri_client/xf86drm.c new file mode 100644 index 00000000000..dba0f98deba --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/xf86drm.c @@ -0,0 +1,2333 @@ +/** + * \file xf86drm.c + * User-level interface to DRM device + * + * \author Rickard E. (Rik) Faith <[email protected]> + * \author Kevin E. Martin <[email protected]> + */ + +/* + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "drm.h" +# include "xf86_ansic.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# define stat_t struct stat +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# include <stdarg.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +# else +# include <X11/Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +# include "drm.h" +#endif + +/* No longer needed with CVS kernel modules on alpha +#if defined(__alpha__) && defined(__linux__) +extern unsigned long _bus_base(void); +#define BUS_BASE _bus_base() +#endif +*/ + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include "xf86drm.h" + +#ifdef __FreeBSD__ +#define DRM_MAJOR 145 +#endif + +#ifdef __NetBSD__ +#define DRM_MAJOR 34 +#endif + +# ifdef __OpenBSD__ +# define DRM_MAJOR 81 +# endif + +#ifndef DRM_MAJOR +#define DRM_MAJOR 226 /* Linux */ +#endif + +#ifndef DRM_MAX_MINOR +#define DRM_MAX_MINOR 16 +#endif + +#ifdef __linux__ +#include <sys/sysmacros.h> /* for makedev() */ +#endif + +#ifndef makedev + /* This definition needs to be changed on + some systems if dev_t is a structure. + If there is a header file we can get it + from, there would be best. */ +#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) +#endif + +#define DRM_MSG_VERBOSITY 3 + +/** + * Output a message to stderr. + * + * \param format printf() like format string. + * + * \internal + * This function is a wrapper around vfprintf(). + */ +static void +drmMsg(const char *format, ...) +{ + va_list ap; + +#ifndef XFree86Server + const char *env; + if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) +#endif + { + va_start(ap, format); +#ifdef XFree86Server + xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); +#else + vfprintf(stderr, format, ap); +#endif + va_end(ap); + } +} + +static void *drmHashTable = NULL; /* Context switch callbacks */ + +typedef struct drmHashEntry { + int fd; + void (*f)(int, void *, void *); + void *tagTable; +} drmHashEntry; + +void *drmMalloc(int size) +{ + void *pt; + if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size); + return pt; +} + +void drmFree(void *pt) +{ + if (pt) _DRM_FREE(pt); +} + +/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */ +static char *drmStrdup(const char *s) +{ + char *retval = NULL; + + if (s) { + retval = _DRM_MALLOC(strlen(s)+1); + strcpy(retval, s); + } + return retval; +} + + +static unsigned long drmGetKeyFromFd(int fd) +{ + stat_t st; + + st.st_rdev = 0; + fstat(fd, &st); + return st.st_rdev; +} + +static drmHashEntry *drmGetEntry(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + void *value; + drmHashEntry *entry; + + if (!drmHashTable) drmHashTable = drmHashCreate(); + + if (drmHashLookup(drmHashTable, key, &value)) { + entry = drmMalloc(sizeof(*entry)); + entry->fd = fd; + entry->f = NULL; + entry->tagTable = drmHashCreate(); + drmHashInsert(drmHashTable, key, entry); + } else { + entry = value; + } + return entry; +} + +/** + * Compare two busid strings + * + * \param first + * \param second + * + * \return 1 if matched. + * + * \internal + * This function compares two bus ID strings. It understands the older + * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is + * domain, b is bus, d is device, f is function. + */ +static int drmMatchBusID(const char *id1, const char *id2) +{ + /* First, check if the IDs are exactly the same */ + if (strcasecmp(id1, id2) == 0) + return 1; + + /* Try to match old/new-style PCI bus IDs. */ + if (strncasecmp(id1, "pci", 3) == 0) { + int o1, b1, d1, f1; + int o2, b2, d2, f2; + int ret; + + ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1); + if (ret != 4) { + o1 = 0; + ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1); + if (ret != 3) + return 0; + } + + ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2); + if (ret != 4) { + o2 = 0; + ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2); + if (ret != 3) + return 0; + } + + if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) + return 0; + else + return 1; + } + return 0; +} + +/** + * Open the DRM device, creating it if necessary. + * + * \param dev major and minor numbers of the device. + * \param minor minor number of the device. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * Assembles the device name from \p minor and opens it, creating the device + * special file node with the major and minor numbers specified by \p dev and + * parent directory if necessary and was called by root. + */ +static int drmOpenDevice(long dev, int minor) +{ + stat_t st; + char buf[64]; + int fd; + mode_t devmode = DRM_DEV_MODE; + int isroot = !geteuid(); +#if defined(XFree86Server) + uid_t user = DRM_DEV_UID; + gid_t group = DRM_DEV_GID; +#endif + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + drmMsg("drmOpenDevice: node name is %s\n", buf); + +#if defined(XFree86Server) + devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; + devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); + group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID; +#endif + + if (stat(DRM_DIR_NAME, &st)) { + if (!isroot) return DRM_ERR_NOT_ROOT; + mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE); + chown(DRM_DIR_NAME, 0, 0); /* root:root */ + chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); + } + + /* Check if the device node exists and create it if necessary. */ + if (stat(buf, &st)) { + if (!isroot) return DRM_ERR_NOT_ROOT; + remove(buf); + mknod(buf, S_IFCHR | devmode, dev); + } +#if defined(XFree86Server) + chown(buf, user, group); + chmod(buf, devmode); +#endif + + fd = open(buf, O_RDWR, 0); + drmMsg("drmOpenDevice: open result is %d, (%s)\n", + fd, fd < 0 ? strerror(errno) : "OK"); + if (fd >= 0) return fd; + + /* Check if the device node is not what we expect it to be, and recreate it + * and try again if so. + */ + if (st.st_rdev != dev) { + if (!isroot) return DRM_ERR_NOT_ROOT; + remove(buf); + mknod(buf, S_IFCHR | devmode, dev); +#if defined(XFree86Server) + chown(buf, user, group); + chmod(buf, devmode); +#endif + } + fd = open(buf, O_RDWR, 0); + drmMsg("drmOpenDevice: open result is %d, (%s)\n", + fd, fd < 0 ? strerror(errno) : "OK"); + if (fd >= 0) return fd; + + drmMsg("drmOpenDevice: Open failed\n"); + remove(buf); + return -errno; +} + + +/** + * Open the DRM device + * + * \param minor device minor number. + * \param create allow to create the device if set. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * Calls drmOpenDevice() if \p create is set, otherwise assembles the device + * name from \p minor and opens it. + */ +static int drmOpenMinor(int minor, int create) +{ + int fd; + char buf[64]; + + if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor); + + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd; + return -errno; +} + + +/** + * Determine whether the DRM kernel driver has been loaded. + * + * \return 1 if the DRM driver is loaded, 0 otherwise. + * + * \internal + * Determine the presence of the kernel driver by attempting to open the 0 + * minor and get version information. For backward compatibility with older + * Linux implementations, /proc/dri is also checked. + */ +int drmAvailable(void) +{ + drmVersionPtr version; + int retval = 0; + int fd; + + if ((fd = drmOpenMinor(0, 1)) < 0) { +#ifdef __linux__ + /* Try proc for backward Linux compatibility */ + if (!access("/proc/dri/0", R_OK)) return 1; +#endif + return 0; + } + + if ((version = drmGetVersion(fd))) { + retval = 1; + drmFreeVersion(version); + } + close(fd); + + return retval; +} + + +/** + * Open the device by bus ID. + * + * \param busid bus ID. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * This function attempts to open every possible minor (up to DRM_MAX_MINOR), + * comparing the device bus ID with the one supplied. + * + * \sa drmOpenMinor() and drmGetBusid(). + */ +static int drmOpenByBusid(const char *busid) +{ + int i; + int fd; + const char *buf; + drmSetVersion sv; + + drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); + for (i = 0; i < DRM_MAX_MINOR; i++) { + fd = drmOpenMinor(i, 1); + drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); + if (fd >= 0) { + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; /* Don't care */ + drmSetInterfaceVersion(fd, &sv); + buf = drmGetBusid(fd); + drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); + if (buf && drmMatchBusID(buf, busid)) { + drmFreeBusid(buf); + return fd; + } + if (buf) drmFreeBusid(buf); + close(fd); + } + } + return -1; +} + + +/** + * Open the device by name. + * + * \param name driver name. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * This function opens the first minor number that matches the driver name and + * isn't already in use. If it's in use it then it will already have a bus ID + * assigned. + * + * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid(). + */ +static int drmOpenByName(const char *name) +{ + int i; + int fd; + drmVersionPtr version; + char * id; + + if (!drmAvailable()) { +#if !defined(XFree86Server) + return -1; +#else + /* try to load the kernel module now */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } +#endif + } + + /* + * Open the first minor number that matches the driver name and isn't + * already in use. If it's in use it will have a busid assigned already. + */ + for (i = 0; i < DRM_MAX_MINOR; i++) { + if ((fd = drmOpenMinor(i, 1)) >= 0) { + if ((version = drmGetVersion(fd))) { + if (!strcmp(version->name, name)) { + drmFreeVersion(version); + id = drmGetBusid(fd); + drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); + if (!id || !*id) { + if (id) { + drmFreeBusid(id); + } + return fd; + } else { + drmFreeBusid(id); + } + } else { + drmFreeVersion(version); + } + } + close(fd); + } + } + +#ifdef __linux__ + /* Backward-compatibility /proc support */ + for (i = 0; i < 8; i++) { + char proc_name[64], buf[512]; + char *driver, *pt, *devstring; + int retcode; + + sprintf(proc_name, "/proc/dri/%d/name", i); + if ((fd = open(proc_name, 0, 0)) >= 0) { + retcode = read(fd, buf, sizeof(buf)-1); + close(fd); + if (retcode) { + buf[retcode-1] = '\0'; + for (driver = pt = buf; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Device is next */ + *pt = '\0'; + if (!strcmp(driver, name)) { /* Match */ + for (devstring = ++pt; *pt && *pt != ' '; ++pt) + ; + if (*pt) { /* Found busid */ + return drmOpenByBusid(++pt); + } else { /* No busid */ + return drmOpenDevice(strtol(devstring, NULL, 0),i); + } + } + } + } + } + } +#endif + + return -1; +} + + +/** + * Open the DRM device. + * + * Looks up the specified name and bus ID, and opens the device found. The + * entry in /dev/dri is created if necessary and if called by root. + * + * \param name driver name. Not referenced if bus ID is supplied. + * \param busid bus ID. Zero if not known. + * + * \return a file descriptor on success, or a negative value on error. + * + * \internal + * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName() + * otherwise. + */ +int drmOpen(const char *name, const char *busid) +{ +#ifdef XFree86Server + if (!drmAvailable() && name != NULL) { + /* try to load the kernel */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } + } +#endif + + if (busid) { + int fd; + + fd = drmOpenByBusid(busid); + if (fd >= 0) + return fd; + } + if (name) + return drmOpenByName(name); + return -1; +} + + +/** + * Free the version information returned by drmGetVersion(). + * + * \param v pointer to the version information. + * + * \internal + * It frees the memory pointed by \p %v as well as all the non-null strings + * pointers in it. + */ +void drmFreeVersion(drmVersionPtr v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + + +/** + * Free the non-public version information returned by the kernel. + * + * \param v pointer to the version information. + * + * \internal + * Used by drmGetVersion() to free the memory pointed by \p %v as well as all + * the non-null strings pointers in it. + */ +static void drmFreeKernelVersion(drm_version_t *v) +{ + if (!v) return; + if (v->name) drmFree(v->name); + if (v->date) drmFree(v->date); + if (v->desc) drmFree(v->desc); + drmFree(v); +} + + +/** + * Copy version information. + * + * \param d destination pointer. + * \param s source pointer. + * + * \internal + * Used by drmGetVersion() to translate the information returned by the ioctl + * interface in a private structure into the public structure counterpart. + */ +static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s) +{ + d->version_major = s->version_major; + d->version_minor = s->version_minor; + d->version_patchlevel = s->version_patchlevel; + d->name_len = s->name_len; + d->name = drmStrdup(s->name); + d->date_len = s->date_len; + d->date = drmStrdup(s->date); + d->desc_len = s->desc_len; + d->desc = drmStrdup(s->desc); +} + + +/** + * Query the driver version information. + * + * \param fd file descriptor. + * + * \return pointer to a drmVersion structure which should be freed with + * drmFreeVersion(). + * + * \note Similar information is available via /proc/dri. + * + * \internal + * It gets the version information via successive DRM_IOCTL_VERSION ioctls, + * first with zeros to get the string lengths, and then the actually strings. + * It also null-terminates them since they might not be already. + */ +drmVersionPtr drmGetVersion(int fd) +{ + drmVersionPtr retval; + drm_version_t *version = drmMalloc(sizeof(*version)); + + /* First, get the lengths */ + version->name_len = 0; + version->name = NULL; + version->date_len = 0; + version->date = NULL; + version->desc_len = 0; + version->desc = NULL; + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmFreeKernelVersion(version); + return NULL; + } + + /* Now, allocate space and get the data */ + if (version->name_len) + version->name = drmMalloc(version->name_len + 1); + if (version->date_len) + version->date = drmMalloc(version->date_len + 1); + if (version->desc_len) + version->desc = drmMalloc(version->desc_len + 1); + + if (ioctl(fd, DRM_IOCTL_VERSION, version)) { + drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno)); + drmFreeKernelVersion(version); + return NULL; + } + + /* The results might not be null-terminated + strings, so terminate them. */ + + if (version->name_len) version->name[version->name_len] = '\0'; + if (version->date_len) version->date[version->date_len] = '\0'; + if (version->desc_len) version->desc[version->desc_len] = '\0'; + + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + drmCopyVersion(retval, version); + drmFreeKernelVersion(version); + return retval; +} + + +/** + * Get version information for the DRM user space library. + * + * This version number is driver independent. + * + * \param fd file descriptor. + * + * \return version information. + * + * \internal + * This function allocates and fills a drm_version structure with a hard coded + * version number. + */ +drmVersionPtr drmGetLibVersion(int fd) +{ + drm_version_t *version = drmMalloc(sizeof(*version)); + + /* Version history: + * revision 1.0.x = original DRM interface with no drmGetLibVersion + * entry point and many drm<Device> extensions + * revision 1.1.x = added drmCommand entry points for device extensions + * added drmGetLibVersion to identify libdrm.a version + * revision 1.2.x = added drmSetInterfaceVersion + * modified drmOpen to handle both busid and name + */ + version->version_major = 1; + version->version_minor = 2; + version->version_patchlevel = 0; + + return (drmVersionPtr)version; +} + + +/** + * Free the bus ID information. + * + * \param busid bus ID information string as given by drmGetBusid(). + * + * \internal + * This function is just frees the memory pointed by \p busid. + */ +void drmFreeBusid(const char *busid) +{ + drmFree((void *)busid); +} + + +/** + * Get the bus ID of the device. + * + * \param fd file descriptor. + * + * \return bus ID string. + * + * \internal + * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to + * get the string length and data, passing the arguments in a drm_unique + * structure. + */ +char *drmGetBusid(int fd) +{ + drm_unique_t u; + + u.unique_len = 0; + u.unique = NULL; + + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique = drmMalloc(u.unique_len + 1); + if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; + u.unique[u.unique_len] = '\0'; + + return u.unique; +} + + +/** + * Set the bus ID of the device. + * + * \param fd file descriptor. + * \param busid bus ID string. + * + * \return zero on success, negative on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing + * the arguments in a drm_unique structure. + */ +int drmSetBusid(int fd, const char *busid) +{ + drm_unique_t u; + + u.unique = (char *)busid; + u.unique_len = strlen(busid); + + if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) { + return -errno; + } + return 0; +} + +int drmGetMagic(int fd, drm_magic_t * magic) +{ + drm_auth_t auth; + + *magic = 0; + if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno; + *magic = auth.magic; + return 0; +} + +int drmAuthMagic(int fd, drm_magic_t magic) +{ + drm_auth_t auth; + + auth.magic = magic; + if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno; + return 0; +} + +/** + * Specifies a range of memory that is available for mapping by a + * non-root process. + * + * \param fd file descriptor. + * \param offset usually the physical address. The actual meaning depends of + * the \p type parameter. See below. + * \param size of the memory in bytes. + * \param type type of the memory to be mapped. + * \param flags combination of several flags to modify the function actions. + * \param handle will be set to a value that may be used as the offset + * parameter for mmap(). + * + * \return zero on success or a negative value on error. + * + * \par Mapping the frame buffer + * For the frame buffer + * - \p offset will be the physical address of the start of the frame buffer, + * - \p size will be the size of the frame buffer in bytes, and + * - \p type will be DRM_FRAME_BUFFER. + * + * \par + * The area mapped will be uncached. If MTRR support is available in the + * kernel, the frame buffer area will be set to write combining. + * + * \par Mapping the MMIO register area + * For the MMIO register area, + * - \p offset will be the physical address of the start of the register area, + * - \p size will be the size of the register area bytes, and + * - \p type will be DRM_REGISTERS. + * \par + * The area mapped will be uncached. + * + * \par Mapping the SAREA + * For the SAREA, + * - \p offset will be ignored and should be set to zero, + * - \p size will be the desired size of the SAREA in bytes, + * - \p type will be DRM_SHM. + * + * \par + * A shared memory area of the requested size will be created and locked in + * kernel memory. This area may be mapped into client-space by using the handle + * returned. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing + * the arguments in a drm_map structure. + */ +int drmAddMap(int fd, + drm_handle_t offset, + drmSize size, + drmMapType type, + drmMapFlags flags, + drm_handle_t * handle) +{ + drm_map_t map; + + map.offset = offset; +/* No longer needed with CVS kernel modules on alpha +#ifdef __alpha__ + if (type != DRM_SHM) + map.offset += BUS_BASE; +#endif +*/ + map.size = size; + map.handle = 0; + map.type = type; + map.flags = flags; + if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno; + if (handle) *handle = (drm_handle_t)map.handle; + return 0; +} + +int drmRmMap(int fd, drm_handle_t handle) +{ + drm_map_t map; + + map.handle = (void *)handle; + + if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno; + return 0; +} + +/** + * Make buffers available for DMA transfers. + * + * \param fd file descriptor. + * \param count number of buffers. + * \param size size of each buffer. + * \param flags buffer allocation flags. + * \param agp_offset offset in the AGP aperture + * + * \return number of buffers allocated, negative on error. + * + * \internal + * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl. + * + * \sa drm_buf_desc. + */ +int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags, + int agp_offset) +{ + drm_buf_desc_t request; + + request.count = count; + request.size = size; + request.low_mark = 0; + request.high_mark = 0; + request.flags = flags; + request.agp_start = agp_offset; + + if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno; + return request.count; +} + +int drmMarkBufs(int fd, double low, double high) +{ + drm_buf_info_t info; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL; + + if (!info.count) return -EINVAL; + + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return -ENOMEM; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + int retval = -errno; + drmFree(info.list); + return retval; + } + + for (i = 0; i < info.count; i++) { + info.list[i].low_mark = low * info.list[i].count; + info.list[i].high_mark = high * info.list[i].count; + if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) { + int retval = -errno; + drmFree(info.list); + return retval; + } + } + drmFree(info.list); + + return 0; +} + +/** + * Free buffers. + * + * \param fd file descriptor. + * \param count number of buffers to free. + * \param list list of buffers to be freed. + * + * \return zero on success, or a negative value on failure. + * + * \note This function is primarily used for debugging. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing + * the arguments in a drm_buf_free structure. + */ +int drmFreeBufs(int fd, int count, int *list) +{ + drm_buf_free_t request; + + request.count = count; + request.list = list; + if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno; + return 0; +} + + +/** + * Close the device. + * + * \param fd file descriptor. + * + * \internal + * This function closes the file descriptor. + */ +int drmClose(int fd) +{ + unsigned long key = drmGetKeyFromFd(fd); + drmHashEntry *entry = drmGetEntry(fd); + + drmHashDestroy(entry->tagTable); + entry->fd = 0; + entry->f = NULL; + entry->tagTable = NULL; + + drmHashDelete(drmHashTable, key); + drmFree(entry); + + return close(fd); +} + + +/** + * Map a region of memory. + * + * \param fd file descriptor. + * \param handle handle returned by drmAddMap(). + * \param size size in bytes. Must match the size used by drmAddMap(). + * \param address will contain the user-space virtual address where the mapping + * begins. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper for mmap(). + */ +int drmMap(int fd, + drm_handle_t handle, + drmSize size, + drmAddressPtr address) +{ + static unsigned long pagesize_mask = 0; + + if (fd < 0) return -EINVAL; + + if (!pagesize_mask) + pagesize_mask = getpagesize() - 1; + + size = (size + pagesize_mask) & ~pagesize_mask; + + *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle); + if (*address == MAP_FAILED) return -errno; + return 0; +} + + +/** + * Unmap mappings obtained with drmMap(). + * + * \param address address as given by drmMap(). + * \param size size in bytes. Must match the size used by drmMap(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper for unmap(). + */ +int drmUnmap(drmAddress address, drmSize size) +{ + return munmap(address, size); +} + +drmBufInfoPtr drmGetBufInfo(int fd) +{ + drm_buf_info_t info; + drmBufInfoPtr retval; + int i; + + info.count = 0; + info.list = NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL; + + if (info.count) { + if (!(info.list = drmMalloc(info.count * sizeof(*info.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) { + drmFree(info.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = info.count; + retval->list = drmMalloc(info.count * sizeof(*retval->list)); + for (i = 0; i < info.count; i++) { + retval->list[i].count = info.list[i].count; + retval->list[i].size = info.list[i].size; + retval->list[i].low_mark = info.list[i].low_mark; + retval->list[i].high_mark = info.list[i].high_mark; + } + drmFree(info.list); + return retval; + } + return NULL; +} + +/** + * Map all DMA buffers into client-virtual space. + * + * \param fd file descriptor. + * + * \return a pointer to a ::drmBufMap structure. + * + * \note The client may not use these buffers until obtaining buffer indices + * with drmDMA(). + * + * \internal + * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned + * information about the buffers in a drm_buf_map structure into the + * client-visible data structures. + */ +drmBufMapPtr drmMapBufs(int fd) +{ + drm_buf_map_t bufs; + drmBufMapPtr retval; + int i; + + bufs.count = 0; + bufs.list = NULL; + bufs.virtual = NULL; + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL; + + if (!bufs.count) return NULL; + + if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list)))) + return NULL; + + if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) { + drmFree(bufs.list); + return NULL; + } + /* Now, copy it all back into the + client-visible data structure... */ + retval = drmMalloc(sizeof(*retval)); + retval->count = bufs.count; + retval->list = drmMalloc(bufs.count * sizeof(*retval->list)); + for (i = 0; i < bufs.count; i++) { + retval->list[i].idx = bufs.list[i].idx; + retval->list[i].total = bufs.list[i].total; + retval->list[i].used = 0; + retval->list[i].address = bufs.list[i].address; + } + + drmFree(bufs.list); + + return retval; +} + + +/** + * Unmap buffers allocated with drmMapBufs(). + * + * \return zero on success, or negative value on failure. + * + * \internal + * Calls munmap() for every buffer stored in \p bufs and frees the + * memory allocated by drmMapBufs(). + */ +int drmUnmapBufs(drmBufMapPtr bufs) +{ + int i; + + for (i = 0; i < bufs->count; i++) { + munmap(bufs->list[i].address, bufs->list[i].total); + } + + drmFree(bufs->list); + drmFree(bufs); + + return 0; +} + + +#define DRM_DMA_RETRY 16 + +/** + * Reserve DMA buffers. + * + * \param fd file descriptor. + * \param request + * + * \return zero on success, or a negative value on failure. + * + * \internal + * Assemble the arguments into a drm_dma structure and keeps issuing the + * DRM_IOCTL_DMA ioctl until success or until maximum number of retries. + */ +int drmDMA(int fd, drmDMAReqPtr request) +{ + drm_dma_t dma; + int ret, i = 0; + + /* Copy to hidden structure */ + dma.context = request->context; + dma.send_count = request->send_count; + dma.send_indices = request->send_list; + dma.send_sizes = request->send_sizes; + dma.flags = request->flags; + dma.request_count = request->request_count; + dma.request_size = request->request_size; + dma.request_indices = request->request_list; + dma.request_sizes = request->request_sizes; + dma.granted_count = 0; + + do { + ret = ioctl( fd, DRM_IOCTL_DMA, &dma ); + } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY ); + + if ( ret == 0 ) { + request->granted_count = dma.granted_count; + return 0; + } else { + return -errno; + } +} + + +/** + * Obtain heavyweight hardware lock. + * + * \param fd file descriptor. + * \param context context. + * \param flags flags that determine the sate of the hardware when the function + * returns. + * + * \return always zero. + * + * \internal + * This function translates the arguments into a drm_lock structure and issue + * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired. + */ +int drmGetLock(int fd, drm_context_t context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + + while (ioctl(fd, DRM_IOCTL_LOCK, &lock)) + ; + return 0; +} + +/** + * Release the hardware lock. + * + * \param fd file descriptor. + * \param context context. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the + * argument in a drm_lock structure. + */ +int drmUnlock(int fd, drm_context_t context) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + return ioctl(fd, DRM_IOCTL_UNLOCK, &lock); +} + +drm_context_t * drmGetReservedContextList(int fd, int *count) +{ + drm_ctx_res_t res; + drm_ctx_t *list; + drm_context_t * retval; + int i; + + res.count = 0; + res.contexts = NULL; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + if (!res.count) return NULL; + + if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL; + if (!(retval = drmMalloc(res.count * sizeof(*retval)))) { + drmFree(list); + return NULL; + } + + res.contexts = list; + if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL; + + for (i = 0; i < res.count; i++) retval[i] = list[i].handle; + drmFree(list); + + *count = res.count; + return retval; +} + +void drmFreeReservedContextList(drm_context_t * pt) +{ + drmFree(pt); +} + +/** + * Create context. + * + * Used by the X server during GLXContext initialization. This causes + * per-context kernel-level resources to be allocated. + * + * \param fd file descriptor. + * \param handle is set on success. To be used by the client when requesting DMA + * dispatch with drmDMA(). + * + * \return zero on success, or a negative value on failure. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the + * argument in a drm_ctx structure. + */ +int drmCreateContext(int fd, drm_context_t * handle) +{ + drm_ctx_t ctx; + + ctx.flags = 0; /* Modified with functions below */ + if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno; + *handle = ctx.handle; + return 0; +} + +int drmSwitchToContext(int fd, drm_context_t context) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno; + return 0; +} + +int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags) +{ + drm_ctx_t ctx; + + /* Context preserving means that no context + switched are done between DMA buffers + from one context and the next. This is + suitable for use in the X server (which + promises to maintain hardware context, + or in the client-side library when + buffers are swapped on behalf of two + threads. */ + ctx.handle = context; + ctx.flags = 0; + if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED; + if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY; + if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno; + return 0; +} + +int drmGetContextFlags(int fd, drm_context_t context, drm_context_tFlagsPtr flags) +{ + drm_ctx_t ctx; + + ctx.handle = context; + if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno; + *flags = 0; + if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED; + if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY; + return 0; +} + +/** + * Destroy context. + * + * Free any kernel-level resources allocated with drmCreateContext() associated + * with the context. + * + * \param fd file descriptor. + * \param handle handle given by drmCreateContext(). + * + * \return zero on success, or a negative value on failure. + * + * \note May only be called by root. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the + * argument in a drm_ctx structure. + */ +int drmDestroyContext(int fd, drm_context_t handle) +{ + drm_ctx_t ctx; + ctx.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno; + return 0; +} + +int drmCreateDrawable(int fd, drm_drawable_t * handle) +{ + drm_draw_t draw; + if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno; + *handle = draw.handle; + return 0; +} + +int drmDestroyDrawable(int fd, drm_drawable_t handle) +{ + drm_draw_t draw; + draw.handle = handle; + if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno; + return 0; +} + +/** + * Acquire the AGP device. + * + * Must be called before any of the other AGP related calls. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl. + */ +int drmAgpAcquire(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno; + return 0; +} + + +/** + * Release the AGP device. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl. + */ +int drmAgpRelease(int fd) +{ + if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno; + return 0; +} + + +/** + * Set the AGP mode. + * + * \param fd file descriptor. + * \param mode AGP mode. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the + * argument in a drm_agp_mode structure. + */ +int drmAgpEnable(int fd, unsigned long mode) +{ + drm_agp_mode_t m; + + m.mode = mode; + if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno; + return 0; +} + + +/** + * Allocate a chunk of AGP memory. + * + * \param fd file descriptor. + * \param size requested memory size in bytes. Will be rounded to page boundary. + * \param type type of memory to allocate. + * \param address if not zero, will be set to the physical address of the + * allocated memory. + * \param handle on success will be set to a handle of the allocated memory. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the + * arguments in a drm_agp_buffer structure. + */ +int drmAgpAlloc(int fd, unsigned long size, unsigned long type, + unsigned long *address, unsigned long *handle) +{ + drm_agp_buffer_t b; + + *handle = DRM_AGP_NO_HANDLE; + b.size = size; + b.handle = 0; + b.type = type; + if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno; + if (address != 0UL) *address = b.physical; + *handle = b.handle; + return 0; +} + + +/** + * Free a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the + * argument in a drm_agp_buffer structure. + */ +int drmAgpFree(int fd, unsigned long handle) +{ + drm_agp_buffer_t b; + + b.size = 0; + b.handle = handle; + if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno; + return 0; +} + + +/** + * Bind a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * \param offset offset in bytes. It will round to page boundary. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the + * argument in a drm_agp_binding structure. + */ +int drmAgpBind(int fd, unsigned long handle, unsigned long offset) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = offset; + if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno; + return 0; +} + + +/** + * Unbind a chunk of AGP memory. + * + * \param fd file descriptor. + * \param handle handle to the allocated memory, as given by drmAgpAllocate(). + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing + * the argument in a drm_agp_binding structure. + */ +int drmAgpUnbind(int fd, unsigned long handle) +{ + drm_agp_binding_t b; + + b.handle = handle; + b.offset = 0; + if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno; + return 0; +} + + +/** + * Get AGP driver major version number. + * + * \param fd file descriptor. + * + * \return major version number on success, or a negative value on failure.. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +int drmAgpVersionMajor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_major; +} + + +/** + * Get AGP driver minor version number. + * + * \param fd file descriptor. + * + * \return minor version number on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +int drmAgpVersionMinor(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno; + return i.agp_version_minor; +} + + +/** + * Get AGP mode. + * + * \param fd file descriptor. + * + * \return mode on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpGetMode(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.mode; +} + + +/** + * Get AGP aperture base. + * + * \param fd file descriptor. + * + * \return aperture base on success, zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpBase(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_base; +} + + +/** + * Get AGP aperture size. + * + * \param fd file descriptor. + * + * \return aperture size on success, zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpSize(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.aperture_size; +} + + +/** + * Get used AGP memory. + * + * \param fd file descriptor. + * + * \return memory used on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpMemoryUsed(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_used; +} + + +/** + * Get available AGP memory. + * + * \param fd file descriptor. + * + * \return memory available on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned long drmAgpMemoryAvail(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.memory_allowed; +} + + +/** + * Get hardware vendor ID. + * + * \param fd file descriptor. + * + * \return vendor ID on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned int drmAgpVendorId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_vendor; +} + + +/** + * Get hardware device ID. + * + * \param fd file descriptor. + * + * \return zero on success, or zero on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the + * necessary information in a drm_agp_info structure. + */ +unsigned int drmAgpDeviceId(int fd) +{ + drm_agp_info_t i; + + if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0; + return i.id_device; +} + +int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle) +{ + drm_scatter_gather_t sg; + + *handle = 0; + sg.size = size; + sg.handle = 0; + if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno; + *handle = sg.handle; + return 0; +} + +int drmScatterGatherFree(int fd, unsigned long handle) +{ + drm_scatter_gather_t sg; + + sg.size = 0; + sg.handle = handle; + if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno; + return 0; +} + +/** + * Wait for VBLANK. + * + * \param fd file descriptor. + * \param vbl pointer to a drmVBlank structure. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl. + */ +int drmWaitVBlank(int fd, drmVBlankPtr vbl) +{ + int ret; + + do { + ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); + vbl->request.type &= ~DRM_VBLANK_RELATIVE; + } while (ret && errno == EINTR); + + return ret; +} + +int drmError(int err, const char *label) +{ + switch (err) { + case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break; + case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break; + case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break; + case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break; + default: + if (err < 0) err = -err; + fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) ); + break; + } + + return 1; +} + +/** + * Install IRQ handler. + * + * \param fd file descriptor. + * \param irq IRQ number. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the + * argument in a drm_control structure. + */ +int drmCtlInstHandler(int fd, int irq) +{ + drm_control_t ctl; + + ctl.func = DRM_INST_HANDLER; + ctl.irq = irq; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + + +/** + * Uninstall IRQ handler. + * + * \param fd file descriptor. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the + * argument in a drm_control structure. + */ +int drmCtlUninstHandler(int fd) +{ + drm_control_t ctl; + + ctl.func = DRM_UNINST_HANDLER; + ctl.irq = 0; + if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno; + return 0; +} + +int drmFinish(int fd, int context, drmLockFlags flags) +{ + drm_lock_t lock; + + lock.context = context; + lock.flags = 0; + if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY; + if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT; + if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH; + if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL; + if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES; + if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES; + if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno; + return 0; +} + +/** + * Get IRQ from bus ID. + * + * \param fd file descriptor. + * \param busnum bus number. + * \param devnum device number. + * \param funcnum function number. + * + * \return IRQ number on success, or a negative value on failure. + * + * \internal + * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the + * arguments in a drm_irq_busid structure. + */ +int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum) +{ + drm_irq_busid_t p; + + p.busnum = busnum; + p.devnum = devnum; + p.funcnum = funcnum; + if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno; + return p.irq; +} + +int drmAddContextTag(int fd, drm_context_t context, void *tag) +{ + drmHashEntry *entry = drmGetEntry(fd); + + if (drmHashInsert(entry->tagTable, context, tag)) { + drmHashDelete(entry->tagTable, context); + drmHashInsert(entry->tagTable, context, tag); + } + return 0; +} + +int drmDelContextTag(int fd, drm_context_t context) +{ + drmHashEntry *entry = drmGetEntry(fd); + + return drmHashDelete(entry->tagTable, context); +} + +void *drmGetContextTag(int fd, drm_context_t context) +{ + drmHashEntry *entry = drmGetEntry(fd); + void *value; + + if (drmHashLookup(entry->tagTable, context, &value)) return NULL; + + return value; +} + +int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t handle) +{ + drm_ctx_priv_map_t map; + + map.ctx_id = ctx_id; + map.handle = (void *)handle; + + if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno; + return 0; +} + +int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t * handle) +{ + drm_ctx_priv_map_t map; + + map.ctx_id = ctx_id; + + if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno; + if (handle) *handle = (drm_handle_t)map.handle; + + return 0; +} + +int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size, + drmMapType *type, drmMapFlags *flags, drm_handle_t *handle, + int *mtrr) +{ + drm_map_t map; + + map.offset = idx; + if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno; + *offset = map.offset; + *size = map.size; + *type = map.type; + *flags = map.flags; + *handle = (unsigned long)map.handle; + *mtrr = map.mtrr; + return 0; +} + +int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid, + unsigned long *magic, unsigned long *iocs) +{ + drm_client_t client; + + client.idx = idx; + if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno; + *auth = client.auth; + *pid = client.pid; + *uid = client.uid; + *magic = client.magic; + *iocs = client.iocs; + return 0; +} + +int drmGetStats(int fd, drmStatsT *stats) +{ + drm_stats_t s; + int i; + + if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno; + + stats->count = 0; + memset(stats, 0, sizeof(*stats)); + if (s.count > sizeof(stats->data)/sizeof(stats->data[0])) + return -1; + +#define SET_VALUE \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%8.8s"; \ + stats->data[i].isvalue = 1; \ + stats->data[i].verbose = 0 + +#define SET_COUNT \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%5.5s"; \ + stats->data[i].isvalue = 0; \ + stats->data[i].mult_names = "kgm"; \ + stats->data[i].mult = 1000; \ + stats->data[i].verbose = 0 + +#define SET_BYTE \ + stats->data[i].long_format = "%-20.20s"; \ + stats->data[i].rate_format = "%5.5s"; \ + stats->data[i].isvalue = 0; \ + stats->data[i].mult_names = "KGM"; \ + stats->data[i].mult = 1024; \ + stats->data[i].verbose = 0 + + + stats->count = s.count; + for (i = 0; i < s.count; i++) { + stats->data[i].value = s.data[i].value; + switch (s.data[i].type) { + case _DRM_STAT_LOCK: + stats->data[i].long_name = "Lock"; + stats->data[i].rate_name = "Lock"; + SET_VALUE; + break; + case _DRM_STAT_OPENS: + stats->data[i].long_name = "Opens"; + stats->data[i].rate_name = "O"; + SET_COUNT; + stats->data[i].verbose = 1; + break; + case _DRM_STAT_CLOSES: + stats->data[i].long_name = "Closes"; + stats->data[i].rate_name = "Lock"; + SET_COUNT; + stats->data[i].verbose = 1; + break; + case _DRM_STAT_IOCTLS: + stats->data[i].long_name = "Ioctls"; + stats->data[i].rate_name = "Ioc/s"; + SET_COUNT; + break; + case _DRM_STAT_LOCKS: + stats->data[i].long_name = "Locks"; + stats->data[i].rate_name = "Lck/s"; + SET_COUNT; + break; + case _DRM_STAT_UNLOCKS: + stats->data[i].long_name = "Unlocks"; + stats->data[i].rate_name = "Unl/s"; + SET_COUNT; + break; + case _DRM_STAT_IRQ: + stats->data[i].long_name = "IRQs"; + stats->data[i].rate_name = "IRQ/s"; + SET_COUNT; + break; + case _DRM_STAT_PRIMARY: + stats->data[i].long_name = "Primary Bytes"; + stats->data[i].rate_name = "PB/s"; + SET_BYTE; + break; + case _DRM_STAT_SECONDARY: + stats->data[i].long_name = "Secondary Bytes"; + stats->data[i].rate_name = "SB/s"; + SET_BYTE; + break; + case _DRM_STAT_DMA: + stats->data[i].long_name = "DMA"; + stats->data[i].rate_name = "DMA/s"; + SET_COUNT; + break; + case _DRM_STAT_SPECIAL: + stats->data[i].long_name = "Special DMA"; + stats->data[i].rate_name = "dma/s"; + SET_COUNT; + break; + case _DRM_STAT_MISSED: + stats->data[i].long_name = "Miss"; + stats->data[i].rate_name = "Ms/s"; + SET_COUNT; + break; + case _DRM_STAT_VALUE: + stats->data[i].long_name = "Value"; + stats->data[i].rate_name = "Value"; + SET_VALUE; + break; + case _DRM_STAT_BYTE: + stats->data[i].long_name = "Bytes"; + stats->data[i].rate_name = "B/s"; + SET_BYTE; + break; + case _DRM_STAT_COUNT: + default: + stats->data[i].long_name = "Count"; + stats->data[i].rate_name = "Cnt/s"; + SET_COUNT; + break; + } + } + return 0; +} + +/** + * Issue a set-version ioctl. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be read and written. + * \param size size of the data to be read and written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read-write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmSetInterfaceVersion(int fd, drmSetVersion *version ) +{ + int retcode = 0; + drm_set_version_t sv; + + sv.drm_di_major = version->drm_di_major; + sv.drm_di_minor = version->drm_di_minor; + sv.drm_dd_major = version->drm_dd_major; + sv.drm_dd_minor = version->drm_dd_minor; + + if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { + retcode = -errno; + } + + version->drm_di_major = sv.drm_di_major; + version->drm_di_minor = sv.drm_di_minor; + version->drm_dd_major = sv.drm_dd_major; + version->drm_dd_minor = sv.drm_dd_minor; + + return retcode; +} + +/** + * Send a device-specific command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandNone(int fd, unsigned long drmCommandIndex) +{ + void *data = NULL; /* dummy */ + unsigned long request; + + request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific read command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data destination pointer of the data to be read. + * \param size size of the data to be read. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific write command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be written. + * \param size size of the data to be written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandWrite(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + + +/** + * Send a device-specific read-write command. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be read and written. + * \param size size of the data to be read and written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read-write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, + void *data, unsigned long size ) +{ + unsigned long request; + + request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, + DRM_COMMAND_BASE + drmCommandIndex, size); + + if (ioctl(fd, request, data)) { + return -errno; + } + return 0; +} + +#if defined(XFree86Server) +static void drmSIGIOHandler(int interrupt, void *closure) +{ + unsigned long key; + void *value; + ssize_t count; + drm_ctx_t ctx; + typedef void (*_drmCallback)(int, void *, void *); + char buf[256]; + drm_context_t old; + drm_context_t new; + void *oldctx; + void *newctx; + char *pt; + drmHashEntry *entry; + + if (!drmHashTable) return; + if (drmHashFirst(drmHashTable, &key, &value)) { + entry = value; + do { +#if 0 + fprintf(stderr, "Trying %d\n", entry->fd); +#endif + if ((count = read(entry->fd, buf, sizeof(buf))) > 0) { + buf[count] = '\0'; +#if 0 + fprintf(stderr, "Got %s\n", buf); +#endif + + for (pt = buf; *pt != ' '; ++pt); /* Find first space */ + ++pt; + old = strtol(pt, &pt, 0); + new = strtol(pt, NULL, 0); + oldctx = drmGetContextTag(entry->fd, old); + newctx = drmGetContextTag(entry->fd, new); +#if 0 + fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); +#endif + ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); + ctx.handle = new; + ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); + } + } while (drmHashNext(drmHashTable, &key, &value)); + } +} + +int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) +{ + drmHashEntry *entry; + + entry = drmGetEntry(fd); + entry->f = f; + + return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); +} + +int drmRemoveSIGIOHandler(int fd) +{ + drmHashEntry *entry = drmGetEntry(fd); + + entry->f = NULL; + + return xf86RemoveSIGIOHandler(fd); +} +#endif diff --git a/src/mesa/drivers/dri/dri_client/xf86drmHash.c b/src/mesa/drivers/dri/dri_client/xf86drmHash.c new file mode 100644 index 00000000000..5f89d540dc2 --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/xf86drmHash.c @@ -0,0 +1,433 @@ +/* xf86drmHash.c -- Small hash table support for integer -> integer mapping + * Created: Sun Apr 18 09:35:45 1999 by [email protected] + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <[email protected]> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.4 2001/03/21 18:08:54 dawes Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward implementation of a fixed-sized + * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for + * collision resolution. There are two potentially interesting things + * about this implementation: + * + * 1) The table is power-of-two sized. Prime sized tables are more + * traditional, but do not have a significant advantage over power-of-two + * sized table, especially when double hashing is not used for collision + * resolution. + * + * 2) The hash computation uses a table of random integers [Hanson97, + * pp. 39-41]. + * + * FUTURE ENHANCEMENTS + * + * With a table size of 512, the current implementation is sufficient for a + * few hundred keys. Since this is well above the expected size of the + * tables for which this implementation was designed, the implementation of + * dynamic hash tables was postponed until the need arises. A common (and + * naive) approach to dynamic hash table implementation simply creates a + * new hash table when necessary, rehashes all the data into the new table, + * and destroys the old table. The approach in [Larson88] is superior in + * two ways: 1) only a portion of the table is expanded when needed, + * distributing the expansion cost over several insertions, and 2) portions + * of the table can be locked, enabling a scalable thread-safe + * implementation. + * + * REFERENCES + * + * [Hanson97] David R. Hanson. C Interfaces and Implementations: + * Techniques for Creating Reusable Software. Reading, Massachusetts: + * Addison-Wesley, 1997. + * + * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3: + * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973. + * + * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April + * 1988, pp. 446-457. + * + */ + +#define HASH_MAIN 0 + +#if HASH_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define HASH_MAGIC 0xdeadbeef +#define HASH_DEBUG 0 +#define HASH_SIZE 512 /* Good for about 100 entries */ + /* If you change this value, you probably + have to change the HashHash hashing + function! */ + +#if HASH_MAIN +#define HASH_ALLOC malloc +#define HASH_FREE free +#define HASH_RANDOM_DECL +#define HASH_RANDOM_INIT(seed) srandom(seed) +#define HASH_RANDOM random() +#else +#define HASH_ALLOC drmMalloc +#define HASH_FREE drmFree +#define HASH_RANDOM_DECL void *state +#define HASH_RANDOM_INIT(seed) state = drmRandomCreate(seed) +#define HASH_RANDOM drmRandom(state) + +#endif + +typedef struct HashBucket { + unsigned long key; + void *value; + struct HashBucket *next; +} HashBucket, *HashBucketPtr; + +typedef struct HashTable { + unsigned long magic; + unsigned long entries; + unsigned long hits; /* At top of linked list */ + unsigned long partials; /* Not at top of linked list */ + unsigned long misses; /* Not in table */ + HashBucketPtr buckets[HASH_SIZE]; + int p0; + HashBucketPtr p1; +} HashTable, *HashTablePtr; + +#if HASH_MAIN +extern void *drmHashCreate(void); +extern int drmHashDestroy(void *t); +extern int drmHashLookup(void *t, unsigned long key, unsigned long *value); +extern int drmHashInsert(void *t, unsigned long key, unsigned long value); +extern int drmHashDelete(void *t, unsigned long key); +#endif + +static unsigned long HashHash(unsigned long key) +{ + unsigned long hash = 0; + unsigned long tmp = key; + static int init = 0; + static unsigned long scatter[256]; + int i; + + if (!init) { + HASH_RANDOM_DECL; + HASH_RANDOM_INIT(37); + for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM; + ++init; + } + + while (tmp) { + hash = (hash << 1) + scatter[tmp & 0xff]; + tmp >>= 8; + } + + hash %= HASH_SIZE; +#if HASH_DEBUG + printf( "Hash(%d) = %d\n", key, hash); +#endif + return hash; +} + +void *drmHashCreate(void) +{ + HashTablePtr table; + int i; + + table = HASH_ALLOC(sizeof(*table)); + if (!table) return NULL; + table->magic = HASH_MAGIC; + table->entries = 0; + table->hits = 0; + table->partials = 0; + table->misses = 0; + + for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL; + return table; +} + +int drmHashDestroy(void *t) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + HashBucketPtr next; + int i; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + for (i = 0; i < HASH_SIZE; i++) { + for (bucket = table->buckets[i]; bucket;) { + next = bucket->next; + HASH_FREE(bucket); + bucket = next; + } + } + HASH_FREE(table); + return 0; +} + +/* Find the bucket and organize the list so that this bucket is at the + top. */ + +static HashBucketPtr HashFind(HashTablePtr table, + unsigned long key, unsigned long *h) +{ + unsigned long hash = HashHash(key); + HashBucketPtr prev = NULL; + HashBucketPtr bucket; + + if (h) *h = hash; + + for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) { + if (bucket->key == key) { + if (prev) { + /* Organize */ + prev->next = bucket->next; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; + ++table->partials; + } else { + ++table->hits; + } + return bucket; + } + prev = bucket; + } + ++table->misses; + return NULL; +} + +int drmHashLookup(void *t, unsigned long key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + + if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, NULL); + if (!bucket) return 1; /* Not found */ + *value = bucket->value; + return 0; /* Found */ +} + +int drmHashInsert(void *t, unsigned long key, void *value) +{ + HashTablePtr table = (HashTablePtr)t; + HashBucketPtr bucket; + unsigned long hash; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + if (HashFind(table, key, &hash)) return 1; /* Already in table */ + + bucket = HASH_ALLOC(sizeof(*bucket)); + if (!bucket) return -1; /* Error */ + bucket->key = key; + bucket->value = value; + bucket->next = table->buckets[hash]; + table->buckets[hash] = bucket; +#if HASH_DEBUG + printf("Inserted %d at %d/%p\n", key, hash, bucket); +#endif + return 0; /* Added to table */ +} + +int drmHashDelete(void *t, unsigned long key) +{ + HashTablePtr table = (HashTablePtr)t; + unsigned long hash; + HashBucketPtr bucket; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + bucket = HashFind(table, key, &hash); + + if (!bucket) return 1; /* Not found */ + + table->buckets[hash] = bucket->next; + HASH_FREE(bucket); + return 0; +} + +int drmHashNext(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + for (; table->p0 < HASH_SIZE; + ++table->p0, table->p1 = table->buckets[table->p0]) { + if (table->p1) { + *key = table->p1->key; + *value = table->p1->value; + table->p1 = table->p1->next; + return 1; + } + } + return 0; +} + +int drmHashFirst(void *t, unsigned long *key, void **value) +{ + HashTablePtr table = (HashTablePtr)t; + + if (table->magic != HASH_MAGIC) return -1; /* Bad magic */ + + table->p0 = 0; + table->p1 = table->buckets[0]; + return drmHashNext(table, key, value); +} + +#if HASH_MAIN +#define DIST_LIMIT 10 +static int dist[DIST_LIMIT]; + +static void clear_dist(void) { + int i; + + for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0; +} + +static int count_entries(HashBucketPtr bucket) +{ + int count = 0; + + for (; bucket; bucket = bucket->next) ++count; + return count; +} + +static void update_dist(int count) +{ + if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1]; + else ++dist[count]; +} + +static void compute_dist(HashTablePtr table) +{ + int i; + HashBucketPtr bucket; + + printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n", + table->entries, table->hits, table->partials, table->misses); + clear_dist(); + for (i = 0; i < HASH_SIZE; i++) { + bucket = table->buckets[i]; + update_dist(count_entries(bucket)); + } + for (i = 0; i < DIST_LIMIT; i++) { + if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]); + else printf("other %10d\n", dist[i]); + } +} + +static void check_table(HashTablePtr table, + unsigned long key, unsigned long value) +{ + unsigned long retval = 0; + int retcode = drmHashLookup(table, key, &retval); + + switch (retcode) { + case -1: + printf("Bad magic = 0x%08lx:" + " key = %lu, expected = %lu, returned = %lu\n", + table->magic, key, value, retval); + break; + case 1: + printf("Not found: key = %lu, expected = %lu returned = %lu\n", + key, value, retval); + break; + case 0: + if (value != retval) + printf("Bad value: key = %lu, expected = %lu, returned = %lu\n", + key, value, retval); + break; + default: + printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n", + retcode, key, value, retval); + break; + } +} + +int main(void) +{ + HashTablePtr table; + int i; + + printf("\n***** 256 consecutive integers ****\n"); + table = drmHashCreate(); + for (i = 0; i < 256; i++) drmHashInsert(table, i, i); + for (i = 0; i < 256; i++) check_table(table, i, i); + for (i = 256; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + drmHashDestroy(table); + + printf("\n***** 1024 consecutive integers ****\n"); + table = drmHashCreate(); + for (i = 0; i < 1024; i++) drmHashInsert(table, i, i); + for (i = 0; i < 1024; i++) check_table(table, i, i); + for (i = 1024; i >= 0; i--) check_table(table, i, i); + compute_dist(table); + drmHashDestroy(table); + + printf("\n***** 1024 consecutive page addresses (4k pages) ****\n"); + table = drmHashCreate(); + for (i = 0; i < 1024; i++) drmHashInsert(table, i*4096, i); + for (i = 0; i < 1024; i++) check_table(table, i*4096, i); + for (i = 1024; i >= 0; i--) check_table(table, i*4096, i); + compute_dist(table); + drmHashDestroy(table); + + printf("\n***** 1024 random integers ****\n"); + table = drmHashCreate(); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) drmHashInsert(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 1024; i++) check_table(table, random(), i); + compute_dist(table); + drmHashDestroy(table); + + printf("\n***** 5000 random integers ****\n"); + table = drmHashCreate(); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) drmHashInsert(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + srandom(0xbeefbeef); + for (i = 0; i < 5000; i++) check_table(table, random(), i); + compute_dist(table); + drmHashDestroy(table); + + return 0; +} +#endif diff --git a/src/mesa/drivers/dri/dri_client/xf86drmRandom.c b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c new file mode 100644 index 00000000000..cca831d7517 --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c @@ -0,0 +1,217 @@ +/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation + * Created: Mon Apr 19 08:28:13 1999 by [email protected] + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <[email protected]> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.4 2000/06/17 00:03:34 martin Exp $ + * + * DESCRIPTION + * + * This file contains a simple, straightforward implementation of the Park + * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer + * multiplicative linear congruential generator (MLCG) with a period of + * 2^31-1. + * + * This implementation is intended to provide a reliable, portable PRNG + * that is suitable for testing a hash table implementation and for + * implementing skip lists. + * + * FUTURE ENHANCEMENTS + * + * If initial seeds are not selected randomly, two instances of the PRNG + * can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique + * that can eliminate this problem. + * + * If PRNGs are used for simulation, the period of the current + * implementation may be too short. [LE88] discusses methods of combining + * MLCGs to produce much longer periods, and suggests some alternative + * values for A and M. [LE90 and Sch92] also provide information on + * long-period PRNGs. + * + * REFERENCES + * + * [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2: + * Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981. + * + * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number + * Generators". CACM 31(6), June 1988, pp. 742-774. + * + * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10, + * October 1990, pp. 85-97. + * + * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators: + * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201. + * + * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit + * CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40. + * + * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In + * "Technical Correspondence: Remarks on Choosing and Implementing Random + * Number Generators". CACM 36(7), July 1993, pp. 105-110. + * + */ + +#define RANDOM_MAIN 0 + +#if RANDOM_MAIN +# include <stdio.h> +# include <stdlib.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define RANDOM_MAGIC 0xfeedbeef +#define RANDOM_DEBUG 0 + +#if RANDOM_MAIN +#define RANDOM_ALLOC malloc +#define RANDOM_FREE free +#else +#define RANDOM_ALLOC drmMalloc +#define RANDOM_FREE drmFree +#endif + +typedef struct RandomState { + unsigned long magic; + unsigned long a; + unsigned long m; + unsigned long q; /* m div a */ + unsigned long r; /* m mod a */ + unsigned long check; + long seed; +} RandomState; + +#if RANDOM_MAIN +extern void *drmRandomCreate(unsigned long seed); +extern int drmRandomDestroy(void *state); +extern unsigned long drmRandom(void *state); +extern double drmRandomDouble(void *state); +#endif + +void *drmRandomCreate(unsigned long seed) +{ + RandomState *state; + + state = RANDOM_ALLOC(sizeof(*state)); + if (!state) return NULL; + state->magic = RANDOM_MAGIC; +#if 0 + /* Park & Miller, October 1988 */ + state->a = 16807; + state->m = 2147483647; + state->check = 1043618065; /* After 10000 iterations */ +#else + /* Park, Miller, and Stockmeyer, July 1993 */ + state->a = 48271; + state->m = 2147483647; + state->check = 399268537; /* After 10000 iterations */ +#endif + state->q = state->m / state->a; + state->r = state->m % state->a; + + state->seed = seed; + /* Check for illegal boundary conditions, + and choose closest legal value. */ + if (state->seed <= 0) state->seed = 1; + if (state->seed >= state->m) state->seed = state->m - 1; + + return state; +} + +int drmRandomDestroy(void *state) +{ + RANDOM_FREE(state); + return 0; +} + +unsigned long drmRandom(void *state) +{ + RandomState *s = (RandomState *)state; + long hi; + long lo; + + hi = s->seed / s->q; + lo = s->seed % s->q; + s->seed = s->a * lo - s->r * hi; + if (s->seed <= 0) s->seed += s->m; + + return s->seed; +} + +double drmRandomDouble(void *state) +{ + RandomState *s = (RandomState *)state; + + return (double)drmRandom(state)/(double)s->m; +} + +#if RANDOM_MAIN +static void check_period(long seed) +{ + unsigned long count = 0; + unsigned long initial; + void *state; + + state = drmRandomCreate(seed); + initial = drmRandom(state); + ++count; + while (initial != drmRandom(state)) { + if (!++count) break; + } + printf("With seed of %10ld, period = %10lu (0x%08lx)\n", + seed, count, count); + drmRandomDestroy(state); +} + +int main(void) +{ + RandomState *state; + int i; + unsigned long rand; + + state = drmRandomCreate(1); + for (i = 0; i < 10000; i++) { + rand = drmRandom(state); + } + printf("After 10000 iterations: %lu (%lu expected): %s\n", + rand, state->check, + rand - state->check ? "*INCORRECT*" : "CORRECT"); + drmRandomDestroy(state); + + printf("Checking periods...\n"); + check_period(1); + check_period(2); + check_period(31415926); + + return 0; +} +#endif diff --git a/src/mesa/drivers/dri/dri_client/xf86drmSL.c b/src/mesa/drivers/dri/dri_client/xf86drmSL.c new file mode 100644 index 00000000000..a9d64c920f0 --- /dev/null +++ b/src/mesa/drivers/dri/dri_client/xf86drmSL.c @@ -0,0 +1,488 @@ +/* xf86drmSL.c -- Skip list support + * Created: Mon May 10 09:28:13 1999 by [email protected] + * + * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <[email protected]> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.3 2000/06/17 00:03:34 martin Exp $ + * + * DESCRIPTION + * + * This file contains a straightforward skip list implementation.n + * + * FUTURE ENHANCEMENTS + * + * REFERENCES + * + * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to + * Balanced Trees. CACM 33(6), June 1990, pp. 668-676. + * + */ + +#define SL_MAIN 0 + +#if SL_MAIN +# include <stdio.h> +# include <stdlib.h> +# include <sys/time.h> +#else +# include "xf86drm.h" +# ifdef XFree86LOADER +# include "xf86.h" +# include "xf86_ansic.h" +# else +# include <stdio.h> +# include <stdlib.h> +# endif +#endif + +#define SL_LIST_MAGIC 0xfacade00LU +#define SL_ENTRY_MAGIC 0x00fab1edLU +#define SL_FREED_MAGIC 0xdecea5edLU +#define SL_MAX_LEVEL 16 +#define SL_DEBUG 0 +#define SL_RANDOM_SEED 0xc01055a1LU + +#if SL_MAIN +#define SL_ALLOC malloc +#define SL_FREE free +#define SL_RANDOM_DECL static int state = 0; +#define SL_RANDOM_INIT(seed) if (!state) { srandom(seed); ++state; } +#define SL_RANDOM random() +#else +#define SL_ALLOC drmMalloc +#define SL_FREE drmFree +#define SL_RANDOM_DECL static void *state = NULL +#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed) +#define SL_RANDOM drmRandom(state) + +#endif + +typedef struct SLEntry { + unsigned long magic; /* SL_ENTRY_MAGIC */ + unsigned long key; + void *value; + int levels; + struct SLEntry *forward[1]; /* variable sized array */ +} SLEntry, *SLEntryPtr; + +typedef struct SkipList { + unsigned long magic; /* SL_LIST_MAGIC */ + int level; + int count; + SLEntryPtr head; + SLEntryPtr p0; /* Position for iteration */ +} SkipList, *SkipListPtr; + +#if SL_MAIN +extern void *drmSLCreate(void); +extern int drmSLDestroy(void *l); +extern int drmSLLookup(void *l, unsigned long key, void **value); +extern int drmSLInsert(void *l, unsigned long key, void *value); +extern int drmSLDelete(void *l, unsigned long key); +extern int drmSLNext(void *l, unsigned long *key, void **value); +extern int drmSLFirst(void *l, unsigned long *key, void **value); +extern void drmSLDump(void *l); +extern int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value); +#endif + +static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value) +{ + SLEntryPtr entry; + + if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL; + + entry = SL_ALLOC(sizeof(*entry) + + (max_level + 1) * sizeof(entry->forward[0])); + if (!entry) return NULL; + entry->magic = SL_ENTRY_MAGIC; + entry->key = key; + entry->value = value; + entry->levels = max_level + 1; + + return entry; +} + +static int SLRandomLevel(void) +{ + int level = 1; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(SL_RANDOM_SEED); + + while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level; + return level; +} + +void *drmSLCreate(void) +{ + SkipListPtr list; + int i; + + list = SL_ALLOC(sizeof(*list)); + if (!list) return NULL; + list->magic = SL_LIST_MAGIC; + list->level = 0; + list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL); + list->count = 0; + + for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL; + + return list; +} + +int drmSLDestroy(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr next; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + for (entry = list->head; entry; entry = next) { + if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */ + next = entry->forward[0]; + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + } + + list->magic = SL_FREED_MAGIC; + SL_FREE(list); + return 0; +} + +static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return NULL; + + for (i = list->level, entry = list->head; i >= 0; i--) { + while (entry->forward[i] && entry->forward[i]->key < key) + entry = entry->forward[i]; + update[i] = entry; + } + + return entry->forward[0]; +} + +int drmSLInsert(void *l, unsigned long key, void *value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + int level; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) return 1; /* Already in list */ + + + level = SLRandomLevel(); + if (level > list->level) { + level = ++list->level; + update[level] = list->head; + } + + entry = SLCreateEntry(level, key, value); + + /* Fix up forward pointers */ + for (i = 0; i <= level; i++) { + entry->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = entry; + } + + ++list->count; + return 0; /* Added to table */ +} + +int drmSLDelete(void *l, unsigned long key) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = SLLocate(list, key, update); + + if (!entry || entry->key != key) return 1; /* Not found */ + + /* Fix up forward pointers */ + for (i = 0; i <= list->level; i++) { + if (update[i]->forward[i] == entry) + update[i]->forward[i] = entry->forward[i]; + } + + entry->magic = SL_FREED_MAGIC; + SL_FREE(entry); + + while (list->level && !list->head->forward[list->level]) --list->level; + --list->count; + return 0; +} + +int drmSLLookup(void *l, unsigned long key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + + entry = SLLocate(list, key, update); + + if (entry && entry->key == key) { + *value = entry; + return 0; + } + *value = NULL; + return -1; +} + +int drmSLLookupNeighbors(void *l, unsigned long key, + unsigned long *prev_key, void **prev_value, + unsigned long *next_key, void **next_value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr update[SL_MAX_LEVEL + 1]; + SLEntryPtr entry; + int retcode = 0; + + entry = SLLocate(list, key, update); + + *prev_key = *next_key = key; + *prev_value = *next_value = NULL; + + if (update[0]) { + *prev_key = update[0]->key; + *prev_value = update[0]->value; + ++retcode; + if (update[0]->forward[0]) { + *next_key = update[0]->forward[0]->key; + *next_value = update[0]->forward[0]->value; + ++retcode; + } + } + return retcode; +} + +int drmSLNext(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + entry = list->p0; + + if (entry) { + list->p0 = entry->forward[0]; + *key = entry->key; + *value = entry->value; + return 1; + } + list->p0 = NULL; + return 0; +} + +int drmSLFirst(void *l, unsigned long *key, void **value) +{ + SkipListPtr list = (SkipListPtr)l; + + if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ + + list->p0 = list->head->forward[0]; + return drmSLNext(list, key, value); +} + +/* Dump internal data structures for debugging. */ +void drmSLDump(void *l) +{ + SkipListPtr list = (SkipListPtr)l; + SLEntryPtr entry; + int i; + + if (list->magic != SL_LIST_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_LIST_MAGIC); + return; + } + + printf("Level = %d, count = %d\n", list->level, list->count); + for (entry = list->head; entry; entry = entry->forward[0]) { + if (entry->magic != SL_ENTRY_MAGIC) { + printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", + list->magic, SL_ENTRY_MAGIC); + } + printf("\nEntry %p <0x%08lx, %p> has %2d levels\n", + entry, entry->key, entry->value, entry->levels); + for (i = 0; i < entry->levels; i++) { + if (entry->forward[i]) { + printf(" %2d: %p <0x%08lx, %p>\n", + i, + entry->forward[i], + entry->forward[i]->key, + entry->forward[i]->value); + } else { + printf(" %2d: %p\n", i, entry->forward[i]); + } + } + } +} + +#if SL_MAIN +static void print(SkipListPtr list) +{ + unsigned long key; + void *value; + + if (drmSLFirst(list, &key, &value)) { + do { + printf("key = %5lu, value = %p\n", key, value); + } while (drmSLNext(list, &key, &value)); + } +} + +static double do_time(int size, int iter) +{ + SkipListPtr list; + int i, j; + unsigned long keys[1000000]; + unsigned long previous; + unsigned long key; + void *value; + struct timeval start, stop; + double usec; + SL_RANDOM_DECL; + + SL_RANDOM_INIT(12345); + + list = drmSLCreate(); + + for (i = 0; i < size; i++) { + keys[i] = SL_RANDOM; + drmSLInsert(list, keys[i], NULL); + } + + previous = 0; + if (drmSLFirst(list, &key, &value)) { + do { + if (key <= previous) { + printf( "%lu !< %lu\n", previous, key); + } + previous = key; + } while (drmSLNext(list, &key, &value)); + } + + gettimeofday(&start, NULL); + for (j = 0; j < iter; j++) { + for (i = 0; i < size; i++) { + if (drmSLLookup(list, keys[i], &value)) + printf("Error %lu %d\n", keys[i], i); + } + } + gettimeofday(&stop, NULL); + + usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec + - start.tv_sec * 1000000 - start.tv_usec) / (size * iter); + + printf("%0.2f microseconds for list length %d\n", usec, size); + + drmSLDestroy(list); + + return usec; +} + +static void print_neighbors(void *list, unsigned long key) +{ + unsigned long prev_key = 0; + unsigned long next_key = 0; + void *prev_value; + void *next_value; + int retval; + + retval = drmSLLookupNeighbors(list, key, + &prev_key, &prev_value, + &next_key, &next_value); + printf("Neighbors of %5lu: %d %5lu %5lu\n", + key, retval, prev_key, next_key); +} + +int main(void) +{ + SkipListPtr list; + double usec, usec2, usec3, usec4; + + list = drmSLCreate(); + printf( "list at %p\n", list); + + print(list); + printf("\n==============================\n\n"); + + drmSLInsert(list, 123, NULL); + drmSLInsert(list, 213, NULL); + drmSLInsert(list, 50, NULL); + print(list); + printf("\n==============================\n\n"); + + print_neighbors(list, 0); + print_neighbors(list, 50); + print_neighbors(list, 51); + print_neighbors(list, 123); + print_neighbors(list, 200); + print_neighbors(list, 213); + print_neighbors(list, 256); + printf("\n==============================\n\n"); + + drmSLDelete(list, 50); + print(list); + printf("\n==============================\n\n"); + + drmSLDump(list); + drmSLDestroy(list); + printf("\n==============================\n\n"); + + usec = do_time(100, 10000); + usec2 = do_time(1000, 500); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 1000.0/100.0, usec2 / usec); + + usec3 = do_time(10000, 50); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 10000.0/100.0, usec3 / usec); + + usec4 = do_time(100000, 4); + printf("Table size increased by %0.2f, search time increased by %0.2f\n", + 100000.0/100.0, usec4 / usec); + + return 0; +} +#endif diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c index d6a61d98e52..9c1b770fbd1 100644 --- a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c +++ b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c @@ -341,7 +341,8 @@ void ffbInitTnlModule(GLcontext *ctx) ffb_init_norm_funcs(); ffb_init_vert_funcs(); - MEMSET(vfmt, 0, sizeof(GLvertexformat)); + /* start by initializing to no-op functions */ + _mesa_noop_vtxfmt_init(vfmt); /* Handled fully in supported states: */ vfmt->ArrayElement = NULL; /* FIXME: ... */ @@ -389,18 +390,8 @@ void ffbInitTnlModule(GLcontext *ctx) vfmt->Begin = ffb_Begin; vfmt->End = ffb_End; - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ - vfmt->DrawArrays = NULL; vfmt->DrawElements = NULL; - vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */ - - - /* Not active in supported states; just keep ctx->Current uptodate: */ - vfmt->EdgeFlag = _mesa_noop_EdgeFlag; - vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; - vfmt->Indexi = _mesa_noop_Indexi; - vfmt->Indexiv = _mesa_noop_Indexiv; /* Active but unsupported -- fallback if we receive these: * diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c index a622051eddf..23373ef73b1 100644 --- a/src/mesa/drivers/dri/i810/i810context.c +++ b/src/mesa/drivers/dri/i810/i810context.c @@ -133,6 +133,7 @@ const struct dri_extension card_extensions[] = { "GL_EXT_texture_edge_clamp", NULL }, { "GL_EXT_texture_env_combine", NULL }, { "GL_EXT_texture_lod_bias", NULL }, + { "GL_EXT_texture_rectangle", NULL }, { "GL_MESA_ycbcr_texture", NULL }, { "GL_NV_blend_square", NULL }, { "GL_SGIS_generate_mipmap", NULL }, diff --git a/src/mesa/drivers/dri/i810/i810state.c b/src/mesa/drivers/dri/i810/i810state.c index a79c3a3e4df..680b818d286 100644 --- a/src/mesa/drivers/dri/i810/i810state.c +++ b/src/mesa/drivers/dri/i810/i810state.c @@ -597,6 +597,7 @@ static void i810Enable(GLcontext *ctx, GLenum cap, GLboolean state) imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE; break; case GL_TEXTURE_2D: + case GL_TEXTURE_RECTANGLE_NV: I810_STATECHANGE(imesa, I810_UPLOAD_CTX); if (ctx->Texture.CurrentUnit == 0) { imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE; diff --git a/src/mesa/drivers/dri/i810/i810texstate.c b/src/mesa/drivers/dri/i810/i810texstate.c index 5133ea44d4b..558aef9eee4 100644 --- a/src/mesa/drivers/dri/i810/i810texstate.c +++ b/src/mesa/drivers/dri/i810/i810texstate.c @@ -115,8 +115,6 @@ static void i810SetTexImages( i810ContextPtr imesa, t->max_level = i-1; t->dirty = I810_UPLOAD_TEX0 | I810_UPLOAD_TEX1; t->Setup[I810_TEXREG_MI1] = (MI1_MAP_0 | textureFormat | log_pitch); - t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 | - (log2Height << 16) | log2Width); t->Setup[I810_TEXREG_MLL] = (GFX_OP_MAP_LOD_LIMITS | MLL_MAP_0 | MLL_UPDATE_MAX_MIP | @@ -537,6 +535,92 @@ i810UpdateTexEnvCombine( GLcontext *ctx, GLuint unit, return GL_TRUE; } +static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + + if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { + return GL_FALSE; + } + + /* Upload teximages (not pipelined) + */ + if (t->base.dirty_images[0]) { + I810_FIREVERTICES(imesa); + i810SetTexImages( imesa, tObj ); + if (!t->base.memBlock) { + return GL_FALSE; + } + } + + /* Update state if this is a different texture object to last + * time. + */ + if (imesa->CurrentTexObj[unit] != t) { + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + imesa->CurrentTexObj[unit] = t; + t->base.bound |= (1U << unit); + + /* XXX: should be locked */ + driUpdateTextureLRU( (driTextureObject *) t ); + } + + imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + return GL_TRUE; +} + +static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + GLint Width, Height; + + Width = tObj->Image[0][t->base.firstLevel]->Width - 1; + Height = tObj->Image[0][t->base.firstLevel]->Height - 1; + + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + t->Setup[I810_TEXREG_MCS] &= ~MCS_NORMALIZED_COORDS; + t->Setup[I810_TEXREG_MCS] |= MCS_UPDATE_NORMALIZED; + t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_EXACT | + (Height << MI2_HEIGHT_SHIFT) | Width); + + return GL_TRUE; +} + +static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; + GLint log2Width, log2Height; + + + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; + + I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); + t->Setup[I810_TEXREG_MCS] |= MCS_NORMALIZED_COORDS | MCS_UPDATE_NORMALIZED; + t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 | + (log2Height << MI2_HEIGHT_SHIFT) | log2Width); + + return GL_TRUE; +} + +static void disable_tex( GLcontext *ctx, GLuint unit ) +{ + i810ContextPtr imesa = I810_CONTEXT(ctx); + + imesa->CurrentTexObj[unit] = 0; + imesa->TexEnvImageFmt[unit] = 0; + imesa->dirty &= ~(I810_UPLOAD_TEX0<<unit); + +} /** * Update hardware state for a texture unit. @@ -550,62 +634,32 @@ static void i810UpdateTexUnit( GLcontext *ctx, GLuint unit, { i810ContextPtr imesa = I810_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLboolean ret; + + switch(texUnit->_ReallyEnabled) { + case TEXTURE_2D_BIT: + ret = enable_tex_common( ctx, unit); + ret &= enable_tex_2d(ctx, unit); + if (ret == GL_FALSE) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + } + break; + case TEXTURE_RECT_BIT: + ret = enable_tex_common( ctx, unit); + ret &= enable_tex_rect(ctx, unit); + if (ret == GL_FALSE) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + } + break; + case 0: + disable_tex(ctx, unit); + break; + } - if ( (texUnit->_ReallyEnabled == TEXTURE_2D_BIT) - || (texUnit->_ReallyEnabled == 0) ) { - if (texUnit->_ReallyEnabled != 0) { - struct gl_texture_object *tObj = texUnit->_Current; - i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData; - - if (tObj->Image[0][tObj->BaseLevel]->Border > 0) { - FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); - return; - } - - - /* Upload teximages (not pipelined) - */ - if (t->base.dirty_images[0]) { - I810_FIREVERTICES(imesa); - i810SetTexImages( imesa, tObj ); - if (!t->base.memBlock) { - FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); - return; - } - } - - - /* Update state if this is a different texture object to last - * time. - */ - if (imesa->CurrentTexObj[unit] != t) { - I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit)); - imesa->CurrentTexObj[unit] = t; - t->base.bound |= (1U << unit); - - /* XXX: should be locked */ - driUpdateTextureLRU( (driTextureObject *) t ); - } - - /* Update texture environment if texture object image format or - * texture environment state has changed. - */ - imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; - } - else { - imesa->CurrentTexObj[unit] = 0; - imesa->TexEnvImageFmt[unit] = 0; - imesa->dirty &= ~(I810_UPLOAD_TEX0<<unit); - } - - if (!i810UpdateTexEnvCombine( ctx, unit, - next_color_stage, next_alpha_stage )) { - FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); - } - } - else if (texUnit->_ReallyEnabled) { - FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); + if (!i810UpdateTexEnvCombine( ctx, unit, + next_color_stage, next_alpha_stage )) { + FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE ); } return; diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile index 53349364d04..805abf75e08 100644 --- a/src/mesa/drivers/dri/i915/Makefile +++ b/src/mesa/drivers/dri/i915/Makefile @@ -4,6 +4,8 @@ include $(TOP)/configs/current LIBNAME = i915_dri.so +MINIGLX_SOURCES = server/intel_dri.c + DRIVER_SOURCES = \ i915_context.c \ i915_debug.c \ @@ -37,7 +39,6 @@ DRIVER_SOURCES = \ C_SOURCES = \ $(COMMON_SOURCES) \ - $(MINIGLX_SOURCES) \ $(DRIVER_SOURCES) ASM_SOURCES = diff --git a/src/mesa/drivers/dri/i915/i830_context.c b/src/mesa/drivers/dri/i915/i830_context.c index 7a251ac6e89..d16b153fac2 100644 --- a/src/mesa/drivers/dri/i915/i830_context.c +++ b/src/mesa/drivers/dri/i915/i830_context.c @@ -84,7 +84,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis, 12, I830_NR_TEX_REGIONS, intel->sarea->texList, - & intel->sarea->texAge, + (unsigned *) & intel->sarea->texAge, & intel->swapped, sizeof( struct i830_texture_object ), (destroy_texture_object_t *)intelDestroyTexObj ); diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h index 5bdcc21c5ab..d5811e6c349 100644 --- a/src/mesa/drivers/dri/i915/i830_context.h +++ b/src/mesa/drivers/dri/i915/i830_context.h @@ -118,7 +118,7 @@ struct i830_context { struct intel_context intel; - GLuint last_index; + DECLARE_RENDERINPUTS(last_index_bitset); struct i830_hw_state meta, initial, state, *current; }; diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index e8913e8063c..9e71b111091 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -65,11 +65,13 @@ static void i830_render_start( intelContextPtr intel ) i830ContextPtr i830 = I830_CONTEXT(intel); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint v0 = _3DSTATE_VFT0_CMD; GLuint v2 = _3DSTATE_VFT1_CMD; GLuint mcsb1 = 0; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + /* Important: */ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; @@ -78,7 +80,7 @@ static void i830_render_start( intelContextPtr intel ) /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW ); intel->coloroffset = 4; } @@ -87,36 +89,37 @@ static void i830_render_start( intelContextPtr intel ) intel->coloroffset = 3; } - if (index & _TNL_BIT_POINTSIZE) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) { EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH ); } EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE ); intel->specoffset = 0; - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { - if (index & _TNL_BIT_COLOR1) { - intel->specoffset = intel->coloroffset + 1; - EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC ); + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { + intel->specoffset = intel->coloroffset + 1; + EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC ); } - else - EMIT_PAD( 3 ); - - if (index & _TNL_BIT_FOG) - EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC ); else - EMIT_PAD( 1 ); + EMIT_PAD( 3 ); + + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) + EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC ); + else + EMIT_PAD( 1 ); } - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { int i, count = 0; for (i = 0; i < I830_TEX_UNITS; i++) { - if (index & _TNL_BIT_TEX(i)) { - GLuint sz = VB->TexCoordPtr[i]->size; - GLuint emit; - GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] & - ~TEXCOORDTYPE_MASK); + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { + GLuint sz = VB->TexCoordPtr[i]->size; + GLuint emit; + GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] & + ~TEXCOORDTYPE_MASK); switch (sz) { case 1: @@ -162,7 +165,7 @@ static void i830_render_start( intelContextPtr intel ) if (v0 != i830->state.Ctx[I830_CTXREG_VF] || v2 != i830->state.Ctx[I830_CTXREG_VF2] || mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || - index != i830->last_index) { + !RENDERINPUTS_EQUAL( index_bitset, i830->last_index_bitset )) { I830_STATECHANGE( i830, I830_UPLOAD_CTX ); @@ -180,7 +183,7 @@ static void i830_render_start( intelContextPtr intel ) i830->state.Ctx[I830_CTXREG_VF] = v0; i830->state.Ctx[I830_CTXREG_VF2] = v2; i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; - i830->last_index = index; + RENDERINPUTS_COPY( i830->last_index_bitset, index_bitset ); assert(i830_check_vertex_size( intel, intel->vertex_size )); } diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index b5c3f58d458..783bbc2ab89 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -127,7 +127,7 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, 12, I830_NR_TEX_REGIONS, intel->sarea->texList, - & intel->sarea->texAge, + (unsigned *) & intel->sarea->texAge, & intel->swapped, sizeof( struct i915_texture_object ), (destroy_texture_object_t *)intelDestroyTexObj ); diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index 26b8c69be9e..a088c087b65 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -311,6 +311,7 @@ extern void i915_print_ureg( const char *msg, GLuint ureg ); */ extern void i915InitStateFunctions( struct dd_function_table *functions ); extern void i915InitState( i915ContextPtr i915 ); +extern void i915_update_fog(GLcontext *ctxx); /*====================================================================== diff --git a/src/mesa/drivers/dri/i915/i915_texprog.c b/src/mesa/drivers/dri/i915/i915_texprog.c index 74ece96f8b7..4fbce34ba21 100644 --- a/src/mesa/drivers/dri/i915/i915_texprog.c +++ b/src/mesa/drivers/dri/i915/i915_texprog.c @@ -576,11 +576,13 @@ void i915ValidateTextureProgram( i915ContextPtr i915 ) GLcontext *ctx = &intel->ctx; TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); int i, offset; GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; GLuint s2 = S2_TEXCOORD_NONE; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + /* Important: */ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; @@ -591,9 +593,9 @@ void i915ValidateTextureProgram( i915ContextPtr i915 ) if (i915->vertex_fog == I915_FOG_PIXEL) { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 ); - index &= ~_TNL_BIT_FOG; + RENDERINPUTS_CLEAR( index_bitset, _TNL_ATTRIB_FOG ); } - else if (index & _TNL_BITS_TEX_ANY) { + else if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 ); } else { @@ -601,29 +603,30 @@ void i915ValidateTextureProgram( i915ContextPtr i915 ) } /* How undefined is undefined? */ - if (index & _TNL_BIT_POINTSIZE) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) { EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 ); } intel->coloroffset = offset / 4; EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4 ); - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { intel->specoffset = offset / 4; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3 ); } else EMIT_PAD( 3 ); - if (index & _TNL_BIT_FOG) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 ); else EMIT_PAD( 1 ); } - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { for (i = 0; i < 8; i++) { - if (index & _TNL_BIT_TEX(i)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { int sz = VB->TexCoordPtr[i]->size; s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index 87eddfecdef..3b639e71443 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -456,7 +456,7 @@ static void i915SetTexImages( i915ContextPtr i915, textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); break; - case MESA_FORMAT_DEPTH_COMPONENT16: + case MESA_FORMAT_Z16: t->intel.texelBytes = 2; textureFormat = (MAPSURF_16BIT | MT_16BIT_L16); break; @@ -483,7 +483,7 @@ static void i915SetTexImages( i915ContextPtr i915, break; #if 0 - case MESA_FORMAT_DEPTH_COMPONENT_X8Z24: + case MESA_FORMAT_Z24_S8: t->intel.texelBytes = 4; textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824); break; diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c index 5979e236bcd..06312372776 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c @@ -216,7 +216,7 @@ void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim ) } #if 1 - if (((int)intel->batch.ptr) & 0x4) { + if (((unsigned long)intel->batch.ptr) & 0x4) { BEGIN_BATCH(1); OUT_BATCH(0); ADVANCE_BATCH(); @@ -762,11 +762,6 @@ void intelInitBatchBuffer( GLcontext *ctx ) break; } - /* KW: temporary - this make crashes & lockups more frequent, so - * leave in until they are solved. - */ - intel->alloc.size = 8 * 1024; - intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size ); if (intel->alloc.ptr) intel->alloc.offset = diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.h b/src/mesa/drivers/dri/i915/intel_batchbuffer.h index b0aed89af55..577d07137ff 100644 --- a/src/mesa/drivers/dri/i915/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.h @@ -43,8 +43,9 @@ extern int VERBOSE; #define BEGIN_BATCH(n) \ do { \ if (VERBOSE) fprintf(stderr, \ - "BEGIN_BATCH(%d) in %s, %d dwords free\n", \ - (n), __FUNCTION__, intel->batch.space/4); \ + "BEGIN_BATCH(%ld) in %s, %d dwords free\n", \ + ((unsigned long)n), __FUNCTION__, \ + intel->batch.space/4); \ if (intel->batch.space < (n)*4) \ intelFlushBatch(intel, GL_TRUE); \ if (intel->batch.space == intel->batch.size) intel->batch.func = __FUNCTION__; \ diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h index 2f362f9c2fb..19213b7bc55 100644 --- a/src/mesa/drivers/dri/i915/intel_context.h +++ b/src/mesa/drivers/dri/i915/intel_context.h @@ -207,7 +207,7 @@ struct intel_context GLenum render_primitive; GLenum reduced_primitive; GLuint vertex_size; - char *verts; /* points to tnl->clipspace.vertex_buf */ + unsigned char *verts; /* points to tnl->clipspace.vertex_buf */ /* Fallback rasterization functions diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c index 82ad14ca114..d8530367664 100644 --- a/src/mesa/drivers/dri/i915/intel_ioctl.c +++ b/src/mesa/drivers/dri/i915/intel_ioctl.c @@ -140,7 +140,7 @@ void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); intel->batch.start_offset = intel->alloc.offset + buf * half; - intel->batch.ptr = (char *)intel->alloc.ptr + buf * half; + intel->batch.ptr = (unsigned char *)intel->alloc.ptr + buf * half; intel->batch.size = half - 8; intel->batch.space = half - 8; assert(intel->batch.space >= 0); @@ -418,7 +418,7 @@ void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all, if (!intel->hw_stencil) { swrast_mask |= BUFFER_BIT_STENCIL; } - else if (ctx->Stencil.WriteMask[0] != 0xff) { + else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { tri_mask |= BUFFER_BIT_STENCIL; } else { diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c index aaafe84a6a0..2af38541d9c 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.c +++ b/src/mesa/drivers/dri/i915/intel_pixel.c @@ -157,13 +157,15 @@ intersect_region(const drm_clip_rect_t *box, if (by < y) bh -= y - by, by = y; if (bx + bw > x + width) bw = x + width - bx; if (by + bh > y + height) bh = y + height - by; - if (bw <= 0) return GL_FALSE; - if (bh <= 0) return GL_FALSE; *xOut = bx; *yOut = by; *wOut = bw; *hOut = bh; + + if (bw <= 0) return GL_FALSE; + if (bh <= 0) return GL_FALSE; + return GL_TRUE; } @@ -423,6 +425,8 @@ intelTryDrawPixels( GLcontext *ctx, } else return GL_FALSE; + + return GL_FALSE; } static void diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c index c8649d8243a..a87de17304f 100644 --- a/src/mesa/drivers/dri/i915/intel_screen.c +++ b/src/mesa/drivers/dri/i915/intel_screen.c @@ -666,7 +666,7 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc *driver_modes = intelFillInModes( dri_priv->cpp * 8, (dri_priv->cpp == 2) ? 16 : 24, (dri_priv->cpp == 2) ? 0 : 8, - (dri_priv->backOffset != dri_priv->depthOffset) ); + 1 ); /* Calling driInitExtensions here, with a NULL context pointer, does not actually * enable the extensions. It just makes sure that all the dispatch offsets for all diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c index 4bd7f92db0a..6012d3e7999 100644 --- a/src/mesa/drivers/dri/i915/intel_tex.c +++ b/src/mesa/drivers/dri/i915/intel_tex.c @@ -572,7 +572,7 @@ intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32: - return &_mesa_texformat_depth_component16; + return &_mesa_texformat_z16; default: fprintf(stderr, "unexpected texture format %s in %s\n", @@ -787,7 +787,8 @@ int intelUploadTexImages( intelContextPtr intel, } /* Set the base offset of the texture image */ - t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs; + t->BufAddr = (GLubyte *) (intel->intelScreen->tex.map + + t->base.memBlock->ofs); t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs; t->dirty = ~0; } diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c index cef6db7a195..e1a53212a51 100644 --- a/src/mesa/drivers/dri/i915/intel_tris.c +++ b/src/mesa/drivers/dri/i915/intel_tris.c @@ -642,7 +642,7 @@ void intelChooseRenderState(GLcontext *ctx) TNLcontext *tnl = TNL_CONTEXT(ctx); intelContextPtr intel = INTEL_CONTEXT(ctx); GLuint flags = ctx->_TriangleCaps; - struct fragment_program *fprog = ctx->FragmentProgram._Current; + const struct fragment_program *fprog = ctx->FragmentProgram._Current; GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS)); GLuint index = 0; diff --git a/src/mesa/drivers/dri/i915/server/intel.h b/src/mesa/drivers/dri/i915/server/intel.h index 606db974b1c..d7858a20c8d 100644 --- a/src/mesa/drivers/dri/i915/server/intel.h +++ b/src/mesa/drivers/dri/i915/server/intel.h @@ -137,11 +137,6 @@ typedef struct { int space; } I830RingBuffer; -typedef struct { - unsigned int Fence[8]; -} I830RegRec, *I830RegPtr; - - typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; @@ -194,6 +189,7 @@ typedef struct _I830Rec { int GttBound; drm_handle_t ring_map; + unsigned int Fence[8]; } I830Rec; @@ -271,6 +267,44 @@ typedef struct _I830Rec { #define RING_INVALID 0x00000000 +/* Fence/Tiling ranges [0..7] + */ +#define FENCE 0x2000 +#define FENCE_NR 8 + +#define I915G_FENCE_START_MASK 0x0ff00000 + +#define I830_FENCE_START_MASK 0x07f80000 + +#define FENCE_START_MASK 0x03F80000 +#define FENCE_X_MAJOR 0x00000000 +#define FENCE_Y_MAJOR 0x00001000 +#define FENCE_SIZE_MASK 0x00000700 +#define FENCE_SIZE_512K 0x00000000 +#define FENCE_SIZE_1M 0x00000100 +#define FENCE_SIZE_2M 0x00000200 +#define FENCE_SIZE_4M 0x00000300 +#define FENCE_SIZE_8M 0x00000400 +#define FENCE_SIZE_16M 0x00000500 +#define FENCE_SIZE_32M 0x00000600 +#define FENCE_SIZE_64M 0x00000700 +#define I915G_FENCE_SIZE_1M 0x00000000 +#define I915G_FENCE_SIZE_2M 0x00000100 +#define I915G_FENCE_SIZE_4M 0x00000200 +#define I915G_FENCE_SIZE_8M 0x00000300 +#define I915G_FENCE_SIZE_16M 0x00000400 +#define I915G_FENCE_SIZE_32M 0x00000500 +#define I915G_FENCE_SIZE_64M 0x00000600 +#define I915G_FENCE_SIZE_128M 0x00000700 +#define FENCE_PITCH_1 0x00000000 +#define FENCE_PITCH_2 0x00000010 +#define FENCE_PITCH_4 0x00000020 +#define FENCE_PITCH_8 0x00000030 +#define FENCE_PITCH_16 0x00000040 +#define FENCE_PITCH_32 0x00000050 +#define FENCE_PITCH_64 0x00000060 +#define FENCE_VALID 0x00000001 + #include <mmio.h> # define MMIO_IN8(base, offset) \ diff --git a/src/mesa/drivers/dri/i915/server/intel_dri.c b/src/mesa/drivers/dri/i915/server/intel_dri.c index 2fd4a13052f..169fdbece30 100644 --- a/src/mesa/drivers/dri/i915/server/intel_dri.c +++ b/src/mesa/drivers/dri/i915/server/intel_dri.c @@ -46,10 +46,250 @@ #include "pciaccess.h" static size_t drm_page_size; +static int nextTile = 0; #define xf86DrvMsg(...) do {} while(0) +static const int pitches[] = { + 128 * 8, + 128 * 16, + 128 * 32, + 128 * 64, + 0 +}; + static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea); +static unsigned long +GetBestTileAlignment(unsigned long size) +{ + unsigned long i; + + for (i = KB(512); i < size; i <<= 1) + ; + + if (i > MB(64)) + i = MB(64); + + return i; +} + +static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830) +{ + int i; + unsigned char *MMIO = ctx->MMIOAddress; + + for (i = 0; i < 8; i++) { + OUTREG(FENCE + i * 4, pI830->Fence[i]); + // if (I810_DEBUG & DEBUG_VERBOSE_VGA) + fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]); + } +} + +/* Tiled memory is good... really, really good... + * + * Need to make it less likely that we miss out on this - probably + * need to move the frontbuffer away from the 'guarenteed' alignment + * of the first memory segment, or perhaps allocate a discontigous + * framebuffer to get more alignment 'sweet spots'. + */ +static void +SetFence(const DRIDriverContext *ctx, I830Rec *pI830, + int nr, unsigned int start, unsigned int pitch, + unsigned int size) +{ + unsigned int val; + unsigned int fence_mask = 0; + unsigned int fence_pitch; + + if (nr < 0 || nr > 7) { + fprintf(stderr, + "SetFence: fence %d out of range\n",nr); + return; + } + + pI830->Fence[nr] = 0; + + if (IS_I9XX(pI830)) + fence_mask = ~I915G_FENCE_START_MASK; + else + fence_mask = ~I830_FENCE_START_MASK; + + if (start & fence_mask) { + fprintf(stderr, + "SetFence: %d: start (0x%08x) is not %s aligned\n", + nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k"); + return; + } + + if (start % size) { + fprintf(stderr, + "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n", + nr, start, size / 1024); + return; + } + + if (pitch & 127) { + fprintf(stderr, + "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n", + nr, pitch); + return; + } + + val = (start | FENCE_X_MAJOR | FENCE_VALID); + + if (IS_I9XX(pI830)) { + switch (size) { + case MB(1): + val |= I915G_FENCE_SIZE_1M; + break; + case MB(2): + val |= I915G_FENCE_SIZE_2M; + break; + case MB(4): + val |= I915G_FENCE_SIZE_4M; + break; + case MB(8): + val |= I915G_FENCE_SIZE_8M; + break; + case MB(16): + val |= I915G_FENCE_SIZE_16M; + break; + case MB(32): + val |= I915G_FENCE_SIZE_32M; + break; + case MB(64): + val |= I915G_FENCE_SIZE_64M; + break; + default: + fprintf(stderr, + "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); + return; + } + } else { + switch (size) { + case KB(512): + val |= FENCE_SIZE_512K; + break; + case MB(1): + val |= FENCE_SIZE_1M; + break; + case MB(2): + val |= FENCE_SIZE_2M; + break; + case MB(4): + val |= FENCE_SIZE_4M; + break; + case MB(8): + val |= FENCE_SIZE_8M; + break; + case MB(16): + val |= FENCE_SIZE_16M; + break; + case MB(32): + val |= FENCE_SIZE_32M; + break; + case MB(64): + val |= FENCE_SIZE_64M; + break; + default: + fprintf(stderr, + "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); + return; + } + } + + if (IS_I9XX(pI830)) + fence_pitch = pitch / 512; + else + fence_pitch = pitch / 128; + + switch (fence_pitch) { + case 1: + val |= FENCE_PITCH_1; + break; + case 2: + val |= FENCE_PITCH_2; + break; + case 4: + val |= FENCE_PITCH_4; + break; + case 8: + val |= FENCE_PITCH_8; + break; + case 16: + val |= FENCE_PITCH_16; + break; + case 32: + val |= FENCE_PITCH_32; + break; + case 64: + val |= FENCE_PITCH_64; + break; + default: + fprintf(stderr, + "SetFence: %d: illegal pitch (%d)\n", nr, pitch); + return; + } + + pI830->Fence[nr] = val; +} + +static Bool +MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem) +{ + int pitch, ntiles, i; + + pitch = pMem->Pitch * ctx->cpp; + /* + * Simply try to break the region up into at most four pieces of size + * equal to the alignment. + */ + ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment; + if (ntiles >= 4) { + return FALSE; + } + + for (i = 0; i < ntiles; i++, nextTile++) { + SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment, + pitch, pMem->Alignment); + } + return TRUE; +} + +static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830) +{ + int i; + + /* Clear out */ + for (i = 0; i < 8; i++) + pI830->Fence[i] = 0; + + nextTile = 0; + + if (pI830->BackBuffer.Alignment >= KB(512)) { + if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) { + fprintf(stderr, + "Activating tiled memory for the back buffer.\n"); + } else { + fprintf(stderr, + "MakeTiles failed for the back buffer.\n"); + pI830->allowPageFlip = FALSE; + } + } + + if (pI830->DepthBuffer.Alignment >= KB(512)) { + if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) { + fprintf(stderr, + "Activating tiled memory for the depth buffer.\n"); + } else { + fprintf(stderr, + "MakeTiles failed for the depth buffer.\n"); + } + } + + return; +} + static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830) { struct pci_device host_bridge; @@ -139,6 +379,43 @@ static int AgpInit(const DRIDriverContext *ctx, I830Rec *info) return 1; } +/* + * Allocate memory from the given pool. Grow the pool if needed and if + * possible. + */ +static unsigned long +AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830, + I830MemRange *result, I830MemPool *pool, + long size, unsigned long alignment, int flags) +{ + long needed, start, end; + + if (!result || !pool || !size) + return 0; + + /* Calculate how much space is needed. */ + if (alignment <= GTT_PAGE_SIZE) + needed = size; + else { + start = ROUND_TO(pool->Free.Start, alignment); + end = ROUND_TO(start + size, alignment); + needed = end - pool->Free.Start; + } + if (needed > pool->Free.Size) { + return 0; + } + + result->Start = ROUND_TO(pool->Free.Start, alignment); + pool->Free.Start += needed; + result->End = pool->Free.Start; + + pool->Free.Size = pool->Free.End - pool->Free.Start; + result->Size = result->End - result->Start; + result->Pool = pool; + result->Alignment = alignment; + return needed; +} + static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result) { unsigned long start, end; @@ -166,7 +443,7 @@ static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, l pI830->MemoryAperture.Start = newApStart; pI830->MemoryAperture.End = newApEnd; pI830->MemoryAperture.Size = newApEnd - newApStart; - pI830->FreeMemory -= size; + // pI830->FreeMemory -= size; result->Start = start; result->End = start + size; result->Size = size; @@ -177,6 +454,34 @@ static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, l return size; } +unsigned long +I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags) +{ + int ret; + + if (!result) + return 0; + + /* Make sure these are initialised. */ + result->Size = 0; + result->Key = -1; + + if (!size) { + return 0; + } + + if (pool->Free.Size < size) + return AllocFromAGP(ctx, pI830, size, alignment, result); + else + { + ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags); + + if (ret==0) + return AllocFromAGP(ctx, pI830, size, alignment, result); + return ret; + } +} + static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem) { if (!mem) @@ -185,7 +490,7 @@ static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem) if (mem->Key == -1) return TRUE; - return drmAgpBind(ctx->drmFD, mem->Key, mem->Offset); + return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset); } /* simple memory allocation routines needed */ @@ -207,7 +512,7 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) size = PRIMARY_RINGBUFFER_SIZE; - ret = AllocFromAGP(ctx, pI830, size, 0x1000, &pI830->LpRing->mem); + ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0); if (ret != size) { @@ -230,8 +535,10 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) size = lineSize * lines; size = ROUND_TO_PAGE(size); - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->FrontBuffer); - if (ret != size) + align = GetBestTileAlignment(size); + + ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0); + if (ret < size) { fprintf(stderr,"unable to allocate front buffer %ld\n", ret); return FALSE; @@ -241,8 +548,8 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) pI830->BackBuffer.Key = -1; pI830->BackBuffer.Pitch = ctx->shared.virtualWidth; - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->BackBuffer); - if (ret != size) + ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0); + if (ret < size) { fprintf(stderr,"unable to allocate back buffer %ld\n", ret); return FALSE; @@ -252,8 +559,8 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) pI830->DepthBuffer.Key = -1; pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth; - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->DepthBuffer); - if (ret != size) + ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0); + if (ret < size) { fprintf(stderr,"unable to allocate depth buffer %ld\n", ret); return FALSE; @@ -263,10 +570,10 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) pI830->ContextMem.Key = -1; size = KB(32); - ret = AllocFromAGP(ctx, pI830, size, align, &pI830->ContextMem); - if (ret != size) + ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0); + if (ret < size) { - fprintf(stderr,"unable to allocate back buffer %ld\n", ret); + fprintf(stderr,"unable to allocate context buffer %ld\n", ret); return FALSE; } @@ -275,7 +582,7 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) size = 32768 * 1024; ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem); - if (ret != size) + if (ret < size) { fprintf(stderr,"unable to allocate texture memory %ld\n", ret); return FALSE; @@ -287,17 +594,17 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830) static Bool I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830) { - if (BindAgpRange(ctx, &pI830->LpRing->mem)) + if (!BindAgpRange(ctx, &pI830->LpRing->mem)) return FALSE; - if (BindAgpRange(ctx, &pI830->FrontBuffer)) + if (!BindAgpRange(ctx, &pI830->FrontBuffer)) return FALSE; - if (BindAgpRange(ctx, &pI830->BackBuffer)) + if (!BindAgpRange(ctx, &pI830->BackBuffer)) return FALSE; - if (BindAgpRange(ctx, &pI830->DepthBuffer)) + if (!BindAgpRange(ctx, &pI830->DepthBuffer)) return FALSE; - if (BindAgpRange(ctx, &pI830->ContextMem)) + if (!BindAgpRange(ctx, &pI830->ContextMem)) return FALSE; - if (BindAgpRange(ctx, &pI830->TexMem)) + if (!BindAgpRange(ctx, &pI830->TexMem)) return FALSE; return TRUE; @@ -313,7 +620,7 @@ I830CleanupDma(const DRIDriverContext *ctx) if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, &info, sizeof(drmI830Init))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n"); + fprintf(stderr, "I830 Dma Cleanup Failed\n"); return FALSE; } @@ -345,11 +652,11 @@ I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830) info.pitch = ctx->shared.virtualWidth; info.back_pitch = pI830->BackBuffer.Pitch; info.depth_pitch = pI830->DepthBuffer.Pitch; - info.cpp = pI830->cpp; + info.cpp = ctx->cpp; if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT, &info, sizeof(drmI830Init))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "I830 Dma Initialization Failed\n"); return FALSE; } @@ -408,7 +715,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830) if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) != pI830->LpRing->mem.Start) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "I830SetRingRegs: Ring buffer start (%lx) violates its " "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK); } @@ -418,7 +725,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830) if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) != pI830->LpRing->mem.Size - 4096) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " "mask (%x)\n", pI830->LpRing->mem.Size - 4096, I830_RING_NR_PAGES); @@ -433,6 +740,8 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830) pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); if (pI830->LpRing->space < 0) pI830->LpRing->space += pI830->LpRing->mem.Size; + + SetFenceRegs(ctx, pI830); /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky hacky hacky */ @@ -450,7 +759,7 @@ I830SetParam(const DRIDriverContext *ctx, int param, int value) sp.value = value; if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n"); + fprintf(stderr, "I830 SetParam Failed\n"); return FALSE; } @@ -482,7 +791,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar (drm_handle_t)(sarea->back_offset), sarea->back_size, DRM_AGP, 0, &sarea->back_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "[drm] drmAddMap(back_handle) failed. Disabling DRI\n"); return FALSE; } @@ -493,7 +802,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar (drm_handle_t)sarea->depth_offset, sarea->depth_size, DRM_AGP, 0, &sarea->depth_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n"); return FALSE; } @@ -504,7 +813,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar (drm_handle_t)sarea->tex_offset, sarea->tex_size, DRM_AGP, 0, &sarea->tex_handle) < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n"); return FALSE; } @@ -549,10 +858,10 @@ I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *s if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP, &drmHeap, sizeof(drmHeap))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "[drm] Failed to initialized agp heap manager\n"); } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + fprintf(stderr, "[drm] Initialized kernel agp heap manager, %d\n", sarea->tex_size); @@ -597,18 +906,18 @@ I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea) ctx->pciFunc); if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + fprintf(stderr, "[drm] failure adding irq handler\n"); pI830->irq = 0; return FALSE; } else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + fprintf(stderr, "[drm] dma control initialized, using IRQ %d\n", - pI830DRI->irq); + pI830->irq); } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n"); + fprintf(stderr, "[dri] visual configs initialized\n"); return TRUE; } @@ -663,7 +972,6 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) I830DRIPtr pI830DRI; drmI830Sarea *pSAREAPriv; int err; - drm_page_size = getpagesize(); @@ -675,7 +983,7 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) */ ctx->shared.SAREASize = SAREA_MAX; - /* Note that drmOpen will try to load the kernel module, if needed. */ + /* Note that drmOpen will try to load the kernel module, if needed. */ ctx->drmFD = drmOpen("i915", NULL ); if (ctx->drmFD < 0) { fprintf(stderr, "[drm] drmOpen failed\n"); @@ -757,6 +1065,11 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) pI830->MemoryAperture.End = KB(40000); pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start; + pI830->StolenPool.Fixed = pI830->StolenMemory; + pI830->StolenPool.Total = pI830->StolenMemory; + pI830->StolenPool.Free = pI830->StolenPool.Total; + pI830->FreeMemory = pI830->StolenPool.Total.Size; + if (!AgpInit(ctx, pI830)) return FALSE; @@ -810,6 +1123,8 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830) if (err == FALSE) return FALSE; + I830SetupMemoryTiling(ctx, pI830); + /* Quick hack to clear the front & back buffers. Could also use * the clear ioctl to do this, but would need to setup hw state * first. @@ -873,6 +1188,7 @@ static int i830PostValidateMode( const DRIDriverContext *ctx ) static int i830InitFBDev( DRIDriverContext *ctx ) { I830Rec *pI830 = calloc(1, sizeof(I830Rec)); + int i; { int dummy = ctx->shared.virtualWidth; @@ -885,6 +1201,15 @@ static int i830InitFBDev( DRIDriverContext *ctx ) } ctx->shared.virtualWidth = dummy; + ctx->shared.Width = ctx->shared.virtualWidth; + } + + + for (i = 0; pitches[i] != 0; i++) { + if (pitches[i] >= ctx->shared.virtualWidth) { + ctx->shared.virtualWidth = pitches[i]; + break; + } } ctx->driverPrivate = (void *)pI830; diff --git a/src/mesa/drivers/dri/mga/README b/src/mesa/drivers/dri/mga/README new file mode 100644 index 00000000000..a7133fa66f4 --- /dev/null +++ b/src/mesa/drivers/dri/mga/README @@ -0,0 +1,26 @@ +MGA DRI driver ported from XF86DRI to FBDRI +by Denis Oliver Kropp <[email protected]> + + +INFO + +This driver has been ported from the head branch of XFree86 to +the embedded-1-branch of Mesa. + + +STATUS + +Already working very well as far as I've tested it (16/32 bit). +glxgears runs at 935 fps (G550 32MB AGP 4x, Athlon 1.33) vs 744 fps with XFree. +Other demos (terrain, fire, etc.) have been successfully tested as well. + + +TODO + +- mgaEngineShutdown +- mgaEngineRestore +- SGRAM detection +- remove some unused bits from server/* +- subset driver support +- mgaWaitForVBlank +- deinitialization (from MGADRICloseScreen) a la radeonDestroyScreen diff --git a/src/mesa/drivers/dri/mga/mgaioctl.c b/src/mesa/drivers/dri/mga/mgaioctl.c index df253d15934..6e653f8c73d 100644 --- a/src/mesa/drivers/dri/mga/mgaioctl.c +++ b/src/mesa/drivers/dri/mga/mgaioctl.c @@ -50,7 +50,7 @@ #include "vblank.h" -int +static int mgaSetFence( mgaContextPtr mmesa, uint32_t * fence ) { int ret = ENOSYS; @@ -68,7 +68,7 @@ mgaSetFence( mgaContextPtr mmesa, uint32_t * fence ) } -int +static int mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence ) { int ret = ENOSYS; diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c index 75f618ad37a..2f30bd253bf 100644 --- a/src/mesa/drivers/dri/r128/r128_context.c +++ b/src/mesa/drivers/dri/r128/r128_context.c @@ -190,7 +190,7 @@ GLboolean r128CreateContext( const __GLcontextModes *glVisual, rmesa->RenderIndex = -1; /* Impossible value */ rmesa->vert_buf = NULL; rmesa->num_verts = 0; - rmesa->tnl_state = ~0; + RENDERINPUTS_ONES( rmesa->tnl_state_bitset ); /* Set the maximum texture size small enough that we can guarentee that * all texture units can bind a maximal texture and have them both in @@ -296,10 +296,6 @@ void r128DestroyContext( __DRIcontextPrivate *driContextPriv ) _ac_DestroyContext( rmesa->glCtx ); _swrast_DestroyContext( rmesa->glCtx ); - /* free the Mesa context */ - rmesa->glCtx->DriverCtx = NULL; - _mesa_destroy_context(rmesa->glCtx); - if ( release_texture_heaps ) { /* This share group is about to go away, free our private * texture object data. @@ -314,6 +310,10 @@ void r128DestroyContext( __DRIcontextPrivate *driContextPriv ) assert( is_empty_list( & rmesa->swapped ) ); } + /* free the Mesa context */ + rmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context(rmesa->glCtx); + /* free the option cache */ driDestroyOptionCache (&rmesa->optionCache); diff --git a/src/mesa/drivers/dri/r128/r128_context.h b/src/mesa/drivers/dri/r128/r128_context.h index b3552ac7639..c51dd7fa58d 100644 --- a/src/mesa/drivers/dri/r128/r128_context.h +++ b/src/mesa/drivers/dri/r128/r128_context.h @@ -130,7 +130,7 @@ struct r128_context { char *verts; /* points to tnl->clipspace.vertex_buf */ GLuint num_verts; int coloroffset, specoffset; - int tnl_state; /* tnl->render_inputs for this _tnl_install_attrs */ + DECLARE_RENDERINPUTS(tnl_state_bitset); /* tnl->render_inputs for this _tnl_install_attrs */ GLuint NewGLState; GLuint Fallback; diff --git a/src/mesa/drivers/dri/r128/r128_lock.c b/src/mesa/drivers/dri/r128/r128_lock.c index ef67bc6a43a..393dd1ed74c 100644 --- a/src/mesa/drivers/dri/r128/r128_lock.c +++ b/src/mesa/drivers/dri/r128/r128_lock.c @@ -89,7 +89,7 @@ void r128GetLock( r128ContextPtr rmesa, GLuint flags ) driUpdateFramebufferSize(rmesa->glCtx, dPriv); rmesa->lastStamp = dPriv->lastStamp; rmesa->new_state |= R128_NEW_CLIP; - rmesa->tnl_state = ~0; + RENDERINPUTS_ONES( rmesa->tnl_state_bitset ); } rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS; diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c index e9149306d87..1b2c2a5284e 100644 --- a/src/mesa/drivers/dri/r128/r128_state.c +++ b/src/mesa/drivers/dri/r128/r128_state.c @@ -260,9 +260,9 @@ r128DDStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, GLint ref, GLuint mask ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref[0] << 0) | - (ctx->Stencil.ValueMask[0] << 16) | - (ctx->Stencil.WriteMask[0] << 24)); + GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) | + ((ctx->Stencil.ValueMask[0] & 0xff) << 16) | + ((ctx->Stencil.WriteMask[0] & 0xff) << 24)); GLuint z = rmesa->setup.z_sten_cntl_c; z &= ~R128_STENCIL_TEST_MASK; @@ -307,9 +307,9 @@ static void r128DDStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref[0] << 0) | - (ctx->Stencil.ValueMask[0] << 16) | - (ctx->Stencil.WriteMask[0] << 24)); + GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) | + ((ctx->Stencil.ValueMask[0] & 0xff) << 16) | + ((ctx->Stencil.WriteMask[0] & 0xff) << 24)); if ( rmesa->setup.sten_ref_mask_c != refmask ) { rmesa->setup.sten_ref_mask_c = refmask; diff --git a/src/mesa/drivers/dri/r128/r128_tris.c b/src/mesa/drivers/dri/r128/r128_tris.c index 64f54682b6e..46315225165 100644 --- a/src/mesa/drivers/dri/r128/r128_tris.c +++ b/src/mesa/drivers/dri/r128/r128_tris.c @@ -564,11 +564,13 @@ static void r128RenderStart( GLcontext *ctx ) r128ContextPtr rmesa = R128_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint vc_frmt = 0; GLboolean fallback_projtex = GL_FALSE; GLuint offset = 0; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + /* Important: */ VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; rmesa->vertex_attr_count = 0; @@ -577,7 +579,7 @@ static void r128RenderStart( GLcontext *ctx ) /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ - if ( index & _TNL_BITS_TEX_ANY ) + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R128_CCE_VC_FRMT_RHW, 16 ); else EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 12 ); @@ -591,28 +593,29 @@ static void r128RenderStart( GLcontext *ctx ) R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 ); #endif - if ( index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG) ) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { #if MESA_LITTLE_ENDIAN - if ( index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, R128_CCE_VC_FRMT_SPEC_FRGB, 3 ); } else EMIT_PAD( 3 ); - if (index & _TNL_BIT_FOG) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB, 1 ); else EMIT_PAD( 1 ); #else - if (index & _TNL_BIT_FOG) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB, 1 ); else EMIT_PAD( 1 ); - if ( index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, R128_CCE_VC_FRMT_SPEC_FRGB, 3 ); @@ -621,12 +624,12 @@ static void r128RenderStart( GLcontext *ctx ) #endif } - if ( index & _TNL_BIT_TEX(rmesa->tmu_source[0]) ) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[0]) )) { if ( VB->TexCoordPtr[rmesa->tmu_source[0]]->size > 2 ) fallback_projtex = GL_TRUE; EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, R128_CCE_VC_FRMT_S_T, 8 ); } - if ( index & _TNL_BIT_TEX(rmesa->tmu_source[1]) ) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[1]) )) { if ( VB->TexCoordPtr[rmesa->tmu_source[1]]->size > 2 ) fallback_projtex = GL_TRUE; EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, R128_CCE_VC_FRMT_S2_T2, 8 ); @@ -638,7 +641,7 @@ static void r128RenderStart( GLcontext *ctx ) /* Only need to change the vertex emit code if there has been a * statechange to a TNL index. */ - if ( index != rmesa->tnl_state ) { + if (!RENDERINPUTS_EQUAL( index_bitset, rmesa->tnl_state_bitset )) { FLUSH_BATCH( rmesa ); rmesa->dirty |= R128_UPLOAD_CONTEXT; @@ -763,7 +766,7 @@ void r128InitTriFuncs( GLcontext *ctx ) _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, (6 + 2 * ctx->Const.MaxTextureUnits) * sizeof(GLfloat) ); rmesa->verts = (char *)tnl->clipspace.vertex_buf; - rmesa->tnl_state = -1; + RENDERINPUTS_ONES( rmesa->tnl_state_bitset ); rmesa->NewGLState |= _R128_NEW_RENDER_STATE; } diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile index 7d8a170a650..2084d52132e 100644 --- a/src/mesa/drivers/dri/r200/Makefile +++ b/src/mesa/drivers/dri/r200/Makefile @@ -38,7 +38,7 @@ C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES) X86_SOURCES = r200_vtxtmp_x86.S -DEFINES += -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200 +DRIVER_DEFINES = -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200 SYMLINKS = \ server/radeon_egl.c \ diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c index e4d9e264bf9..aaaaa5a95bf 100644 --- a/src/mesa/drivers/dri/r200/r200_context.c +++ b/src/mesa/drivers/dri/r200/r200_context.c @@ -107,7 +107,7 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name ) r200ContextPtr rmesa = R200_CONTEXT(ctx); static char buffer[128]; unsigned offset; - GLuint agp_mode = rmesa->r200Screen->IsPCI ? 0 : + GLuint agp_mode = (rmesa->r200Screen->card_type == RADEON_CARD_PCI)? 0 : rmesa->r200Screen->AGPMode; switch ( name ) { @@ -590,10 +590,6 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv ) r200VtxfmtDestroy( rmesa->glCtx ); } - /* free the Mesa context */ - rmesa->glCtx->DriverCtx = NULL; - _mesa_destroy_context( rmesa->glCtx ); - if (rmesa->state.scissor.pClipRects) { FREE(rmesa->state.scissor.pClipRects); rmesa->state.scissor.pClipRects = NULL; @@ -613,6 +609,10 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv ) assert( is_empty_list( & rmesa->swapped ) ); } + /* free the Mesa context */ + rmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context( rmesa->glCtx ); + /* free the option cache */ driDestroyOptionCache (&rmesa->optionCache); diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h index faf1b96a2b8..f6709d3d7fd 100644 --- a/src/mesa/drivers/dri/r200/r200_context.h +++ b/src/mesa/drivers/dri/r200/r200_context.h @@ -897,7 +897,7 @@ struct r200_context { GLuint TclFallback; GLuint Fallback; GLuint NewGLState; - GLuint tnl_index; /* index of bits for last tnl_install_attrs */ + DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */ /* Vertex buffers */ diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c index 43ae7b66780..6ffb48c1505 100644 --- a/src/mesa/drivers/dri/r200/r200_state.c +++ b/src/mesa/drivers/dri/r200/r200_state.c @@ -1452,8 +1452,8 @@ r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, GLint ref, GLuint mask ) { r200ContextPtr rmesa = R200_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) | - (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT)); + GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) | + ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT)); R200_STATECHANGE( rmesa, ctx ); R200_STATECHANGE( rmesa, msk ); @@ -1500,7 +1500,7 @@ r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) R200_STATECHANGE( rmesa, msk ); rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK; rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= - (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT); + ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT); } static void @@ -1601,9 +1601,9 @@ static void r200ClearStencil( GLcontext *ctx, GLint s ) r200ContextPtr rmesa = R200_CONTEXT(ctx); rmesa->state.stencil.clear = - ((GLuint) ctx->Stencil.Clear | + ((GLuint) (ctx->Stencil.Clear & 0xff) | (0xff << R200_STENCIL_MASK_SHIFT) | - (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT)); + ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT)); } diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c index 7ab3f7cd032..aa78f382868 100644 --- a/src/mesa/drivers/dri/r200/r200_swtcl.c +++ b/src/mesa/drivers/dri/r200/r200_swtcl.c @@ -85,11 +85,12 @@ static void r200SetVertexFormat( GLcontext *ctx ) r200ContextPtr rmesa = R200_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); int fmt_0 = 0; int fmt_1 = 0; int offset = 0; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); /* Important: */ @@ -106,7 +107,8 @@ static void r200SetVertexFormat( GLcontext *ctx ) /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ - if ( !rmesa->swtcl.needproj || (index & _TNL_BITS_TEX_ANY)) { /* need w coord for projected textures */ + if ( !rmesa->swtcl.needproj || + RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* need w coord for projected textures */ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 ); offset = 4; } @@ -124,10 +126,11 @@ static void r200SetVertexFormat( GLcontext *ctx ) offset += 1; rmesa->swtcl.specoffset = 0; - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { #if MESA_LITTLE_ENDIAN - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } @@ -135,21 +138,21 @@ static void r200SetVertexFormat( GLcontext *ctx ) EMIT_PAD( 3 ); } - if (index & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } else { EMIT_PAD( 1 ); } #else - if (index & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } else { EMIT_PAD( 1 ); } - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); } @@ -159,11 +162,11 @@ static void r200SetVertexFormat( GLcontext *ctx ) #endif } - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { int i; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { - if (index & _TNL_BIT_TEX(i)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { GLuint sz = VB->TexCoordPtr[i]->size; fmt_1 |= sz << (3 * i); @@ -179,7 +182,7 @@ static void r200SetVertexFormat( GLcontext *ctx ) rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA; } - if ( rmesa->tnl_index != index || + if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) || (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { R200_NEWPRIM(rmesa); @@ -193,7 +196,7 @@ static void r200SetVertexFormat( GLcontext *ctx ) rmesa->swtcl.vertex_attr_count, NULL, 0 ); rmesa->swtcl.vertex_size /= 4; - rmesa->tnl_index = index; + RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset ); } } @@ -235,12 +238,12 @@ void r200ChooseVertexState( GLcontext *ctx ) /* HW perspective divide is a win, but tiny vertex formats are a * bigger one. */ - if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0) + if (!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { rmesa->swtcl.needproj = GL_TRUE; vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT; vte &= ~R200_VTX_W0_FMT; - if (tnl->render_inputs & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { vap &= ~R200_VAP_FORCE_W_TO_ONE; } else { @@ -719,7 +722,7 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ) */ _tnl_invalidate_vertex_state( ctx, ~0 ); _tnl_invalidate_vertices( ctx, ~0 ); - rmesa->tnl_index = 0; + RENDERINPUTS_ZERO( rmesa->tnl_index_bitset ); r200ChooseVertexState( ctx ); r200ChooseRenderState( ctx ); } diff --git a/src/mesa/drivers/dri/r200/r200_vtxfmt.c b/src/mesa/drivers/dri/r200/r200_vtxfmt.c index f42a046c00d..673076d0605 100644 --- a/src/mesa/drivers/dri/r200/r200_vtxfmt.c +++ b/src/mesa/drivers/dri/r200/r200_vtxfmt.c @@ -1056,12 +1056,16 @@ static void r200VtxFmtFlushVertices( GLcontext *ctx, GLuint flags ) */ +/** + * Called once during context creation. + */ void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) { r200ContextPtr rmesa = R200_CONTEXT( ctx ); GLvertexformat *vfmt = &(rmesa->vb.vtxfmt); - MEMSET( vfmt, 0, sizeof(GLvertexformat) ); + /* start by initializing to no-op functions */ + _mesa_noop_vtxfmt_init(vfmt); /* Hook in chooser functions for codegen, etc: */ @@ -1071,7 +1075,6 @@ void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) */ vfmt->Materialfv = r200_Materialfv; vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ vfmt->Begin = r200_Begin; vfmt->End = r200_End; @@ -1085,15 +1088,6 @@ void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) vfmt->DrawElements = r200_fallback_DrawElements; vfmt->DrawRangeElements = r200_fallback_DrawRangeElements; - - /* Not active in supported states; just keep ctx->Current uptodate: - */ - vfmt->EdgeFlag = _mesa_noop_EdgeFlag; - vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; - vfmt->Indexf = _mesa_noop_Indexf; - vfmt->Indexfv = _mesa_noop_Indexfv; - - /* Active but unsupported -- fallback if we receive these: */ vfmt->CallList = r200_fallback_CallList; diff --git a/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S b/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S index 57a35c657b8..5e33c7bdeea 100644 --- a/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S +++ b/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S @@ -493,3 +493,7 @@ GLOBL( _sse_MultiTexCoord2f_2 ) ret GLOBL( _sse_MultiTexCoord2f_2_end ) #endif + +#if defined (__ELF__) && defined (__linux__) + .section .note.GNU-stack,"",%progbits +#endif diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile index 3158ac8412b..5abb91d9876 100644 --- a/src/mesa/drivers/dri/r300/Makefile +++ b/src/mesa/drivers/dri/r300/Makefile @@ -5,7 +5,6 @@ TOP = ../../../../.. include $(TOP)/configs/current LIBNAME = r300_dri.so -DEFINES += -DCOMPILE_R300 -DGLX_DIRECT_RENDERING -DR200_MERGED=0 MINIGLX_SOURCES = server/radeon_dri.c @@ -70,7 +69,8 @@ C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES) X86_SOURCES = #r200_vtxtmp_x86.S -DEFINES += -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300 +DRIVER_DEFINES = -DCOMPILE_R300 -DGLX_DIRECT_RENDERING -DR200_MERGED=0 \ + -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300 SYMLINKS = \ server/radeon_dri.c \ diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 09f7669bd71..f39f71584ce 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -337,8 +337,10 @@ void r300InitCmdBuf(r300ContextPtr r300) r300->hw.unk4260.cmd[0] = cmdpacket0(0x4260, 3); ALLOC_STATE( unk4274, always, 5, "unk4274", 0 ); r300->hw.unk4274.cmd[0] = cmdpacket0(0x4274, 4); - ALLOC_STATE( unk4288, always, 6, "unk4288", 0 ); - r300->hw.unk4288.cmd[0] = cmdpacket0(0x4288, 5); + ALLOC_STATE( unk4288, always, 4, "unk4288", 0 ); + r300->hw.unk4288.cmd[0] = cmdpacket0(0x4288, 3); + ALLOC_STATE( fogp, always, 3, "fogp", 0 ); + r300->hw.fogp.cmd[0] = cmdpacket0(R300_RE_FOG_SCALE, 2); ALLOC_STATE( unk42A0, always, 2, "unk42A0", 0 ); r300->hw.unk42A0.cmd[0] = cmdpacket0(0x42A0, 1); ALLOC_STATE( zbs, always, R300_ZBS_CMDSIZE, "zbs", 0 ); @@ -374,10 +376,10 @@ void r300InitCmdBuf(r300ContextPtr r300) r300->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR2_0, 1); ALLOC_STATE( fpi[3], variable, R300_FPI_CMDSIZE, "fpi/3", 3 ); r300->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR3_0, 1); - ALLOC_STATE( unk4BC0, always, 2, "unk4BC0", 0 ); - r300->hw.unk4BC0.cmd[0] = cmdpacket0(0x4BC0, 1); - ALLOC_STATE( unk4BC8, always, 4, "unk4BC8", 0 ); - r300->hw.unk4BC8.cmd[0] = cmdpacket0(0x4BC8, 3); + ALLOC_STATE( fogs, always, R300_FOGS_CMDSIZE, "fogs", 0 ); + r300->hw.fogs.cmd[R300_FOGS_CMD_0] = cmdpacket0(R300_RE_FOG_STATE, 1); + ALLOC_STATE( fogc, always, R300_FOGC_CMDSIZE, "fogc", 0 ); + r300->hw.fogc.cmd[R300_FOGC_CMD_0] = cmdpacket0(R300_FOG_COLOR_R, 3); ALLOC_STATE( at, always, R300_AT_CMDSIZE, "at", 0 ); r300->hw.at.cmd[R300_AT_CMD_0] = cmdpacket0(R300_PP_ALPHA_TEST, 2); ALLOC_STATE( unk4BD8, always, 2, "unk4BD8", 0 ); @@ -478,6 +480,7 @@ void r300InitCmdBuf(r300ContextPtr r300) insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4260); insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4274); insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4288); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fogp); insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42A0); insert_at_tail(&r300->hw.atomlist, &r300->hw.zbs); insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42B4); @@ -495,8 +498,8 @@ void r300InitCmdBuf(r300ContextPtr r300) insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[1]); insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[2]); insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[3]); - insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC0); - insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC8); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fogs); + insert_at_tail(&r300->hw.atomlist, &r300->hw.fogc); insert_at_tail(&r300->hw.atomlist, &r300->hw.at); insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BD8); insert_at_tail(&r300->hw.atomlist, &r300->hw.fpp); @@ -541,9 +544,9 @@ void r300InitCmdBuf(r300ContextPtr r300) size = 64*256; if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) { - fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%d\n", + fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%ld\n", sizeof(drm_r300_cmd_header_t)); - fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%d\n", + fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%ld\n", sizeof(drm_radeon_cmd_buffer_t)); fprintf(stderr, "Allocating %d bytes command buffer (max state is %d bytes)\n", diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c index 4943d549973..cadb27ba8b9 100644 --- a/src/mesa/drivers/dri/r300/r300_context.c +++ b/src/mesa/drivers/dri/r300/r300_context.c @@ -372,6 +372,61 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual, return GL_TRUE; } +static void r300FreeGartAllocations(r300ContextPtr r300) +{ + int i, ret, tries=0, done_age; + drm_radeon_mem_free_t memfree; + + memfree.region = RADEON_MEM_REGION_GART; + +#ifdef USER_BUFFERS + done_age = radeonGetAge((radeonContextPtr)r300); + + for (i = r300->rmm->u_last; i > 0; i--) { + if (r300->rmm->u_list[i].ptr == NULL) { + continue; + } + + assert(r300->rmm->u_list[i].pending); + assert(r300->rmm->u_list[i].h_pending == 0); + + tries = 0; + while(r300->rmm->u_list[i].age > done_age && tries++ < 1000) { + usleep(10); + done_age = radeonGetAge((radeonContextPtr)r300); + } + if (tries >= 1000) { + WARN_ONCE("Failed to idle region!"); + } + + memfree.region_offset = (char *)r300->rmm->u_list[i].ptr - + (char *)r300->radeon.radeonScreen->gartTextures.map; + + ret = drmCommandWrite(r300->radeon.radeonScreen->driScreen->fd, + DRM_RADEON_FREE, &memfree, sizeof(memfree)); + if (ret) { + fprintf(stderr, "Failed to free at %p\nret = %s\n", + r300->rmm->u_list[i].ptr, strerror(-ret)); + } else { + if (i == r300->rmm->u_last) + r300->rmm->u_last--; + + r300->rmm->u_list[i].pending = 0; + r300->rmm->u_list[i].ptr = NULL; + if (r300->rmm->u_list[i].fb) { + LOCK_HARDWARE(&(r300->radeon)); + ret = mmFreeMem(r300->rmm->u_list[i].fb); + UNLOCK_HARDWARE(&(r300->radeon)); + if (ret) fprintf(stderr, "failed to free!\n"); + r300->rmm->u_list[i].fb = NULL; + } + r300->rmm->u_list[i].ref_count = 0; + } + } + r300->rmm->u_head = i; +#endif /* USER_BUFFERS */ +} + /* Destroy the device specific context. */ void r300DestroyContext(__DRIcontextPrivate * driContextPriv) @@ -403,12 +458,11 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv) _ac_DestroyContext(r300->radeon.glCtx); _swrast_DestroyContext(r300->radeon.glCtx); - r300ReleaseArrays(r300->radeon.glCtx); if (r300->dma.current.buf) { r300ReleaseDmaRegion(r300, &r300->dma.current, __FUNCTION__ ); - r300FlushCmdBuf(r300, __FUNCTION__ ); } - + r300FlushCmdBuf(r300, __FUNCTION__); + r300FreeGartAllocations(r300); r300DestroyCmdBuf(r300); if (radeon->state.scissor.pClipRects) { diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 176341d7715..7ff805fd5d3 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -47,11 +47,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "colormac.h" #include "radeon_context.h" -/* PPC doesnt support 16 bit elts ... */ -#ifndef MESA_BIG_ENDIAN #define USER_BUFFERS #define RADEON_VTXFMT_A #define HW_VBOS + +/* We don't handle 16 bits elts swapping yet */ +#ifdef MESA_BIG_ENDIAN +#define FORCE_32BITS_ELTS #endif //#define OPTIMIZE_ELTS @@ -346,6 +348,21 @@ struct r300_state_atom { #define R300_FPP_PARAM_0 1 #define R300_FPP_CMDSIZE (32*4+1) +#define R300_FOGS_CMD_0 0 +#define R300_FOGS_STATE 1 +#define R300_FOGS_CMDSIZE 2 + +#define R300_FOGC_CMD_0 0 +#define R300_FOGC_R 1 +#define R300_FOGC_G 2 +#define R300_FOGC_B 3 +#define R300_FOGC_CMDSIZE 4 + +#define R300_FOGP_CMD_0 0 +#define R300_FOGP_SCALE 1 +#define R300_FOGP_START 2 +#define R300_FOGP_CMDSIZE 3 + #define R300_AT_CMD_0 0 #define R300_AT_ALPHA_TEST 1 #define R300_AT_UNKNOWN 2 @@ -432,6 +449,8 @@ struct r300_hw_state { struct r300_state_atom unk4260; /* (4260) */ struct r300_state_atom unk4274; /* (4274) */ struct r300_state_atom unk4288; /* (4288) */ + struct r300_state_atom fogp; /* fog parameters (4294) */ + struct r300_state_atom unk429C; /* (429C) */ struct r300_state_atom unk42A0; /* (42A0) */ struct r300_state_atom zbs; /* zbias (42A4) */ struct r300_state_atom unk42B4; /* (42B4) */ @@ -446,8 +465,8 @@ struct r300_hw_state { struct r300_state_atom fpt; /* texi - (4620) */ struct r300_state_atom unk46A4; /* (46A4) */ struct r300_state_atom fpi[4]; /* fp instructions (46C0/47C0/48C0/49C0) */ - struct r300_state_atom unk4BC0; /* (4BC0) */ - struct r300_state_atom unk4BC8; /* (4BC8) */ + struct r300_state_atom fogs; /* fog state (4BC0) */ + struct r300_state_atom fogc; /* fog color (4BC8) */ struct r300_state_atom at; /* alpha test (4BD4) */ struct r300_state_atom unk4BD8; /* (4BD8) */ struct r300_state_atom fpp; /* 0x4C00 and following */ @@ -532,7 +551,8 @@ struct r300_vap_reg_state { /* Vertex shader state */ /* Perhaps more if we store programs in vmem? */ -#define VSF_MAX_FRAGMENT_LENGTH (256*4) +/* drm_r300_cmd_header_t->vpu->count is unsigned char */ +#define VSF_MAX_FRAGMENT_LENGTH (255*4) /* Can be tested with colormat currently. */ #define VSF_MAX_FRAGMENT_TEMPS (14) @@ -759,7 +779,7 @@ struct r300_state { GLuint *Elts; struct r300_dma_region elt_dma; - GLuint render_inputs; /* actual render inputs that R300 was configured for. + DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for. They are the same as tnl->render_inputs for fixed pipeline */ struct { @@ -810,6 +830,7 @@ struct r300_context { #endif GLboolean texmicrotile; + GLboolean span_dlocking; }; struct r300_buffer_object { diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c index db509059dd7..e045f0c6a1e 100644 --- a/src/mesa/drivers/dri/r300/r300_fragprog.c +++ b/src/mesa/drivers/dri/r300/r300_fragprog.c @@ -1039,7 +1039,7 @@ static GLboolean parse_program(struct r300_fragment_program *rp) const struct prog_instruction *inst = mp->Base.Instructions; struct prog_instruction *fpi; pfs_reg_t src[3], dest, temp; - int flags, mask; + int flags, mask = 0; if (!inst || inst[0].Opcode == OPCODE_END) { ERROR("empty program?\n"); diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c index 0115d622a99..159285962d2 100644 --- a/src/mesa/drivers/dri/r300/r300_ioctl.c +++ b/src/mesa/drivers/dri/r300/r300_ioctl.c @@ -380,10 +380,16 @@ static void r300EmitClearState(GLcontext * ctx) int i; LOCAL_VARS; + R300_STATECHANGE(r300, vir[0]); reg_start(R300_VAP_INPUT_ROUTE_0_0, 0); e32(0x21030003); + /* disable fog */ + R300_STATECHANGE(r300, fogs); + reg_start(R300_RE_FOG_STATE, 0); + e32(0x0); + R300_STATECHANGE(r300, vir[1]); reg_start(R300_VAP_INPUT_ROUTE_1_0, 0); e32(0xF688F688); @@ -553,7 +559,7 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all, #ifdef CB_DPATH /* Make sure it fits there. */ - r300EnsureCmdBufSpace(r300, 419*3, __FUNCTION__); + r300EnsureCmdBufSpace(r300, 421*3, __FUNCTION__); if(flags || bits) r300EmitClearState(ctx); #endif diff --git a/src/mesa/drivers/dri/r300/r300_maos.c b/src/mesa/drivers/dri/r300/r300_maos.c index 1aa005c7207..6b8365e6d9e 100644 --- a/src/mesa/drivers/dri/r300/r300_maos.c +++ b/src/mesa/drivers/dri/r300/r300_maos.c @@ -252,6 +252,43 @@ void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts, int elt_siz memcpy(out, elts, n_elts * elt_size); } + /* Mesa assumes that all missing components are from (0, 0, 0, 1) */ +#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT)) + +#define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \ + | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT)) + + +static GLuint t_comps(GLuint aos_size) +{ + GLuint mask; + mask = (1 << (aos_size*3)) - 1; + return (ALL_COMPONENTS & mask) | (ALL_DEFAULT & ~mask); +} + +static GLuint fix_comps(GLuint dw, int fmt) +{ +#ifdef MESA_BIG_ENDIAN + if (fmt == 2) { + GLuint dw_temp = 0; + + dw_temp |= ((dw >> R300_INPUT_ROUTE_X_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_W_SHIFT; + dw_temp |= ((dw >> R300_INPUT_ROUTE_Y_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_Z_SHIFT; + dw_temp |= ((dw >> R300_INPUT_ROUTE_Z_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_Y_SHIFT; + dw_temp |= ((dw >> R300_INPUT_ROUTE_W_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_X_SHIFT; + + return dw_temp; + } +#endif /* MESA_BIG_ENDIAN */ + return dw; + +} + /* Emit vertex data to GART memory (unless immediate mode) * Route inputs to the vertex processor */ @@ -264,12 +301,14 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) //struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; GLuint nr = 0; GLuint count = VB->Count; - GLuint dw,mask; + GLuint dw; GLuint vic_1 = 0; /* R300_VAP_INPUT_CNTL_1 */ GLuint aa_vap_reg = 0; /* VAP register assignment */ GLuint i; - GLuint inputs = 0; - + DECLARE_RENDERINPUTS(inputs_bitset); + + RENDERINPUTS_ZERO( inputs_bitset ); + #define CONFIGURE_AOS(r, f, v, sz, cn) { \ if (RADEON_DEBUG & DEBUG_STATE) \ fprintf(stderr, "Enabling "#v "\n"); \ @@ -300,23 +339,23 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) GLuint InputsRead = CURRENT_VERTEX_SHADER(ctx)->Base.InputsRead; struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx); if (InputsRead & (1<<VERT_ATTRIB_POS)) { - inputs |= _TNL_BIT_POS; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_POS ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_POS]; } if (InputsRead & (1<<VERT_ATTRIB_NORMAL)) { - inputs |= _TNL_BIT_NORMAL; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_NORMAL ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_NORMAL]; } if (InputsRead & (1<<VERT_ATTRIB_COLOR0)) { - inputs |= _TNL_BIT_COLOR0; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_COLOR0 ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR0]; } if (InputsRead & (1<<VERT_ATTRIB_COLOR1)) { - inputs |= _TNL_BIT_COLOR1; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_COLOR1 ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR1]; } if (InputsRead & (1<<VERT_ATTRIB_FOG)) { - inputs |= _TNL_BIT_FOG; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_FOG ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_FOG]; } if(ctx->Const.MaxTextureUnits > 8) { /* Not sure if this can even happen... */ @@ -325,17 +364,17 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) } for (i=0;i<ctx->Const.MaxTextureUnits;i++) { if (InputsRead & (1<<(VERT_ATTRIB_TEX0+i))) { - inputs |= _TNL_BIT_TEX0<<i; + RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_TEX(i) ); rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_TEX0+i]; } } nr = 0; } else { - inputs = TNL_CONTEXT(ctx)->render_inputs; + RENDERINPUTS_COPY( inputs_bitset, TNL_CONTEXT(ctx)->render_inputs_bitset ); } - rmesa->state.render_inputs = inputs; + RENDERINPUTS_COPY( rmesa->state.render_inputs_bitset, inputs_bitset ); - if (inputs & _TNL_BIT_POS) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_POS )) { CONFIGURE_AOS(i_coords, AOS_FORMAT_FLOAT, VB->AttribPtr[VERT_ATTRIB_POS], immd ? 4 : VB->AttribPtr[VERT_ATTRIB_POS].size, @@ -344,7 +383,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) vic_1 |= R300_INPUT_CNTL_POS; } - if (inputs & _TNL_BIT_NORMAL) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_NORMAL )) { CONFIGURE_AOS(i_normal, AOS_FORMAT_FLOAT, VB->AttribPtr[VERT_ATTRIB_NORMAL], immd ? 4 : VB->AttribPtr[VERT_ATTRIB_NORMAL].size, @@ -353,7 +392,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) vic_1 |= R300_INPUT_CNTL_NORMAL; } - if (inputs & _TNL_BIT_COLOR0) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR0 )) { int emitsize=4; if (!immd) { @@ -376,7 +415,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) vic_1 |= R300_INPUT_CNTL_COLOR; } - if (inputs & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR1 )) { int emitsize=4; if (!immd) { @@ -398,7 +437,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) } #if 0 - if (inputs & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_FOG )) { CONFIGURE_AOS( AOS_FORMAT_FLOAT, VB->FogCoordPtr, immd ? 4 : VB->FogCoordPtr->size, @@ -408,7 +447,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) r300->state.texture.tc_count = 0; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { - if (inputs & (_TNL_BIT_TEX0 << i)) { + if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_TEX(i) )) { CONFIGURE_AOS(i_tex[i], AOS_FORMAT_FLOAT, VB->AttribPtr[VERT_ATTRIB_TEX0+i], immd ? 4 : VB->AttribPtr[VERT_ATTRIB_TEX0+i].size, @@ -467,17 +506,6 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = (nr+1)>>1; - /* Mesa assumes that all missing components are from (0, 0, 0, 1) */ -#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT)) - -#define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \ - | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT)) - R300_STATECHANGE(r300, vir[1]); for(i=0; i < nr; i++) @@ -486,33 +514,22 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) r300->state.aos[i].aos_size=/*3*/4; /* XXX */ } - - for(i=0;i+1<nr;i+=2){ + for (i=0;i+1<nr;i+=2) { /* do i first.. */ - mask=(1<<(r300->state.aos[i].aos_size*3))-1; - dw=(ALL_COMPONENTS & mask) - | (ALL_DEFAULT & ~mask) - | R300_INPUT_ROUTE_ENABLE; - + dw = fix_comps(t_comps(r300->state.aos[i].aos_size), r300->state.aos[i].aos_format) | R300_INPUT_ROUTE_ENABLE; /* i+1 */ - mask=(1<<(r300->state.aos[i+1].aos_size*3))-1; - dw|=( - (ALL_COMPONENTS & mask) - | (ALL_DEFAULT & ~mask) - | R300_INPUT_ROUTE_ENABLE - )<<16; - + dw |= (fix_comps(t_comps(r300->state.aos[i+1].aos_size), r300->state.aos[i+1].aos_format) | R300_INPUT_ROUTE_ENABLE) << 16; + //fprintf(stderr, "vir1 dw=%08x\n", dw); r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw; - } - if(nr & 1){ - mask=(1<<(r300->state.aos[nr-1].aos_size*3))-1; - dw=(ALL_COMPONENTS & mask) - | (ALL_DEFAULT & ~mask) - | R300_INPUT_ROUTE_ENABLE; - r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw; + } + if (nr & 1) { + dw = fix_comps(t_comps(r300->state.aos[nr-1].aos_size), r300->state.aos[nr-1].aos_format) | R300_INPUT_ROUTE_ENABLE; + //fprintf(stderr, "vir1 dw=%08x\n", dw); - } + r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw; + } + /* Set the rest of INPUT_ROUTE_1 to 0 */ //for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=0x0; ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->packet0.count = (nr+1)>>1; @@ -531,17 +548,17 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) #if 0 r300->hw.vic.cmd[R300_VIC_CNTL_1]=0; - if(r300->state.render_inputs & _TNL_BIT_POS) + if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_POS )) r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_POS; - if(r300->state.render_inputs & _TNL_BIT_NORMAL) + if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_NORMAL )) r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_NORMAL; - if(r300->state.render_inputs & _TNL_BIT_COLOR0) + if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_COLOR0 )) r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_COLOR; for(i=0;i < ctx->Const.MaxTextureUnits;i++) - if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)) + if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_TEX(i) )) r300->hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<<i); #endif @@ -573,15 +590,15 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd) if(OutputsWritten & (1<<(VERT_RESULT_TEX0+i))) r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4<<(3*i)); } else { - if(inputs & _TNL_BIT_POS) + if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_POS )) r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; - if(inputs & _TNL_BIT_COLOR0) + if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR0 )) r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT; - if(inputs & _TNL_BIT_COLOR1) + if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR1 )) r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT; for(i=0;i < ctx->Const.MaxTextureUnits;i++) - if(inputs & (_TNL_BIT_TEX0<<i)) + if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_TEX(i) )) r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i)); } diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h index c78462af2ed..4afe4f239c2 100644 --- a/src/mesa/drivers/dri/r300/r300_reg.h +++ b/src/mesa/drivers/dri/r300/r300_reg.h @@ -517,6 +517,10 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PM_BACK_LINE (1 << 7) # define R300_PM_BACK_FILL (1 << 8) +/* Fog parameters */ +#define R300_RE_FOG_SCALE 0x4294 +#define R300_RE_FOG_START 0x4298 + /* Not sure why there are duplicate of factor and constant values. My best guess so far is that there are seperate zbiases for test and write. Ordering might be wrong. @@ -1113,7 +1117,17 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI2_UNKNOWN_31 (1 << 31) /* END */ -/* gap */ +/* Fog state and color */ +#define R300_RE_FOG_STATE 0x4BC0 +# define R300_FOG_ENABLE (1 << 0) +# define R300_FOG_MODE_LINEAR (0 << 1) +# define R300_FOG_MODE_EXP (1 << 1) +# define R300_FOG_MODE_EXP2 (2 << 1) +# define R300_FOG_MODE_MASK (3 << 1) +#define R300_FOG_COLOR_R 0x4BC8 +#define R300_FOG_COLOR_G 0x4BCC +#define R300_FOG_COLOR_B 0x4BD0 + #define R300_PP_ALPHA_TEST 0x4BD4 # define R300_REF_ALPHA_MASK 0x000000ff # define R300_ALPHA_TEST_FAIL (0 << 8) diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c index a0375f90227..f86a439bc29 100644 --- a/src/mesa/drivers/dri/r300/r300_render.c +++ b/src/mesa/drivers/dri/r300/r300_render.c @@ -382,7 +382,6 @@ GLboolean r300_run_vb_render(GLcontext *ctx, r300UpdateShaders(rmesa); if (rmesa->state.VB.LockCount == 0 || 1) { - r300ReleaseArrays(ctx); r300EmitArrays(ctx, GL_FALSE); r300UpdateShaderStates(rmesa); @@ -446,6 +445,7 @@ GLboolean r300_run_vb_render(GLcontext *ctx, #ifdef USER_BUFFERS r300UseArrays(ctx); #endif + r300ReleaseArrays(ctx); return GL_FALSE; } @@ -462,19 +462,19 @@ int r300Fallback(GLcontext *ctx) { int i; - //FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?) + FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?) #if 0 /* These should work now.. */ FALLBACK_IF(ctx->Color.DitherFlag); FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL + FALLBACK_IF(ctx->Fog.Enabled); #endif FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST - //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this //FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index d4dafe62a73..70d42c2ea3b 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -417,6 +417,24 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state) case GL_TEXTURE_3D: break; + case GL_FOG: + R300_STATECHANGE(r300, fogs); + if (state) { + r300->hw.fogs.cmd[R300_FOGS_STATE] |= + R300_FOG_ENABLE; + + ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL ); + ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); + ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); + ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); + ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); + } else { + r300->hw.fogs.cmd[R300_FOGS_STATE] &= + ~R300_FOG_ENABLE; + } + + break; + case GL_ALPHA_TEST: R300_STATECHANGE(r300, at); if (state) { @@ -640,6 +658,101 @@ static void r300ColorMask(GLcontext* ctx, } /* ============================================================= + * Fog + */ +static void r300Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) +{ + r300ContextPtr r300 = R300_CONTEXT(ctx); + union { int i; float f; } fogScale, fogStart; + + (void) param; + + fogScale.i = r300->hw.fogp.cmd[R300_FOGP_SCALE]; + fogStart.i = r300->hw.fogp.cmd[R300_FOGP_START]; + + switch (pname) { + case GL_FOG_MODE: + if (!ctx->Fog.Enabled) + return; + switch (ctx->Fog.Mode) { + case GL_LINEAR: + R300_STATECHANGE(r300, fogs); + r300->hw.fogs.cmd[R300_FOGS_STATE] = + (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_LINEAR; + + if (ctx->Fog.Start == ctx->Fog.End) { + fogScale.f = -1.0; + fogStart.f = 1.0; + } + else { + fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start); + fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start); + } + break; + case GL_EXP: + R300_STATECHANGE(r300, fogs); + r300->hw.fogs.cmd[R300_FOGS_STATE] = + (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP; + fogScale.f = 0.0933*ctx->Fog.Density; + fogStart.f = 0.0; + break; + case GL_EXP2: + R300_STATECHANGE(r300, fogs); + r300->hw.fogs.cmd[R300_FOGS_STATE] = + (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP2; + fogScale.f = 0.3*ctx->Fog.Density; + fogStart.f = 0.0; + default: + return; + } + break; + case GL_FOG_DENSITY: + switch (ctx->Fog.Mode) { + case GL_EXP: + fogScale.f = 0.0933*ctx->Fog.Density; + fogStart.f = 0.0; + break; + case GL_EXP2: + fogScale.f = 0.3*ctx->Fog.Density; + fogStart.f = 0.0; + default: + break; + } + break; + case GL_FOG_START: + case GL_FOG_END: + if (ctx->Fog.Mode == GL_LINEAR) { + if (ctx->Fog.Start == ctx->Fog.End) { + fogScale.f = -1.0; + fogStart.f = 1.0; + } + else { + fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start); + fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start); + } + } + break; + case GL_FOG_COLOR: + R300_STATECHANGE(r300, fogc); + r300->hw.fogc.cmd[R300_FOGC_R] = (GLuint) (ctx->Fog.Color[0]*1023.0F) & 0x3FF; + r300->hw.fogc.cmd[R300_FOGC_G] = (GLuint) (ctx->Fog.Color[1]*1023.0F) & 0x3FF; + r300->hw.fogc.cmd[R300_FOGC_B] = (GLuint) (ctx->Fog.Color[2]*1023.0F) & 0x3FF; + break; + case GL_FOG_COORD_SRC: + break; + default: + return; + } + + if (fogScale.i != r300->hw.fogp.cmd[R300_FOGP_SCALE] || + fogStart.i != r300->hw.fogp.cmd[R300_FOGP_START]) { + R300_STATECHANGE(r300, fogp); + r300->hw.fogp.cmd[R300_FOGP_SCALE] = fogScale.i; + r300->hw.fogp.cmd[R300_FOGP_START] = fogStart.i; + } +} + +/* ============================================================= * Point state */ static void r300PointSize(GLcontext * ctx, GLfloat size) @@ -750,8 +863,8 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref, GLuint mask) { r300ContextPtr rmesa = R300_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | - (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); + GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R300_RB3D_ZS2_STENCIL_REF_SHIFT) | + ((ctx->Stencil.ValueMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_MASK_SHIFT)); GLuint flag; @@ -777,7 +890,7 @@ static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask) R300_STATECHANGE(rmesa, zs); rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT); - rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT; + rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= (ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT; } @@ -807,9 +920,9 @@ static void r300ClearStencil(GLcontext * ctx, GLint s) r300ContextPtr rmesa = R300_CONTEXT(ctx); rmesa->state.stencil.clear = - ((GLuint) ctx->Stencil.Clear | + ((GLuint) (ctx->Stencil.Clear & 0xff) | (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) | - (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT)); + ((ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT)); } /* ============================================================= @@ -1157,6 +1270,15 @@ void r300_setup_textures(GLcontext *ctx) fprintf(stderr, "TX_ENABLE: %08x last_hw_tmu=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], last_hw_tmu); } +union r300_outputs_written { + GLuint vp_outputs; /* hw_tcl_on */ + DECLARE_RENDERINPUTS(index_bitset); /* !hw_tcl_on */ +}; + +#define R300_OUTPUTS_WRITTEN_TEST(ow, vp_result, tnl_attrib) \ + ((hw_tcl_on) ? (ow).vp_outputs & (1 << (vp_result)) : \ + RENDERINPUTS_TEST( (ow.index_bitset), (tnl_attrib) )) + void r300_setup_rs_unit(GLcontext *ctx) { r300ContextPtr r300 = R300_CONTEXT(ctx); @@ -1171,16 +1293,16 @@ void r300_setup_rs_unit(GLcontext *ctx) 0x00, 0x00 }; - GLuint OutputsWritten; + union r300_outputs_written OutputsWritten; GLuint InputsRead; int fp_reg, high_rr; int in_texcoords, col_interp_nr; int i; if(hw_tcl_on) - OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; + OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten; else - OutputsWritten = r300->state.render_inputs; + RENDERINPUTS_COPY( OutputsWritten.index_bitset, r300->state.render_inputs_bitset ); if (ctx->FragmentProgram._Current) InputsRead = ctx->FragmentProgram._Current->Base.InputsRead; @@ -1211,7 +1333,7 @@ void r300_setup_rs_unit(GLcontext *ctx) | (fp_reg << R300_RS_ROUTE_DEST_SHIFT); high_rr = fp_reg; - if (!(OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i)))) { + if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) )) { /* Passing invalid data here can lock the GPU. */ WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i); //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base); @@ -1221,12 +1343,12 @@ void r300_setup_rs_unit(GLcontext *ctx) fp_reg++; } /* Need to count all coords enabled at vof */ - if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i))) + if (R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) )) in_texcoords++; } if (InputsRead & FRAG_BIT_COL0) { - if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL0) : _TNL_BIT_COLOR0))) { + if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0 )) { WARN_ONCE("fragprog wants col0, vp doesn't provide it\n"); goto out; /* FIXME */ //_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base); @@ -1242,7 +1364,7 @@ void r300_setup_rs_unit(GLcontext *ctx) out: if (InputsRead & FRAG_BIT_COL1) { - if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL1) : _TNL_BIT_COLOR1))) { + if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1 )) { WARN_ONCE("fragprog wants col1, vp doesn't provide it\n"); //exit(-1); } @@ -1281,6 +1403,7 @@ void r300_setup_rs_unit(GLcontext *ctx) #define bump_vpu_count(ptr, new_count) do{\ drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\ int _nc=(new_count)/4; \ + assert(_nc < 256); \ if(_nc>_p->vpu.count)_p->vpu.count=_nc;\ }while(0) @@ -1402,7 +1525,7 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300) ) o_reg += 2; - if (r300->state.render_inputs & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_COLOR1 )) { WRITE_OP( EASY_VSF_OP(MUL, o_reg++, ALL, RESULT), VSF_REG(r300->state.vap_reg.i_color[1]), @@ -1413,7 +1536,7 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300) /* Pass through texture coordinates, if any */ for(i=0;i < r300->radeon.glCtx->Const.MaxTextureUnits;i++) - if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)){ + if (RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_TEX(i) )){ // fprintf(stderr, "i_tex[%d]=%d\n", i, r300->state.vap_reg.i_tex[i]); WRITE_OP( EASY_VSF_OP(MUL, o_reg++ /* 2+i */, ALL, RESULT), @@ -1870,7 +1993,8 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE | R300_GB_TILE_PIPE_COUNT_RV300 | R300_GB_TILE_SIZE_16; - r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = 0x00000000; + /* set to 0 when fog is disabled? */ + r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = R300_GB_FOG_SELECT_1_1_W; r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = 0x00000000; /* No antialiasing */ //r300->hw.txe.cmd[R300_TXE_ENABLE] = 0; @@ -1907,9 +2031,6 @@ void r300ResetHwState(r300ContextPtr r300) r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode); r300->hw.unk4288.cmd[2] = 0x00000001; r300->hw.unk4288.cmd[3] = 0x00000000; - r300->hw.unk4288.cmd[4] = 0x00000000; - r300->hw.unk4288.cmd[5] = 0x00000000; - r300->hw.unk42A0.cmd[1] = 0x00000000; r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits); @@ -1949,13 +2070,13 @@ void r300ResetHwState(r300ContextPtr r300) r300->hw.fpi[3].cmd[i] = FP_SELA(0,W,NO,FP_TMP(0),0,0); } #endif - - r300->hw.unk4BC0.cmd[1] = 0; - - r300->hw.unk4BC8.cmd[1] = 0; - r300->hw.unk4BC8.cmd[2] = 0; - r300->hw.unk4BC8.cmd[3] = 0; - + r300Enable(ctx, GL_FOG, ctx->Fog.Enabled); + ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL ); + ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); + ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); + ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); + ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); + ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL ); r300->hw.at.cmd[R300_AT_UNKNOWN] = 0; r300->hw.unk4BD8.cmd[1] = 0; @@ -2128,6 +2249,7 @@ void r300InitStateFuncs(struct dd_function_table* functions) functions->DepthFunc = r300DepthFunc; functions->DepthMask = r300DepthMask; functions->CullFace = r300CullFace; + functions->Fogfv = r300Fogfv; functions->FrontFace = r300FrontFace; functions->ShadeModel = r300ShadeModel; diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c index a9f64b47c4c..c1d01020cdb 100644 --- a/src/mesa/drivers/dri/r300/r300_texmem.c +++ b/src/mesa/drivers/dri/r300/r300_texmem.c @@ -130,6 +130,12 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, srcPitch = t->image[0][0].width * texFormat->TexelBytes; dstPitch = t->image[0][0].width * texFormat->TexelBytes; break; + case 8: + case 16: + blit_format = R200_CP_COLOR_FORMAT_CI8; + srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes; + break; default: return; } @@ -144,6 +150,10 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, width = texImage->Width; height = texImage->Height; + if (texFormat->TexelBytes > 4) { + width *= texFormat->TexelBytes; + } + r300EmitWait(rmesa, R300_WAIT_3D); r300EmitBlit(rmesa, blit_format, @@ -177,6 +187,10 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, case 4: blit_format = R200_CP_COLOR_FORMAT_ARGB8888; break; + case 8: + case 16: + blit_format = R200_CP_COLOR_FORMAT_CI8; + break; default: return; } @@ -189,6 +203,10 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, height = texImage->Height; dstPitch = t->pitch; + if (texFormat->TexelBytes > 4) { + width *= texFormat->TexelBytes; + } + if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) { /* In this case, could also use GART texturing. This is * currently disabled, but has been tested & works. diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c index f794c9aa67a..9e32cfcfef9 100644 --- a/src/mesa/drivers/dri/r300/r300_vertexprog.c +++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c @@ -916,6 +916,16 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp) fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode); exit(-1); break; + case OPCODE_SWZ: + hw_op=(src[0].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD; + + o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg), + t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File)); + o_inst->src1=t_src(vp, &src[0]); + o_inst->src2=ONE_SRC_0; + o_inst->src3=ZERO_SRC_0; + + goto next; case OPCODE_END: break; default: diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c index 4e351dd66b0..0147c6492e5 100644 --- a/src/mesa/drivers/dri/r300/radeon_context.c +++ b/src/mesa/drivers/dri/r300/radeon_context.c @@ -76,7 +76,7 @@ static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name) case GL_RENDERER: { unsigned offset; - GLuint agp_mode = radeon->radeonScreen->IsPCI ? 0 : + GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 : radeon->radeonScreen->AGPMode; const char* chipname; diff --git a/src/mesa/drivers/dri/r300/radeon_span.c b/src/mesa/drivers/dri/r300/radeon_span.c index 1f000b97666..1b74f6779b4 100644 --- a/src/mesa/drivers/dri/r300/radeon_span.c +++ b/src/mesa/drivers/dri/r300/radeon_span.c @@ -40,7 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Keith Whitwell <[email protected]> * */ - +#include <unistd.h> #include "glheader.h" #include "imports.h" #include "swrast/swrast.h" @@ -252,6 +252,29 @@ do { \ static void radeonSpanRenderStart( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + { + static int first = 1; + r300ContextPtr r300 = (r300ContextPtr)rmesa; + + if (first) { + r300->span_dlocking = getenv("R300_SPAN_DISABLE_LOCKING") ? 1 : 0; + if (r300->span_dlocking == 0) { + fprintf(stderr, "Try R300_SPAN_DISABLE_LOCKING env var if this hangs.\n"); + fflush(stderr); + sleep(1); + } + first = 0; + } + + if (r300->span_dlocking) { + r300Flush(ctx); + LOCK_HARDWARE( rmesa ); + radeonWaitForIdleLocked( rmesa ); + UNLOCK_HARDWARE( rmesa ); + + return; + } + } // R300_FIREVERTICES( rmesa ); // old code has flush r300Flush(ctx); @@ -262,8 +285,10 @@ static void radeonSpanRenderStart( GLcontext *ctx ) static void radeonSpanRenderFinish( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + r300ContextPtr r300 = (r300ContextPtr)rmesa; _swrast_flush( ctx ); - UNLOCK_HARDWARE( rmesa ); + if (r300->span_dlocking == 0) + UNLOCK_HARDWARE( rmesa ); } void radeonInitSpanFuncs( GLcontext *ctx ) diff --git a/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c index 5ea9bb4eb45..1044973b001 100644 --- a/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c +++ b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c @@ -71,7 +71,7 @@ void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, st CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]); CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr); - for (i=0; i < MAX_TEXTURE_COORD_UNITS; i++) + for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++) CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]); rvb->Primitive = vb->Primitive; @@ -182,7 +182,7 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G unsigned int min = ~0, max = 0; struct tnl_prim prim; static void *ptr = NULL; - static struct r300_dma_region rvb; + struct r300_dma_region rvb; const GLvoid *indices = c_indices; if (count > 65535) { @@ -205,8 +205,8 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G return; FLUSH_CURRENT( ctx, 0 ); - r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); + memset(&rvb, 0, sizeof(rvb)); switch (type) { case GL_UNSIGNED_BYTE: for (i=0; i < count; i++) { @@ -216,14 +216,22 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G max = ((unsigned char *)indices)[i]; } +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else elt_size = 2; - +#endif r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size); rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; +#ifdef FORCE_32BITS_ELTS + for (i=0; i < count; i++) + ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min; +#else for (i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min; +#endif break; case GL_UNSIGNED_SHORT: @@ -234,14 +242,23 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G max = ((unsigned short int *)indices)[i]; } +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else elt_size = 2; +#endif r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size); rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; +#ifdef FORCE_32BITS_ELTS + for (i=0; i < count; i++) + ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min; +#else for (i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min; +#endif break; case GL_UNSIGNED_INT: @@ -252,17 +269,20 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G max = ((unsigned int *)indices)[i]; } +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else if (max - min <= 65535) elt_size = 2; else elt_size = 4; - +#endif r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size); rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; - if (max - min <= 65535) + if (elt_size == 2) for (i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min; else @@ -278,12 +298,12 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G if (ctx->NewState) _mesa_update_state( ctx ); - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i]; TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i]; } r300UpdateShaders(rmesa); - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i]; } @@ -311,8 +331,10 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G return; } } else { - if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) + if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) { + r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); goto fallback; + } rmesa->state.VB.Count = max - min + 1; } @@ -337,6 +359,7 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G if(rvb.buf) radeon_mm_use(rmesa, rvb.buf->id); + r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); return; fallback: @@ -355,7 +378,7 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei int elt_size; int i; void *ptr = NULL; - static struct r300_dma_region rvb; + struct r300_dma_region rvb; const GLvoid *indices = c_indices; if (count > 65535) { @@ -381,23 +404,34 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei #ifdef OPTIMIZE_ELTS min = 0; #endif - r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); - switch(type){ + memset(&rvb, 0, sizeof(rvb)); + switch (type){ case GL_UNSIGNED_BYTE: +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else elt_size = 2; - +#endif r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size); rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; +#ifdef FORCE_32BITS_ELTS + for(i=0; i < count; i++) + ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min; +#else for(i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min; +#endif break; case GL_UNSIGNED_SHORT: +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else elt_size = 2; - +#endif #ifdef OPTIMIZE_ELTS if (min == 0 && ctx->Array.ElementArrayBufferObj->Name){ ptr = indices; @@ -408,21 +442,29 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; +#ifdef FORCE_32BITS_ELTS + for(i=0; i < count; i++) + ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min; +#else for(i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min; +#endif break; case GL_UNSIGNED_INT: +#ifdef FORCE_32BITS_ELTS + elt_size = 4; +#else if (max - min <= 65535) elt_size = 2; else elt_size = 4; - +#endif r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size); rvb.aos_offset = GET_START(&rvb); ptr = rvb.address + rvb.start; - if (max - min <= 65535) + if (elt_size == 2) for (i=0; i < count; i++) ((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min; else @@ -440,12 +482,12 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei if (ctx->NewState) _mesa_update_state( ctx ); - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i]; TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i]; } r300UpdateShaders(rmesa); - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i]; } @@ -473,8 +515,10 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei return; }*/ } else { - if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) + if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) { + r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); goto fallback; + } rmesa->state.VB.Count = max - min + 1; } @@ -501,6 +545,7 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei if(rvb.buf) radeon_mm_use(rmesa, rvb.buf->id); + r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__); return ; fallback: @@ -533,12 +578,12 @@ static void radeonDrawArrays( GLenum mode, GLint start, GLsizei count ) /* XXX: setup_arrays before state update? */ - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i]; TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i]; } r300UpdateShaders(rmesa); - for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i]; } diff --git a/src/mesa/drivers/dri/radeon/Makefile b/src/mesa/drivers/dri/radeon/Makefile index 34dc58e2dc2..6e46620b397 100644 --- a/src/mesa/drivers/dri/radeon/Makefile +++ b/src/mesa/drivers/dri/radeon/Makefile @@ -32,7 +32,7 @@ C_SOURCES = \ $(COMMON_SOURCES) \ $(DRIVER_SOURCES) -DEFINES += -DRADEON_COMMON=0 +DRIVER_DEFINES = -DRADEON_COMMON=0 X86_SOURCES = \ radeon_vtxtmp_x86.S diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c index 791d1a37bc0..21161d2f69d 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.c +++ b/src/mesa/drivers/dri/radeon/radeon_context.c @@ -102,7 +102,7 @@ static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name ) radeonContextPtr rmesa = RADEON_CONTEXT(ctx); static char buffer[128]; unsigned offset; - GLuint agp_mode = rmesa->radeonScreen->IsPCI ? 0 : + GLuint agp_mode = (rmesa->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 : rmesa->radeonScreen->AGPMode; switch ( name ) { @@ -521,10 +521,6 @@ void radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) radeonVtxfmtDestroy( rmesa->glCtx ); } - /* free the Mesa context */ - rmesa->glCtx->DriverCtx = NULL; - _mesa_destroy_context( rmesa->glCtx ); - _mesa_vector4f_free( &rmesa->tcl.ObjClean ); if (rmesa->state.scissor.pClipRects) { @@ -546,6 +542,10 @@ void radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) assert( is_empty_list( & rmesa->swapped ) ); } + /* free the Mesa context */ + rmesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context( rmesa->glCtx ); + /* free the option cache */ driDestroyOptionCache (&rmesa->optionCache); diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h index 9abd8667308..9902e60c595 100644 --- a/src/mesa/drivers/dri/radeon/radeon_context.h +++ b/src/mesa/drivers/dri/radeon/radeon_context.h @@ -735,7 +735,7 @@ struct radeon_context { GLuint TclFallback; GLuint Fallback; GLuint NewGLState; - GLuint tnl_index; /* index of bits for last tnl_install_attrs */ + DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */ /* Vertex buffers */ diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c index 5257e541e5f..3a0a8d208b2 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.c +++ b/src/mesa/drivers/dri/radeon/radeon_screen.c @@ -159,7 +159,7 @@ DRI_CONF_BEGIN DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN) DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) - DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(16, 2, 16) + DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(8, 2, 8) DRI_CONF_MAX_TEXTURE_COORD_UNITS(8, 2, 8) DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32) DRI_CONF_SECTION_END @@ -209,6 +209,19 @@ extern const struct dri_extension card_extensions[]; static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ); +static int +radeonGetParam(int fd, int param, void *value) +{ + int ret; + drm_radeon_getparam_t gp; + + gp.param = param; + gp.value = value; + + ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp)); + return ret; +} + static __GLcontextModes * radeonFillInModes( unsigned pixel_bits, unsigned depth_bits, unsigned stencil_bits, GLboolean have_back_buffer ) @@ -326,52 +339,39 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv ) /* This is first since which regions we map depends on whether or * not we are using a PCI card. */ - screen->IsPCI = dri_priv->IsPCI; - + screen->card_type = (dri_priv->IsPCI ? RADEON_CARD_PCI : RADEON_CARD_AGP); { int ret; - drm_radeon_getparam_t gp; - - gp.param = RADEON_PARAM_GART_BUFFER_OFFSET; - gp.value = &screen->gart_buffer_offset; - - ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, - &gp, sizeof(gp)); + ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BUFFER_OFFSET, + &screen->gart_buffer_offset); + if (ret) { FREE( screen ); fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret); return NULL; } - if (sPriv->drmMinor >= 6) { - gp.param = RADEON_PARAM_GART_BASE; - gp.value = &screen->gart_base; - - ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, - &gp, sizeof(gp)); - if (ret) { - FREE( screen ); - fprintf(stderr, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret); - return NULL; - } - - gp.param = RADEON_PARAM_IRQ_NR; - gp.value = &screen->irq; - - ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, - &gp, sizeof(gp)); - if (ret) { - FREE( screen ); - fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret); - return NULL; - } - screen->drmSupportsCubeMapsR200 = (sPriv->drmMinor >= 7); - screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11); - screen->drmSupportsTriPerf = (sPriv->drmMinor >= 16); - screen->drmSupportsFragShader = (sPriv->drmMinor >= 18); - screen->drmSupportsPointSprites = (sPriv->drmMinor >= 13); - screen->drmSupportsCubeMapsR100 = (sPriv->drmMinor >= 15); + ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BASE, + &screen->gart_base); + if (ret) { + FREE( screen ); + fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BASE): %d\n", ret); + return NULL; + } + + ret = radeonGetParam( sPriv->fd, RADEON_PARAM_IRQ_NR, + &screen->irq); + if (ret) { + FREE( screen ); + fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret); + return NULL; } + screen->drmSupportsCubeMapsR200 = (sPriv->drmMinor >= 7); + screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11); + screen->drmSupportsTriPerf = (sPriv->drmMinor >= 16); + screen->drmSupportsFragShader = (sPriv->drmMinor >= 18); + screen->drmSupportsPointSprites = (sPriv->drmMinor >= 13); + screen->drmSupportsCubeMapsR100 = (sPriv->drmMinor >= 15); } screen->mmio.handle = dri_priv->registerHandle; @@ -425,9 +425,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv ) return NULL; } - screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI - ? INREG( RADEON_AIC_LO_ADDR ) - : ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) ); + screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base; } screen->chip_flags = 0; @@ -976,12 +974,12 @@ __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, static const char *driver_name = "Radeon"; static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 }; static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = { 1, 3, 0 }; + static const __DRIversion drm_expected = { 1, 6, 0 }; #elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R200) static const char *driver_name = "R200"; static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 }; static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = { 1, 5, 0 }; + static const __DRIversion drm_expected = { 1, 6, 0 }; #elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300) static const char *driver_name = "R300"; static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 }; diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h index 08433c445b8..3e0f9454e7f 100644 --- a/src/mesa/drivers/dri/radeon/radeon_screen.h +++ b/src/mesa/drivers/dri/radeon/radeon_screen.h @@ -59,7 +59,7 @@ typedef struct { int chip_family; int chip_flags; int cpp; - int IsPCI; /* Current card is a PCI card */ + int card_type; int AGPMode; unsigned int irq; /* IRQ number (0 means none) */ diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index 447619b56d0..307c1f341b4 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -1282,8 +1282,8 @@ radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, GLint ref, GLuint mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) | - (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT)); + GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) | + ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT)); RADEON_STATECHANGE( rmesa, ctx ); RADEON_STATECHANGE( rmesa, msk ); @@ -1330,7 +1330,7 @@ radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) RADEON_STATECHANGE( rmesa, msk ); rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK; rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= - (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT); + ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT); } static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail, @@ -1458,9 +1458,9 @@ static void radeonClearStencil( GLcontext *ctx, GLint s ) radeonContextPtr rmesa = RADEON_CONTEXT(ctx); rmesa->state.stencil.clear = - ((GLuint) ctx->Stencil.Clear | + ((GLuint) (ctx->Stencil.Clear & 0xff) | (0xff << RADEON_STENCIL_MASK_SHIFT) | - (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT)); + ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT)); } diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c index 9924931e1a2..4d5bbbd1f18 100644 --- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c +++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c @@ -92,10 +92,11 @@ static void radeonSetVertexFormat( GLcontext *ctx ) radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); int fmt_0 = 0; int offset = 0; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); /* Important: */ @@ -113,7 +114,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) * build up a hardware vertex. */ if ( !rmesa->swtcl.needproj || - (index & _TNL_BITS_TEX_ANY)) { /* for projtex */ + RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* for projtex */ EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z | RADEON_CP_VC_FRMT_W0 ); offset = 4; @@ -135,10 +136,11 @@ static void radeonSetVertexFormat( GLcontext *ctx ) offset += 1; rmesa->swtcl.specoffset = 0; - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { #if MESA_LITTLE_ENDIAN - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, RADEON_CP_VC_FRMT_PKSPEC ); @@ -147,7 +149,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) EMIT_PAD( 3 ); } - if (index & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, RADEON_CP_VC_FRMT_PKSPEC ); } @@ -155,7 +157,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) EMIT_PAD( 1 ); } #else - if (index & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, RADEON_CP_VC_FRMT_PKSPEC ); } @@ -163,7 +165,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) EMIT_PAD( 1 ); } - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { rmesa->swtcl.specoffset = offset; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, RADEON_CP_VC_FRMT_PKSPEC ); @@ -174,11 +176,11 @@ static void radeonSetVertexFormat( GLcontext *ctx ) #endif } - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { int i; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { - if (index & _TNL_BIT_TEX(i)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) { GLuint sz = VB->TexCoordPtr[i]->size; switch (sz) { @@ -204,7 +206,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) } } - if ( rmesa->tnl_index != index || + if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) || fmt_0 != rmesa->swtcl.vertex_format) { RADEON_NEWPRIM(rmesa); rmesa->swtcl.vertex_format = fmt_0; @@ -214,7 +216,7 @@ static void radeonSetVertexFormat( GLcontext *ctx ) rmesa->swtcl.vertex_attr_count, NULL, 0 ); rmesa->swtcl.vertex_size /= 4; - rmesa->tnl_index = index; + RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset ); if (RADEON_DEBUG & DEBUG_VERTS) fprintf( stderr, "%s: vertex_size= %d floats\n", __FUNCTION__, rmesa->swtcl.vertex_size); @@ -257,8 +259,9 @@ void radeonChooseVertexState( GLcontext *ctx ) * bigger one. */ - if ( ((tnl->render_inputs & (_TNL_BITS_TEX_ANY|_TNL_BIT_COLOR1) ) == 0) - || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + if ((!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) && + !RENDERINPUTS_TEST( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 )) + || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { rmesa->swtcl.needproj = GL_TRUE; se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | @@ -938,7 +941,7 @@ void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) */ _tnl_invalidate_vertex_state( ctx, ~0 ); _tnl_invalidate_vertices( ctx, ~0 ); - rmesa->tnl_index = 0; + RENDERINPUTS_ZERO( rmesa->tnl_index_bitset ); radeonChooseVertexState( ctx ); radeonChooseRenderState( ctx ); } diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c index 3b3f459dffb..e9a76dc92eb 100644 --- a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c +++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c @@ -929,7 +929,8 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); GLvertexformat *vfmt = &(rmesa->vb.vtxfmt); - MEMSET( vfmt, 0, sizeof(GLvertexformat) ); + /* start by initializing to no-op functions */ + _mesa_noop_vtxfmt_init(vfmt); /* Hook in chooser functions for codegen, etc: */ @@ -939,7 +940,6 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) */ vfmt->Materialfv = radeon_Materialfv; vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ vfmt->Begin = radeon_Begin; vfmt->End = radeon_End; @@ -953,15 +953,6 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen ) vfmt->DrawElements = radeon_fallback_DrawElements; vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements; - - /* Not active in supported states; just keep ctx->Current uptodate: - */ - vfmt->EdgeFlag = _mesa_noop_EdgeFlag; - vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; - vfmt->Indexf = _mesa_noop_Indexf; - vfmt->Indexfv = _mesa_noop_Indexfv; - - /* Active but unsupported -- fallback if we receive these: */ vfmt->CallList = radeon_fallback_CallList; diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S b/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S index d2bb1d15192..1b433491aa8 100644 --- a/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S +++ b/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S @@ -492,3 +492,7 @@ GLOBL( _sse_MultiTexCoord2f_2 ) ret GLOBL( _sse_MultiTexCoord2f_2_end ) #endif + +#if defined (__ELF__) && defined (__linux__) + .section .note.GNU-stack,"",%progbits +#endif diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c index 7f83d868cb8..7ead588dac8 100644 --- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c +++ b/src/mesa/drivers/dri/radeon/server/radeon_dri.c @@ -1260,6 +1260,7 @@ static int radeonInitFBDev( DRIDriverContext *ctx ) } ctx->shared.virtualWidth = dummy; + ctx->shared.Width = dummy; } fprintf(stderr,"shared virtual width is %d\n", ctx->shared.virtualWidth); diff --git a/src/mesa/drivers/dri/savage/savagestate.c b/src/mesa/drivers/dri/savage/savagestate.c index 44cf2f20d37..3a267e025c9 100644 --- a/src/mesa/drivers/dri/savage/savagestate.c +++ b/src/mesa/drivers/dri/savage/savagestate.c @@ -986,8 +986,8 @@ savageDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, const u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui; const u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui; - imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0]; - imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0]; + imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff; + imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0] & 0xff; switch (ctx->Stencil.Function[0]) { @@ -1015,8 +1015,8 @@ savageDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask) { savageContextPtr imesa = SAVAGE_CONTEXT(ctx); - if (imesa->regs.s4.stencilCtrl.ni.writeMask != ctx->Stencil.WriteMask[0]) { - imesa->regs.s4.stencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0]; + if (imesa->regs.s4.stencilCtrl.ni.writeMask != (ctx->Stencil.WriteMask[0] & 0xff)) { + imesa->regs.s4.stencilCtrl.ni.writeMask = (ctx->Stencil.WriteMask[0] & 0xff); imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; } } diff --git a/src/mesa/drivers/dri/savage/savagetex.c b/src/mesa/drivers/dri/savage/savagetex.c index b2802904bda..f0fe0c52594 100644 --- a/src/mesa/drivers/dri/savage/savagetex.c +++ b/src/mesa/drivers/dri/savage/savagetex.c @@ -525,80 +525,11 @@ savageAllocTexObj( struct gl_texture_object *texObj ) * because we can't tell the hardware to ignore the color components * and only use the alpha component. So we define our own texture * formats that promote to ARGB8888 or ARGB4444 and set the color - * components to white. This way we get the correct result. */ -static GLboolean -_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims, - GLenum baseInternalFormat, - const struct gl_texture_format *dstFormat, - GLvoid *dstAddr, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking); -static GLboolean -_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims, - GLenum baseInternalFormat, - const struct gl_texture_format *dstFormat, - GLvoid *dstAddr, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking); - -static struct gl_texture_format _savage_texformat_a1114444 = { - MESA_FORMAT_ARGB4444, /* MesaFormat */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ - 4, /* RedBits */ - 4, /* GreenBits */ - 4, /* BlueBits */ - 4, /* AlphaBits */ - 0, /* LuminanceBits */ - 0, /* IntensityBits */ - 0, /* IndexBits */ - 0, /* DepthBits */ - 0, /* StencilBits */ - 2, /* TexelBytes */ - _savage_texstore_a1114444, /* StoreTexImageFunc */ - NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by - * savageDDInitTextureFuncs */ -}; -static struct gl_texture_format _savage_texformat_a1118888 = { - MESA_FORMAT_ARGB8888, /* MesaFormat */ - GL_RGBA, /* BaseFormat */ - GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ - 8, /* RedBits */ - 8, /* GreenBits */ - 8, /* BlueBits */ - 8, /* AlphaBits */ - 0, /* LuminanceBits */ - 0, /* IntensityBits */ - 0, /* IndexBits */ - 0, /* DepthBits */ - 0, /* StencilBits */ - 4, /* TexelBytes */ - _savage_texstore_a1118888, /* StoreTexImageFunc */ - NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by - * savageDDInitTextureFuncs */ -}; - + * components to white. This way we get the correct result. + */ static GLboolean -_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims, - GLenum baseInternalFormat, - const struct gl_texture_format *dstFormat, - GLvoid *dstAddr, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking) +_savage_texstore_a1114444(TEXSTORE_PARAMS) { - /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, baseInternalFormat, @@ -606,10 +537,6 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims, srcFormat, srcType, srcAddr, srcPacking); const GLchan *src = tempImage; - GLubyte *dstImage = (GLubyte *) dstAddr - + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * dstFormat->TexelBytes; GLint img, row, col; ASSERT(dstFormat == &_savage_texformat_a1114444); @@ -619,7 +546,10 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims, return GL_FALSE; _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstImage; + GLubyte *dstRow = (GLubyte *) dstAddr + + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; for (row = 0; row < srcHeight; row++) { GLushort *dstUI = (GLushort *) dstRow; for (col = 0; col < srcWidth; col++) { @@ -629,25 +559,16 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims, } dstRow += dstRowStride; } - dstImage += dstImageStride; } _mesa_free((void *) tempImage); return GL_TRUE; } + + static GLboolean -_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims, - GLenum baseInternalFormat, - const struct gl_texture_format *dstFormat, - GLvoid *dstAddr, - GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, - GLint dstRowStride, GLint dstImageStride, - GLint srcWidth, GLint srcHeight, GLint srcDepth, - GLenum srcFormat, GLenum srcType, - const GLvoid *srcAddr, - const struct gl_pixelstore_attrib *srcPacking) +_savage_texstore_a1118888(TEXSTORE_PARAMS) { - /* general path */ const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, baseInternalFormat, @@ -655,10 +576,6 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims, srcFormat, srcType, srcAddr, srcPacking); const GLchan *src = tempImage; - GLubyte *dstImage = (GLubyte *) dstAddr - + dstZoffset * dstImageStride - + dstYoffset * dstRowStride - + dstXoffset * dstFormat->TexelBytes; GLint img, row, col; ASSERT(dstFormat == &_savage_texformat_a1118888); @@ -668,7 +585,10 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims, return GL_FALSE; _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); for (img = 0; img < srcDepth; img++) { - GLubyte *dstRow = dstImage; + GLubyte *dstRow = (GLubyte *) dstAddr + + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes + + dstYoffset * dstRowStride + + dstXoffset * dstFormat->TexelBytes; for (row = 0; row < srcHeight; row++) { GLuint *dstUI = (GLuint *) dstRow; for (col = 0; col < srcWidth; col++) { @@ -678,13 +598,51 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims, } dstRow += dstRowStride; } - dstImage += dstImageStride; } _mesa_free((void *) tempImage); return GL_TRUE; } + +static struct gl_texture_format _savage_texformat_a1114444 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 4, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* StencilBits */ + 2, /* TexelBytes */ + _savage_texstore_a1114444, /* StoreTexImageFunc */ + NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by + * savageDDInitTextureFuncs */ +}; +static struct gl_texture_format _savage_texformat_a1118888 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 8, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 0, /* StencilBits */ + 4, /* TexelBytes */ + _savage_texstore_a1118888, /* StoreTexImageFunc */ + NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by + * savageDDInitTextureFuncs */ +}; + + /* Called by the _mesa_store_teximage[123]d() functions. */ static const struct gl_texture_format * savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat, diff --git a/src/mesa/drivers/dri/savage/savagetris.c b/src/mesa/drivers/dri/savage/savagetris.c index 18470401372..3dd821a4d39 100644 --- a/src/mesa/drivers/dri/savage/savagetris.c +++ b/src/mesa/drivers/dri/savage/savagetris.c @@ -867,15 +867,17 @@ static GLboolean savageCheckPTexHack( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); - if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) { - if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0)) + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) { + if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX )) return GL_TRUE; /* apply ptex hack */ else FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE); } - if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4) FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE); return GL_FALSE; /* don't apply ptex hack */ @@ -929,10 +931,11 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx ) savageContextPtr imesa = SAVAGE_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint setupIndex = SAVAGE_EMIT_XYZ; GLubyte skip; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); imesa->vertex_attr_count = 0; skip = SAVAGE_SKIP_ALL_S3D; @@ -941,7 +944,7 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx ) /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ - if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE)) + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE)) EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W ); else { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 ); @@ -952,17 +955,17 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx ) /* t_context.c always includes a diffuse color */ EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 ); - if ((index & _TNL_BIT_COLOR1)) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 ); else EMIT_PAD( 3 ); - if ((index & _TNL_BIT_FOG)) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 ); else EMIT_PAD( 1 ); skip &= ~SAVAGE_SKIP_C1; - if (index & _TNL_BIT_TEX(0)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) { if (imesa->ptexHack) EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0); else if (VB->TexCoordPtr[0]->size == 4) @@ -991,28 +994,27 @@ static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx ) savageContextPtr imesa = SAVAGE_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint setupIndex = SAVAGE_EMIT_XYZ; GLubyte skip; GLuint size, mask; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); skip = SAVAGE_SKIP_ALL_S4; skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */ - if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE)) + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE)) NEED_ATTR( SAVAGE_EMIT_W, SAVAGE_SKIP_W ); /* t_context.c always includes a diffuse color */ NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 ); - - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { - if ((index & _TNL_BIT_COLOR1)) - NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 ); - if ((index & _TNL_BIT_FOG)) - NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 ); - } - if (index & _TNL_BIT_TEX(0)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) + NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 ); + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) + NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 ); + + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) { if (imesa->ptexHack) NEED_ATTR( SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0); else if (VB->TexCoordPtr[0]->size == 4) @@ -1024,7 +1026,7 @@ static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx ) else NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 ); } - if (index & _TNL_BIT_TEX(1)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) { if (VB->TexCoordPtr[1]->size == 4) /* projective textures are not supported by the hardware */ assert (0); /* should be caught by savageCheckPTexHack */ diff --git a/src/mesa/drivers/dri/sis/sis_clear.c b/src/mesa/drivers/dri/sis/sis_clear.c index d7807b157e9..637d502381e 100644 --- a/src/mesa/drivers/dri/sis/sis_clear.c +++ b/src/mesa/drivers/dri/sis/sis_clear.c @@ -133,7 +133,8 @@ sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean all, if ((smesa->current.hwCapEnable2 & (MASK_AlphaMaskWriteEnable | MASK_ColorMaskWriteEnable) && (mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0) || - (ctx->Stencil.WriteMask[0] < 0xff && (mask & BUFFER_BIT_STENCIL) != 0) ) + ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff && + (mask & BUFFER_BIT_STENCIL) != 0) ) { mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 ); } @@ -213,13 +214,13 @@ sis_3D_Clear( GLcontext * ctx, GLbitfield mask, if (bClrStencil) { dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS | - (ctx->Stencil.Clear << 8) | 0xff; + ((ctx->Stencil.Clear & 0xff) << 8) | 0xff; dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE | SiS_SPASS_ZPASS_REPLACE; dwEnable1 = MASK_ZWriteEnable | MASK_StencilWriteEnable | MASK_StencilTestEnable; dwEnable2 |= MASK_ZMaskWriteEnable; - dwDepthMask |= ctx->Stencil.WriteMask[0] << 24; + dwDepthMask |= (ctx->Stencil.WriteMask[0] & 0xff) << 24; } else if (bClrDepth) { dwEnable1 = MASK_ZWriteEnable; dwEnable2 |= MASK_ZMaskWriteEnable; diff --git a/src/mesa/drivers/dri/sis/sis_context.h b/src/mesa/drivers/dri/sis/sis_context.h index ead4a26678e..c349bf96ed2 100644 --- a/src/mesa/drivers/dri/sis/sis_context.h +++ b/src/mesa/drivers/dri/sis/sis_context.h @@ -332,7 +332,7 @@ struct sis_context GLint drawableID; GLint GlobalFlag; - GLuint last_tcl_state; + DECLARE_RENDERINPUTS(last_tcl_state_bitset); /* Stereo */ GLboolean useStereo; diff --git a/src/mesa/drivers/dri/sis/sis_state.c b/src/mesa/drivers/dri/sis/sis_state.c index 1a4c3241153..a30001c7462 100644 --- a/src/mesa/drivers/dri/sis/sis_state.c +++ b/src/mesa/drivers/dri/sis/sis_state.c @@ -251,7 +251,7 @@ sisDDDepthMask( GLcontext * ctx, GLboolean flag ) if (ctx->Visual.stencilBits) { if (flag || (ctx->Stencil.WriteMask[0] != 0)) { current->hwCapEnable |= MASK_ZWriteEnable; - if (flag && (ctx->Stencil.WriteMask[0] == 0xff)) { + if (flag && ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff)) { current->hwCapEnable2 &= ~MASK_ZMaskWriteEnable; } else { current->hwCapEnable2 |= MASK_ZMaskWriteEnable; diff --git a/src/mesa/drivers/dri/sis/sis_stencil.c b/src/mesa/drivers/dri/sis/sis_stencil.c index 1febe86b94c..a1ce2966e89 100644 --- a/src/mesa/drivers/dri/sis/sis_stencil.c +++ b/src/mesa/drivers/dri/sis/sis_stencil.c @@ -45,8 +45,9 @@ sisDDStencilFuncSeparate( GLcontext * ctx, GLenum face, __GLSiSHardware *current = &smesa->current; /* set reference */ - current->hwStSetting = STENCIL_FORMAT_8 | (ctx->Stencil.Ref[0] << 8) | - ctx->Stencil.ValueMask[0]; + current->hwStSetting = (STENCIL_FORMAT_8 | + ((ctx->Stencil.Ref[0] & 0xff) << 8) | + (ctx->Stencil.ValueMask[0] & 0xff)); switch (func) { diff --git a/src/mesa/drivers/dri/sis/sis_tris.c b/src/mesa/drivers/dri/sis/sis_tris.c index 24f6cb9aa87..a0e39dcd3c9 100644 --- a/src/mesa/drivers/dri/sis/sis_tris.c +++ b/src/mesa/drivers/dri/sis/sis_tris.c @@ -842,10 +842,12 @@ static void sisRenderStart( GLcontext *ctx ) TNLcontext *tnl = TNL_CONTEXT(ctx); sisContextPtr smesa = SIS_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint AGPParseSet = smesa->AGPParseSet; GLboolean tex_fallback = GL_FALSE; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + if (ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT && smesa->driDrawable->numClipRects != 0) { @@ -869,7 +871,7 @@ static void sisRenderStart( GLcontext *ctx ) AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat); AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE; - if (index & _TNL_BITS_TEX_ANY) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT); AGPParseSet |= SiS_PS_HAS_W; smesa->coloroffset = 4; @@ -881,17 +883,18 @@ static void sisRenderStart( GLcontext *ctx ) EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA); smesa->specoffset = 0; - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { AGPParseSet |= SiS_PS_HAS_SPECULAR; - if (index & _TNL_BIT_COLOR1) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR); smesa->specoffset = smesa->coloroffset + 1; } else { EMIT_PAD(3); } - if (index & _TNL_BIT_FOG) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F); } else { EMIT_PAD(1); @@ -899,14 +902,14 @@ static void sisRenderStart( GLcontext *ctx ) } /* projective textures are not supported by the hardware */ - if (index & _TNL_BIT_TEX(0)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) { if (VB->TexCoordPtr[0]->size > 2) tex_fallback = GL_TRUE; EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F); AGPParseSet |= SiS_PS_HAS_UV0; } /* Will only hit tex1 on SiS300 */ - if (index & _TNL_BIT_TEX(1)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) { if (VB->TexCoordPtr[1]->size > 2) tex_fallback = GL_TRUE; EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F); @@ -914,7 +917,7 @@ static void sisRenderStart( GLcontext *ctx ) } FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback); - if (smesa->last_tcl_state != index) { + if (!RENDERINPUTS_EQUAL( smesa->last_tcl_state_bitset, index_bitset )) { smesa->AGPParseSet = AGPParseSet; smesa->vertex_size = _tnl_install_attrs( ctx, smesa->vertex_attrs, diff --git a/src/mesa/drivers/dri/tdfx/BUGS b/src/mesa/drivers/dri/tdfx/BUGS new file mode 100644 index 00000000000..b15f6a91ed8 --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/BUGS @@ -0,0 +1,64 @@ +REMOVE THIS FILE BEFORE MERGING WITH TRUNK +------------------------------------------ + +OUTSTANDING BUGS + +demos/reflect - reading back Z on Voodoo3, image offset to right + Fixed in latest Glide. + +Q3 - some polygons drawn as vertical strips, similar to bug that was + seen in demos/fire. Voodoo3 only. May be related to glDepthMask + or glColorMask. + +book/fog - not fogging + Fog in orthograph mode still not implemented. Checking with + 3dfx engineers for ideas. + +Q3 demo crashes after changing display settings + but the full Q3 game version seems OK. + + + +MORE OUTSTANDING BUGS + +private context was NULL! causing immediate failure of any glx prog. cant +reproduce after restarting the X server. putting it down as halluc. + +texture object image was NULL, causing segmentation failure. happens with +prboom. ive put a check in tdfx_texstate.c but this isn't a fix. + +prboom, wall textures near first chainsaw aren't bound properly. sideways +movements causes the wall textures to move with you. prboom busted? + +16bpp mode, quake3, windowed, q3dm1, floor under rocketlauncher bands. it +looks like multitexturing gone wrong. i'll disable a tmu and test. + +sof, polygons appear at wrong x,y,z positions, intermittent, have not yet +found reliable way of reproducing. culling? sometimes polys disappear. + +descent3 is all black in 16bpp mode - FIXED (palette problems) + +smeared pixels in quake3 - FIXED (texture memory overlapped FB) + + + +PERFORMANCE COMPARISON (Brian / Alan) + + V3/16 is Voodoo3 in 16bpp on a P3/500 + V5/16 is Voodoo5 in 16bpp on a P3/600 + V5/32 is Voodoo5 in 32bpp on a P3/600 + V5A/16 is Voodoo5 in 16bpp on an Alpha AXP/600 + V5A/32 is Voodoo5 in 32bpp on an Alpha AXP/600 + + tdfx-2-1-branch tdfx-3-0-0-branch +demo V3/16 V5/16 V5/32 V3/16 V5/16 V5/32 V5A/16 V5A/32 +------------------------------------------------------------------------ +gloss 257 183 174 320 308 177 313 167 +fire 42 39 52 41 +fire (no help) 98 80 50 106 113 73 124 80 +tunnel 61 50 70 58 +tunnel (no help) 167 142 57 138 152 113 171 122 +gears 663 554 540 881 1232 776 1484 830 +teapot 20 21 37 36 +teapot (no help) 22 14 14 24 30 30 43 42 + diff --git a/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S new file mode 100644 index 00000000000..0f4cc45089b --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S @@ -0,0 +1,84 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fastpath.S,v 1.2 2000/09/26 15:56:51 tsi Exp $ */ + +#include "../../X86/assyntax.h" + +#define SETUP_RGBA 0x1 +#define SETUP_TMU0 0x2 +#define SETUP_TMU1 0x4 + + +/* Pack either rgba or texture into the remaining half of a 32 byte vertex. + */ +#define CLIP_R 24 +#define CLIP_G 16 +#define CLIP_B 20 +#define CLIP_A 28 /* defined inf fxdrv.h */ + +#define CLIP_S0 16 +#define CLIP_T0 20 +#define CLIP_S1 24 +#define CLIP_T1 28 + +#define SIZE 4 +#define TYPE (0) +#define TAG(x) x +#include "fx_3dnow_fasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_RGBA) +#define TAG(x) x##_RGBA +#include "fx_3dnow_fasttmp.h" + +#define SIZE 6 +#define TYPE (SETUP_TMU0) +#define TAG(x) x##_TMU0 +#include "fx_3dnow_fasttmp.h" + +#define SIZE 8 +#define TYPE (SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_TMU0_TMU1 +#include "fx_3dnow_fasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 16 +#define CLIP_T1 20 + +#define SIZE 6 +#define TYPE (SETUP_TMU1) +#define TAG(x) x##_TMU1 +#include "fx_3dnow_fasttmp.h" + +/* These three need to use a full 64 byte clip-space vertex. + */ +#undef CLIP_S0 +#undef CLIP_T0 +#undef CLIP_S1 +#undef CLIP_T1 + +#define CLIP_S0 32 +#define CLIP_T0 36 +#define CLIP_S1 40 +#define CLIP_T1 44 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU0) +#define TAG(x) x##_RGBA_TMU0 +#include "fx_3dnow_fasttmp.h" + +#define SIZE 12 +#define TYPE (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1) +#define TAG(x) x##_RGBA_TMU0_TMU1 +#include "fx_3dnow_fasttmp.h" + +#undef CLIP_S1 +#undef CLIP_T1 +#define CLIP_S1 32 +#define CLIP_T1 36 + +#define SIZE 10 +#define TYPE (SETUP_RGBA|SETUP_TMU1) +#define TAG(x) x##_RGBA_TMU1 +#include "fx_3dnow_fasttmp.h" + + diff --git a/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h new file mode 100644 index 00000000000..9ec4935d781 --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h @@ -0,0 +1,314 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fasttmp.h,v 1.2 2000/09/26 15:56:51 tsi Exp $ */ + +#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER) +#define TAGLLBL(a) TAG(.L##a) +#else +#define TAGLLBL(a) TAG(a) +#endif + +#if !GLIDE3 + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 4 +#define GR_VERTEX_Z_OFFSET 8 +#define GR_VERTEX_R_OFFSET 12 +#define GR_VERTEX_G_OFFSET 16 +#define GR_VERTEX_B_OFFSET 20 +#define GR_VERTEX_OOZ_OFFSET 24 +#define GR_VERTEX_A_OFFSET 28 +#define GR_VERTEX_OOW_OFFSET 32 + +#else /* GLIDE3 */ + +#define GR_VERTEX_X_OFFSET 0 +#define GR_VERTEX_Y_OFFSET 4 +#define GR_VERTEX_OOZ_OFFSET 8 +#define GR_VERTEX_OOW_OFFSET 12 +#define GR_VERTEX_R_OFFSET 16 +#define GR_VERTEX_G_OFFSET 20 +#define GR_VERTEX_B_OFFSET 24 +#define GR_VERTEX_A_OFFSET 28 +#define GR_VERTEX_Z_OFFSET 32 + +#endif /* GLIDE3 */ + +#define GR_VERTEX_SOW_TMU0_OFFSET 36 +#define GR_VERTEX_TOW_TMU0_OFFSET 40 +#define GR_VERTEX_OOW_TMU0_OFFSET 44 +#define GR_VERTEX_SOW_TMU1_OFFSET 48 +#define GR_VERTEX_TOW_TMU1_OFFSET 52 +#define GR_VERTEX_OOW_TMU1_OFFSET 56 + + + + +/*#define MAT_SX 0 /* accessed by REGIND !! */ +#define MAT_SY 20 +#define MAT_SZ 40 +#define MAT_TX 48 +#define MAT_TY 52 +#define MAT_TZ 56 + + + + +/* Do viewport map, device scale and perspective projection. + * + * void project_verts( GLfloat *first, + * GLfloat *last, + * const GLfloat *m, + * GLuint stride ) + * + * + * Rearrange fxVertices to look like grVertices. + */ + +GLOBL GLNAME( TAG(fx_3dnow_project_vertices) ) +GLNAME( TAG(fx_3dnow_project_vertices) ): + + PUSH_L ( EBP ) + + MOV_L ( REGOFF(8, ESP), ECX ) /* first_vert */ + MOV_L ( REGOFF(12, ESP), EDX ) /* last_vert */ + + CMP_L ( ECX, EDX ) + JE ( TAGLLBL(FXPV_end) ) + + FEMMS + + PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */ + + MOV_L ( REGOFF(16, ESP), EBP ) /* matrix */ + MOV_L ( REGOFF(20, ESP), EAX ) /* stride */ + + MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */ + PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */ + +#if !defined(FX_V2) + MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */ + MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */ +#endif + + MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */ + PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */ + + MOVD ( REGIND(EBP), MM5 ) + PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */ + + MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */ + + +ALIGNTEXT32 +TAGLLBL(FXPV_loop_start): + + PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */ + + + MOVD ( REGOFF(12, ECX), MM0 ) /* | f[3] */ + PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */ + + MOVD ( REGOFF(12, ECX), MM7 ) /* | f[3] */ + PFRCPIT1 ( MM0, MM7 ) + PFRCPIT2 ( MM0, MM7 ) /* oow | oow */ + + PUNPCKLDQ ( MM7, MM7 ) + + +#if (TYPE & SETUP_RGBA) + MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */ + MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) ) +#endif + +#if (TYPE & SETUP_TMU1) + MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */ + PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) ) +#endif + + +#if (TYPE & SETUP_TMU0) + MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */ + PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) ) +#endif + + + + + +/* DO_SETUP_XYZ */ + + MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */ + PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */ + + MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */ + PFMUL ( MM7, MM3 ) /* | f[2] * oow */ + + MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */ + PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */ + + PFADD ( MM0, MM3 ) /* | f[2] += vtz */ + PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */ + + PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */ + +#if !defined(FX_V2) + PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */ +#endif + + MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) ) + MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) ) + + +/* end of DO_SETUP_XYZ */ + + MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */ + ADD_L ( EAX, ECX ) /* f += stride */ + + CMP_L ( ECX, EDX ) /* stall??? */ + JA ( TAGLLBL(FXPV_loop_start) ) + +TAGLLBL(FXPV_end): + FEMMS + POP_L ( EBP ) + RET + + + + + + + +/* void project_verts( GLfloat *first, + * GLfloat *last, + * const GLfloat *m, + * GLuint stride, + * const GLubyte *mask ) + * + */ + +GLOBL GLNAME( TAG(fx_3dnow_project_clipped_vertices) ) +GLNAME( TAG(fx_3dnow_project_clipped_vertices) ): + + PUSH_L ( EBP ) + + MOV_L ( REGOFF(8, ESP), ECX ) /* first FXDRIVER(VB)->verts*/ + MOV_L ( REGOFF(12, ESP), EDX ) /* last FXDRIVER(VB)->last_vert */ + + FEMMS + + PUSH_L ( EDI ) + PUSH_L ( ESI ) + + PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */ + + MOV_L ( REGOFF(24, ESP), EBP ) /* mat ctx->Viewport.WindowMap.M */ + MOV_L ( REGOFF(28, ESP), EAX ) /* stride */ + MOV_L ( REGOFF(32, ESP), ESI ) /* VB->ClipMask */ + + MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */ + PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */ + +#if !defined(FX_V2) + MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */ + MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */ +#endif + + MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */ + PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */ + + MOVD ( REGIND(EBP), MM5 ) + PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */ + + MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */ + + + +ALIGNTEXT32 +TAGLLBL(FXPCV_loop_start): + + PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */ + + CMP_B ( CONST(0), REGIND(ESI) ) + JNE ( TAGLLBL(FXPCV_skip) ) + + MOVD ( REGOFF(12, ECX), MM0) /* | f[3] */ + PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */ + + MOVD ( REGOFF(12, ECX), MM7) /* | f[3] */ + PFRCPIT1 ( MM0, MM7 ) + PFRCPIT2 ( MM0, MM7 ) /* oow | oow */ + + PUNPCKLDQ ( MM7, MM7 ) + + +#if (TYPE & SETUP_RGBA) + MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */ + MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) ) +#endif + +#if (TYPE & SETUP_TMU1) + MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */ + PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) ) +#endif + + +#if (TYPE & SETUP_TMU0) + MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */ + PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */ + MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) ) +#endif + + + + +/* DO_SETUP_XYZ */ + + MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */ + PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */ + + MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */ + PFMUL ( MM7, MM3 ) /* | f[2] * oow */ + + MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */ + PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */ + + PFADD ( MM0, MM3 ) /* | f[2] += vtz */ + PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */ + + PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */ + +#if !defined(FX_V2) + PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */ +#endif + + MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) ) + MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) ) + + +/* end of DO_SETUP_XYZ */ + + MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */ + +TAGLLBL(FXPCV_skip): + ADD_L ( EAX, ECX ) /* f += stride */ + + INC_L ( ESI ) /* next ClipMask */ + CMP_L ( ECX, EDX ) + JA ( TAGLLBL(FXPCV_loop_start) ) + + POP_L ( ESI ) + POP_L ( EDI ) + +TAGLLBL(FXPCV_end): + FEMMS + POP_L ( EBP ) + RET + + + +#undef TYPE +#undef TAG +#undef SIZE + diff --git a/src/mesa/drivers/dri/tdfx/tdfx_render.c b/src/mesa/drivers/dri/tdfx/tdfx_render.c index 56f5f147eeb..a30ec78a558 100644 --- a/src/mesa/drivers/dri/tdfx/tdfx_render.c +++ b/src/mesa/drivers/dri/tdfx/tdfx_render.c @@ -70,7 +70,7 @@ static void tdfxClear( GLcontext *ctx, mask &= ~(BUFFER_BIT_ACCUM); if (mask & BUFFER_BIT_STENCIL) { - if (!fxMesa->haveHwStencil || ctx->Stencil.WriteMask[0] != 0xff) { + if (!fxMesa->haveHwStencil || (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { /* Napalm seems to have trouble with stencil write masks != 0xff */ /* do stencil clear in software */ mask &= ~(BUFFER_BIT_STENCIL); @@ -98,7 +98,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff); /* set stencil ref value = desired clear value */ fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS, - fxMesa->Stencil.Clear, 0xff); + (fxMesa->Stencil.Clear & 0xff), 0xff); fxMesa->Glide.grStencilOp(GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE); fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT); @@ -129,7 +129,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); } else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, @@ -152,11 +152,11 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, - fxMesa->Depth.Clear); + fxMesa->Depth.Clear & 0xff); /* clear front */ FX_grColorMaskv_NoLock(ctx, true4); fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER); @@ -164,7 +164,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -181,7 +181,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -198,7 +198,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -215,7 +215,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -225,7 +225,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -242,7 +242,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -254,7 +254,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -272,7 +272,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); else fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, @@ -293,7 +293,7 @@ static void tdfxClear( GLcontext *ctx, fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor, fxMesa->Color.ClearAlpha, fxMesa->Depth.Clear, - (FxU32) ctx->Stencil.Clear); + (FxU32) (ctx->Stencil.Clear & 0xff)); if (ctx->Depth.Mask && ctx->Depth.Test) { fxMesa->Glide.grDepthMask(FXTRUE); } diff --git a/src/mesa/drivers/dri/tdfx/tdfx_state.c b/src/mesa/drivers/dri/tdfx/tdfx_state.c index 1869de47374..a389273b2f0 100644 --- a/src/mesa/drivers/dri/tdfx/tdfx_state.c +++ b/src/mesa/drivers/dri/tdfx/tdfx_state.c @@ -462,9 +462,9 @@ static void tdfxUpdateStencil( GLcontext *ctx ) if (fxMesa->haveHwStencil) { if (ctx->Stencil.Enabled) { fxMesa->Stencil.Function = ctx->Stencil.Function[0] - GL_NEVER + GR_CMP_NEVER; - fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0]; - fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0]; - fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0]; + fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0] & 0xff; + fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0] & 0xff; + fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0] & 0xff; fxMesa->Stencil.FailFunc = convertGLStencilOp(ctx->Stencil.FailFunc[0]); fxMesa->Stencil.ZFailFunc = convertGLStencilOp(ctx->Stencil.ZFailFunc[0]); fxMesa->Stencil.ZPassFunc = convertGLStencilOp(ctx->Stencil.ZPassFunc[0]); diff --git a/src/mesa/drivers/dri/tdfx/tdfx_tex.c b/src/mesa/drivers/dri/tdfx/tdfx_tex.c index d8a80534bb9..04ddfaad24b 100644 --- a/src/mesa/drivers/dri/tdfx/tdfx_tex.c +++ b/src/mesa/drivers/dri/tdfx/tdfx_tex.c @@ -52,7 +52,7 @@ /* no borders! can't halve 1x1! (stride > width * comp) not allowed */ -void +static void _mesa_halve2x2_teximage2d ( GLcontext *ctx, struct gl_texture_image *texImage, GLuint bytesPerPixel, @@ -65,6 +65,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx, GLint srcRowStride = srcWidth * bytesPerPixel; GLubyte *src = (GLubyte *)srcImage; GLubyte *dst = dstImage; + GLuint dstImageOffsets = 0; GLuint bpt = 0; GLubyte *_s = NULL; @@ -96,7 +97,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx, &_mesa_texformat_rgba8888_rev, src, 0, 0, 0, /* dstX/Y/Zoffset */ srcRowStride, /* dstRowStride */ - 0, /* dstImageStride */ + &dstImageOffsets, srcWidth, srcHeight, 1, texImage->_BaseFormat, _t, srcImage, &ctx->DefaultPacking); } @@ -143,7 +144,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx, texImage->TexFormat, dstImage, 0, 0, 0, /* dstX/Y/Zoffset */ dstWidth * bpt, - 0, /* dstImageStride */ + &dstImageOffsets, dstWidth, dstHeight, 1, GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking); FREE(dst); @@ -1177,6 +1178,7 @@ adjust2DRatio (GLcontext *ctx, const GLint newWidth = width * mml->wScale; const GLint newHeight = height * mml->hScale; GLvoid *tempImage; + GLuint dstImageOffsets = 0; if (!texImage->IsCompressed) { GLubyte *destAddr; @@ -1189,7 +1191,7 @@ adjust2DRatio (GLcontext *ctx, texImage->TexFormat, tempImage, 0, 0, 0, /* dstX/Y/Zoffset */ width * texelBytes, /* dstRowStride */ - 0, /* dstImageStride */ + &dstImageOffsets, width, height, 1, format, type, pixels, packing); @@ -1213,6 +1215,7 @@ adjust2DRatio (GLcontext *ctx, } tempImage = MALLOC(newWidth * newHeight * rawBytes); if (!tempImage) { + FREE(rawImage); return GL_FALSE; } /* unpack image, apply transfer ops and store in rawImage */ @@ -1220,7 +1223,7 @@ adjust2DRatio (GLcontext *ctx, &_mesa_texformat_rgba8888_rev, rawImage, 0, 0, 0, /* dstX/Y/Zoffset */ width * rawBytes, /* dstRowStride */ - 0, /* dstImageStride */ + &dstImageOffsets, width, height, 1, format, type, pixels, packing); _mesa_rescale_teximage2d(rawBytes, @@ -1233,7 +1236,7 @@ adjust2DRatio (GLcontext *ctx, texImage->TexFormat, texImage->Data, xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */ dstRowStride, - 0, /* dstImageStride */ + &dstImageOffsets, newWidth, newHeight, 1, GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking); FREE(rawImage); @@ -1257,6 +1260,7 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level, tdfxTexInfo *ti; tdfxMipMapLevel *mml; GLint texelBytes, dstRowStride; + GLuint mesaFormat; /* printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n", @@ -1344,9 +1348,10 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level, texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, internalFormat, format, type); assert(texImage->TexFormat); - mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat); + mesaFormat = texImage->TexFormat->MesaFormat; + mml->glideFormat = fxGlideFormat(mesaFormat); ti->info.format = mml->glideFormat; - texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat); + texImage->FetchTexelc = fxFetchFunction(mesaFormat); texelBytes = texImage->TexFormat->TexelBytes; if (texImage->IsCompressed) { @@ -1354,12 +1359,13 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level, mml->width, mml->height, 1, - internalFormat); - dstRowStride = _mesa_compressed_row_stride(internalFormat, mml->width); - texImage->Data = _mesa_malloc(texImage->CompressedSize); + mesaFormat); + dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width); + texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize); } else { dstRowStride = mml->width * texelBytes; - texImage->Data = _mesa_malloc(mml->width * mml->height * texelBytes); + texImage->Data = _mesa_alloc_texmemory(mml->width * mml->height * + texelBytes); } if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); @@ -1387,12 +1393,12 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level, /* no rescaling needed */ /* unpack image, apply transfer ops and store in texImage->Data */ texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, - texImage->TexFormat, texImage->Data, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - 0, /* dstImageStride */ - width, height, 1, - format, type, pixels, packing); + texImage->TexFormat, texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, + texImage->ImageOffsets, + width, height, 1, + format, type, pixels, packing); } /* GL_SGIS_generate_mipmap */ @@ -1473,7 +1479,7 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, texelBytes = texImage->TexFormat->TexelBytes; if (texImage->IsCompressed) { - dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, mml->width); + dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width); } else { dstRowStride = mml->width * texelBytes; } @@ -1497,12 +1503,12 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, else { /* no rescaling needed */ texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, - texImage->TexFormat, texImage->Data, - xoffset, yoffset, 0, - dstRowStride, - 0, /* dstImageStride */ - width, height, 1, - format, type, pixels, packing); + texImage->TexFormat, texImage->Data, + xoffset, yoffset, 0, + dstRowStride, + texImage->ImageOffsets, + width, height, 1, + format, type, pixels, packing); } /* GL_SGIS_generate_mipmap */ @@ -1600,6 +1606,7 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target, tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); tdfxTexInfo *ti; tdfxMipMapLevel *mml; + GLuint mesaFormat; if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) { fprintf(stderr, "tdfxCompressedTexImage2D: id=%d int 0x%x %dx%d\n", @@ -1651,9 +1658,10 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target, /* Determine the appropriate Glide texel format, * given the user's internal texture format hint. */ - mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat); + mesaFormat = texImage->TexFormat->MesaFormat; + mml->glideFormat = fxGlideFormat(mesaFormat); ti->info.format = mml->glideFormat; - texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat); + texImage->FetchTexelc = fxFetchFunction(mesaFormat); /* allocate new storage for texture image, if needed */ if (!texImage->Data) { @@ -1661,8 +1669,8 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target, mml->width, mml->height, 1, - internalFormat); - texImage->Data = _mesa_malloc(texImage->CompressedSize); + mesaFormat); + texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize); if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); return; @@ -1685,9 +1693,10 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target, * we replicate the data over the padded area. * For now, we take 2) + 3) but texelfetchers will be wrong! */ - GLuint srcRowStride = _mesa_compressed_row_stride(internalFormat, width); + const GLuint mesaFormat = texImage->TexFormat->MesaFormat; + GLuint srcRowStride = _mesa_compressed_row_stride(mesaFormat, width); - GLuint destRowStride = _mesa_compressed_row_stride(internalFormat, + GLuint destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width); _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4, @@ -1726,6 +1735,7 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint destRowStride, srcRowStride; GLint i, rows; GLubyte *dest; + const GLuint mesaFormat = texImage->TexFormat->MesaFormat; if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) { fprintf(stderr, "tdfxCompressedTexSubImage2D: id=%d\n", texObj->Name); @@ -1736,12 +1746,11 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target, mml = TDFX_TEXIMAGE_DATA(texImage); assert(mml); - srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, width); + srcRowStride = _mesa_compressed_row_stride(mesaFormat, width); - destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, - mml->width); + destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width); dest = _mesa_compressed_image_address(xoffset, yoffset, 0, - texImage->InternalFormat, + mesaFormat, mml->width, (GLubyte*) texImage->Data); @@ -1757,10 +1766,9 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target, * see fxDDCompressedTexImage2D for caveats */ if (mml->wScale != 1 || mml->hScale != 1) { - srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, texImage->Width); + srcRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width); - destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, - mml->width); + destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width); _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4, destRowStride, mml->height / 4, 1, texImage->Data, destRowStride, diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.c b/src/mesa/drivers/dri/unichrome/via_ioctl.c index 1daf49f151f..c8c6dc01933 100644 --- a/src/mesa/drivers/dri/unichrome/via_ioctl.c +++ b/src/mesa/drivers/dri/unichrome/via_ioctl.c @@ -233,7 +233,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all, if (mask & BUFFER_BIT_STENCIL) { if (vmesa->have_hw_stencil) { - if (ctx->Stencil.WriteMask[0] == 0xff) { + if ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff) { flag |= VIA_DEPTH; clear_depth &= ~0xff; clear_depth |= (ctx->Stencil.Clear & 0xff); diff --git a/src/mesa/drivers/dri/unichrome/via_tex.c b/src/mesa/drivers/dri/unichrome/via_tex.c index 19b270955eb..b344c009318 100644 --- a/src/mesa/drivers/dri/unichrome/via_tex.c +++ b/src/mesa/drivers/dri/unichrome/via_tex.c @@ -691,6 +691,14 @@ static void viaTexImage(GLcontext *ctx, } texelBytes = texImage->TexFormat->TexelBytes; + if (texelBytes == 0) { + /* compressed format */ + texImage->IsCompressed = GL_TRUE; + texImage->CompressedSize = + ctx->Driver.CompressedTextureSize(ctx, texImage->Width, + texImage->Height, texImage->Depth, + texImage->TexFormat->MesaFormat); + } /* Minimum pitch of 32 bytes */ if (postConvWidth * texelBytes < 32) { @@ -779,10 +787,10 @@ static void viaTexImage(GLcontext *ctx, return; } else { - GLint dstRowStride, dstImageStride = 0; + GLint dstRowStride; GLboolean success; if (texImage->IsCompressed) { - dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width); + dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); } else { dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes; @@ -793,7 +801,8 @@ static void viaTexImage(GLcontext *ctx, texImage->TexFormat, texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, dstImageStride, + dstRowStride, + texImage->ImageOffsets, width, height, 1, format, type, pixels, packing); if (!success) { diff --git a/src/mesa/drivers/dri/unichrome/via_tris.c b/src/mesa/drivers/dri/unichrome/via_tris.c index 9cb88ae2399..4cc7942b1b6 100644 --- a/src/mesa/drivers/dri/unichrome/via_tris.c +++ b/src/mesa/drivers/dri/unichrome/via_tris.c @@ -744,16 +744,18 @@ static void viaChooseVertexState( GLcontext *ctx ) { struct via_context *vmesa = VIA_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z; GLuint setupIndex = 0; + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); vmesa->vertex_attr_count = 0; /* EMIT_ATTR's must be in order as they tell t_vertex.c how to * build up a hardware vertex. */ - if (index & (_TNL_BITS_TEX_ANY|_TNL_BIT_FOG)) { + if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W ); vmesa->coloroffset = 4; } @@ -767,8 +769,9 @@ static void viaChooseVertexState( GLcontext *ctx ) HC_HVPMSK_Cd ); vmesa->specoffset = 0; - if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) { - if ((index & _TNL_BIT_COLOR1)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || + RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { vmesa->specoffset = vmesa->coloroffset + 1; EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC, HC_HVPMSK_Cs ); @@ -776,13 +779,13 @@ static void viaChooseVertexState( GLcontext *ctx ) else EMIT_PAD( 3 ); - if ((index & _TNL_BIT_FOG)) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs ); else EMIT_PAD( 1 ); } - if (index & _TNL_BIT_TEX(0)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) { if (vmesa->ptexHack) EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0, (HC_HVPMSK_S | HC_HVPMSK_T) ); @@ -791,7 +794,7 @@ static void viaChooseVertexState( GLcontext *ctx ) (HC_HVPMSK_S | HC_HVPMSK_T) ); } - if (index & _TNL_BIT_TEX(1)) { + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) { EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1, (HC_HVPMSK_S | HC_HVPMSK_T) ); } @@ -824,17 +827,19 @@ static GLboolean viaCheckPTexHack( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; - GLuint index = tnl->render_inputs; + DECLARE_RENDERINPUTS(index_bitset); GLboolean fallback = GL_FALSE; GLboolean ptexHack = GL_FALSE; - if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) { - if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0)) + RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); + + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) { + if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX )) ptexHack = GL_TRUE; else fallback = GL_TRUE; } - if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4) + if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4) fallback = GL_TRUE; FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback); diff --git a/src/mesa/drivers/ggi/default/.cvsignore b/src/mesa/drivers/ggi/default/.cvsignore new file mode 100644 index 00000000000..c8a526b14d7 --- /dev/null +++ b/src/mesa/drivers/ggi/default/.cvsignore @@ -0,0 +1 @@ +genkgi.conf diff --git a/src/mesa/drivers/ggi/default/genkgi.h b/src/mesa/drivers/ggi/default/genkgi.h new file mode 100644 index 00000000000..1202150060b --- /dev/null +++ b/src/mesa/drivers/ggi/default/genkgi.h @@ -0,0 +1,76 @@ +/* $Id: genkgi.h,v 1.3 1999-08-22 08:56:50 jtaylor Exp $ +****************************************************************************** + + GGIMesa - KGIcon specific overrides for fbcon-mesa + API header + + Copyright (C) 1999 Jon Taylor [[email protected]] + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +****************************************************************************** +*/ + +#ifndef _GENKGI_MESA_H +#define _GENKGI_MESA_H + +#undef KGI_USE_PPBUFS + +#include <unistd.h> +#include <sys/mman.h> + +#include <ggi/internal/ggi-dl.h> +#include <ggi/mesa/display_fbdev.h> +#include <kgi/kgi.h> + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* FIXME: LibGGI needs to export its genkgi.h */ +struct genkgi_priv +{ + ggi_gc *mapped_gc; + unsigned int gc_size; + ggifunc_drawline *drawline; + ggifunc_drawbox *drawbox; + ggifunc_fillscreen *fillscreen; + int fd_gc; + int close_gc; + int fd_kgicommand; + uint8 *mapped_kgicommand; + uint8 *kgicommand_ptr; + unsigned int kgicommand_buffersize; +}; + +#define GENKGI_PRIV(vis) ((struct genkgi_priv *)FBDEV_PRIV(vis)->accelpriv) + +extern ggifunc_getapi GGIMesa_genkgi_getapi; +extern ggifunc_flush GGIMesa_genkgi_flush; + +struct genkgi_priv_mesa +{ + char accel[100]; + int have_accel; + void *accelpriv; /* Private data of subdrivers */ + struct genkgi_priv *oldpriv; /* LibGGI's private data */ +}; + +#define GENKGI_PRIV_MESA(vis) ((struct genkgi_priv_mesa *)FBDEV_PRIV_MESA(vis)->accelpriv) + +#endif /* _GENKHI_MESA_H */ diff --git a/src/mesa/drivers/ggi/default/genkgi_mode.c b/src/mesa/drivers/ggi/default/genkgi_mode.c index 938024789f9..a81f553f49b 100644 --- a/src/mesa/drivers/ggi/default/genkgi_mode.c +++ b/src/mesa/drivers/ggi/default/genkgi_mode.c @@ -1,4 +1,4 @@ -/* $Id: genkgi_mode.c,v 1.4 2000/01/07 08:34:44 jtaylor Exp $ +/* $Id: genkgi_mode.c,v 1.4 2000-01-07 08:34:44 jtaylor Exp $ ****************************************************************************** display-fbdev-kgicon-generic-mesa diff --git a/src/mesa/drivers/ggi/default/genkgi_visual.c b/src/mesa/drivers/ggi/default/genkgi_visual.c index 17ef9679bb8..1b49a4ae528 100644 --- a/src/mesa/drivers/ggi/default/genkgi_visual.c +++ b/src/mesa/drivers/ggi/default/genkgi_visual.c @@ -1,4 +1,4 @@ -/* $Id: genkgi_visual.c,v 1.7 2000/06/11 20:11:55 jtaylor Exp $ +/* $Id: genkgi_visual.c,v 1.7 2000-06-11 20:11:55 jtaylor Exp $ ****************************************************************************** genkgi_visual.c: visual handling for the generic KGI helper diff --git a/src/mesa/drivers/ggi/display/.cvsignore b/src/mesa/drivers/ggi/display/.cvsignore new file mode 100644 index 00000000000..98858db2c0e --- /dev/null +++ b/src/mesa/drivers/ggi/display/.cvsignore @@ -0,0 +1 @@ +fbdev.conf diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/debug.h b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h index 35d11624c64..e4c2a250454 100644 --- a/src/mesa/drivers/ggi/include/ggi/mesa/debug.h +++ b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h @@ -1,4 +1,4 @@ -/* $Id: debug.h,v 1.5 2003/09/22 15:18:51 brianp Exp $ +/* $Id: debug.h,v 1.5 2003-09-22 15:18:51 brianp Exp $ ****************************************************************************** GGIMesa debugging macros diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c index 2ba3b81706c..942692c8bb0 100644 --- a/src/mesa/drivers/osmesa/osmesa.c +++ b/src/mesa/drivers/osmesa/osmesa.c @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 6.5.1 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -38,7 +38,6 @@ #include "context.h" #include "extensions.h" #include "framebuffer.h" -#include "fbobject.h" #include "imports.h" #include "mtypes.h" #include "renderbuffer.h" @@ -46,7 +45,6 @@ #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "swrast/s_context.h" -#include "swrast/s_depth.h" #include "swrast/s_lines.h" #include "swrast/s_triangle.h" #include "tnl/tnl.h" @@ -56,32 +54,32 @@ -/* - * This is the OS/Mesa context struct. - * Notice how it includes a GLcontext. By doing this we're mimicking - * C++ inheritance/derivation. - * Later, we can cast a GLcontext pointer into an OSMesaContext pointer - * or vice versa. +/** + * OSMesa rendering context, derived from core Mesa GLcontext. */ -struct osmesa_context { - GLcontext mesa; /* The core GL/Mesa context */ - GLvisual *gl_visual; /* Describes the buffers */ - GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ - GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ - void *buffer; /* the image buffer */ - GLint width, height; /* size of image buffer */ - GLint rowlength; /* number of pixels per row */ - GLint userRowLength; /* user-specified number of pixels per row */ - GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */ - GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ - GLboolean yup; /* TRUE -> Y increases upward */ - /* FALSE -> Y increases downward */ +struct osmesa_context +{ + GLcontext mesa; /*< Base class - this must be first */ + GLvisual *gl_visual; /*< Describes the buffers */ + struct gl_renderbuffer *rb; /*< The user's colorbuffer */ + GLframebuffer *gl_buffer; /*< The framebuffer, containing user's rb */ + GLenum format; /*< User-specified context format */ + GLint width, height; /*< size of image buffer */ + GLint rowlength; /*< number of pixels per row */ + GLint userRowLength; /*< user-specified number of pixels per row */ + GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */ + GLvoid *rowaddr[MAX_HEIGHT]; /*< address of first pixel in each image row */ + GLboolean yup; /*< TRUE -> Y increases upward */ + /*< FALSE -> Y increases downward */ }; -/* Just cast, since we're using structure containment */ -#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx)) - +static INLINE OSMesaContext +OSMESA_CONTEXT(GLcontext *ctx) +{ + /* Just cast, since we're using structure containment */ + return (OSMesaContext) ctx; +} /**********************************************************************/ @@ -119,7 +117,7 @@ osmesa_update_state( GLcontext *ctx, GLuint new_state ) } -/* +/** * Just return the current buffer size. * There's no window to track the size of. */ @@ -141,26 +139,39 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) /***** Read/write spans/arrays of pixels *****/ /**********************************************************************/ -/* RGBA */ -#define NAME(PREFIX) PREFIX##_RGBA -#define FORMAT GL_RGBA +/* 8-bit RGBA */ +#define NAME(PREFIX) PREFIX##_RGBA8 +#define RB_TYPE GLubyte #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ - GLchan *P = osmesa->rowaddr[Y] + 4 * (X) + GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) #define INC_PIXEL_PTR(P) P += 4 -#if CHAN_TYPE == GL_FLOAT #define STORE_PIXEL(DST, X, Y, VALUE) \ - DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ - DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ - DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ - DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, CHAN_MAXF) + DST[0] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[BCOMP]; \ + DST[3] = VALUE[ACOMP] #define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ - DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ - DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ - DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ - DST[3] = CHAN_MAXF -#else + DST[0] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[BCOMP]; \ + DST[3] = 255 +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[0]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[2]; \ + DST[ACOMP] = SRC[3] +#include "swrast/s_spantemp.h" + +/* 16-bit RGBA */ +#define NAME(PREFIX) PREFIX##_RGBA16 +#define RB_TYPE GLushort +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 #define STORE_PIXEL(DST, X, Y, VALUE) \ DST[0] = VALUE[RCOMP]; \ DST[1] = VALUE[GCOMP]; \ @@ -170,8 +181,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[0] = VALUE[RCOMP]; \ DST[1] = VALUE[GCOMP]; \ DST[2] = VALUE[BCOMP]; \ - DST[3] = CHAN_MAX -#endif + DST[3] = 65535 #define FETCH_PIXEL(DST, SRC) \ DST[RCOMP] = SRC[0]; \ DST[GCOMP] = SRC[1]; \ @@ -179,13 +189,89 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[ACOMP] = SRC[3] #include "swrast/s_spantemp.h" -/* BGRA */ -#define NAME(PREFIX) PREFIX##_BGRA -#define FORMAT GL_RGBA +/* 32-bit RGBA */ +#define NAME(PREFIX) PREFIX##_RGBA32 +#define RB_TYPE GLfloat +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ + DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ + DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ + DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F) +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ + DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ + DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ + DST[3] = 1.0F +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[0]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[2]; \ + DST[ACOMP] = SRC[3] +#include "swrast/s_spantemp.h" + + +/* 8-bit BGRA */ +#define NAME(PREFIX) PREFIX##_BGRA8 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP]; \ + DST[3] = VALUE[ACOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP]; \ + DST[3] = 255 +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = SRC[3] +#include "swrast/s_spantemp.h" + +/* 16-bit BGRA */ +#define NAME(PREFIX) PREFIX##_BGRA16 +#define RB_TYPE GLushort +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP]; \ + DST[3] = VALUE[ACOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP]; \ + DST[3] = 65535 +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = SRC[3] +#include "swrast/s_spantemp.h" + +/* 32-bit BGRA */ +#define NAME(PREFIX) PREFIX##_BGRA32 +#define RB_TYPE GLfloat #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ - GLchan *P = osmesa->rowaddr[Y] + 4 * (X) + GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) #define INC_PIXEL_PTR(P) P += 4 #define STORE_PIXEL(DST, X, Y, VALUE) \ DST[2] = VALUE[RCOMP]; \ @@ -196,7 +282,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[2] = VALUE[RCOMP]; \ DST[1] = VALUE[GCOMP]; \ DST[0] = VALUE[BCOMP]; \ - DST[3] = CHAN_MAX + DST[3] = 1.0F #define FETCH_PIXEL(DST, SRC) \ DST[RCOMP] = SRC[2]; \ DST[GCOMP] = SRC[1]; \ @@ -204,13 +290,14 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[ACOMP] = SRC[3] #include "swrast/s_spantemp.h" -/* ARGB */ -#define NAME(PREFIX) PREFIX##_ARGB -#define FORMAT GL_RGBA + +/* 8-bit ARGB */ +#define NAME(PREFIX) PREFIX##_ARGB8 +#define RB_TYPE GLubyte #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ - GLchan *P = osmesa->rowaddr[Y] + 4 * (X) + GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) #define INC_PIXEL_PTR(P) P += 4 #define STORE_PIXEL(DST, X, Y, VALUE) \ DST[1] = VALUE[RCOMP]; \ @@ -221,7 +308,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[1] = VALUE[RCOMP]; \ DST[2] = VALUE[GCOMP]; \ DST[3] = VALUE[BCOMP]; \ - DST[0] = CHAN_MAX + DST[0] = 255 #define FETCH_PIXEL(DST, SRC) \ DST[RCOMP] = SRC[1]; \ DST[GCOMP] = SRC[2]; \ @@ -229,13 +316,64 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[ACOMP] = SRC[0] #include "swrast/s_spantemp.h" -/* RGB */ -#define NAME(PREFIX) PREFIX##_RGB -#define FORMAT GL_RGBA +/* 16-bit ARGB */ +#define NAME(PREFIX) PREFIX##_ARGB16 +#define RB_TYPE GLushort #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ - GLchan *P = osmesa->rowaddr[Y] + 3 * (X) + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[1] = VALUE[RCOMP]; \ + DST[2] = VALUE[GCOMP]; \ + DST[3] = VALUE[BCOMP]; \ + DST[0] = VALUE[ACOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[1] = VALUE[RCOMP]; \ + DST[2] = VALUE[GCOMP]; \ + DST[3] = VALUE[BCOMP]; \ + DST[0] = 65535 +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[1]; \ + DST[GCOMP] = SRC[2]; \ + DST[BCOMP] = SRC[3]; \ + DST[ACOMP] = SRC[0] +#include "swrast/s_spantemp.h" + +/* 32-bit ARGB */ +#define NAME(PREFIX) PREFIX##_ARGB32 +#define RB_TYPE GLfloat +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) +#define INC_PIXEL_PTR(P) P += 4 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[1] = VALUE[RCOMP]; \ + DST[2] = VALUE[GCOMP]; \ + DST[3] = VALUE[BCOMP]; \ + DST[0] = VALUE[ACOMP] +#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ + DST[1] = VALUE[RCOMP]; \ + DST[2] = VALUE[GCOMP]; \ + DST[3] = VALUE[BCOMP]; \ + DST[0] = 1.0F +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[1]; \ + DST[GCOMP] = SRC[2]; \ + DST[BCOMP] = SRC[3]; \ + DST[ACOMP] = SRC[0] +#include "swrast/s_spantemp.h" + + +/* 8-bit RGB */ +#define NAME(PREFIX) PREFIX##_RGB8 +#define RB_TYPE GLubyte +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X) #define INC_PIXEL_PTR(P) P += 3 #define STORE_PIXEL(DST, X, Y, VALUE) \ DST[0] = VALUE[RCOMP]; \ @@ -245,16 +383,55 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[RCOMP] = SRC[0]; \ DST[GCOMP] = SRC[1]; \ DST[BCOMP] = SRC[2]; \ - DST[ACOMP] = CHAN_MAX + DST[ACOMP] = 255 +#include "swrast/s_spantemp.h" + +/* 16-bit RGB */ +#define NAME(PREFIX) PREFIX##_RGB16 +#define RB_TYPE GLushort +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X) +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[0]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[2]; \ + DST[ACOMP] = 65535U +#include "swrast/s_spantemp.h" + +/* 32-bit RGB */ +#define NAME(PREFIX) PREFIX##_RGB32 +#define RB_TYPE GLfloat +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X) +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[0] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[2] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[0]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[2]; \ + DST[ACOMP] = 1.0F #include "swrast/s_spantemp.h" -/* BGR */ -#define NAME(PREFIX) PREFIX##_BGR -#define FORMAT GL_RGBA + +/* 8-bit BGR */ +#define NAME(PREFIX) PREFIX##_BGR8 +#define RB_TYPE GLubyte #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ - GLchan *P = osmesa->rowaddr[Y] + 3 * (X) + GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X) #define INC_PIXEL_PTR(P) P += 3 #define STORE_PIXEL(DST, X, Y, VALUE) \ DST[2] = VALUE[RCOMP]; \ @@ -264,13 +441,51 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[RCOMP] = SRC[2]; \ DST[GCOMP] = SRC[1]; \ DST[BCOMP] = SRC[0]; \ - DST[ACOMP] = CHAN_MAX + DST[ACOMP] = 255 #include "swrast/s_spantemp.h" -/* 16-bit RGB */ -#if CHAN_TYPE == GL_UNSIGNED_BYTE +/* 16-bit BGR */ +#define NAME(PREFIX) PREFIX##_BGR16 +#define RB_TYPE GLushort +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X) +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = 65535 +#include "swrast/s_spantemp.h" + +/* 32-bit BGR */ +#define NAME(PREFIX) PREFIX##_BGR32 +#define RB_TYPE GLfloat +#define SPAN_VARS \ + const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); +#define INIT_PIXEL_PTR(P, X, Y) \ + GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X) +#define INC_PIXEL_PTR(P) P += 3 +#define STORE_PIXEL(DST, X, Y, VALUE) \ + DST[2] = VALUE[RCOMP]; \ + DST[1] = VALUE[GCOMP]; \ + DST[0] = VALUE[BCOMP] +#define FETCH_PIXEL(DST, SRC) \ + DST[RCOMP] = SRC[2]; \ + DST[GCOMP] = SRC[1]; \ + DST[BCOMP] = SRC[0]; \ + DST[ACOMP] = 1.0F +#include "swrast/s_spantemp.h" + + +/* 16-bit 5/6/5 RGB */ #define NAME(PREFIX) PREFIX##_RGB_565 -#define FORMAT GL_RGBA +#define RB_TYPE GLubyte #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ @@ -284,11 +499,12 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC) ) & 0x7) ); \ DST[ACOMP] = CHAN_MAX #include "swrast/s_spantemp.h" -#endif /* CHAN_TYPE == GL_UNSIGNED_BYTE */ + /* color index */ #define NAME(PREFIX) PREFIX##_CI -#define FORMAT GL_COLOR_INDEX8_EXT +#define CI_MODE +#define RB_TYPE GLubyte #define SPAN_VARS \ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); #define INIT_PIXEL_PTR(P, X, Y) \ @@ -303,20 +519,11 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) -/**********************************************************************/ -/***** Optimized line rendering *****/ -/**********************************************************************/ - +/** + * Macros for optimized line/triangle rendering. + * Only for 8-bit channel, RGBA, BGRA, ARGB formats. + */ -#if CHAN_TYPE == GL_FLOAT -#define PACK_RGBA(DST, R, G, B, A) \ -do { \ - (DST)[0] = MAX2( R, 0.0F ); \ - (DST)[1] = MAX2( G, 0.0F ); \ - (DST)[2] = MAX2( B, 0.0F ); \ - (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ -} while (0) -#else #define PACK_RGBA(DST, R, G, B, A) \ do { \ (DST)[osmesa->rInd] = R; \ @@ -324,39 +531,11 @@ do { \ (DST)[osmesa->bInd] = B; \ (DST)[osmesa->aInd] = A; \ } while (0) -#endif - -#define PACK_RGB(DST, R, G, B) \ -do { \ - (DST)[0] = R; \ - (DST)[1] = G; \ - (DST)[2] = B; \ -} while (0) -#define PACK_BGR(DST, R, G, B) \ -do { \ - (DST)[0] = B; \ - (DST)[1] = G; \ - (DST)[2] = R; \ -} while (0) - -#define PACK_RGB_565(DST, R, G, B) \ -do { \ - (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ -} while (0) +#define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X)) -#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) -#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) -#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) -#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) -#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) -#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) -#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) -#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) - - -/* +/** * Draw a flat-shaded, RGB line into an osmesa buffer. */ #define NAME flat_rgba_line @@ -379,7 +558,7 @@ do { \ -/* +/** * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. */ #define NAME flat_rgba_z_line @@ -408,9 +587,9 @@ do { \ -/* +/** * Analyze context state to see if we can provide a fast line drawing - * function, like those in lines.c. Otherwise, return NULL. + * function. Otherwise, return NULL. */ static swrast_line_func osmesa_choose_line_function( GLcontext *ctx ) @@ -518,8 +697,8 @@ osmesa_choose_line_function( GLcontext *ctx ) -/* - * Return pointer to an accelerated triangle function if possible. +/** + * Return pointer to an optimized triangle function if possible. */ static swrast_tri_func osmesa_choose_triangle_function( GLcontext *ctx ) @@ -600,73 +779,170 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); + GLint bpc; /* bits per channel */ + + if (rb->DataType == GL_UNSIGNED_BYTE) + bpc = 8; + else if (rb->DataType == GL_UNSIGNED_SHORT) + bpc = 16; + else + bpc = 32; /* Note: we can ignoring internalFormat for "window-system" renderbuffers */ + (void) internalFormat; + if (osmesa->format == OSMESA_RGBA) { - rb->GetRow = get_row_RGBA; - rb->GetValues = get_values_RGBA; - rb->PutRow = put_row_RGBA; - rb->PutRowRGB = put_row_rgb_RGBA; - rb->PutMonoRow = put_mono_row_RGBA; - rb->PutValues = put_values_RGBA; - rb->PutMonoValues = put_mono_values_RGBA; - rb->RedBits = - rb->GreenBits = - rb->BlueBits = - rb->AlphaBits = 8 * sizeof(GLchan); + if (rb->DataType == GL_UNSIGNED_BYTE) { + rb->GetRow = get_row_RGBA8; + rb->GetValues = get_values_RGBA8; + rb->PutRow = put_row_RGBA8; + rb->PutRowRGB = put_row_rgb_RGBA8; + rb->PutMonoRow = put_mono_row_RGBA8; + rb->PutValues = put_values_RGBA8; + rb->PutMonoValues = put_mono_values_RGBA8; + } + else if (rb->DataType == GL_UNSIGNED_SHORT) { + rb->GetRow = get_row_RGBA16; + rb->GetValues = get_values_RGBA16; + rb->PutRow = put_row_RGBA16; + rb->PutRowRGB = put_row_rgb_RGBA16; + rb->PutMonoRow = put_mono_row_RGBA16; + rb->PutValues = put_values_RGBA16; + rb->PutMonoValues = put_mono_values_RGBA16; + } + else { + rb->GetRow = get_row_RGBA32; + rb->GetValues = get_values_RGBA32; + rb->PutRow = put_row_RGBA32; + rb->PutRowRGB = put_row_rgb_RGBA32; + rb->PutMonoRow = put_mono_row_RGBA32; + rb->PutValues = put_values_RGBA32; + rb->PutMonoValues = put_mono_values_RGBA32; + } + rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc; } else if (osmesa->format == OSMESA_BGRA) { - rb->GetRow = get_row_BGRA; - rb->GetValues = get_values_BGRA; - rb->PutRow = put_row_BGRA; - rb->PutRowRGB = put_row_rgb_BGRA; - rb->PutMonoRow = put_mono_row_BGRA; - rb->PutValues = put_values_BGRA; - rb->PutMonoValues = put_mono_values_BGRA; - rb->RedBits = - rb->GreenBits = - rb->BlueBits = - rb->AlphaBits = 8 * sizeof(GLchan); + if (rb->DataType == GL_UNSIGNED_BYTE) { + rb->GetRow = get_row_BGRA8; + rb->GetValues = get_values_BGRA8; + rb->PutRow = put_row_BGRA8; + rb->PutRowRGB = put_row_rgb_BGRA8; + rb->PutMonoRow = put_mono_row_BGRA8; + rb->PutValues = put_values_BGRA8; + rb->PutMonoValues = put_mono_values_BGRA8; + } + else if (rb->DataType == GL_UNSIGNED_SHORT) { + rb->GetRow = get_row_BGRA16; + rb->GetValues = get_values_BGRA16; + rb->PutRow = put_row_BGRA16; + rb->PutRowRGB = put_row_rgb_BGRA16; + rb->PutMonoRow = put_mono_row_BGRA16; + rb->PutValues = put_values_BGRA16; + rb->PutMonoValues = put_mono_values_BGRA16; + } + else { + rb->GetRow = get_row_BGRA32; + rb->GetValues = get_values_BGRA32; + rb->PutRow = put_row_BGRA32; + rb->PutRowRGB = put_row_rgb_BGRA32; + rb->PutMonoRow = put_mono_row_BGRA32; + rb->PutValues = put_values_BGRA32; + rb->PutMonoValues = put_mono_values_BGRA32; + } + rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc; } else if (osmesa->format == OSMESA_ARGB) { - rb->GetRow = get_row_ARGB; - rb->GetValues = get_values_ARGB; - rb->PutRow = put_row_ARGB; - rb->PutRowRGB = put_row_rgb_ARGB; - rb->PutMonoRow = put_mono_row_ARGB; - rb->PutValues = put_values_ARGB; - rb->PutMonoValues = put_mono_values_ARGB; - rb->RedBits = - rb->GreenBits = - rb->BlueBits = - rb->AlphaBits = 8 * sizeof(GLchan); + if (rb->DataType == GL_UNSIGNED_BYTE) { + rb->GetRow = get_row_ARGB8; + rb->GetValues = get_values_ARGB8; + rb->PutRow = put_row_ARGB8; + rb->PutRowRGB = put_row_rgb_ARGB8; + rb->PutMonoRow = put_mono_row_ARGB8; + rb->PutValues = put_values_ARGB8; + rb->PutMonoValues = put_mono_values_ARGB8; + } + else if (rb->DataType == GL_UNSIGNED_SHORT) { + rb->GetRow = get_row_ARGB16; + rb->GetValues = get_values_ARGB16; + rb->PutRow = put_row_ARGB16; + rb->PutRowRGB = put_row_rgb_ARGB16; + rb->PutMonoRow = put_mono_row_ARGB16; + rb->PutValues = put_values_ARGB16; + rb->PutMonoValues = put_mono_values_ARGB16; + } + else { + rb->GetRow = get_row_ARGB32; + rb->GetValues = get_values_ARGB32; + rb->PutRow = put_row_ARGB32; + rb->PutRowRGB = put_row_rgb_ARGB32; + rb->PutMonoRow = put_mono_row_ARGB32; + rb->PutValues = put_values_ARGB32; + rb->PutMonoValues = put_mono_values_ARGB32; + } + rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc; } else if (osmesa->format == OSMESA_RGB) { - rb->GetRow = get_row_RGB; - rb->GetValues = get_values_RGB; - rb->PutRow = put_row_RGB; - rb->PutRowRGB = put_row_rgb_RGB; - rb->PutMonoRow = put_mono_row_RGB; - rb->PutValues = put_values_RGB; - rb->PutMonoValues = put_mono_values_RGB; - rb->RedBits = - rb->GreenBits = - rb->BlueBits = 8 * sizeof(GLchan); + if (rb->DataType == GL_UNSIGNED_BYTE) { + rb->GetRow = get_row_RGB8; + rb->GetValues = get_values_RGB8; + rb->PutRow = put_row_RGB8; + rb->PutRowRGB = put_row_rgb_RGB8; + rb->PutMonoRow = put_mono_row_RGB8; + rb->PutValues = put_values_RGB8; + rb->PutMonoValues = put_mono_values_RGB8; + } + else if (rb->DataType == GL_UNSIGNED_SHORT) { + rb->GetRow = get_row_RGB16; + rb->GetValues = get_values_RGB16; + rb->PutRow = put_row_RGB16; + rb->PutRowRGB = put_row_rgb_RGB16; + rb->PutMonoRow = put_mono_row_RGB16; + rb->PutValues = put_values_RGB16; + rb->PutMonoValues = put_mono_values_RGB16; + } + else { + rb->GetRow = get_row_RGB32; + rb->GetValues = get_values_RGB32; + rb->PutRow = put_row_RGB32; + rb->PutRowRGB = put_row_rgb_RGB32; + rb->PutMonoRow = put_mono_row_RGB32; + rb->PutValues = put_values_RGB32; + rb->PutMonoValues = put_mono_values_RGB32; + } + rb->RedBits = rb->GreenBits = rb->BlueBits = bpc; } else if (osmesa->format == OSMESA_BGR) { - rb->GetRow = get_row_BGR; - rb->GetValues = get_values_BGR; - rb->PutRow = put_row_BGR; - rb->PutRowRGB = put_row_rgb_BGR; - rb->PutMonoRow = put_mono_row_BGR; - rb->PutValues = put_values_BGR; - rb->PutMonoValues = put_mono_values_BGR; - rb->RedBits = - rb->GreenBits = - rb->BlueBits = 8 * sizeof(GLchan); + if (rb->DataType == GL_UNSIGNED_BYTE) { + rb->GetRow = get_row_BGR8; + rb->GetValues = get_values_BGR8; + rb->PutRow = put_row_BGR8; + rb->PutRowRGB = put_row_rgb_BGR8; + rb->PutMonoRow = put_mono_row_BGR8; + rb->PutValues = put_values_BGR8; + rb->PutMonoValues = put_mono_values_BGR8; + } + else if (rb->DataType == GL_UNSIGNED_SHORT) { + rb->GetRow = get_row_BGR16; + rb->GetValues = get_values_BGR16; + rb->PutRow = put_row_BGR16; + rb->PutRowRGB = put_row_rgb_BGR16; + rb->PutMonoRow = put_mono_row_BGR16; + rb->PutValues = put_values_BGR16; + rb->PutMonoValues = put_mono_values_BGR16; + } + else { + rb->GetRow = get_row_BGR32; + rb->GetValues = get_values_BGR32; + rb->PutRow = put_row_BGR32; + rb->PutRowRGB = put_row_rgb_BGR32; + rb->PutMonoRow = put_mono_row_BGR32; + rb->PutValues = put_values_BGR32; + rb->PutMonoValues = put_mono_values_BGR32; + } + rb->RedBits = rb->GreenBits = rb->BlueBits = bpc; } -#if CHAN_TYPE == GL_UNSIGNED_BYTE else if (osmesa->format == OSMESA_RGB_565) { + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); rb->GetRow = get_row_RGB_565; rb->GetValues = get_values_RGB_565; rb->PutRow = put_row_RGB_565; @@ -678,7 +954,6 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, rb->GreenBits = 6; rb->BlueBits = 5; } -#endif else if (osmesa->format == OSMESA_COLOR_INDEX) { rb->GetRow = get_row_CI; rb->GetValues = get_values_CI; @@ -692,33 +967,36 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage"); } + rb->Width = width; + rb->Height = height; + return GL_TRUE; } /** - * Allocate a new renderbuffer tpo describe the user-provided color buffer. + * Allocate a new renderbuffer to describe the user-provided color buffer. */ static struct gl_renderbuffer * -new_osmesa_renderbuffer(GLenum format) +new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type) { - struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); + const GLuint name = 0; + struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); if (rb) { - const GLuint name = 0; - _mesa_init_renderbuffer(rb, name); - rb->Delete = osmesa_delete_renderbuffer; rb->AllocStorage = osmesa_renderbuffer_storage; if (format == OSMESA_COLOR_INDEX) { - rb->_BaseFormat = GL_COLOR_INDEX; rb->InternalFormat = GL_COLOR_INDEX; + rb->_ActualFormat = GL_COLOR_INDEX8_EXT; + rb->_BaseFormat = GL_COLOR_INDEX; rb->DataType = GL_UNSIGNED_BYTE; } else { - rb->_BaseFormat = GL_RGBA; rb->InternalFormat = GL_RGBA; - rb->DataType = CHAN_TYPE; + rb->_ActualFormat = GL_RGBA; + rb->_BaseFormat = GL_RGBA; + rb->DataType = type; } } return rb; @@ -726,12 +1004,70 @@ new_osmesa_renderbuffer(GLenum format) +/** + * Recompute the values of the context's rowaddr array. + */ +static void +compute_row_addresses( OSMesaContext osmesa ) +{ + GLint bytesPerPixel, bytesPerRow, i; + GLubyte *origin = (GLubyte *) osmesa->rb->Data; + GLint bpc; /* bytes per channel */ + + if (osmesa->rb->DataType == GL_UNSIGNED_BYTE) + bpc = 1; + else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT) + bpc = 2; + else if (osmesa->rb->DataType == GL_FLOAT) + bpc = 4; + else { + _mesa_problem(&osmesa->mesa, + "Unexpected datatype in osmesa::compute_row_addresses"); + return; + } + + if (osmesa->format == OSMESA_COLOR_INDEX) { + /* CI mode */ + bytesPerPixel = 1 * sizeof(GLubyte); + } + else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) { + /* RGB mode */ + bytesPerPixel = 3 * bpc; + } + else if (osmesa->format == OSMESA_RGB_565) { + /* 5/6/5 RGB pixel in 16 bits */ + bytesPerPixel = 2; + } + else { + /* RGBA mode */ + bytesPerPixel = 4 * bpc; + } + + bytesPerRow = osmesa->rowlength * bytesPerPixel; + + if (osmesa->yup) { + /* Y=0 is bottom line of window */ + for (i = 0; i < MAX_HEIGHT; i++) { + osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow); + } + } + else { + /* Y=0 is top line of window */ + for (i = 0; i < MAX_HEIGHT; i++) { + GLint j = osmesa->height - i - 1; + osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow); + } + } +} + + + /**********************************************************************/ /***** Public Functions *****/ /**********************************************************************/ -/* +/** * Create an Off-Screen Mesa rendering context. The only attribute needed is * an RGBA vs Color-Index mode flag. * @@ -750,7 +1086,7 @@ OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) -/* +/** * New in Mesa 3.5 * * Create context and specify size of ancillary buffers. @@ -764,6 +1100,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, GLint rind, gind, bind, aind; GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; GLboolean rgbmode; + GLenum type = CHAN_TYPE; rind = gind = bind = aind = 0; if (format==OSMESA_COLOR_INDEX) { @@ -864,7 +1201,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 1 /* num samples */ ); if (!osmesa->gl_visual) { - FREE(osmesa); + _mesa_free(osmesa); return NULL; } @@ -881,7 +1218,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, : (GLcontext *) NULL, &functions, (void *) osmesa)) { _mesa_destroy_visual( osmesa->gl_visual ); - FREE(osmesa); + _mesa_free(osmesa); return NULL; } @@ -894,13 +1231,14 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, if (!osmesa->gl_buffer) { _mesa_destroy_visual( osmesa->gl_visual ); _mesa_free_context_data( &osmesa->mesa ); - FREE(osmesa); + _mesa_free(osmesa); return NULL; } /* create front color buffer in user-provided memory (no back buffer) */ - _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, - new_osmesa_renderbuffer(format)); + osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type); + _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb); + _mesa_add_soft_renderbuffers(osmesa->gl_buffer, GL_FALSE, /* color */ osmesa->gl_visual->haveDepthBuffer, @@ -910,7 +1248,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, GL_FALSE /* aux */ ); osmesa->format = format; - osmesa->buffer = NULL; osmesa->width = 0; osmesa->height = 0; osmesa->userRowLength = 0; @@ -955,73 +1292,29 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, } -/* +/** * Destroy an Off-Screen Mesa rendering context. * - * Input: ctx - the context to destroy + * \param osmesa the context to destroy */ GLAPI void GLAPIENTRY -OSMesaDestroyContext( OSMesaContext ctx ) -{ - if (ctx) { - _swsetup_DestroyContext( &ctx->mesa ); - _tnl_DestroyContext( &ctx->mesa ); - _ac_DestroyContext( &ctx->mesa ); - _swrast_DestroyContext( &ctx->mesa ); - - _mesa_destroy_visual( ctx->gl_visual ); - _mesa_destroy_framebuffer( ctx->gl_buffer ); - _mesa_free_context_data( &ctx->mesa ); - FREE( ctx ); - } -} - - -/* - * Recompute the values of the context's rowaddr array. - */ -static void -compute_row_addresses( OSMesaContext ctx ) +OSMesaDestroyContext( OSMesaContext osmesa ) { - GLint bytesPerPixel, bytesPerRow, i; - GLubyte *origin = (GLubyte *) ctx->buffer; - - if (ctx->format == OSMESA_COLOR_INDEX) { - /* CI mode */ - bytesPerPixel = 1 * sizeof(GLubyte); - } - else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { - /* RGB mode */ - bytesPerPixel = 3 * sizeof(GLchan); - } - else if (ctx->format == OSMESA_RGB_565) { - /* 5/6/5 RGB pixel in 16 bits */ - bytesPerPixel = 2; - } - else { - /* RGBA mode */ - bytesPerPixel = 4 * sizeof(GLchan); - } - - bytesPerRow = ctx->rowlength * bytesPerPixel; - - if (ctx->yup) { - /* Y=0 is bottom line of window */ - for (i = 0; i < MAX_HEIGHT; i++) { - ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); - } - } - else { - /* Y=0 is top line of window */ - for (i = 0; i < MAX_HEIGHT; i++) { - GLint j = ctx->height - i - 1; - ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); - } + if (osmesa) { + _swsetup_DestroyContext( &osmesa->mesa ); + _tnl_DestroyContext( &osmesa->mesa ); + _ac_DestroyContext( &osmesa->mesa ); + _swrast_DestroyContext( &osmesa->mesa ); + + _mesa_destroy_visual( osmesa->gl_visual ); + _mesa_destroy_framebuffer( osmesa->gl_buffer ); + _mesa_free_context_data( &osmesa->mesa ); + _mesa_free( osmesa ); } } -/* +/** * Bind an OSMesaContext to an image buffer. The image buffer is just a * block of memory which the client provides. Its size must be at least * as large as width*height*sizeof(type). Its address should be a multiple @@ -1034,33 +1327,37 @@ compute_row_addresses( OSMesaContext ctx ) * If the context's viewport hasn't been initialized yet, it will now be * initialized to (0,0,width,height). * - * Input: ctx - the rendering context + * Input: osmesa - the rendering context * buffer - the image buffer memory * type - data type for pixel components * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 * are supported. But if Mesa's been compiled with CHAN_BITS==16 - * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build - * with CHAN_BITS==32 then type must be GL_FLOAT. + * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if + * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT, + * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. * width, height - size of image buffer in pixels, at least 1 - * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, + * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, * invalid buffer address, invalid type, width<1, height<1, * width>internal limit or height>internal limit. */ GLAPI GLboolean GLAPIENTRY -OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, +OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type, GLsizei width, GLsizei height ) { - if (!ctx || !buffer || + if (!osmesa || !buffer || width < 1 || height < 1 || width > MAX_WIDTH || height > MAX_HEIGHT) { return GL_FALSE; } - if (ctx->format == OSMESA_RGB_565) { - if (type != GL_UNSIGNED_SHORT_5_6_5) - return GL_FALSE; + if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) { + return GL_FALSE; } - else if (type != CHAN_TYPE) { + + if (!(type == GL_UNSIGNED_BYTE || + (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) || + (type == GL_FLOAT && CHAN_BITS == 32))) { + /* i.e. is sizeof(type) * 8 > CHAN_BITS? */ return GL_FALSE; } @@ -1069,28 +1366,43 @@ OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, * get_buffer_size() function to initialize the viewport. These are the * values returned by get_buffer_size(): */ - ctx->buffer = buffer; - ctx->width = width; - ctx->height = height; + osmesa->width = width; + osmesa->height = height; - osmesa_update_state( &ctx->mesa, 0 ); + osmesa_update_state( &osmesa->mesa, 0 ); /* Call this periodically to detect when the user has begun using * GL rendering from multiple threads. */ _glapi_check_multithread(); - _mesa_make_current( &ctx->mesa, ctx->gl_buffer, ctx->gl_buffer ); + _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer ); - if (ctx->userRowLength) - ctx->rowlength = ctx->userRowLength; + if (osmesa->userRowLength) + osmesa->rowlength = osmesa->userRowLength; else - ctx->rowlength = width; + osmesa->rowlength = width; + + osmesa->rb->Data = buffer; + osmesa->rb->DataType = type; + compute_row_addresses( osmesa ); + + /* update the color renderbuffer's format, type, width, height */ + osmesa_renderbuffer_storage(&osmesa->mesa, osmesa->rb, + osmesa->rb->InternalFormat, width, height); - compute_row_addresses( ctx ); + /* Remove renderbuffer attachment, then re-add. This installs the + * renderbuffer adaptor/wrapper if needed. + */ + _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); + _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb); - /* this will make ensure we recognize the new buffer size */ - _mesa_resize_framebuffer(&ctx->mesa, ctx->gl_buffer, width, height); + + /* this updates the visual's red/green/blue/alphaBits fields */ + _mesa_update_framebuffer_visual(osmesa->gl_buffer); + + /* update the framebuffer size */ + _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); return GL_TRUE; } @@ -1152,7 +1464,13 @@ OSMesaGetIntegerv( GLint pname, GLint *value ) *value = osmesa->format; return; case OSMESA_TYPE: - *value = CHAN_TYPE; + /* current color buffer's data type */ + if (osmesa->rb) { + *value = osmesa->rb->DataType; + } + else { + *value = 0; + } return; case OSMESA_ROW_LENGTH: *value = osmesa->userRowLength; @@ -1172,7 +1490,8 @@ OSMesaGetIntegerv( GLint pname, GLint *value ) } } -/* + +/** * Return the depth buffer associated with an OSMesa context. * Input: c - the OSMesa context * Output: width, height - size of buffer in pixels @@ -1190,7 +1509,6 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer; if (!rb || !rb->Data) { - /*if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {*/ *width = 0; *height = 0; *bytesPerValue = 0; @@ -1209,7 +1527,8 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, } } -/* + +/** * Return the color buffer associated with an OSMesa context. * Input: c - the OSMesa context * Output: width, height - size of buffer in pixels @@ -1218,23 +1537,23 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, * Return: GL_TRUE or GL_FALSE to indicate success or failure. */ GLAPI GLboolean GLAPIENTRY -OSMesaGetColorBuffer( OSMesaContext c, GLint *width, +OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width, GLint *height, GLint *format, void **buffer ) { - if (!c->buffer) { + if (osmesa->rb && osmesa->rb->Data) { + *width = osmesa->rb->Width; + *height = osmesa->rb->Height; + *format = osmesa->format; + *buffer = osmesa->rb->Data; + return GL_TRUE; + } + else { *width = 0; *height = 0; *format = 0; *buffer = 0; return GL_FALSE; } - else { - *width = c->width; - *height = c->height; - *format = c->format; - *buffer = c->buffer; - return GL_TRUE; - } } diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c index 09330e78ab5..ca79ebb6c74 100644 --- a/src/mesa/drivers/svga/svgamesa.c +++ b/src/mesa/drivers/svga/svgamesa.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa.c,v 1.26 2005/09/07 23:26:01 brianp Exp $ */ +/* $Id: svgamesa.c,v 1.26 2005-09-07 23:26:01 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa15.c b/src/mesa/drivers/svga/svgamesa15.c index 54b6c977a7b..817da34ef1d 100644 --- a/src/mesa/drivers/svga/svgamesa15.c +++ b/src/mesa/drivers/svga/svgamesa15.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa15.c,v 1.11 2002/11/11 18:42:39 brianp Exp $ */ +/* $Id: svgamesa15.c,v 1.11 2002-11-11 18:42:39 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa15.h b/src/mesa/drivers/svga/svgamesa15.h index 3ed7db82ee5..4a318d3aa73 100644 --- a/src/mesa/drivers/svga/svgamesa15.h +++ b/src/mesa/drivers/svga/svgamesa15.h @@ -1,4 +1,4 @@ -/* $Id: svgamesa15.h,v 1.7 2002/11/11 18:42:39 brianp Exp $ */ +/* $Id: svgamesa15.h,v 1.7 2002-11-11 18:42:39 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa16.c b/src/mesa/drivers/svga/svgamesa16.c index 72ac8183294..483158ccdb4 100644 --- a/src/mesa/drivers/svga/svgamesa16.c +++ b/src/mesa/drivers/svga/svgamesa16.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa16.c,v 1.11 2002/11/11 18:42:40 brianp Exp $ */ +/* $Id: svgamesa16.c,v 1.11 2002-11-11 18:42:40 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa16.h b/src/mesa/drivers/svga/svgamesa16.h index 247c1f40455..91ac404ab77 100644 --- a/src/mesa/drivers/svga/svgamesa16.h +++ b/src/mesa/drivers/svga/svgamesa16.h @@ -1,4 +1,4 @@ -/* $Id: svgamesa16.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */ +/* $Id: svgamesa16.h,v 1.6 2002-11-11 18:42:41 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa24.c b/src/mesa/drivers/svga/svgamesa24.c index 07491cc67ac..ff3b24894e1 100644 --- a/src/mesa/drivers/svga/svgamesa24.c +++ b/src/mesa/drivers/svga/svgamesa24.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa24.c,v 1.12 2002/11/11 18:42:41 brianp Exp $ */ +/* $Id: svgamesa24.c,v 1.12 2002-11-11 18:42:41 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa24.h b/src/mesa/drivers/svga/svgamesa24.h index 54d1a8298ba..be41bd4abb5 100644 --- a/src/mesa/drivers/svga/svgamesa24.h +++ b/src/mesa/drivers/svga/svgamesa24.h @@ -1,4 +1,4 @@ -/* $Id: svgamesa24.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */ +/* $Id: svgamesa24.h,v 1.6 2002-11-11 18:42:41 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa32.c b/src/mesa/drivers/svga/svgamesa32.c index 8a366998d6b..a7829526dda 100644 --- a/src/mesa/drivers/svga/svgamesa32.c +++ b/src/mesa/drivers/svga/svgamesa32.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa32.c,v 1.12 2002/11/11 18:42:42 brianp Exp $ */ +/* $Id: svgamesa32.c,v 1.12 2002-11-11 18:42:42 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa32.h b/src/mesa/drivers/svga/svgamesa32.h index f518e11ad5b..f622fbfa64b 100644 --- a/src/mesa/drivers/svga/svgamesa32.h +++ b/src/mesa/drivers/svga/svgamesa32.h @@ -1,4 +1,4 @@ -/* $Id: svgamesa32.h,v 1.6 2002/11/11 18:42:42 brianp Exp $ */ +/* $Id: svgamesa32.h,v 1.6 2002-11-11 18:42:42 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa8.c b/src/mesa/drivers/svga/svgamesa8.c index fd880ef85ad..6f57ae7e4d6 100644 --- a/src/mesa/drivers/svga/svgamesa8.c +++ b/src/mesa/drivers/svga/svgamesa8.c @@ -1,4 +1,4 @@ -/* $Id: svgamesa8.c,v 1.9 2005/05/04 20:11:39 brianp Exp $ */ +/* $Id: svgamesa8.c,v 1.9 2005-05-04 20:11:39 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgamesa8.h b/src/mesa/drivers/svga/svgamesa8.h index 1aa25f93fce..d9c1979f0e0 100644 --- a/src/mesa/drivers/svga/svgamesa8.h +++ b/src/mesa/drivers/svga/svgamesa8.h @@ -1,4 +1,4 @@ -/* $Id: svgamesa8.h,v 1.4 2001/02/06 00:03:48 brianp Exp $ */ +/* $Id: svgamesa8.h,v 1.4 2001-02-06 00:03:48 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/svga/svgapix.h b/src/mesa/drivers/svga/svgapix.h index 0b19551bf6e..00c1292bb3a 100644 --- a/src/mesa/drivers/svga/svgapix.h +++ b/src/mesa/drivers/svga/svgapix.h @@ -1,4 +1,4 @@ -/* $Id: svgapix.h,v 1.5 2002/11/11 18:42:44 brianp Exp $ */ +/* $Id: svgapix.h,v 1.5 2002-11-11 18:42:44 brianp Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/windows/fx/fx.rc b/src/mesa/drivers/windows/fx/fx.rc new file mode 100644 index 00000000000..f920b8768dd --- /dev/null +++ b/src/mesa/drivers/windows/fx/fx.rc @@ -0,0 +1,39 @@ +#include <windows.h> + +#define PRODNAME "Mesa 6.x" +#define CONTACTSTR "http://www.mesa3d.org" +#define HWSTR "3dfx Voodoo Graphics, Voodoo Rush, Voodoo^2, Voodoo Banshee, Velocity 100/200, Voodoo3, Voodoo4, Voodoo5" +#define COPYRIGHTSTR "Copyright \251 Brian E. Paul" + +#define VERSIONSTR "6.3.0.1" +#define MANVERSION 6 +#define MANREVISION 3 +#define BUILD_NUMBER 1 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER + PRODUCTVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER + FILEFLAGSMASK 0x0030003FL + + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DRV + FILESUBTYPE VFT2_DRV_INSTALLABLE +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "FileDescription", PRODNAME + VALUE "FileVersion", VERSIONSTR + VALUE "LegalCopyright", COPYRIGHTSTR + VALUE "ProductName", PRODNAME + VALUE "Graphics Subsystem", HWSTR + VALUE "Contact", CONTACTSTR + END + END + BLOCK "VarFileInfo" + BEGIN + /* the following line should be extended for localized versions */ + VALUE "Translation", 0x409, 1252 + END +END diff --git a/src/mesa/drivers/windows/gdi/wgl.c b/src/mesa/drivers/windows/gdi/wgl.c index 197de0743c7..2eef039d5d8 100644 --- a/src/mesa/drivers/windows/gdi/wgl.c +++ b/src/mesa/drivers/windows/gdi/wgl.c @@ -1,4 +1,4 @@ -/* $Id: wgl.c,v 1.12 2006/03/30 07:58:24 kschultz Exp $ */ +/* $Id: wgl.c,v 1.12 2006-03-30 07:58:24 kschultz Exp $ */ /* * This library is free software; you can redistribute it and/or diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c index 21292494242..8e861da5081 100644 --- a/src/mesa/drivers/windows/gdi/wmesa.c +++ b/src/mesa/drivers/windows/gdi/wmesa.c @@ -782,7 +782,7 @@ static void read_rgba_pixels_32(const GLcontext *ctx, for (i=0; i<n; i++) { GLint y2 = FLIP(y[i]); lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; - pixel = lpdw[i]; + pixel = *lpdw; rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16; rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8; rgba[i][BCOMP] = (pixel & 0x000000ff); @@ -966,7 +966,7 @@ static void read_rgba_pixels_16(const GLcontext *ctx, for (i=0; i<n; i++) { GLint y2 = FLIP(y[i]); lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; - pixel = lpw[i]; + pixel = *lpw; /* Windows uses 5,5,5 for 16-bit */ rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c new file mode 100644 index 00000000000..cad299540d7 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c @@ -0,0 +1,1196 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Driver interface code to Mesa +* +****************************************************************************/ + +//#include <windows.h> +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +extern BOOL dglSwapBuffers(HDC hDC); + +// HACK: Hack the _33 member of the OpenGL perspective projection matrix +const float _fPersp_33 = 1.6f; + +//--------------------------------------------------------------------------- +// Internal functions +//--------------------------------------------------------------------------- + +void _gld_mesa_warning( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal warning mechanism + gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str); +} + +//--------------------------------------------------------------------------- + +void _gld_mesa_fatal( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal fatal-message mechanism + gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str); + + // Mesa calls abort(0) here. + ddlogClose(); + exit(0); +} + +//--------------------------------------------------------------------------- + +D3DSTENCILOP _gldConvertStencilOp( + GLenum StencilOp) +{ + // Used by Stencil: pass, fail and zfail + + switch (StencilOp) { + case GL_KEEP: + return D3DSTENCILOP_KEEP; + case GL_ZERO: + return D3DSTENCILOP_ZERO; + case GL_REPLACE: + return D3DSTENCILOP_REPLACE; + case GL_INCR: + return D3DSTENCILOP_INCRSAT; + case GL_DECR: + return D3DSTENCILOP_DECRSAT; + case GL_INVERT: + return D3DSTENCILOP_INVERT; + case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_INCR; + case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_DECR; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n"); +#endif + + return D3DSTENCILOP_KEEP; +} + +//--------------------------------------------------------------------------- + +D3DCMPFUNC _gldConvertCompareFunc( + GLenum CmpFunc) +{ + // Used for Alpha func, depth func and stencil func. + + switch (CmpFunc) { + case GL_NEVER: + return D3DCMP_NEVER; + case GL_LESS: + return D3DCMP_LESS; + case GL_EQUAL: + return D3DCMP_EQUAL; + case GL_LEQUAL: + return D3DCMP_LESSEQUAL; + case GL_GREATER: + return D3DCMP_GREATER; + case GL_NOTEQUAL: + return D3DCMP_NOTEQUAL; + case GL_GEQUAL: + return D3DCMP_GREATEREQUAL; + case GL_ALWAYS: + return D3DCMP_ALWAYS; + }; + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n"); +#endif + + return D3DCMP_ALWAYS; +} + +//--------------------------------------------------------------------------- + +D3DBLEND _gldConvertBlendFunc( + GLenum blend, + GLenum DefaultBlend) +{ + switch (blend) { + case GL_ZERO: + return D3DBLEND_ZERO; + case GL_ONE: + return D3DBLEND_ONE; + case GL_DST_COLOR: + return D3DBLEND_DESTCOLOR; + case GL_SRC_COLOR: + return D3DBLEND_SRCCOLOR; + case GL_ONE_MINUS_DST_COLOR: + return D3DBLEND_INVDESTCOLOR; + case GL_ONE_MINUS_SRC_COLOR: + return D3DBLEND_INVSRCCOLOR; + case GL_SRC_ALPHA: + return D3DBLEND_SRCALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + return D3DBLEND_INVSRCALPHA; + case GL_DST_ALPHA: + return D3DBLEND_DESTALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return D3DBLEND_INVDESTALPHA; + case GL_SRC_ALPHA_SATURATE: + return D3DBLEND_SRCALPHASAT; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n"); +#endif + + return DefaultBlend; +} + +//--------------------------------------------------------------------------- +// Misc. functions +//--------------------------------------------------------------------------- + +void gld_Noop_DX7( + GLcontext *ctx) +{ +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n"); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_Error_DX7( + GLcontext *ctx) +{ +#ifdef _DEBUG + // Quite useless. +// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n"); +#endif +} + +//--------------------------------------------------------------------------- +// Required Mesa functions +//--------------------------------------------------------------------------- + +static GLboolean gld_set_draw_buffer_DX7( + GLcontext *ctx, + GLenum mode) +{ + (void) ctx; + if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +//--------------------------------------------------------------------------- + +static void gld_set_read_buffer_DX7( + GLcontext *ctx, + GLframebuffer *buffer, + GLenum mode) +{ + /* separate read buffer not supported */ +/* + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(mode == GL_FRONT_LEFT); +*/ +} + +//--------------------------------------------------------------------------- + +void gld_Clear_DX7( + GLcontext *ctx, + GLbitfield mask, + GLboolean all, + GLint x, + GLint y, + GLint width, + GLint height) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DCOLOR Color = 0; + float Z = 0.0f; + DWORD Stencil = 0; + D3DRECT d3dClearRect; + + // TODO: Colourmask + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if (!gld->pDev) + return; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + GLubyte col[4]; + CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]); + dwFlags |= D3DCLEAR_TARGET; + Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]); +// ctx->Color.ClearColor[1], +// ctx->Color.ClearColor[2], +// ctx->Color.ClearColor[3]); + } + + if (mask & DD_DEPTH_BIT) { + // D3D7 will fail the Clear call if we try and clear a + // depth buffer and we haven't created one. + // Also, some apps try and clear a depth buffer, + // when a depth buffer hasn't been requested by the app. + if (ctx->Visual.depthBits == 0) { + mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask + } else { + dwFlags |= D3DCLEAR_ZBUFFER; + Z = ctx->Depth.Clear; + } + } + + if (mask & DD_STENCIL_BIT) { + if (ctx->Visual.stencilBits == 0) { + // No stencil bits in depth buffer + mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask + } else { + dwFlags |= D3DCLEAR_STENCIL; + Stencil = ctx->Stencil.Clear; + } + } + + // Some apps do really weird things with the rect, such as Quake3. + if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) { + all = GL_TRUE; + } + + if (!all) { + // Calculate clear subrect + d3dClearRect.x1 = x; + d3dClearRect.y1 = gldCtx->dwHeight - (y + height); + d3dClearRect.x2 = x + width; + d3dClearRect.y2 = d3dClearRect.y1 + height; + } + + // dwFlags will be zero if there's nothing to clear + if (dwFlags) { + _GLD_DX7_DEV(Clear( + gld->pDev, + all ? 0 : 1, + all ? NULL : &d3dClearRect, + dwFlags, + Color, Z, Stencil)); + } + + if (mask & DD_ACCUM_BIT) { + // Clear accumulation buffer + } +} + +//--------------------------------------------------------------------------- + +// Mesa 5: Parameter change +static void gld_buffer_size_DX7( +// GLcontext *ctx, + GLframebuffer *fb, + GLuint *width, + GLuint *height) +{ +// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + + *width = fb->Width; // gldCtx->dwWidth; + *height = fb->Height; // gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +static void gld_Finish_DX7( + GLcontext *ctx) +{ +} + +//--------------------------------------------------------------------------- + +static void gld_Flush_DX7( + GLcontext *ctx) +{ + GLD_context *gld = GLD_GET_CONTEXT(ctx); + + // TODO: Detect apps that glFlush() then SwapBuffers() ? + + if (gld->EmulateSingle) { + // Emulating a single-buffered context. + // [Direct3D doesn't allow rendering to front buffer] + dglSwapBuffers(gld->hDC); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_STENCIL( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Two-sided stencil. New for Mesa 5 + const GLuint uiFace = 0UL; + + struct gl_stencil_attrib *pStencil = &ctx->Stencil; + + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE)); + if (pStencil->Enabled) { + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace]))); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILREF, pStencil->Ref[uiFace])); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILMASK, pStencil->ValueMask[uiFace])); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILWRITEMASK, pStencil->WriteMask[uiFace])); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace]))); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace]))); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace]))); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_COLOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DBLEND src; + D3DBLEND dest; + + // Alpha func + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc))); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, (DWORD)ctx->Color.AlphaRef)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, ctx->Color.AlphaEnabled)); + + // Blend func + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHABLENDENABLE, ctx->Color.BlendEnabled)); + src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE); + dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SRCBLEND, src)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_DESTBLEND, dest)); + +/* + // Color mask - unsupported by DX7 + if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED; + if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN; + if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE; + if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA; + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_COLORWRITEENABLE, dwFlags)); +*/ +} + +//--------------------------------------------------------------------------- + +void gld_NEW_DEPTH( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func))); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_POLYGON( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DFILLMODE d3dFillMode = D3DFILL_SOLID; + D3DCULL d3dCullMode = D3DCULL_NONE; + int iOffset = 0; + + // Fillmode + switch (ctx->Polygon.FrontMode) { + case GL_POINT: + d3dFillMode = D3DFILL_POINT; + break; + case GL_LINE: + d3dFillMode = D3DFILL_WIREFRAME; + break; + case GL_FILL: + d3dFillMode = D3DFILL_SOLID; + break; + } + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FILLMODE, d3dFillMode)); + + if (ctx->Polygon.CullFlag) { + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CW; + else + d3dCullMode = D3DCULL_CCW; + break; + case GL_FRONT: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CCW; + else + d3dCullMode = D3DCULL_CW; + break; + case GL_FRONT_AND_BACK: + d3dCullMode = D3DCULL_NONE; + break; + default: + break; + } + } else { + d3dCullMode = D3DCULL_NONE; + } +// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, d3dCullMode)); + + // Polygon offset + // ZBIAS ranges from 0 to 16 and can only move towards the viewer + // Mesa5: ctx->Polygon._OffsetAny removed + if (ctx->Polygon.OffsetFill) { + iOffset = (int)ctx->Polygon.OffsetUnits; + if (iOffset < 0) + iOffset = -iOffset; + else + iOffset = 0; // D3D can't push away + } + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZBIAS, iOffset)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_FOG( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DCOLOR d3dFogColour; + D3DFOGMODE d3dFogMode = D3DFOG_LINEAR; + + // TODO: Fog is calculated seperately in the Mesa pipeline + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, FALSE)); + return; + + // Fog enable + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, ctx->Fog.Enabled)); + if (!ctx->Fog.Enabled) { + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE)); + return; // If disabled, don't bother setting any fog state + } + + // Fog colour + d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0], + ctx->Fog.Color[1], + ctx->Fog.Color[2], + ctx->Fog.Color[3]); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGCOLOR, d3dFogColour)); + + // Fog density + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density)))); + + // Fog start + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGSTART, *((DWORD*) (&ctx->Fog.Start)))); + + // Fog end + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGEND, *((DWORD*) (&ctx->Fog.End)))); + + // Fog mode + switch (ctx->Fog.Mode) { + case GL_LINEAR: + d3dFogMode = D3DFOG_LINEAR; + break; + case GL_EXP: + d3dFogMode = D3DFOG_EXP; + break; + case GL_EXP2: + d3dFogMode = D3DFOG_EXP2; + break; + } + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, d3dFogMode)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_LIGHT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + DWORD dwSpecularEnable; + + // Shademode + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); + + // Separate specular colour + if (ctx->Light.Enabled) + dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE; + else + dwSpecularEnable = FALSE; + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SPECULARENABLE, dwSpecularEnable)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_MODELVIEW( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ModelView.m; + // Mesa5: Model-view is now a stack + GLfloat *pM = ctx->ModelviewMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10]; + m._34 = pM[11]; + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14]; + m._44 = pM[15]; +/* m[0][0] = pM[0]; + m[0][1] = pM[1]; + m[0][2] = pM[2]; + m[0][3] = pM[3]; + m[1][0] = pM[4]; + m[1][1] = pM[5]; + m[1][2] = pM[6]; + m[1][3] = pM[7]; + m[2][0] = pM[8]; + m[2][1] = pM[9]; + m[2][2] = pM[10]; + m[2][3] = pM[11]; + m[3][0] = pM[12]; + m[3][1] = pM[13]; + m[3][2] = pM[14]; + m[3][3] = pM[15];*/ + + gld->matModelView = m; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_PROJECTION( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ProjectionMatrix.m; + // Mesa 5: Now a stack + GLfloat *pM = ctx->ProjectionMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10] / _fPersp_33; // / 1.6f; + m._34 = pM[11]; + + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14] / 2.0f; + m._44 = pM[15]; + + gld->matProjection = m; +} + +//--------------------------------------------------------------------------- +/* +void gldFrustumHook_DX7( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Frustum(left, right, bottom, top, nearval, farval); + + _fPersp_33 = farval / (nearval - farval); + +// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval); +} + +//--------------------------------------------------------------------------- + +void gldOrthoHook_DX7( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Ortho(left, right, bottom, top, nearval, farval); + + _fPersp_33 = 1.6f; + +// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval); +} +*/ +//--------------------------------------------------------------------------- + +void gld_NEW_VIEWPORT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DVIEWPORT7 d3dvp; +// GLint x, y; +// GLsizei w, h; + + // Set depth range + _GLD_DX7_DEV(GetViewport(gld->pDev, &d3dvp)); + // D3D can't do Quake1/Quake2 z-trick + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.dvMinZ = ctx->Viewport.Near; + d3dvp.dvMaxZ = ctx->Viewport.Far; + } else { + d3dvp.dvMinZ = ctx->Viewport.Far; + d3dvp.dvMaxZ = ctx->Viewport.Near; + } +/* x = ctx->Viewport.X; + y = ctx->Viewport.Y; + w = ctx->Viewport.Width; + h = ctx->Viewport.Height; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h;*/ + _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp)); + +// gld->fFlipWindowY = (float)gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +__inline BOOL _gldAnyEvalEnabled( + GLcontext *ctx) +{ + struct gl_eval_attrib *eval = &ctx->Eval; + + if ((eval->AutoNormal) || + (eval->Map1Color4) || + (eval->Map1Index) || + (eval->Map1Normal) || + (eval->Map1TextureCoord1) || + (eval->Map1TextureCoord2) || + (eval->Map1TextureCoord3) || + (eval->Map1TextureCoord4) || + (eval->Map1Vertex3) || + (eval->Map1Vertex4) || + (eval->Map2Color4) || + (eval->Map2Index) || + (eval->Map2Normal) || + (eval->Map2TextureCoord1) || + (eval->Map2TextureCoord2) || + (eval->Map2TextureCoord3) || + (eval->Map2TextureCoord4) || + (eval->Map2Vertex3) || + (eval->Map2Vertex4) + ) + return TRUE; + + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL _gldChooseInternalPipeline( + GLcontext *ctx, + GLD_driver_dx7 *gld) +{ +// return TRUE; // DEBUGGING: ALWAYS USE MESA +// return FALSE; // DEBUGGING: ALWAYS USE D3D + + if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE)) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; // Force Mesa TnL + } + + if ((ctx->Light.Enabled) || + (1) || + (ctx->Texture._TexGenEnabled) || + (ctx->Texture._TexMatEnabled) || +// (ctx->Transform._AnyClip) || + (ctx->Scissor.Enabled) || + _gldAnyEvalEnabled(ctx) // Put this last so we can early-out + ) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; + } + + gld->PipelineUsage.qwD3DFVF.QuadPart++; + return FALSE; + +/* // Force Mesa pipeline? + if (glb.dwTnL == GLDS_TNL_MESA) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Test for functionality not exposed in the D3D pathways + if ((ctx->Texture._GenFlags)) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Now decide if vertex shader can be used. + // If two sided lighting is enabled then we must either + // use Mesa TnL or the vertex shader + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) { + // Use Vertex Shader + gld->PipelineUsage.dwD3D2SVS.QuadPart++; + return GLD_PIPELINE_D3D_VS_TWOSIDE; + } else { + // Use Mesa TnL + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + } + + // Must be D3D fixed-function pipeline + gld->PipelineUsage.dwD3DFVF.QuadPart++; + return GLD_PIPELINE_D3D_FVF; +*/ +} + +//--------------------------------------------------------------------------- + +void gld_update_state_DX7( + GLcontext *ctx, + GLuint new_state) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLD_pb_dx7 *gldPB; + + if (!gld || !gld->pDev) + return; + + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + + // SetupIndex will be used in the pipelines for choosing setup function + if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) || + (ctx->Fog.Enabled)) + { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT_EXTRAS; + else + gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS; + } else { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture + else + gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture + } + + gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld); + if (gld->bUseMesaTnL) { + gldPB = &gld->PB2d; + // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING +// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, TRUE)); + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, FALSE)); +// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF)); + } else { + gldPB = &gld->PB3d; + _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE)); +// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) { +// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware)); +// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); +// } else { + // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING +// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL)); +// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF)); +// } + } + +#define _GLD_TEST_STATE(a) \ + if (new_state & (a)) { \ + gld##a(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_TEST_STATE_DX7(a) \ + if (new_state & (a)) { \ + gld##a##_DX7(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_IGNORE_STATE(a) new_state &= ~(a); + +// if (!gld->bUseMesaTnL) { + // Not required if Mesa is doing the TnL. + // Problem: If gld->bUseMesaTnL is TRUE when these are signaled, + // then we'll miss updating the D3D TnL pipeline. + // Therefore, don't test for gld->bUseMesaTnL + _GLD_TEST_STATE(_NEW_MODELVIEW); + _GLD_TEST_STATE(_NEW_PROJECTION); +// } + + _GLD_TEST_STATE_DX7(_NEW_TEXTURE); // extern, so guard with _DX7 + _GLD_TEST_STATE(_NEW_COLOR); + _GLD_TEST_STATE(_NEW_DEPTH); + _GLD_TEST_STATE(_NEW_POLYGON); + _GLD_TEST_STATE(_NEW_STENCIL); + _GLD_TEST_STATE(_NEW_FOG); + _GLD_TEST_STATE(_NEW_LIGHT); + _GLD_TEST_STATE(_NEW_VIEWPORT); + + _GLD_IGNORE_STATE(_NEW_TRANSFORM); + + +// Stubs for future use. +/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_STATE(_NEW_ACCUM); + _GLD_TEST_STATE(_NEW_EVAL); + _GLD_TEST_STATE(_NEW_HINT); + _GLD_TEST_STATE(_NEW_LINE); + _GLD_TEST_STATE(_NEW_PIXEL); + _GLD_TEST_STATE(_NEW_POINT); + _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_STATE(_NEW_SCISSOR); + _GLD_TEST_STATE(_NEW_PACKUNPACK); + _GLD_TEST_STATE(_NEW_ARRAY); + _GLD_TEST_STATE(_NEW_RENDERMODE); + _GLD_TEST_STATE(_NEW_BUFFERS); + _GLD_TEST_STATE(_NEW_MULTISAMPLE); +*/ + +// For debugging. +#if 0 +#define _GLD_TEST_UNHANDLED_STATE(a) \ + if (new_state & (a)) { \ + gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \ + } + _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); + _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); + _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); + _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL); + _GLD_TEST_UNHANDLED_STATE(_NEW_POINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR); + _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK); + _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY); + _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE); + _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS); + _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE); +#undef _GLD_UNHANDLED_STATE +#endif + +#undef _GLD_TEST_STATE +} + +//--------------------------------------------------------------------------- +// Viewport +//--------------------------------------------------------------------------- + +void gld_Viewport_DX7( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei w, + GLsizei h) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DVIEWPORT7 d3dvp; + + if (!gld || !gld->pDev) + return; + + // This is a hack. When the app is minimized, Mesa passes + // w=1 and h=1 for viewport dimensions. Without this test + // we get a GPF in gld_wgl_resize_buffers(). + if ((w==1) && (h==1)) + return; + + // Call ResizeBuffersMESA. This function will early-out + // if no resize is needed. + //ctx->Driver.ResizeBuffersMESA(ctx); + // Mesa 5: Changed parameters + ctx->Driver.ResizeBuffers(gldCtx->glBuffer); + +#if 0 + ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h); +#endif + + // ** D3D viewport must not be outside the render target surface ** + // Sanity check the GL viewport dimensions + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + + d3dvp.dwX = x; + d3dvp.dwY = gldCtx->dwHeight - (y + h); + d3dvp.dwWidth = w; + d3dvp.dwHeight = h; + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.dvMinZ = ctx->Viewport.Near; + d3dvp.dvMaxZ = ctx->Viewport.Far; + } else { + d3dvp.dvMinZ = ctx->Viewport.Far; + d3dvp.dvMaxZ = ctx->Viewport.Near; + } + + // TODO: DEBUGGING +// d3dvp.MinZ = 0.0f; +// d3dvp.MaxZ = 1.0f; + + _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp)); + +} + +//--------------------------------------------------------------------------- + +extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver); + +// Mesa 5: Parameter change +void gldResizeBuffers_DX7( +// GLcontext *ctx) + GLframebuffer *fb) +{ + GET_CURRENT_CONTEXT(ctx); + dglWglResizeBuffers(ctx, TRUE); +} + +//--------------------------------------------------------------------------- +#ifdef _DEBUG +// This is only for debugging. +// To use, plug into ctx->Driver.Enable pointer below. +void gld_Enable( + GLcontext *ctx, + GLenum e, + GLboolean b) +{ + char buf[1024]; + sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE"); + ddlogMessage(DDLOG_SYSTEM, buf); +} +#endif +//--------------------------------------------------------------------------- +// Driver pointer setup +//--------------------------------------------------------------------------- + +extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum); + +void gldSetupDriverPointers_DX7( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + + // Mandatory functions + ctx->Driver.GetString = _gldGetStringGeneric; + ctx->Driver.UpdateState = gld_update_state_DX7; + ctx->Driver.Clear = gld_Clear_DX7; + ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX7; + ctx->Driver.GetBufferSize = gld_buffer_size_DX7; + ctx->Driver.Finish = gld_Finish_DX7; + ctx->Driver.Flush = gld_Flush_DX7; + ctx->Driver.Error = gld_Error_DX7; + + // Hardware accumulation buffer + ctx->Driver.Accum = NULL; // TODO: gld_Accum; + + // Bitmap functions + ctx->Driver.CopyPixels = gld_CopyPixels_DX7; + ctx->Driver.DrawPixels = gld_DrawPixels_DX7; + ctx->Driver.ReadPixels = gld_ReadPixels_DX7; + ctx->Driver.Bitmap = gld_Bitmap_DX7; + + // Buffer resize + ctx->Driver.ResizeBuffers = gldResizeBuffers_DX7; + + // Texture image functions + ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX7; + ctx->Driver.TexImage1D = gld_TexImage1D_DX7; + ctx->Driver.TexImage2D = gld_TexImage2D_DX7; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX7; + ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX7; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + + ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX7; //NULL; + ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX7; //NULL; + ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX7; //NULL; + ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX7; //NULL; + ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX7; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + // Texture object functions + ctx->Driver.BindTexture = NULL; + ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!; + ctx->Driver.DeleteTexture = gld_DeleteTexture_DX7; + ctx->Driver.PrioritizeTexture = NULL; + + // Imaging functionality + ctx->Driver.CopyColorTable = NULL; + ctx->Driver.CopyColorSubTable = NULL; + ctx->Driver.CopyConvolutionFilter1D = NULL; + ctx->Driver.CopyConvolutionFilter2D = NULL; + + // State changing functions + ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc; + ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc; + ctx->Driver.ClearColor = NULL; //gld_ClearColor; + ctx->Driver.ClearDepth = NULL; //gld_ClearDepth; + ctx->Driver.ClearStencil = NULL; //gld_ClearStencil; + ctx->Driver.ColorMask = NULL; //gld_ColorMask; + ctx->Driver.CullFace = NULL; //gld_CullFace; + ctx->Driver.ClipPlane = NULL; //gld_ClipPlane; + ctx->Driver.FrontFace = NULL; //gld_FrontFace; + ctx->Driver.DepthFunc = NULL; //gld_DepthFunc; + ctx->Driver.DepthMask = NULL; //gld_DepthMask; + ctx->Driver.DepthRange = NULL; + ctx->Driver.Enable = NULL; //gld_Enable; + ctx->Driver.Fogfv = NULL; //gld_Fogfv; + ctx->Driver.Hint = NULL; //gld_Hint; + ctx->Driver.Lightfv = NULL; //gld_Lightfv; + ctx->Driver.LightModelfv = NULL; //gld_LightModelfv; + ctx->Driver.LineStipple = NULL; //gld_LineStipple; + ctx->Driver.LineWidth = NULL; //gld_LineWidth; + ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode; + ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv; + ctx->Driver.PointSize = NULL; //gld_PointSize; + ctx->Driver.PolygonMode = NULL; //gld_PolygonMode; + ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset; + ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple; + ctx->Driver.RenderMode = NULL; //gld_RenderMode; + ctx->Driver.Scissor = NULL; //gld_Scissor; + ctx->Driver.ShadeModel = NULL; //gld_ShadeModel; + ctx->Driver.StencilFunc = NULL; //gld_StencilFunc; + ctx->Driver.StencilMask = NULL; //gld_StencilMask; + ctx->Driver.StencilOp = NULL; //gld_StencilOp; + ctx->Driver.TexGen = NULL; //gld_TexGen; + ctx->Driver.TexEnv = NULL; + ctx->Driver.TexParameter = NULL; + ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix; + ctx->Driver.Viewport = gld_Viewport_DX7; + + _swsetup_Wakeup(ctx); + + tnl->Driver.RunPipeline = _tnl_run_pipeline; + tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX7; + tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; + tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; + + // Hook into glFrustum() and glOrtho() +// ctx->Exec->Frustum = gldFrustumHook_DX7; +// ctx->Exec->Ortho = gldOrthoHook_DX7; + +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h new file mode 100644 index 00000000000..b5a491e41b1 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h @@ -0,0 +1,292 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 7.0a header file +* +****************************************************************************/ + +#ifndef _GLD_DX7_H +#define _GLD_DX7_H + +//--------------------------------------------------------------------------- +// Windows includes +//--------------------------------------------------------------------------- + +#define DIRECTDRAW_VERSION 0x0700 +#define DIRECT3D_VERSION 0x0700 +#include <d3d.h> +#include <d3dx.h> + +// Typedef for obtaining function from d3d7.dll +//typedef IDirect3D7* (WINAPI *FNDIRECT3DCREATE7) (UINT); + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +#ifdef _DEBUG +// Debug build tests the return value of D3D calls +#define _GLD_TEST_HRESULT(h) \ +{ \ + HRESULT _hr = (h); \ + if (FAILED(_hr)) { \ + gldLogError(GLDLOG_ERROR, #h, _hr); \ + } \ +} +#define _GLD_DX7(func) _GLD_TEST_HRESULT(IDirect3D7_##func##) +#define _GLD_DX7_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice7_##func##) +#define _GLD_DX7_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer7_##func##) +#define _GLD_DX7_TEX(func) _GLD_TEST_HRESULT(IDirectDrawSurface7_##func##) +#else +#define _GLD_DX7(func) IDirect3D7_##func +#define _GLD_DX7_DEV(func) IDirect3DDevice7_##func +#define _GLD_DX7_VB(func) IDirect3DVertexBuffer7_##func +#define _GLD_DX7_TEX(func) IDirectDrawSurface7_##func +#endif + +#define SAFE_RELEASE(p) \ +{ \ + if (p) { \ + (p)->lpVtbl->Release(p); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_VB7(p) \ +{ \ + if (p) { \ + IDirect3DVertexBuffer7_Release((p)); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_SURFACE7(p) \ +{ \ + if (p) { \ + IDirectDrawSurface7_Release((p)); \ + (p) = NULL; \ + } \ +} + +// Emulate some DX8 defines +#define D3DCOLOR_ARGB(a,r,g,b) ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) +#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b) +#define D3DCOLOR_COLORVALUE(r,g,b,a) D3DCOLOR_RGBA((DWORD)((r)*255.f),(DWORD)((g)*255.f),(DWORD)((b)*255.f),(DWORD)((a)*255.f)) + + +// Setup index. +enum { + GLD_SI_FLAT = 0, + GLD_SI_SMOOTH = 1, + GLD_SI_FLAT_EXTRAS = 2, + GLD_SI_SMOOTH_EXTRAS = 3, +}; + +//--------------------------------------------------------------------------- +// Vertex definitions for Fixed-Function pipeline +//--------------------------------------------------------------------------- + +// +// NOTE: If the number of texture units is altered then most of +// the texture code will need to be revised. +// + +#define GLD_MAX_TEXTURE_UNITS_DX7 2 + +// +// 2D vertex transformed by Mesa +// +#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \ + D3DFVF_DIFFUSE | \ + D3DFVF_SPECULAR | \ + D3DFVF_TEX2) +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT sz; // Screen Z (depth) + FLOAT rhw; // Reciprocal homogenous W + DWORD diffuse; // Diffuse colour + DWORD specular; // For separate-specular support + FLOAT t0_u, t0_v; // 1st set of texture coords + FLOAT t1_u, t1_v; // 2nd set of texture coords +} GLD_2D_VERTEX; + + +// +// 3D vertex transformed by Direct3D +// +#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \ + D3DFVF_DIFFUSE | \ + D3DFVF_TEX2) + +typedef struct { + D3DXVECTOR3 Position; // XYZ Vector in object space + D3DCOLOR Diffuse; // Diffuse colour + D3DXVECTOR2 TexUnit0; // Texture unit 0 + D3DXVECTOR2 TexUnit1; // Texture unit 1 +} GLD_3D_VERTEX; + +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- + +// This keeps a count of how many times we choose each individual internal +// pathway. Useful for seeing if a certain pathway was ever used by an app, and +// how much each pathway is biased. +// Zero the members at context creation and dump stats at context deletion. +typedef struct { + // Note: DWORD is probably too small + ULARGE_INTEGER qwMesa; // Mesa TnL pipeline + ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline +} GLD_pipeline_usage; + +// GLDirect Primitive Buffer (points, lines, triangles and quads) +typedef struct { + // Data for IDirect3D7::CreateVertexBuffer() + DWORD dwStride; // Stride of vertex + DWORD dwCreateFlags; // Create flags + DWORD dwFVF; // Direct3D Flexible Vertex Format + + IDirect3DVertexBuffer7 *pVB; // Holds points, lines, tris and quads. + + // Point list is assumed to be at start of buffer + DWORD iFirstLine; // Index of start of line list + DWORD iFirstTriangle; // Index of start of triangle list + + BYTE *pPoints; // Pointer to next free point + BYTE *pLines; // Pointer to next free line + BYTE *pTriangles; // Pointer to next free triangle + + DWORD nPoints; // Number of points ready to render + DWORD nLines; // Number of lines ready to render + DWORD nTriangles; // Number of triangles ready to render +} GLD_pb_dx7; + +// GLDirect DX7 driver data +typedef struct { + // GLDirect vars + BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered) + BOOL bDepthStencil; // Depth buffer needed (stencil optional) + D3DX_SURFACEFORMAT RenderFormat; // Format of back/front buffer + D3DX_SURFACEFORMAT DepthFormat; // Format of depth/stencil + + // Direct3D vars + DDCAPS ddCaps; + D3DDEVICEDESC7 d3dCaps; + BOOL bHasHWTnL; // Device has Hardware Transform/Light? + ID3DXContext *pD3DXContext; // Base D3DX context + IDirectDraw7 *pDD; // DirectDraw7 interface + IDirect3D7 *pD3D; // Base Direct3D7 interface + IDirect3DDevice7 *pDev; // Direct3D7 Device interface + GLD_pb_dx7 PB2d; // Vertices transformed by Mesa + GLD_pb_dx7 PB3d; // Vertices transformed by Direct3D + D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type + D3DMATRIX matProjection; // Projection matrix for D3D TnL + D3DMATRIX matModelView; // Model/View matrix for D3D TnL + int iSetupFunc; // Which setup functions to use + BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL + + GLD_pipeline_usage PipelineUsage; +} GLD_driver_dx7; + +#define GLD_GET_DX7_DRIVER(c) (GLD_driver_dx7*)(c)->glPriv + +//--------------------------------------------------------------------------- +// Function prototypes +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX7(LPCSTR a); +void gldEnableExtensions_DX7(GLcontext *ctx); +void gldInstallPipeline_DX7(GLcontext *ctx); +void gldSetupDriverPointers_DX7(GLcontext *ctx); +void gldResizeBuffers_DX7(GLframebuffer *fb); + + +// Texture functions + +void gldCopyTexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void gldCopyTexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void gldCopyTexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ); +void gldCopyTexSubImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); +void gldCopyTexSubImage3D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + +void gld_NEW_TEXTURE_DX7(GLcontext *ctx); +void gld_DrawPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels); +void gld_ReadPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest); +void gld_CopyPixels_DX7(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type); +void gld_Bitmap_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap); +const struct gl_texture_format* gld_ChooseTextureFormat_DX7(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType); +void gld_TexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage); +void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage); +void gld_DeleteTexture_DX7(GLcontext *ctx, struct gl_texture_object *tObj); +void gld_ResetLineStipple_DX7(GLcontext *ctx); + +// 2D primitive functions + +void gld_Points2D_DX7(GLcontext *ctx, GLuint first, GLuint last); + +void gld_Line2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1); + +void gld_Triangle2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); + +void gld_Quad2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// 3D primitive functions + +void gld_Points3D_DX7(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Line3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// Primitive functions for Two-sided-lighting Vertex Shader + +void gld_Points2DTwoside_DX7(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +#endif diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h new file mode 100644 index 00000000000..df6fceb43e6 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h @@ -0,0 +1,77 @@ +/*==========================================================================; + * + * + * File: dxerr8.h + * Content: DirectX Error Library Include File + * + ****************************************************************************/ + +#ifndef _GLD_DXERR7_H_ +#define _GLD_DXERR7_H_ + + +#include <d3d.h> + +// +// DXGetErrorString8 +// +// Desc: Converts an DirectX HRESULT to a string +// +// Args: HRESULT hr Can be any error code from +// DPLAY D3D8 D3DX8 DMUSIC DSOUND +// +// Return: Converted string +// +const char* __stdcall DXGetErrorString8A(HRESULT hr); +const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr); + +#ifdef UNICODE + #define DXGetErrorString8 DXGetErrorString8W +#else + #define DXGetErrorString8 DXGetErrorString8A +#endif + + +// +// DXTrace +// +// Desc: Outputs a formatted error message to the debug stream +// +// Args: CHAR* strFile The current file, typically passed in using the +// __FILE__ macro. +// DWORD dwLine The current line number, typically passed in using the +// __LINE__ macro. +// HRESULT hr An HRESULT that will be traced to the debug stream. +// CHAR* strMsg A string that will be traced to the debug stream (may be NULL) +// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info. +// +// Return: The hr that was passed in. +// +//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE ); +//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE ); +HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox); +HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox); + +#ifdef UNICODE + #define DXTrace DXTraceW +#else + #define DXTrace DXTraceA +#endif + + +// +// Helper macros +// +#if defined(DEBUG) | defined(_DEBUG) + #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE ) + #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE ) + #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE ) +#else + #define DXTRACE_MSG(str) (0L) + #define DXTRACE_ERR(str,hr) (hr) + #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr) +#endif + + +#endif + diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c new file mode 100644 index 00000000000..6be41a80dd3 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c @@ -0,0 +1,346 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GL extensions +* +****************************************************************************/ + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "../gld_settings.h" + +#include <windows.h> +#define GL_GLEXT_PROTOTYPES +#include <GL/gl.h> +#include <GL/glext.h> + +//#include "ddlog.h" +//#include "gld_dx8.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "dglcontext.h" +#include "extensions.h" + +// For some reason this is not defined in an above header... +extern void _mesa_enable_imaging_extensions(GLcontext *ctx); + +//--------------------------------------------------------------------------- +// Hack for the SGIS_multitexture extension that was removed from Mesa +// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel + + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // To enable, uncomment: + // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + +//--------------------------------------------------------------------------- + +enum { + /* Quake2 GL_SGIS_multitexture */ + GL_SELECTED_TEXTURE_SGIS = 0x835B, + GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C, + GL_MAX_TEXTURES_SGIS = 0x835D, + GL_TEXTURE0_SGIS = 0x835E, + GL_TEXTURE1_SGIS = 0x835F, + GL_TEXTURE2_SGIS = 0x8360, + GL_TEXTURE3_SGIS = 0x8361, + GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363, +}; + +//--------------------------------------------------------------------------- + +void APIENTRY gldSelectTextureSGIS( + GLenum target) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glActiveTextureARB(ARB_target); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fSGIS( + GLenum target, + GLfloat s, + GLfloat t) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fARB(ARB_target, s, t); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fvSGIS( + GLenum target, + const GLfloat *v) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fvARB(ARB_target, v); +} + +//--------------------------------------------------------------------------- +// Extensions +//--------------------------------------------------------------------------- + +typedef struct { + PROC proc; + char *name; +} GLD_extension; + +GLD_extension GLD_extList[] = { +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }, + { NULL, "\0" } +}; + +GLD_extension GLD_multitexList[] = { +/* + { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" }, + { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" }, + { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" }, + { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" }, + { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" }, + { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" }, + { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" }, + { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" }, + { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" }, + { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" }, + { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" }, + { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" }, + { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" }, + { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" }, + { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" }, + { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" }, + { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" }, + { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" }, + { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" }, + { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" }, + { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" }, + { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" }, + { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" }, + { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" }, + { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" }, + { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" }, + { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" }, + { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" }, + { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" }, + { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" }, + { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" }, + { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" }, +*/ + { (PROC)glActiveTextureARB, "glActiveTextureARB" }, + { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" }, + { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" }, + { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" }, + { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" }, + { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" }, + { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" }, + { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" }, + { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" }, + { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" }, + { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" }, + { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" }, + { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" }, + { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" }, + { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" }, + { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" }, + { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" }, + { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" }, + { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" }, + { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" }, + { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" }, + { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" }, + { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" }, + { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" }, + { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" }, + { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" }, + { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" }, + { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" }, + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" }, + { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" }, + { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" }, + { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" }, + { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" }, + { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" }, + + // Descent3 doesn't use correct string, hence this hack + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" }, + + // Quake2 SGIS multitexture + { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + + { NULL, "\0" } +}; + +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX( + LPCSTR a) +{ + int i; + PROC proc = NULL; + + for (i=0; GLD_extList[i].proc; i++) { + if (!strcmp(a, GLD_extList[i].name)) { + proc = GLD_extList[i].proc; + break; + } + } + + if (glb.bMultitexture) { + for (i=0; GLD_multitexList[i].proc; i++) { + if (!strcmp(a, GLD_multitexList[i].name)) { + proc = GLD_multitexList[i].proc; + break; + } + } + } + + gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed"); + + return proc; +} + +//--------------------------------------------------------------------------- + +void gldEnableExtensions_DX7( + GLcontext *ctx) +{ + GLuint i; + + // Mesa enables some extensions by default. + // This table decides which ones we want to switch off again. + + // NOTE: GL_EXT_compiled_vertex_array appears broken. + + const char *gld_disable_extensions[] = { +// "GL_ARB_transpose_matrix", +// "GL_EXT_compiled_vertex_array", +// "GL_EXT_polygon_offset", +// "GL_EXT_rescale_normal", + "GL_EXT_texture3D", +// "GL_NV_texgen_reflection", + "GL_EXT_abgr", + "GL_EXT_bgra", + NULL + }; + + const char *gld_multitex_extensions[] = { + "GL_ARB_multitexture", // Quake 3 + NULL + }; + + // Quake 2 engines + const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture"; + + const char *gld_enable_extensions[] = { + "GL_EXT_texture_env_add", // Quake 3 + "GL_ARB_texture_env_add", // Quake 3 + NULL + }; + + for (i=0; gld_disable_extensions[i]; i++) { + _mesa_disable_extension(ctx, gld_disable_extensions[i]); + } + + for (i=0; gld_enable_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_enable_extensions[i]); + } + + if (glb.bMultitexture) { + for (i=0; gld_multitex_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_multitex_extensions[i]); + } + + // GL_SGIS_multitexture + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // Fair bit slower on GeForce256, + // Much slower on 3dfx Voodoo5 5500. +// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + + } + + _mesa_enable_imaging_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + _mesa_enable_1_4_extensions(ctx); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c new file mode 100644 index 00000000000..9ccec69b98a --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c @@ -0,0 +1,77 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Mesa transformation pipeline with GLDirect fastpath +* +****************************************************************************/ + +//#include "../GLDirect.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +extern struct tnl_pipeline_stage _gld_d3d_render_stage; +extern struct tnl_pipeline_stage _gld_mesa_render_stage; + +static const struct tnl_pipeline_stage *gld_pipeline[] = { + &_gld_d3d_render_stage, // Direct3D TnL + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */ + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_point_attenuation_stage, + &_gld_mesa_render_stage, // Mesa TnL, D3D rendering + 0, +}; + +//--------------------------------------------------------------------------- + +void gldInstallPipeline_DX7( + GLcontext *ctx) +{ + // Remove any existing pipeline stages, + // then install GLDirect pipeline stages. + + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, gld_pipeline); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c new file mode 100644 index 00000000000..5da25003c08 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c @@ -0,0 +1,1448 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Primitive (points/lines/tris/quads) rendering +* +****************************************************************************/ + +//#include "../GLDirect.h" + +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "swrast/s_trispan.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +// Disable compiler complaints about unreferenced local variables +#pragma warning (disable:4101) + +//--------------------------------------------------------------------------- +// Helper defines for primitives +//--------------------------------------------------------------------------- + +//static const float ooZ = 1.0f / 65536.0f; // One over Z + +#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3])) +#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3])) +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +//--------------------------------------------------------------------------- +// 2D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_2D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_TRIANGLES \ + BOOL bFog = ctx->Fog.Enabled; \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour; \ + GLuint facing = 0; \ + struct vertex_buffer *VB; \ + GLchan (*vbcolor)[4]; \ + GLchan (*vbspec)[4] + +#define GLD_SETUP_GET_SWVERT(s) \ + swv = &ss->verts[##s] + +#define GLD_SETUP_2D_VERTEX \ + pV->x = swv->win[0]; \ + pV->y = GLD_FLIP_Y(swv->win[1]); \ + pV->rhw = swv->win[3] + +#define GLD_SETUP_SMOOTH_COLOUR \ + pV->diffuse = GLD_COLOUR + +#define GLD_SETUP_GET_FLAT_COLOUR \ + dwFlatColour = GLD_COLOUR +#define GLD_SETUP_GET_FLAT_FOG_COLOUR \ + dwFlatColour = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_USE_FLAT_COLOUR \ + pV->diffuse = dwFlatColour + +#define GLD_SETUP_GET_FLAT_SPECULAR \ + dwSpecularColour= GLD_SPECULAR + +#define GLD_SETUP_USE_FLAT_SPECULAR \ + pV->specular = dwSpecularColour + +#define GLD_SETUP_DEPTH \ + pV->sz = swv->win[2] / ctx->DepthMaxF +// pV->z = swv->win[2] * ooZ; + +#define GLD_SETUP_SPECULAR \ + pV->specular = GLD_SPECULAR + +#define GLD_SETUP_FOG \ + pV->diffuse = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_TEX0 \ + pV->t0_u = swv->texcoord[0][0]; \ + pV->t0_v = swv->texcoord[0][1] + +#define GLD_SETUP_TEX1 \ + pV->t1_u = swv->texcoord[1][0]; \ + pV->t1_v = swv->texcoord[1][1] + +#define GLD_SETUP_LIGHTING(v) \ + if (facing == 1) { \ + pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } else { \ + if (bFog) \ + GLD_SETUP_FOG; \ + else \ + GLD_SETUP_SMOOTH_COLOUR; \ + GLD_SETUP_SPECULAR; \ + } + +#define GLD_SETUP_GET_FLAT_LIGHTING(v) \ + if (facing == 1) { \ + dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } + +#define GLD_SETUP_TWOSIDED_LIGHTING \ + /* Two-sided lighting */ \ + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \ + SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \ + SWvertex *v[3]; \ + GLfloat ex,ey,fx,fy,cc; \ + /* Get vars for later */ \ + VB = &TNL_CONTEXT(ctx)->vb; \ + vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \ + if (VB->SecondaryColorPtr[1]) { \ + vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \ + } else { \ + vbspec = NULL; \ + } \ + v[0] = &verts[v0]; \ + v[1] = &verts[v1]; \ + v[2] = &verts[v2]; \ + ex = v[0]->win[0] - v[2]->win[0]; \ + ey = v[0]->win[1] - v[2]->win[1]; \ + fx = v[1]->win[0] - v[2]->win[0]; \ + fy = v[1]->win[1] - v[2]->win[1]; \ + cc = ex*fy - ey*fx; \ + facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \ + } + +//--------------------------------------------------------------------------- +// 3D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_3D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_TRIANGLES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VERTEX(v) \ + p4f = VB->ObjPtr->data; \ + pV->Position.x = p4f[##v][0]; \ + pV->Position.y = p4f[##v][1]; \ + pV->Position.z = p4f[##v][2]; + +#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + + +#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + +#define GLD_SETUP_USE_FLAT_COLOUR_3D \ + pV->Diffuse = dwColor; + +#define GLD_SETUP_TEX0_3D(v) \ + if (VB->TexCoordPtr[0]) { \ + tc = VB->TexCoordPtr[0]->data; \ + pV->TexUnit0.x = tc[##v][0]; \ + pV->TexUnit0.y = tc[##v][1]; \ + } + +#define GLD_SETUP_TEX1_3D(v) \ + if (VB->TexCoordPtr[1]) { \ + tc = VB->TexCoordPtr[1]->data; \ + pV->TexUnit1.x = tc[##v][0]; \ + pV->TexUnit1.y = tc[##v][1]; \ + } + +//--------------------------------------------------------------------------- +// Helper functions +//--------------------------------------------------------------------------- + +__inline DWORD _gldComputeFog( + GLcontext *ctx, + SWvertex *swv) +{ + // Full fog calculation. + // Based on Mesa code. + + GLchan rFog, gFog, bFog; + GLchan fR, fG, fB; + const GLfloat f = swv->fog; + const GLfloat g = 1.0 - f; + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + fR = f * swv->color[0] + g * rFog; + fG = f * swv->color[1] + g * gFog; + fB = f * swv->color[2] + g * bFog; + return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]); +} + +//--------------------------------------------------------------------------- + +void gld_ResetLineStipple_DX7( + GLcontext *ctx) +{ + // TODO: Fake stipple with a 32x32 texture. +} + +//--------------------------------------------------------------------------- +// 2D (post-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points2D_DX7( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_2D_VARS_POINTS; + + unsigned i; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + // Not supported by DX7 +// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); + GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } else { + GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, swv++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } + + gld->PB2d.pPoints = (BYTE*)pV; + gld->PB2d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_SPECULAR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++;; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatExtras_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v2); + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v2); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothExtras_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatExtras_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v3); + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v3); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothExtras_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v3); + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// 3D (pre-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points3D_DX7( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_3D_VARS_POINTS + + unsigned i; +// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + // Not supported by DX7 +// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); +// GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_3D_VERTEX(VB->Elts[i]) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } else { +// GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } +/* + for (i=first; i<last; i++, pV++) { + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } +*/ + gld->PB3d.pPoints = (BYTE*)pV; + gld->PB3d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- +// Line functions +//--------------------------------------------------------------------------- + +void gld_Line3DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_GET_FLAT_COLOUR_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line3DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- +// Triangle functions +//--------------------------------------------------------------------------- + +void gld_Triangle3DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + GLD_SETUP_GET_FLAT_COLOUR_3D(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle3DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- +// Quad functions +//--------------------------------------------------------------------------- + +void gld_Quad3DFlat_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_GET_FLAT_COLOUR_3D(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad3DSmooth_DX7( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_SMOOTH_COLOUR_3D(v3) + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// Vertex setup for two-sided-lighting vertex shader +//--------------------------------------------------------------------------- + +/* + +void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last) +{ + // NOTE: Two-sided lighting does not apply to Points +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +*/ diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c new file mode 100644 index 00000000000..bbe673516d6 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c @@ -0,0 +1,2196 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Texture / Bitmap functions +* +****************************************************************************/ + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +//#include <d3dx8tex.h> + +#include "texformat.h" +#include "colormac.h" +#include "texstore.h" +#include "image.h" +// #include "mem.h" + +//--------------------------------------------------------------------------- + +#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h)) + +D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface(IDirectDrawSurface7 *pSurface); + +//--------------------------------------------------------------------------- +// 1D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + (i) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (i) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (i)) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (i)) + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 2D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + ((t)->Width * (j) + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 3D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// Direct3D texture formats that have no Mesa equivalent +//--------------------------------------------------------------------------- + +const struct gl_texture_format _gld_texformat_X8R8G8B8 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_argb8888, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */ + gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */ + gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X1R5G5B5 = { + MESA_FORMAT_ARGB1555, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb1555, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */ + gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */ + gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X4R4G4B4 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb4444, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */ + gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */ + gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */ +}; + +//--------------------------------------------------------------------------- +// Texture unit constants +//--------------------------------------------------------------------------- + +// List of possible combinations of texture environments. +// Example: GLD_TEXENV_MODULATE_RGBA means +// GL_MODULATE, GL_RGBA base internal format. +#define GLD_TEXENV_DECAL_RGB 0 +#define GLD_TEXENV_DECAL_RGBA 1 +#define GLD_TEXENV_DECAL_ALPHA 2 +#define GLD_TEXENV_REPLACE_RGB 3 +#define GLD_TEXENV_REPLACE_RGBA 4 +#define GLD_TEXENV_REPLACE_ALPHA 5 +#define GLD_TEXENV_MODULATE_RGB 6 +#define GLD_TEXENV_MODULATE_RGBA 7 +#define GLD_TEXENV_MODULATE_ALPHA 8 +#define GLD_TEXENV_BLEND_RGB 9 +#define GLD_TEXENV_BLEND_RGBA 10 +#define GLD_TEXENV_BLEND_ALPHA 11 +#define GLD_TEXENV_ADD_RGB 12 +#define GLD_TEXENV_ADD_RGBA 13 +#define GLD_TEXENV_ADD_ALPHA 14 + +// Per-stage (i.e. per-unit) texture environment +typedef struct { + DWORD ColorArg1; // Colour argument 1 + D3DTEXTUREOP ColorOp; // Colour operation + DWORD ColorArg2; // Colour argument 2 + DWORD AlphaArg1; // Alpha argument 1 + D3DTEXTUREOP AlphaOp; // Alpha operation + DWORD AlphaArg2; // Alpha argument 2 +} GLD_texenv; + +// TODO: Do we really need to set ARG1 and ARG2 every time? +// They seem to always be TEXTURE and CURRENT respectively. + +// C = Colour out +// A = Alpha out +// Ct = Colour from Texture +// Cf = Colour from fragment (diffuse) +// At = Alpha from Texture +// Af = Alpha from fragment (diffuse) +// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND) +const GLD_texenv gldTexEnv[] = { + // DECAL_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af + {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_ALPHA: <undefined> use DECAL_RGB + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + + // REPLACE_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // REPLACE_RGBA: C=Ct, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + // REPLACE_ALPHA: C=Cf, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + + // MODULATE_RGB: C=CfCt, A=Af + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // MODULATE_RGBA: C=CfCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // MODULATE_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // + // DX7 Does not support D3DTOP_LERP + // Emulate(?) via D3DTOP_ADDSMOOTH + // +#if 0 + // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +#else + // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af + {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +#endif + // BLEND_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // ADD_RGB: C=Cf+Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // ADD_RGBA: C=Cf+Ct, A=AfAt + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // ADD_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +}; + +//--------------------------------------------------------------------------- + +D3DTEXTUREADDRESS _gldConvertWrap( + GLenum wrap) +{ +// ASSERT(wrap==GL_CLAMP || wrap==GL_REPEAT); + return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP; +} + +//--------------------------------------------------------------------------- + +D3DTEXTUREMAGFILTER _gldConvertMagFilter( + GLenum magfilter) +{ + ASSERT(magfilter==GL_LINEAR || magfilter==GL_NEAREST); + return (magfilter == GL_LINEAR) ? D3DTFG_LINEAR : D3DTFG_POINT; +} + +//--------------------------------------------------------------------------- + +void _gldConvertMinFilter( + GLenum minfilter, + D3DTEXTUREMINFILTER *min_filter, + D3DTEXTUREMIPFILTER *mip_filter) +{ + switch (minfilter) { + case GL_NEAREST: + *min_filter = D3DTFN_POINT; + *mip_filter = D3DTFP_NONE; + break; + case GL_LINEAR: + *min_filter = D3DTFN_LINEAR; + *mip_filter = D3DTFP_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *min_filter = D3DTFN_POINT; + *mip_filter = D3DTFP_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *min_filter = D3DTFN_LINEAR; + *mip_filter = D3DTFP_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *min_filter = D3DTFN_POINT; + *mip_filter = D3DTFP_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *min_filter = D3DTFN_LINEAR; + *mip_filter = D3DTFP_LINEAR; + break; + default: + ASSERT(0); + } +} + +//--------------------------------------------------------------------------- + +D3DX_SURFACEFORMAT _gldGLFormatToD3DFormat( + GLenum internalFormat) +{ + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures + return D3DX_SF_L8; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return D3DX_SF_L8; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return D3DX_SF_A8; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return D3DX_SF_X8R8G8B8; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return D3DX_SF_A8L8; + case GL_R3_G3_B2: + // TODO: Mesa does not support RGB332 internally + return D3DX_SF_X4R4G4B4; //D3DFMT_R3G3B2; + case GL_RGB4: + return D3DX_SF_X4R4G4B4; + case GL_RGB5: + return D3DX_SF_R5G5B5; + case 3: + case GL_RGB: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return D3DX_SF_R8G8B8; + case GL_RGBA4: + return D3DX_SF_A4R4G4B4; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return D3DX_SF_A8R8G8B8; + case GL_RGB5_A1: + return D3DX_SF_A1R5G5B5; + } + + ASSERT(0); + + // Return an acceptable default + return D3DX_SF_A8R8G8B8; +} + +//--------------------------------------------------------------------------- + +GLenum _gldDecodeBaseFormat( + IDirectDrawSurface7 *pTex) +{ + // Examine Direct3D texture and return base OpenGL internal texture format + // NOTE: We can't use any base format info from Mesa because D3D might have + // used a different texture format when we used D3DXCreateTexture(). + + // Base internal format is one of (Red Book p355): + // GL_ALPHA, + // GL_LUMINANCE, + // GL_LUMINANCE_ALPHA, + // GL_INTENSITY, + // GL_RGB, + // GL_RGBA + + // NOTE: INTENSITY not used (not supported by Direct3D) + // LUMINANCE has same texture functions as RGB + // LUMINANCE_ALPHA has same texture functions as RGBA + + // TODO: cache format instead of using GetLevelDesc() +// D3DSURFACE_DESC desc; +// _GLD_DX7_TEX(GetLevelDesc(pTex, 0, &desc)); + + D3DX_SURFACEFORMAT sf; + + sf = _gldD3DXFormatFromSurface(pTex); + + switch (sf) { + case D3DX_SF_R8G8B8: + case D3DX_SF_X8R8G8B8: + case D3DX_SF_R5G6B5: + case D3DX_SF_R5G5B5: + case D3DX_SF_R3G3B2: + case D3DX_SF_X4R4G4B4: + case D3DX_SF_PALETTE8: + case D3DX_SF_L8: + return GL_RGB; + case D3DX_SF_A8R8G8B8: + case D3DX_SF_A1R5G5B5: + case D3DX_SF_A4R4G4B4: +// case D3DX_SF_A8R3G3B2: // Unsupported by DX7 +// case D3DX_SF_A8P8: // Unsupported by DX7 + case D3DX_SF_A8L8: +// case D3DX_SF_A4L4: // Unsupported by DX7 + return GL_RGBA; + case D3DX_SF_A8: + return GL_ALPHA; + // Compressed texture formats. Need to check these... + case D3DX_SF_DXT1: + return GL_RGBA; +// case D3DX_SF_DXT2: // Unsupported by DX7 + return GL_RGB; + case D3DX_SF_DXT3: + return GL_RGBA; +// case D3DX_SF_DXT4: // Unsupported by DX7 + return GL_RGB; + case D3DX_SF_DXT5: + return GL_RGBA; + } + + // Fell through. Return arbitary default. + ASSERT(0); // BANG! + return GL_RGBA; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* _gldMesaFormatForD3DFormat( + D3DX_SURFACEFORMAT d3dfmt) +{ + switch (d3dfmt) { + case D3DX_SF_A8R8G8B8: + return &_mesa_texformat_argb8888; + case D3DX_SF_R8G8B8: + return &_mesa_texformat_rgb888; + case D3DX_SF_R5G6B5: + return &_mesa_texformat_rgb565; + case D3DX_SF_A4R4G4B4: + return &_mesa_texformat_argb4444; + case D3DX_SF_A1R5G5B5: + return &_mesa_texformat_argb1555; + case D3DX_SF_A8L8: + return &_mesa_texformat_al88; + case D3DX_SF_R3G3B2: + return &_mesa_texformat_rgb332; + case D3DX_SF_A8: + return &_mesa_texformat_a8; + case D3DX_SF_L8: + return &_mesa_texformat_l8; + case D3DX_SF_X8R8G8B8: + return &_gld_texformat_X8R8G8B8; + case D3DX_SF_R5G5B5: + return &_gld_texformat_X1R5G5B5; + case D3DX_SF_X4R4G4B4: + return &_gld_texformat_X4R4G4B4; + } + + // If we reach here then we've made an error somewhere else + // by allowing a format that is not supported. + ASSERT(0); + + return NULL; // Shut up compiler warning +} + +//--------------------------------------------------------------------------- + +D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface( + IDirectDrawSurface7 *pSurface) +{ + DDPIXELFORMAT ddpf; + + ddpf.dwSize = sizeof(ddpf); + + // Obtain pixel format of surface + _GLD_DX7_TEX(GetPixelFormat(pSurface, &ddpf)); + // Decode to D3DX surface format + return D3DXMakeSurfaceFormat(&ddpf); +} + +//--------------------------------------------------------------------------- + +void _gldClearSurface( + IDirectDrawSurface *pSurface, + D3DCOLOR dwColour) +{ + DDBLTFX bltFX; // Used for colour fill + + // Initialise struct + bltFX.dwSize = sizeof(bltFX); + // Set clear colour + bltFX.dwFillColor = dwColour; + // Clear surface. HW accelerated if available. + IDirectDrawSurface7_Blt(pSurface, NULL, NULL, NULL, DDBLT_COLORFILL, &bltFX); +} + +//--------------------------------------------------------------------------- +// Copy* functions +//--------------------------------------------------------------------------- + +void gldCopyTexImage1D_DX7( + GLcontext *ctx, + GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexImage2D_DX7( + GLcontext *ctx, + GLenum target, + GLint level, + GLenum internalFormat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage1D_DX7( + GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage2D_DX7( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage3D_DX7( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height ) +{ + // TODO ? +} + +//--------------------------------------------------------------------------- +// Bitmap/Pixel functions +//--------------------------------------------------------------------------- + +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1) + +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT z; // depth value + FLOAT rhw; // reciprocal homogenous W (always 1.0f) + FLOAT tu, tv; // texture coords +} _GLD_IMAGE_VERTEX; + +//--------------------------------------------------------------------------- + +HRESULT _gldDrawPixels( + GLcontext *ctx, + BOOL bChromakey, // Alpha test for glBitmap() images + GLint x, // GL x position + GLint y, // GL y position (needs flipping) + GLsizei width, // Width of input image + GLsizei height, // Height of input image + IDirectDrawSurface7 *pImage) +{ + // + // Draw input image as texture implementing PixelZoom and clipping. + // Any fragment operations currently enabled will be used. + // + + // NOTE: This DX7 version does not create a new texture in which + // to copy the input image, as the image is already a texture. + + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + DDSURFACEDESC2 ddsd; + _GLD_IMAGE_VERTEX v[4]; + + float ZoomWidth, ZoomHeight; + float ScaleWidth, ScaleHeight; + + // Fixup for rasterisation rules + const float cfEpsilon = 1.0f / (float)height; + + // + // Set up the quad like this (ascii-art ahead!) + // + // 3--2 + // | | + // 0--1 + // + // + + // Set depth + v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2]; + // Set Reciprocal Homogenous W + v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f; + + // Set texcoords + // Examine texture size - if different to input width and height + // then we'll need to munge the texcoords to fit. + ddsd.dwSize = sizeof(DDSURFACEDESC2); + IDirectDrawSurface7_GetSurfaceDesc(pImage, &ddsd); + ScaleWidth = (float)width / (float)ddsd.dwWidth; + ScaleHeight = (float)height / (float)ddsd.dwHeight; + v[0].tu = 0.0f; v[0].tv = 0.0f; + v[1].tu = ScaleWidth; v[1].tv = 0.0f; + v[2].tu = ScaleWidth; v[2].tv = ScaleHeight; + v[3].tu = 0.0f; v[3].tv = ScaleHeight; + + // Set raster positions + ZoomWidth = (float)width * ctx->Pixel.ZoomX; + ZoomHeight = (float)height * ctx->Pixel.ZoomY; + + v[0].x = x; v[0].y = GLD_FLIP_Y(y+cfEpsilon); + v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y+cfEpsilon); + v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon); + v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon); + + // Draw image with full HW acceleration + // NOTE: Be nice to use a State Block for all this state... + IDirect3DDevice7_SetTexture(gld->pDev, 0, pImage); + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTFN_POINT); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTFP_POINT); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTFG_POINT); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + // Ensure texture unit 1 is disabled + IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + // + // Emulate Chromakey with an Alpha Test. + // [Alpha Test is more widely supported anyway] + // + if (bChromakey) { + // Switch on alpha testing + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE); + // Fragment passes is alpha is greater than reference value + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER); + // Set alpha reference value between Bitmap alpha values of + // zero (transparent) and one (opaque). + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, 0x7f); + } + + IDirect3DDevice7_DrawPrimitive(gld->pDev, D3DPT_TRIANGLEFAN, _GLD_FVF_IMAGE, &v, 4, 0); + + // Reset state to before we messed it up + FLUSH_VERTICES(ctx, _NEW_ALL); + + return S_OK; +} + +//--------------------------------------------------------------------------- + +void gld_DrawPixels_DX7( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + GLD_context *gldCtx; + GLD_driver_dx7 *gld; + + IDirectDrawSurface7 *pImage; + HRESULT hr; + DDSURFACEDESC2 ddsd; + DWORD dwFlags; + D3DX_SURFACEFORMAT sf; + DWORD dwMipmaps; + + const struct gl_texture_format *MesaFormat; + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX7_DRIVER(gldCtx); + + dwFlags = D3DX_TEXTURE_NOMIPMAP; + sf = D3DX_SF_A8R8G8B8; + dwMipmaps = 1; + + hr = D3DXCreateTexture( + gld->pDev, + &dwFlags, + &width, &height, + &sf, // format + NULL, // palette + &pImage, // Output texture + &dwMipmaps); + if (FAILED(hr)) { + return; + } + + // D3DXCreateTexture() may not clear the texture is creates. + _gldClearSurface(pImage, 0); + + // + // Use Mesa to fill in image + // + + // Lock all of surface + ddsd.dwSize = sizeof(DDSURFACEDESC2); + dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT; + hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL); + if (FAILED(hr)) { + SAFE_RELEASE_SURFACE7(pImage); + return; + } + + // unpack image, apply transfer ops and store directly in texture + MesaFormat->StoreImage( + ctx, + 2, + GL_RGBA, + &_mesa_texformat_argb8888, + ddsd.lpSurface, + width, height, 1, 0, 0, 0, + ddsd.lPitch, + 0, /* dstImageStride */ + format, type, pixels, unpack); + + IDirectDrawSurface7_Unlock(pImage, NULL); + + _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage); + + SAFE_RELEASE_SURFACE7(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_ReadPixels_DX7( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *dest) +{ +// TODO +#if 0 + GLD_context *gldCtx; + GLD_driver_dx7 *gld; + + IDirect3DSurface8 *pBackbuffer = NULL; + IDirect3DSurface8 *pNativeImage = NULL; + IDirect3DSurface8 *pCanonicalImage = NULL; + + D3DSURFACE_DESC d3dsd; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + struct gl_pixelstore_attrib srcPacking; + int i; + GLint DstRowStride; + const struct gl_texture_format *MesaFormat; + + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + return; + } + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + DstRowStride = _mesa_image_row_stride(pack, width, format, type); + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice8_GetBackBuffer( + gld->pDev, + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + d3dsd.Format, + &pNativeImage); + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels. + // + // This intermediate surface ensure that we can use CopyRects() + // instead of relying on D3DXLoadSurfaceFromSurface(), which may + // try and lock the backbuffer. This way seems safer. + // + hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pNativeImage, + &ptDst); + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + // Create an RGBA8888 surface + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + &pCanonicalImage); + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + // Convert to RGBA8888 + hr = D3DXLoadSurfaceFromSurface( + pCanonicalImage, // Dest surface + NULL, NULL, // Dest palette, RECT + pNativeImage, // Src surface + NULL, NULL, // Src palette, RECT + D3DX_FILTER_NONE, // Filter + 0); // Colourkey + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + srcPacking.Alignment = 1; + srcPacking.ImageHeight = height; + srcPacking.LsbFirst = GL_FALSE; + srcPacking.RowLength = 0; + srcPacking.SkipImages = 0; + srcPacking.SkipPixels = 0; + srcPacking.SkipRows = 0; + srcPacking.SwapBytes = GL_FALSE; + + // Lock all of image + hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + goto gld_ReadPixels_DX7_return; + } + + // We need to flip the data. Yuck. + // Perhaps Mesa has a span packer we can use in future... + for (i=0; i<height; i++) { + BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0); + BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1)); + texImage->TexFormat->StoreImage( + ctx, + 2, + GL_RGBA, // base format + MesaFormat, // dst format + pDestRow, // dest addr + width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z + DstRowStride, // dst row stride + 0, // dstImageStride + GL_BGRA, // src format + GL_UNSIGNED_BYTE, // src type + pSrcRow, // src addr + &srcPacking); // packing params of source image + } + + IDirect3DSurface8_UnlockRect(pCanonicalImage); + +gld_ReadPixels_DX7_return: + SAFE_RELEASE_SURFACE8(pCanonicalImage); + SAFE_RELEASE_SURFACE8(pNativeImage); + SAFE_RELEASE_SURFACE8(pBackbuffer); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_CopyPixels_DX7( + GLcontext *ctx, + GLint srcx, + GLint srcy, + GLsizei width, + GLsizei height, + GLint dstx, + GLint dsty, + GLenum type) +{ +// TODO +#if 0 + // + // NOTE: Not allowed to copy vidmem to vidmem! + // Therefore we use an intermediate image surface. + // + + GLD_context *gldCtx; + GLD_driver_dx7 *gld; + + IDirect3DSurface8 *pBackbuffer; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface8 *pImage; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + + // Only backbuffer + if (type != GL_COLOR) + return; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice8_GetBackBuffer( + gld->pDev, + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pBackbuffer); + return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + d3dsd.Format, + &pImage); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pBackbuffer); + return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels + hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pImage, + &ptDst); + IDirect3DSurface8_Release(pBackbuffer); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pImage); + return; + } + + _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage); + + IDirect3DSurface8_Release(pImage); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_Bitmap_DX7( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + GLD_context *gldCtx; + GLD_driver_dx7 *gld; + + IDirectDrawSurface7 *pImage; // Bitmap texture + HRESULT hr; + BYTE *pTempBitmap; // Pointer to unpacked bitmap + D3DCOLOR clBitmapOne; // Opaque bitmap colour + D3DCOLOR clBitmapZero; // Transparent bitmap colour + D3DCOLOR *pBits; // Pointer to texture surface + const GLubyte *src; + int i, j, k; + + DDSURFACEDESC2 ddsd; // Surface desc returned by lock call + DWORD dwFlags; + D3DX_SURFACEFORMAT sf; + DWORD dwMipmaps; + + // Keep a copy of width/height as D3DXCreateTexture() call may alter input dimensions + GLsizei dwWidth = width; + GLsizei dwHeight = height; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX7_DRIVER(gldCtx); + + // Bail if no bitmap (only raster pos is updated) + if ((bitmap == NULL) && (width==0) && (height==0)) + return; + + // + // TODO: Detect conditions when created texture (pImage) is non-pow2. + // Texture coords may need to be adjusted to compensate. + // + + clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero + clBitmapOne = D3DCOLOR_COLORVALUE( + ctx->Current.RasterColor[0], + ctx->Current.RasterColor[1], + ctx->Current.RasterColor[2], + 1.0f); // NOTE: Alpha is One + + // Use Mesa to unpack bitmap into a canonical format + pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack); + if (pTempBitmap == NULL) + return; + + // Flags for texture creation + dwFlags = D3DX_TEXTURE_NOMIPMAP; + sf = D3DX_SF_A8R8G8B8; + dwMipmaps = 1; + + // Create a D3D texture to hold the bitmap + hr = D3DXCreateTexture( + gld->pDev, + &dwFlags, + &dwWidth, &dwHeight, + &sf, // format + NULL, // palette + &pImage, // Output texture + &dwMipmaps); + if (FAILED(hr)) { + FREE(pTempBitmap); + return; + } + + // D3DXCreateTexture may return a texture bigger than we asked for + // (i.e. padded to POW2) so let's clear the entire image bitmap. + // Additional: Looks like this is not strictly necessary. +// _gldClearSurface(pImage, clBitmapZero); + + ddsd.dwSize = sizeof(DDSURFACEDESC2); + dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT; + hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL); + if (FAILED(hr)) { + FREE(pTempBitmap); + SAFE_RELEASE_SURFACE7(pImage); + return; + } + +#if 0 + // DEBUG CODE + if (!(width==ddsd.dwWidth && height==ddsd.dwHeight)) + ddlogPrintf(GLDLOG_WARN, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight); +#endif + +#if 0 + // DEBUG CODE + ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight); + ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: bpp=%d", ddsd.ddpfPixelFormat.dwRGBBitCount); +#endif + + // Cast texel pointer to texture surface. + // We can do this because we used D3DX_SF_A8R8G8B8 as the format + pBits = (D3DCOLOR*)ddsd.lpSurface; + + + // Copy from the input bitmap into the texture + for (i=0; i<height; i++) { + GLubyte byte; + pBits = (D3DCOLOR*)((BYTE*)ddsd.lpSurface + (i*ddsd.lPitch)); + src = (const GLubyte *) _mesa_image_address(2, + &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, + 0, i, 0); + for (j=0; j<(width>>3); j++) { + byte = *src++; + for (k=0; k<8; k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + // Fill remaining bits from bitmap + if (width & 7) { + byte = *src; + for (k=0; k<(width & 7); k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + } + + // We're done with the unpacked bitmap + FREE(pTempBitmap); + + // Finished with texture surface - unlock it + IDirectDrawSurface7_Unlock(pImage, NULL); + + // Use internal function to draw bitmap onto rendertarget + _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage); + + // We're done with the bitmap texure - release it + IDirectDrawSurface7_Release(pImage); +} + +//--------------------------------------------------------------------------- +// Texture functions +//--------------------------------------------------------------------------- + +void _gldAllocateTexture( + GLcontext *ctx, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + HRESULT hr; + IDirectDrawSurface7 *pTex; + D3DX_SURFACEFORMAT d3dFormat; + DWORD dwFlags; + DWORD dwMipmaps; + DWORD dwWidth, dwHeight; + + if (!tObj || !texImage) + return; + + pTex = (IDirectDrawSurface7*)tObj->DriverData; + if (pTex) { + // Decide whether we can keep existing D3D texture + // by examining top-level surface. + DDSURFACEDESC2 ddsd; + ddsd.dwSize = sizeof(DDSURFACEDESC2); + _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd)); + // Release existing texture if not compatible + if ((ddsd.dwWidth == texImage->Width) || + (ddsd.dwHeight == texImage->Height)) + { + return; // Keep the existing texture + } + tObj->DriverData = NULL; + _GLD_DX7_TEX(Release(pTex)); + } + + dwFlags = (glb.bUseMipmaps) ? 0 : D3DX_TEXTURE_NOMIPMAP; + dwMipmaps = (glb.bUseMipmaps) ? D3DX_DEFAULT : 1; + dwWidth = texImage->Width; + dwHeight = texImage->Height; + + d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat); + hr = D3DXCreateTexture( + gld->pDev, + &dwFlags, + &dwWidth, + &dwHeight, + &d3dFormat, + NULL, + &pTex, + &dwMipmaps); + if (FAILED(hr)) { + gldLogError(GLDLOG_ERROR, "AllocateTexture failed", hr); + } + tObj->DriverData = pTex; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* gld_ChooseTextureFormat_DX7( + GLcontext *ctx, + GLint internalFormat, + GLenum srcFormat, + GLenum srcType) +{ + // [Based on mesa_choose_tex_format()] + // + // We will choose only texture formats that are supported + // by Direct3D. If the hardware doesn't support a particular + // texture format, then the D3DX texture calls that we use + // will automatically use a HW supported format. + // + // The most critical aim is to reduce copying; if we can use + // texture-image data directly then it will be a big performance assist. + // + + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return &_mesa_texformat_a8; // D3DFMT_A8 + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5 + // Mesa will convert this for us later... + // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5 + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return &_mesa_texformat_al88; // D3DFMT_A8L8 + case GL_R3_G3_B2: + return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2 + case GL_RGB4: + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4 + case 3: + case GL_RGB: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_rgb565; + case 4: + case GL_RGBA: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return &_mesa_texformat_argb8888; + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + default: + _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); + return NULL; + } +} + +//--------------------------------------------------------------------------- + +/* +// Safer(?), slower version. +void gld_TexImage2D_DX7( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + RECT rcSrcRect; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + + if (!tObj || !texImage) + return; + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture8_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface8_Release(pSurface); + return; + } + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + SetRect(&rcSrcRect, 0, 0, width, height); + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + NULL, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface8_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexImage2D_DX7( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + IDirectDrawSurface7 *pTex = NULL; + IDirectDrawSurface7 *pSurface = NULL; + HRESULT hr; + DDSURFACEDESC2 ddsd; + int i; + DDSCAPS2 ddsCaps; + + if (!tObj || !texImage) + return; + + // GLQUAKE FIX + // Test for input alpha data with non-alpha internalformat + if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) { + // Input format has alpha, but a non-alpha format has been requested. + texImage->IntFormat = GL_RGBA; + internalFormat = GL_RGBA; + } + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirectDrawSurface7*)tObj->DriverData; + if (!pTex) { + ASSERT(0); + return; // Texture has not been created + } + + pSurface = pTex; + if (level != 0) { + ddsd.dwSize = sizeof(ddsd); + _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd)); + if ((level > 0) && (level >= ddsd.dwMipMapCount)) + return; // Level does not exist + ZeroMemory(&ddsCaps, sizeof(ddsCaps)); + for (i=0; i<level; i++) { + ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + hr = IDirectDrawSurface7_GetAttachedSurface( + pSurface, + &ddsCaps, + &pSurface); + if (SUCCEEDED(hr)) { + IDirectDrawSurface7_Release(pSurface); + } else { + ; + } + } + } + + // Lock all of surface + ddsd.dwSize = sizeof(ddsd); + hr = IDirectDrawSurface7_Lock(pSurface, NULL, &ddsd, 0, 0); + if (FAILED(hr)) { + IDirectDrawSurface7_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage( + ctx, + 2, + texImage->Format, + //_gldMesaFormatForD3DFormat(d3dsd.Format), + _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)), + ddsd.lpSurface, + width, height, 1, 0, 0, 0, + ddsd.lPitch, + 0, // dstImageStride + format, type, pixels, packing); + + IDirectDrawSurface7_Unlock(pSurface, NULL); +} + +//--------------------------------------------------------------------------- + +void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + // A 1D texture is a 2D texture with a height of zero + gld_TexImage2D_DX7(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +/* +void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_GET_CONTEXT + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + D3DFORMAT d3dFormat; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + RECT rcSrcRect; + RECT rcDstRect; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= _GLD_DX8_TEX(GetLevelCount(pTex)) + return; // Level does not exist + hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + d3dFormat = _gldGLFormatToD3DFormat(texImage->Format); + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface8_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + // Source rectangle is whole of input image + SetRect(&rcSrcRect, 0, 0, width, height); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + &rcDstRect, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface8_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + IDirectDrawSurface7 *pTex; + IDirectDrawSurface7 *pSurface; + HRESULT hr; + RECT rcDstRect; + DDSURFACEDESC2 ddsd; + int i; + DDSCAPS2 ddsCaps; + + if (!tObj || !texImage) + return; + + pTex = (IDirectDrawSurface7*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + + __try { + + ddsd.dwSize = sizeof(ddsd); + _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd)); + if ((level > 0) && (level >= ddsd.dwMipMapCount)) + return; // Level does not exist + + ZeroMemory(&ddsCaps, sizeof(ddsCaps)); + pSurface = pTex; + for (i=0; i<level; i++) { + ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + hr = IDirectDrawSurface7_GetAttachedSurface( + pSurface, + &ddsCaps, + &pSurface); + if(SUCCEEDED(hr)) { + IDirectDrawSurface7_Release(pSurface); + } else { + return; + } + } + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + // Lock sub-rect of surface + hr = IDirectDrawSurface7_Lock(pSurface, &rcDstRect, &ddsd, 0, 0); + if (FAILED(hr)) { + IDirectDrawSurface7_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)), + ddsd.lpSurface, + width, height, 1, + 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!! + ddsd.lPitch, + 0, // dstImageStride + format, type, pixels, packing); + + + IDirectDrawSurface7_Unlock(pSurface, &rcDstRect); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + ; + } +} + +//--------------------------------------------------------------------------- + +void gld_TexSubImage1D_DX7( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + gld_TexSubImage2D_DX7(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +void gld_DeleteTexture_DX7( + GLcontext *ctx, + struct gl_texture_object *tObj) +{ + GLD_context *gld = (GLD_context*)(ctx->DriverCtx); + + __try { + + if (tObj) { + IDirectDrawSurface7 *pTex = (IDirectDrawSurface7*)tObj->DriverData; + if (pTex) { +/* // Make sure texture is not bound to a stage before releasing it + for (int i=0; i<MAX_TEXTURE_UNITS; i++) { + if (gld->CurrentTexture[i] == pTex) { + gld->pDev->SetTexture(i, NULL); + gld->CurrentTexture[i] = NULL; + } + }*/ + _GLD_DX7_TEX(Release(pTex)); + tObj->DriverData = NULL; + } + } + + } + __except(EXCEPTION_EXECUTE_HANDLER) { + ; + } +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetColorOps( + const GLD_driver_dx7 *gld, + GLuint unit, + DWORD ColorArg1, + D3DTEXTUREOP ColorOp, + DWORD ColorArg2) +{ + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2)); +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetAlphaOps( + const GLD_driver_dx7 *gld, + GLuint unit, + DWORD AlphaArg1, + D3DTEXTUREOP AlphaOp, + DWORD AlphaArg2) +{ + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2)); +} + +//--------------------------------------------------------------------------- + +void gldUpdateTextureUnit( + GLcontext *ctx, + GLuint unit, + BOOL bPassThrough) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + D3DTEXTUREMINFILTER minfilter; + D3DTEXTUREMIPFILTER mipfilter; + GLenum BaseFormat; + DWORD dwColorArg0; + int iTexEnv = 0; + GLD_texenv *pTexenv; + + // NOTE: If bPassThrough is FALSE then texture stage can be + // disabled otherwise it must pass-through it's current fragment. + + const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *tObj = pUnit->_Current; + + IDirectDrawSurface7 *pTex = NULL; + if (tObj) { + pTex = (IDirectDrawSurface7*)tObj->DriverData; + } + + __try { + + // Enable texturing if unit is enabled and a valid D3D texture exists + // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT + //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) { + if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) { + // Enable texturing + _GLD_DX7_DEV(SetTexture(gld->pDev, unit, pTex)); + } else { + // Disable texturing, then return + _GLD_DX7_DEV(SetTexture(gld->pDev, unit, NULL)); + if (bPassThrough) { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + } else { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + } + return; + } + + // Texture parameters + _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter)); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS))); + _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + + // Texture priority + _GLD_DX7_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f))); + + // Texture environment + // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops. + // See Page 355 of the Red Book. + BaseFormat = _gldDecodeBaseFormat(pTex); + + switch (BaseFormat) { + case GL_RGB: + iTexEnv = 0; + break; + case GL_RGBA: + iTexEnv = 1; + break; + case GL_ALPHA: + iTexEnv = 2; + break; + } + + switch (pUnit->EnvMode) { + case GL_DECAL: + iTexEnv += 0; + break; + case GL_REPLACE: + iTexEnv += 3; + break; + case GL_MODULATE: + iTexEnv += 6; + break; + case GL_BLEND: + // Set blend colour + // Unsupported by DX7 +// dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]); +// _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0)); +// gldLogMessage(GLDLOG_WARN, "GL_BLEND\n"); + iTexEnv += 9; + break; + case GL_ADD: + iTexEnv += 12; + break; + } + pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv]; + _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2); + _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2); + + } + __except(EXCEPTION_EXECUTE_HANDLER) { + ; + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_TEXTURE_DX7( + GLcontext *ctx) +{ + // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units + + BOOL bUnit0Enabled; + BOOL bUnit1Enabled; + + if (!ctx) + return; // Sanity check + + if (ctx->Const.MaxTextureUnits == 1) { + gldUpdateTextureUnit(ctx, 0, TRUE); + return; + } + + // + // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!! + // + + // Mesa 5: Texture Units altered + bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + + // If Unit0 is disabled and Unit1 is enabled then we must pass-though + gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE); + // We can always disable the last texture unit + gldUpdateTextureUnit(ctx, 1, FALSE); + +#ifdef _DEBUG + { + // Find out whether device supports current renderstates + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + DWORD dwPasses; + _GLD_DX7_DEV(ValidateDevice(gld->pDev, &dwPasses)); +#if 0 + if (FAILED(hr)) { + gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr); + } +#endif + if (dwPasses != 1) { + gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n"); + } + } +#endif +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c new file mode 100644 index 00000000000..a85620dde8d --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c @@ -0,0 +1,257 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect fastpath pipeline stage +* +****************************************************************************/ + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- +/* +__inline void _gldSetVertexShaderConstants( + GLcontext *ctx, + GLD_driver_dx8 *gld) +{ + D3DXMATRIX mat, matView, matProj; + GLfloat *pM; + + // Mesa 5: Altered to a Stack + //pM = ctx->ModelView.m; + pM = ctx->ModelviewMatrixStack.Top->m; + matView._11 = pM[0]; + matView._12 = pM[1]; + matView._13 = pM[2]; + matView._14 = pM[3]; + matView._21 = pM[4]; + matView._22 = pM[5]; + matView._23 = pM[6]; + matView._24 = pM[7]; + matView._31 = pM[8]; + matView._32 = pM[9]; + matView._33 = pM[10]; + matView._34 = pM[11]; + matView._41 = pM[12]; + matView._42 = pM[13]; + matView._43 = pM[14]; + matView._44 = pM[15]; + + // Mesa 5: Altered to a Stack + //pM = ctx->ProjectionMatrix.m; + pM = ctx->ProjectionMatrixStack.Top->m; + matProj._11 = pM[0]; + matProj._12 = pM[1]; + matProj._13 = pM[2]; + matProj._14 = pM[3]; + matProj._21 = pM[4]; + matProj._22 = pM[5]; + matProj._23 = pM[6]; + matProj._24 = pM[7]; + matProj._31 = pM[8]; + matProj._32 = pM[9]; + matProj._33 = pM[10]; + matProj._34 = pM[11]; + matProj._41 = pM[12]; + matProj._42 = pM[13]; + matProj._43 = pM[14]; + matProj._44 = pM[15]; + + D3DXMatrixMultiply( &mat, &matView, &matProj ); + D3DXMatrixTranspose( &mat, &mat ); + + _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4)); +} +*/ +//--------------------------------------------------------------------------- + +static GLboolean gld_d3d_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + TNLcontext *tnl; + struct vertex_buffer *VB; + tnl_render_func *tab; + GLint pass; + GLD_pb_dx7 *gldPB = &gld->PB3d; + DWORD dwFlags; + +/* + static int count = 0; + count++; + if (count != 2) + return GL_FALSE; +*/ + // The "check" function should disable this stage, + // but we'll test gld->bUseMesaTnL anyway. + if (gld->bUseMesaTnL) { + // Do nothing in this stage, but continue pipeline + return GL_TRUE; + } + + tnl = TNL_CONTEXT(ctx); + VB = &tnl->vb; + pass = 0; + + tnl->Driver.Render.Start( ctx ); + +#if 0 + // For debugging: Useful to see if an app passes colour data in + // an unusual format. + switch (VB->ColorPtr[0]->Type) { + case GL_FLOAT: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n"); + break; + case GL_UNSIGNED_BYTE: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n"); + break; + default: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n"); + break; + } +#endif + + tnl->Driver.Render.Points = gld_Points3D_DX7; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line3DFlat_DX7; + tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX7; + tnl->Driver.Render.Quad = gld_Quad3DFlat_DX7; + } else { + tnl->Driver.Render.Line = gld_Line3DSmooth_DX7; + tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX7; + tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX7; + } + +// _GLD_DX7_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY; + _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts); + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) + { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + _GLD_DX7_VB(Unlock(gldPB->pVB)); + +// _GLD_DX7_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride)); + + _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_PROJECTION, &gld->matProjection)); + _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_WORLD, &gld->matModelView)); + + if (gldPB->nPoints) { +// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { +// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines, 0)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { +// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles, 0)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + + +//--------------------------------------------------------------------------- + +const struct tnl_pipeline_stage _gld_d3d_render_stage = +{ + "gld_d3d_render_stage", + NULL, + NULL, + NULL, + NULL, + gld_d3d_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c new file mode 100644 index 00000000000..0a57bde2588 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c @@ -0,0 +1,423 @@ +/* $Id: gld_vb_mesa_render_dx7.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <[email protected]> + */ + + +/* + * Render whole vertex buffers, including projection of vertices from + * clip space and clipping of primitives. + * + * This file makes calls to project vertices and to the point, line + * and triangle rasterizers via the function pointers: + * + * context->Driver.Render.* + * + */ + + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx7.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +/**********************************************************************/ +/* Clip single primitives */ +/**********************************************************************/ + + +#if defined(USE_IEEE) +#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31)) +//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +#define NEGATIVE(x) (x < 0) +//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#endif + + +#define W(i) coord[i][3] +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 4 +#define TAG(x) x##_4 +#include "tnl/t_vb_cliptmp.h" + + + +/**********************************************************************/ +/* Clip and render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte ormask = c1|c2; \ + if (!ormask) \ + LineFunc( ctx, v1, v2 ); \ + else if (!(c1 & c2 & 0x3f)) \ + clip_line_4( ctx, v1, v2, ormask ); \ +} while (0) + +#define RENDER_TRI( v1, v2, v3 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ + GLubyte ormask = c1|c2|c3; \ + if (!ormask) \ + TriangleFunc( ctx, v1, v2, v3 ); \ + else if (!(c1 & c2 & c3 & 0x3f)) \ + clip_tri_4( ctx, v1, v2, v3, ormask ); \ +} while (0) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte c3 = mask[v3], c4 = mask[v4]; \ + GLubyte ormask = c1|c2|c3|c4; \ + if (!ormask) \ + QuadFunc( ctx, v1, v2, v3, v4 ); \ + else if (!(c1 & c2 & c3 & c4 & 0x3f)) \ + clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ +} while (0) + + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const GLubyte *mask = VB->ClipMask; \ + const GLuint sz = VB->ClipPtr->size; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + const GLboolean stipple = ctx->Line.StippleFlag; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; (void) mask; (void) sz; (void) stipple; + +#define TAG(x) clip_##x##_verts +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + + +/* Elts, with the possibility of clipping. + */ +#undef ELT +#undef TAG +#define ELT(x) elt[x] +#define TAG(x) clip_##x##_elts +#include "tnl/t_vb_rendertmp.h" + +/* TODO: do this for all primitives, verts and elts: + */ +static void clip_elt_triangles( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES]; + struct vertex_buffer *VB = &tnl->vb; + const GLuint * const elt = VB->Elts; + GLubyte *mask = VB->ClipMask; + GLuint last = count-2; + GLuint j; + (void) flags; + + tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES ); + + for (j=start; j < last; j+=3 ) { + GLubyte c1 = mask[elt[j]]; + GLubyte c2 = mask[elt[j+1]]; + GLubyte c3 = mask[elt[j+2]]; + GLubyte ormask = c1|c2|c3; + if (ormask) { + if (start < j) + render_tris( ctx, start, j, 0 ); + if (!(c1&c2&c3&0x3f)) + clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); + start = j+3; + } + } + + if (start < j) + render_tris( ctx, start, j, 0 ); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, no clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ + LineFunc( ctx, v1, v2 ) + +#define RENDER_TRI( v1, v2, v3 ) \ + TriangleFunc( ctx, v1, v2, v3 ) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ + QuadFunc( ctx, v1, v2, v3, v4 ) + +#define TAG(x) _gld_tnl_##x##_verts + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; + +#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx ) +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RENDER_TAB_QUALIFIER +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + +/* Elts, no clipping. + */ +#undef ELT +#define TAG(x) _gld_tnl_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Helper functions for drivers */ +/**********************************************************************/ +/* +void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; +} + +void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} +*/ + + +/**********************************************************************/ +/* Clip and render whole vertex buffers */ +/**********************************************************************/ + +tnl_points_func _gldSetupPoints[4] = { + gld_Points2D_DX7, + gld_Points2D_DX7, + gld_Points2D_DX7, + gld_Points2D_DX7 +}; +tnl_line_func _gldSetupLine[4] = { + gld_Line2DFlat_DX7, + gld_Line2DSmooth_DX7, + gld_Line2DFlat_DX7, + gld_Line2DSmooth_DX7, +}; +tnl_triangle_func _gldSetupTriangle[4] = { + gld_Triangle2DFlat_DX7, + gld_Triangle2DSmooth_DX7, + gld_Triangle2DFlatExtras_DX7, + gld_Triangle2DSmoothExtras_DX7 +}; +tnl_quad_func _gldSetupQuad[4] = { + gld_Quad2DFlat_DX7, + gld_Quad2DSmooth_DX7, + gld_Quad2DFlatExtras_DX7, + gld_Quad2DSmoothExtras_DX7 +}; + +//--------------------------------------------------------------------------- + +static GLboolean _gld_mesa_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + tnl_render_func *tab; + GLint pass = 0; + GLD_pb_dx7 *gldPB; + DWORD dwFlags; + + /* Allow the drivers to lock before projected verts are built so + * that window coordinates are guarenteed not to change before + * rendering. + */ + ASSERT(tnl->Driver.Render.Start); + + tnl->Driver.Render.Start( ctx ); + + gldPB = &gld->PB2d; + tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc]; + tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc]; + tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc]; + tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc]; + + dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY; + _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + + // Allocate primitive pointers - gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 ); + + if (VB->ClipOrMask) { + tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; + clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles; + } + else { + tab = (VB->Elts ? + tnl->Driver.Render.PrimTabElts : + tnl->Driver.Render.PrimTabVerts); + } + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + +// tnl->Driver.Render.Finish( ctx ); + + _GLD_DX7_VB(Unlock(gldPB->pVB)); + + if (gldPB->nPoints) { + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines*2, 0)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles*3, 0)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + + +const struct tnl_pipeline_stage _gld_mesa_render_stage = +{ + "gld_mesa_render_stage", + NULL, + NULL, + NULL, + NULL, + _gld_mesa_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c new file mode 100644 index 00000000000..0f8fe33eb15 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c @@ -0,0 +1,1611 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 8.x WGL (WindowsGL) +* +****************************************************************************/ + +#include "dglcontext.h" +#include "gld_driver.h" +//#include "gld_dxerr8.h" +#include "gld_dx7.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +// Copied from dglcontect.c +#define GLDERR_NONE 0 +#define GLDERR_MEM 1 +#define GLDERR_DDRAW 2 +#define GLDERR_D3D 3 +#define GLDERR_BPP 4 +#define GLDERR_DDS 5 +// This external var keeps track of any error +extern int nContextError; + +// Uncomment this for persistant resources +//#define _GLD_PERSISTANT + +#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL + +extern void _gld_mesa_warning(GLcontext *, char *); +extern void _gld_mesa_fatal(GLcontext *, char *); + +//--------------------------------------------------------------------------- + +static char szColorDepthWarning[] = +"GLDirect does not support the current desktop\n\ +color depth.\n\n\ +You may need to change the display resolution to\n\ +16 bits per pixel or higher color depth using\n\ +the Windows Display Settings control panel\n\ +before running this OpenGL application.\n"; + +// The only depth-stencil formats currently supported by Direct3D +// Surface Format Depth Stencil Total Bits +// D3DFMT_D32 32 - 32 +// D3DFMT_D15S1 15 1 16 +// D3DFMT_D24S8 24 8 32 +// D3DFMT_D16 16 - 16 +// D3DFMT_D24X8 24 - 32 +// D3DFMT_D24X4S4 24 4 32 + +// This pixel format will be used as a template when compiling the list +// of pixel formats supported by the hardware. Many fields will be +// filled in at runtime. +// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM +static DGL_pixelFormat pfTemplateHW = +{ + { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure + 1, // Structure version - should be 1 + // Flags: + PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface. + PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM) + PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM) + PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing. + PFD_DOUBLEBUFFER | // The buffer is double-buffered. + 0, // Placeholder for easy commenting of above flags + PFD_TYPE_RGBA, // Pixel type RGBA. + 16, // Total colour bitplanes (excluding alpha bitplanes) + 5, 0, // Red bits, shift + 5, 0, // Green bits, shift + 5, 0, // Blue bits, shift + 0, 0, // Alpha bits, shift (destination alpha) + 0, // Accumulator bits (total) + 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha + 0, // Depth bits + 0, // Stencil bits + 0, // Number of auxiliary buffers + 0, // Layer type + 0, // Specifies the number of overlay and underlay planes. + 0, // Layer mask + 0, // Specifies the transparent color or index of an underlay plane. + 0 // Damage mask + }, + D3DX_SF_UNKNOWN, // No depth/stencil buffer +}; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// Vertex Shader Declaration +static DWORD dwTwoSidedLightingDecl[] = +{ + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position + D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal + D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color + D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color + D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0 + D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1 + D3DVSD_END() +}; + +// Vertex Shader for two-sided lighting +static char *szTwoSidedLightingVS = +// This is a test shader! +"vs.1.0\n" +"m4x4 oPos,v0,c0\n" +"mov oD0,v2\n" +"mov oD1,v3\n" +"mov oT0,v4\n" +"mov oT1,v5\n" +; +*/ +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +typedef struct { +// HINSTANCE hD3D8DLL; // Handle to d3d8.dll +// FNDIRECT3DCREATE7 fnDirect3DCreate7; // Direct3DCreate8 function prototype +// BOOL bDirect3D; // Persistant Direct3D7 exists +// BOOL bDirect3DDevice; // Persistant Direct3DDevice7 exists +// IDirect3D7 *pD3D; // Persistant Direct3D7 +// IDirect3DDevice7 *pDev; // Persistant Direct3DDevice7 + BOOL bD3DXStarted; +} GLD_dx7_globals; + +// These are "global" to all DX7 contexts. KeithH +static GLD_dx7_globals dx7Globals; + +// Added for correct clipping of multiple open windows. (DaveM) +LPDIRECTDRAWSURFACE7 lpDDSPrimary = NULL; +LPDIRECTDRAWCLIPPER lpDDClipper = NULL; + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +BOOL gldGetDXErrorString_DX( + HRESULT hr, + char *buf, + int nBufSize) +{ + // + // Return a string describing the input HRESULT error code + // + + D3DXGetErrorString(hr, nBufSize, buf); + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// DX7 does not support multisample +/* +static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType( + IDirect3D8 *pD3D8, + D3DFORMAT SurfaceFormat, + D3DDEVTYPE d3dDevType, + BOOL Windowed) +{ + int i; + HRESULT hr; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE) + return D3DMULTISAMPLE_NONE; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) { + // Find fastest multisample + for (i=2; i<17; i++) { + hr = IDirect3D8_CheckDeviceMultiSampleType( + pD3D8, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } else { + // Find nicest multisample + for (i=16; i>1; i--) { + hr = IDirect3D8_CheckDeviceMultiSampleType( + pD3D8, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } + + // Nothing found - return default + return D3DMULTISAMPLE_NONE; +} +*/ +//--------------------------------------------------------------------------- + +void _gldDestroyPrimitiveBuffer( + GLD_pb_dx7 *gldVB) +{ + SAFE_RELEASE(gldVB->pVB); + + // Sanity check... + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; +} + +//--------------------------------------------------------------------------- + +HRESULT _gldCreatePrimitiveBuffer( + GLcontext *ctx, + GLD_driver_dx7 *lpCtx, + GLD_pb_dx7 *gldVB) +{ + HRESULT hResult; + char *szCreateVertexBufferFailed = "CreateVertexBuffer failed"; + DWORD dwMaxVertices; // Max number of vertices in vertex buffer + DWORD dwVBSize; // Total size of vertex buffer + D3DVERTEXBUFFERDESC vbdesc; + + // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we + // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize. + // We'll use IMM_SIZE if it's larger (which it should not be). + dwMaxVertices = MAX_ARRAY_LOCK_SIZE; + + // Max vertex buffer size limited in DX7. (DaveM) + if (dwMaxVertices*9 > D3DMAXNUMVERTICES) + dwMaxVertices = D3DMAXNUMVERTICES/9; + + // Now calculate how many vertices to allow for in total + // 1 per point, 2 per line, 6 per quad = 9 + dwVBSize = dwMaxVertices * 9 * gldVB->dwStride; + + vbdesc.dwSize = sizeof(vbdesc); + vbdesc.dwCaps = gldVB->dwCreateFlags; + vbdesc.dwFVF = gldVB->dwFVF; + vbdesc.dwNumVertices = dwMaxVertices * 9; + +/* hResult = IDirect3DDevice8_CreateVertexBuffer( + lpCtx->pDev, + dwVBSize, +RAgldVB->dwUsage, + gldVB->dwFVF, + gldVB->dwPool, + &gldVB->pVB);*/ + hResult = IDirect3D7_CreateVertexBuffer( + lpCtx->pD3D, + &vbdesc, + &gldVB->pVB, + 0); + if (FAILED(hResult)) { + ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed); + return hResult; + } + + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; + gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL; + gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB + gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB + + return S_OK; +} + +//--------------------------------------------------------------------------- +// Function: _gldCreateVertexShaders +// Create DX8 Vertex Shaders. +//--------------------------------------------------------------------------- +/* +void _gldCreateVertexShaders( + GLD_driver_dx8 *gld) +{ + DWORD dwFlags; + LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer + HRESULT hr; + +#ifdef _DEBUG + dwFlags = D3DXASM_DEBUG; +#else + dwFlags = 0; // D3DXASM_SKIPVALIDATION; +#endif + + ddlogMessage(DDLOG_INFO, "Creating shaders...\n"); + + // Init the shader handle + gld->VStwosidelight.hShader = 0; + + if (gld->d3dCaps8.MaxStreams == 0) { + // Lame DX8 driver doesn't support streams + // Not fatal, as defaults will be used + ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n"); + return; + } + + // ** THIS DISABLES VERTEX SHADER SUPPORT ** +// return; + // ** THIS DISABLES VERTEX SHADER SUPPORT ** + + // + // Two-sided lighting + // + +#if 0 + // + // DEBUGGING: Load shader from a text file + // + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + hr = D3DXAssembleShaderFromFile( + "twoside.vsh", + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#else + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + // Assemble ascii shader text into shader opcodes + hr = D3DXAssembleShader( + szTwoSidedLightingVS, + strlen(szTwoSidedLightingVS), + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#endif + if (FAILED(hr)) { + ddlogError(DDLOG_WARN, "AssembleShader failed", hr); + SAFE_RELEASE(pVSOpcodeBuffer); + return; + } + +// This is for debugging. Remove to enable vertex shaders in HW +#define _GLD_FORCE_SW_VS 0 + + if (_GLD_FORCE_SW_VS) { + // _GLD_FORCE_SW_VS should be disabled for Final Release + ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n"); + } + + // Try and create shader in hardware. + // NOTE: The D3D Ref device appears to succeed when trying to + // create the device in hardware, but later complains + // when trying to set it with SetVertexShader(). Go figure. + if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) { + // Don't try and create a hardware shader with the Ref device + hr = E_FAIL; // COM error/fail result + } else { + gld->VStwosidelight.bHardware = TRUE; + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + 0); + } + if (FAILED(hr)) { + ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n"); + // Failed. Try and create shader for software processing + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + D3DUSAGE_SOFTWAREPROCESSING); + if (FAILED(hr)) { + gld->VStwosidelight.hShader = 0; // Sanity check + ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr); + return; + } + // Succeeded, but for software processing + gld->VStwosidelight.bHardware = FALSE; + } + + SAFE_RELEASE(pVSOpcodeBuffer); + + ddlogMessage(DDLOG_INFO, "... OK\n"); +} + +//--------------------------------------------------------------------------- + +void _gldDestroyVertexShaders( + GLD_driver_dx8 *gld) +{ + if (gld->VStwosidelight.hShader) { + IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader); + gld->VStwosidelight.hShader = 0; + } +} +*/ +//--------------------------------------------------------------------------- + +BOOL gldCreateDrawable_DX( + DGL_ctx *ctx, +// BOOL bDefaultDriver, + BOOL bDirectDrawPersistant, + BOOL bPersistantBuffers) +{ + // + // bDirectDrawPersistant: applies to IDirect3D8 + // bPersistantBuffers: applies to IDirect3DDevice8 + // + +// D3DDEVTYPE d3dDevType; +// D3DPRESENT_PARAMETERS d3dpp; +// D3DDISPLAYMODE d3ddm; +// DWORD dwBehaviourFlags; +// D3DADAPTER_IDENTIFIER8 d3dIdent; + + HRESULT hr; + GLD_driver_dx7 *lpCtx = NULL; + D3DX_VIDMODEDESC d3ddm; + + // Parameters for D3DXCreateContextEx + // These will be different for fullscreen and windowed + DWORD dwDeviceIndex; + DWORD dwFlags; + HWND hwnd; + HWND hwndFocus; + DWORD numColorBits; + DWORD numAlphaBits; + DWORD numDepthBits; + DWORD numStencilBits; + DWORD numBackBuffers; + DWORD dwWidth; + DWORD dwHeight; + DWORD refreshRate; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + if (ctx->glPriv) { + lpCtx = ctx->glPriv; + // Release any existing interfaces (in reverse order) + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); + lpCtx->pD3DXContext = NULL; + } else { + lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7)); + ZeroMemory(lpCtx, sizeof(lpCtx)); + } + +// d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level + // of HW acceleration. + dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT; + + // TODO: Check this +// if (bDefaultDriver) +// d3dDevType = D3DDEVTYPE_REF; + +#ifdef _GLD_PERSISTANT + // Use persistant interface if needed + if (bDirectDrawPersistant && dx7Globals.bDirect3D) { + lpCtx->pD3D = dx7Globals.pD3D; + IDirect3D7_AddRef(lpCtx->pD3D); + goto SkipDirectDrawCreate; + } +#endif +/* + // Create Direct3D7 object + lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); + if (lpCtx->pD3D == NULL) { + MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); + ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); + nContextError = GLDERR_D3D; + goto return_with_error; + } +*/ + +#ifdef _GLD_PERSISTANT + // Cache Direct3D interface for subsequent GLRCs + if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { + dx7Globals.pD3D = lpCtx->pD3D; + IDirect3D7_AddRef(dx7Globals.pD3D); + dx7Globals.bDirect3D = TRUE; + } +SkipDirectDrawCreate: +#endif +/* + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; + goto return_with_error; + } +*/ + +#if 0 + // Get device caps + hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Check for hardware transform & lighting + lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; + + // If this flag is present then we can't default to Mesa + // SW rendering between BeginScene() and EndScene(). + if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { + ddlogMessage(DDLOG_WARN, + "Warning : No 2D allowed during 3D scene.\n"); + } +#endif + + // + // Create the Direct3D context + // + +#ifdef _GLD_PERSISTANT + // Re-use original IDirect3DDevice if persistant buffers exist. + // Note that we test for persistant IDirect3D8 as well + // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) + if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D && dx7Globals.pDev) { + lpCtx->pDev = dx7Globals.pDev; + IDirect3DDevice7_AddRef(dx7Globals.pDev); + goto skip_direct3ddevice_create; + } +#endif +/* + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + + // Support for vertical retrace synchronisation. + // Set default presentation interval in case caps bits are missing + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + // FullScreen_PresentationInterval must be default for Windowed mode + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + + // Decide if we can use hardware TnL + dwBehaviourFlags = (lpCtx->bHasHWTnL) ? + D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; + // Add flag to tell D3D to be thread-safe + if (glb.bMultiThreaded) + dwBehaviourFlags |= D3DCREATE_MULTITHREADED; + hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, + glb.dwAdapter, + d3dDevType, + ctx->hWnd, + dwBehaviourFlags, + &d3dpp, + &lpCtx->pDev); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } +*/ + + // Create D3DX context + if (ctx->bFullscreen) { + // + // FULLSCREEN + // + + // Get display mode + D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); + + // Fullscreen Parameters + dwFlags = D3DX_CONTEXT_FULLSCREEN; + hwnd = ctx->hWnd; + hwndFocus = ctx->hWnd; + numColorBits = ctx->lpPF->pfd.cColorBits; + numAlphaBits = ctx->lpPF->pfd.cAlphaBits; + numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; + numStencilBits = ctx->lpPF->pfd.cStencilBits; + numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer + dwWidth = d3ddm.width; + dwHeight = d3ddm.height; + refreshRate = d3ddm.refreshRate; // D3DX_DEFAULT; + } else { + // + // WINDOWED + // + + // Windowed Parameters + dwFlags = 0; // No flags means "windowed" + hwnd = ctx->hWnd; + hwndFocus = (HWND)D3DX_DEFAULT; + numColorBits = D3DX_DEFAULT; // Use Desktop depth + numAlphaBits = ctx->lpPF->pfd.cAlphaBits; + numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits; + numStencilBits = ctx->lpPF->pfd.cStencilBits; + numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer + dwWidth = ctx->dwWidth; + dwHeight = ctx->dwHeight; + refreshRate = D3DX_DEFAULT; + } + hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus, + numColorBits, numAlphaBits, numDepthBits, numStencilBits, + numBackBuffers, + dwWidth, dwHeight, refreshRate, + &lpCtx->pD3DXContext); + if (FAILED(hr)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Obtain D3D7 interfaces from ID3DXContext +// lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext); + lpCtx->pDD = lpCtx->pD3DXContext->lpVtbl->GetDD(lpCtx->pD3DXContext); + if (lpCtx->pDD == NULL) + goto return_with_error; + lpCtx->pD3D = lpCtx->pD3DXContext->lpVtbl->GetD3D(lpCtx->pD3DXContext); + if (lpCtx->pD3D == NULL) + goto return_with_error; + lpCtx->pDev = lpCtx->pD3DXContext->lpVtbl->GetD3DDevice(lpCtx->pD3DXContext); + if (lpCtx->pDev == NULL) + goto return_with_error; + + // Need to manage clipper manually for multiple windows + // since DX7 D3DX utility lib does not appear to do that. (DaveM) + if (!ctx->bFullscreen) { + // Get primary surface too + lpDDSPrimary = lpCtx->pD3DXContext->lpVtbl->GetPrimary(lpCtx->pD3DXContext); + if (lpDDSPrimary == NULL) { + ddlogPrintf(DDLOG_WARN, "GetPrimary"); + goto return_with_error; + } + // Create clipper for correct window updates + if (IDirectDraw7_CreateClipper(lpCtx->pDD, 0, &lpDDClipper, NULL) != DD_OK) { + ddlogPrintf(DDLOG_WARN, "CreateClipper"); + goto return_with_error; + } + // Set the window that the clipper belongs to + if (IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hwnd) != DD_OK) { + ddlogPrintf(DDLOG_WARN, "SetHWnd"); + goto return_with_error; + } + // Attach the clipper to the primary surface + if (IDirectDrawSurface7_SetClipper(lpDDSPrimary, lpDDClipper) != DD_OK) { + ddlogPrintf(DDLOG_WARN, "SetClipper"); + goto return_with_error; + } + } + + // Get device caps + IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps); + + // Determine HW TnL + lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; + +#ifdef _GLD_PERSISTANT + if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) { + dx7Globals.pDev = lpCtx->pDev; + dx7Globals.bDirect3DDevice = TRUE; + } +#endif + +#if 0 + // Dump some useful stats + hResult = IDirect3D8_GetAdapterIdentifier( + lpCtx->pD3D, + glb.dwAdapter, + D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay + &d3dIdent); + if (SUCCEEDED(hResult)) { + ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); + ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", + d3dIdent.Driver, + HIWORD(d3dIdent.DriverVersion.HighPart), + LOWORD(d3dIdent.DriverVersion.HighPart), + HIWORD(d3dIdent.DriverVersion.LowPart), + LOWORD(d3dIdent.DriverVersion.LowPart)); + ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", + d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); + } +#endif + + // Init projection matrix for D3D TnL + D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection); + lpCtx->matModelView = lpCtx->matProjection; +// gld->bUseMesaProjection = TRUE; + +skip_direct3ddevice_create: + + // Create buffers to hold primitives + lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; +// lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; + lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); + lpCtx->PB2d.dwCreateFlags = D3DVBCAPS_DONOTCLIP | + D3DVBCAPS_SYSTEMMEMORY | + D3DVBCAPS_WRITEONLY; + hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); + if (FAILED(hr)) + goto return_with_error; + + lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; +// lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; + lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); + lpCtx->PB3d.dwCreateFlags = D3DVBCAPS_WRITEONLY; + + hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); + if (FAILED(hr)) + goto return_with_error; + + // Zero the pipeline usage counters + lpCtx->PipelineUsage.qwMesa.QuadPart = +// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = + lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; + + // Assign drawable to GL private + ctx->glPriv = lpCtx; + return TRUE; + +return_with_error: + // Clean up and bail + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + //SAFE_RELEASE(lpCtx->pD3DXContext); + lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL gldResizeDrawable_DX( + DGL_ctx *ctx, + BOOL bDefaultDriver, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + GLD_driver_dx7 *gld = NULL; +// D3DDEVTYPE d3dDevType; +// D3DPRESENT_PARAMETERS d3dpp; +// D3DDISPLAYMODE d3ddm; + D3DX_VIDMODEDESC d3ddm; + HRESULT hr; + DWORD dwWidth, dwHeight; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice7_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } +/* + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + if (!bDefaultDriver) + d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software) + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; +// goto return_with_error; + return FALSE; + } +*/ + // Release objects before Reset() + _gldDestroyPrimitiveBuffer(&gld->PB3d); + _gldDestroyPrimitiveBuffer(&gld->PB2d); + +/* + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + // TODO: Sync to refresh + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + // Get better benchmark results? KeithH +// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED; + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult); + return FALSE; + //goto cleanup_and_return_with_error; + } +*/ + // Obtain dimensions of 'window' + if (ctx->bFullscreen) { + D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); + dwWidth = d3ddm.width; + dwHeight = d3ddm.height; + } else { + dwWidth = ctx->dwWidth; + dwHeight = ctx->dwHeight; + } + + // Resize context + hr = gld->pD3DXContext->lpVtbl->Resize(gld->pD3DXContext, dwWidth, dwHeight); + if (FAILED(hr)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "gldResizeDrawable_DX: Resize failed", hr); + return FALSE; + } + + // Clear the resized surface (DaveM) + { + D3DVIEWPORT7 vp1, vp2; + IDirect3DDevice7_GetViewport(gld->pDev, &vp1); + IDirect3DDevice7_GetViewport(gld->pDev, &vp2); + vp2.dwX = 0; + vp2.dwY = 0; + vp2.dwWidth = dwWidth; + vp2.dwHeight = dwHeight; + IDirect3DDevice7_SetViewport(gld->pDev, &vp2); + hr = gld->pD3DXContext->lpVtbl->Clear(gld->pD3DXContext, D3DCLEAR_TARGET); + if (FAILED(hr)) + ddlogError(DDLOG_WARN, "gldResizeDrawable_DX: Clear failed", hr); + IDirect3DDevice7_SetViewport(gld->pDev, &vp1); + } + + // + // Recreate objects + // + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d); + + // Signal a complete state update + ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL); + + // Begin a new scene + IDirect3DDevice7_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyDrawable_DX( + DGL_ctx *ctx) +{ + GLD_driver_dx7 *lpCtx = NULL; + + // Error if context is NULL. + if (!ctx) + return FALSE; + + // Error if the drawable does not exist. + if (!ctx->glPriv) + return FALSE; + + lpCtx = ctx->glPriv; + +#ifdef _DEBUG + // Dump out stats + ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X", + lpCtx->PipelineUsage.qwMesa.HighPart, + lpCtx->PipelineUsage.qwMesa.LowPart, + lpCtx->PipelineUsage.qwD3DFVF.HighPart, + lpCtx->PipelineUsage.qwD3DFVF.LowPart); +#endif + + // Destroy Primtive Buffers + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + // Release DX interfaces (in reverse order) + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + //SAFE_RELEASE(lpCtx->pD3DXContext); + lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext); + + // Free the private drawable data + free(ctx->glPriv); + ctx->glPriv = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldCreatePrivateGlobals_DX(void) +{ +/* + ZeroMemory(&dx7Globals, sizeof(dx7Globals)); + + // Load d3d8.dll + dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL"); + if (dx8Globals.hD3D8DLL == NULL) + return FALSE; + + // Now try and obtain Direct3DCreate8 + dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8"); + if (dx8Globals.fnDirect3DCreate8 == NULL) { + FreeLibrary(dx8Globals.hD3D8DLL); + return FALSE; + } +*/ + + // Initialise D3DX + return FAILED(D3DXInitialize()) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyPrivateGlobals_DX(void) +{ +/* + if (dx7Globals.bDirect3DDevice) { + SAFE_RELEASE(dx7Globals.pDev); + dx7Globals.bDirect3DDevice = FALSE; + } + if (dx7Globals.bDirect3D) { + SAFE_RELEASE(dx7Globals.pD3D); + dx7Globals.bDirect3D = FALSE; + } + + FreeLibrary(dx8Globals.hD3D8DLL); + dx8Globals.hD3D8DLL = NULL; + dx8Globals.fnDirect3DCreate8 = NULL; +*/ + return FAILED(D3DXUninitialize()) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDisplayFormat( + D3DX_SURFACEFORMAT fmt, + BYTE *cColorBits, + BYTE *cRedBits, + BYTE *cGreenBits, + BYTE *cBlueBits, + BYTE *cAlphaBits) +{ + switch (fmt) { +/* case D3DX_SF_X1R5G5B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 5; + *cBlueBits = 5; + *cAlphaBits = 0; + return;*/ + case D3DX_SF_R5G5B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 5; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DX_SF_R5G6B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 6; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DX_SF_X8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; + return; + case D3DX_SF_A8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 8; + return; + } + + // Should not get here! + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDepthStencilFormat( + D3DX_SURFACEFORMAT fmt, + BYTE *cDepthBits, + BYTE *cStencilBits) +{ + // NOTE: GL expects either 32 or 16 as depth bits. + switch (fmt) { + case D3DX_SF_Z16S0: + *cDepthBits = 16; + *cStencilBits = 0; + return; + case D3DX_SF_Z32S0: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DX_SF_Z15S1: + *cDepthBits = 15; + *cStencilBits = 1; + return; + case D3DX_SF_Z24S8: + *cDepthBits = 24; + *cStencilBits = 8; + return; + case D3DX_SF_S1Z15: + *cDepthBits = 15; + *cStencilBits = 1; + return; + case D3DX_SF_S8Z24: + *cDepthBits = 24; + *cStencilBits = 8; + return; + } +} + +//--------------------------------------------------------------------------- +/* +BOOL GLD_CheckDepthStencilMatch( + DWORD dwDeviceIndex, + D3DX_SURFACEFORMAT sfWant) +{ + // Emulate function built in to DX9 + D3DX_SURFACEFORMAT sfFound; + int i; + int nFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER); + if (nFormats) { + for (i=0; i<nFormats; i++) { + D3DXGetSurfaceFormat(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER, i, &sfFound); } + if (sfFound == sfWant) + return TRUE; + } + + return FALSE; +} +*/ +//--------------------------------------------------------------------------- + +D3DX_SURFACEFORMAT _gldFindCompatibleDepthStencilFormat( + DWORD dwDeviceIndex) +{ + // Jump through some hoops... + + ID3DXContext *pD3DXContext = NULL; + IDirectDrawSurface7 *pZBuffer = NULL; + DDPIXELFORMAT ddpf; + HWND hWnd; + + // Get an HWND - use Desktop's + hWnd = GetDesktopWindow(); + + // Create a fully specified default context. + D3DXCreateContextEx(dwDeviceIndex, 0, hWnd, (HWND)D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + &pD3DXContext); + + // Obtain depth buffer that was created in context + pZBuffer = pD3DXContext->lpVtbl->GetZBuffer(pD3DXContext); + + // Get pixel format of depth buffer + ddpf.dwSize = sizeof(ddpf); + pZBuffer->lpVtbl->GetPixelFormat(pZBuffer, &ddpf); + // Done with surface - release it + pZBuffer->lpVtbl->Release(pZBuffer); + + // Done with D3DX context + pD3DXContext->lpVtbl->Release(pD3DXContext); + + // Convert and return + return D3DXMakeSurfaceFormat(&ddpf); +} + +//--------------------------------------------------------------------------- + +BOOL gldBuildPixelformatList_DX(void) +{ + D3DX_DEVICEDESC d3dxdd; + D3DX_VIDMODEDESC d3ddm; + D3DX_SURFACEFORMAT fmt[64]; // 64 should be enough... + DWORD dwDeviceIndex; + DWORD surfClassFlags; +// IDirect3D7 *pD3D = NULL; + HRESULT hr; + int nSupportedFormats = 0; // Total formats + int nDepthOnlyFormats = 0; + int nDepthStencilFormats = 0; + int i; + DGL_pixelFormat *pPF; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; +// char buf[128]; +// char cat[8]; + + // Direct3D (SW or HW) + // These are arranged so that 'best' pixelformat + // is higher in the list (for ChoosePixelFormat). +/* const D3DFORMAT DepthStencil[4] = { + D3DX_SF_Z16S0, //D3DX_SF_D16, + D3DX_SF_Z15S1, //D3DX_SF_D15S1, + D3DX_SF_Z32S0, //D3DX_SF_D32, + D3DX_SF_Z24S8, //D3DX_SF_D24S8, + //D3DX_SF_D24X8, + //D3DX_SF_D24X4S4, + };*/ + + // Dump DX version + ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 7.0\n"); + + // Release any existing pixelformat list + if (glb.lpPF) { + free(glb.lpPF); + } + + glb.nPixelFormatCount = 0; + glb.lpPF = NULL; + + // + // Pixelformats for Direct3D (SW or HW) rendering + // + + dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT; + + // Dump description + D3DXGetDeviceDescription(dwDeviceIndex, &d3dxdd); + ddlogPrintf(GLDLOG_SYSTEM, "Device: %s", d3dxdd.driverDesc); + + // Get display mode + D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); + +#if 0 + // Phooey - this don't work... +/* + // Since D3DXGetMaxSurfaceFormats() can lie to us, we'll need a workaround. + // Explicitly test for matching depth/stencil to display bpp. + if (d3ddm.bpp <= 16) { + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0)) + fmt[nSupportedFormats++] = D3DX_SF_Z16S0; + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z15S1)) + fmt[nSupportedFormats++] = D3DX_SF_Z15S1; + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S1Z15)) + fmt[nSupportedFormats++] = D3DX_SF_S1Z15; + // Didn't find anything? Try default + if (nSupportedFormats == 0) { + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0)) + fmt[nSupportedFormats++] = D3DX_SF_Z32S0; + } + } else { + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0)) + fmt[nSupportedFormats++] = D3DX_SF_Z32S0; + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z24S8)) + fmt[nSupportedFormats++] = D3DX_SF_Z24S8; + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S8Z24)) + fmt[nSupportedFormats++] = D3DX_SF_S8Z24; + // Didn't find anything? Try default + if (nSupportedFormats == 0) { + if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0)) + fmt[nSupportedFormats++] = D3DX_SF_Z16S0; + } + } +*/ + // Go the Whole Hog... + fmt[nSupportedFormats++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex); +#else + // + // Depth buffer formats WITHOUT stencil + // + surfClassFlags = D3DX_SC_DEPTHBUFFER; + nDepthOnlyFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags); + // + // Depth buffer formats WITH stencil + // + surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER; + nDepthStencilFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags); + + // Work out how many formats we have in total + if ((nDepthOnlyFormats + nDepthStencilFormats) == 0) + return FALSE; // Bail: no compliant pixelformats + + // Get depth buffer formats WITHOUT stencil + surfClassFlags = D3DX_SC_DEPTHBUFFER; + for (i=0; i<nDepthOnlyFormats; i++) { + D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]); + } + // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER + /* + // Get depth buffer formats WITH stencil + surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER; + for (i=0; i<nDepthStencilFormats; i++) { + D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]); + } + */ +#endif + + // Total count of pixelformats is: + // (nSupportedFormats+1)*2 + glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat)); + glb.nPixelFormatCount = (nSupportedFormats)*2; + if (glb.lpPF == NULL) { + glb.nPixelFormatCount = 0; + return FALSE; + } + + // Get a copy of pointer that we can alter + pPF = glb.lpPF; + + // Cache colour bits from display format +// _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + // Get display mode + D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); + cColorBits = d3ddm.bpp; + cAlphaBits = 0; + switch (d3ddm.bpp) { + case 15: + cRedBits = 5; cGreenBits = 5; cBlueBits = 5; + break; + case 16: + cRedBits = 5; cGreenBits = 6; cBlueBits = 5; + break; + case 24: + case 32: + cRedBits = 8; cGreenBits = 8; cBlueBits = 8; + break; + default: + cRedBits = 5; cGreenBits = 5; cBlueBits = 5; + } + + // + // Add single-buffer formats + // + +/* // Single-buffer, no depth-stencil buffer + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DX_SF_UNKNOWN; + pPF++;*/ + + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // + // Add double-buffer formats + // + +/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DX_SF_UNKNOWN; + pPF++;*/ + + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // Popup warning message if non RGB color mode + { + // This is a hack. KeithH + HDC hdcDesktop = GetDC(NULL); + DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL); + ReleaseDC(0, hdcDesktop); + if (dwDisplayBitDepth <= 8) { + ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth); + MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING); + } + } + + // Mark list as 'current' + glb.bPixelformatsDirty = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldInitialiseMesa_DX( + DGL_ctx *lpCtx) +{ + GLD_driver_dx7 *gld = NULL; + int MaxTextureSize, TextureLevels; + BOOL bSoftwareTnL; + + if (lpCtx == NULL) + return FALSE; + + gld = lpCtx->glPriv; + if (gld == NULL) + return FALSE; + + if (glb.bMultitexture) { + lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps.wMaxSimultaneousTextures; + // Only support MAX_TEXTURE_UNITS texture units. + // ** If this is altered then the FVF formats must be reviewed **. + if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX7) + lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX7; + } else { + // Multitexture override + lpCtx->glCtx->Const.MaxTextureUnits = 1; + } + + // max texture size +// MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth); + MaxTextureSize = min(gld->d3dCaps.dwMaxTextureHeight, gld->d3dCaps.dwMaxTextureWidth); + if (MaxTextureSize == 0) + MaxTextureSize = 256; // Sanity check + + // + // HACK!! + if (MaxTextureSize > 1024) + MaxTextureSize = 1024; // HACK - CLAMP TO 1024 + // HACK!! + // + + // TODO: Check this again for Mesa 5 + // Got to set MAX_TEXTURE_SIZE as max levels. + // Who thought this stupid idea up? ;) + TextureLevels = 0; + // Calculate power-of-two. + while (MaxTextureSize) { + TextureLevels++; + MaxTextureSize >>= 1; + } + lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8; + + // Defaults + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_LIGHTING, FALSE); + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_DITHERENABLE, TRUE); + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); + + // Set texture coord set to be used with each stage + IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_TEXCOORDINDEX, 0); + IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_TEXCOORDINDEX, 1); + + // Set up Depth buffer + IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE, + (lpCtx->lpPF->dwDriverData!=D3DX_SF_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE); + + // Set the view matrix + { + D3DXMATRIX vm; +#if 1 + D3DXMatrixIdentity(&vm); +#else + D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f); + D3DXVECTOR3 At(0.0f, 0.0f, -1.0f); + D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); + D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up); + vm._31 = -vm._31; + vm._32 = -vm._32; + vm._33 = -vm._33; + vm._34 = -vm._34; +#endif + IDirect3DDevice7_SetTransform(gld->pDev, D3DTRANSFORMSTATE_VIEW, &vm); + } + +// DX7 does not support D3DRS_SOFTWAREVERTEXPROCESSING +/* + if (gld->bHasHWTnL) { + if (glb.dwTnL == GLDS_TNL_DEFAULT) + bSoftwareTnL = FALSE; // HW TnL + else { + bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE; + } + } else { + // No HW TnL, so no choice possible + bSoftwareTnL = TRUE; + } + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL); +*/ + +// Dump this in a Release build as well, now. +//#ifdef _DEBUG + ddlogPrintf(DDLOG_INFO, "HW TnL: %s", +// gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable"); + gld->bHasHWTnL ? "Enabled" : "Unavailable"); +//#endif + + // Set up interfaces to Mesa + gldEnableExtensions_DX7(lpCtx->glCtx); + gldInstallPipeline_DX7(lpCtx->glCtx); + gldSetupDriverPointers_DX7(lpCtx->glCtx); + + // Signal a complete state update + lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL); + + // Start a scene + IDirect3DDevice7_BeginScene(gld->pDev); + lpCtx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldSwapBuffers_DX( + DGL_ctx *ctx, + HDC hDC, + HWND hWnd) +{ + HRESULT hr; + GLD_driver_dx7 *gld = NULL; + DWORD dwFlags; + + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + + // End the scene if one is started + if (ctx->bSceneStarted) { + IDirect3DDevice7_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + // Needed by D3DX for MDI multi-window apps (DaveM) + if (lpDDClipper) + IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hWnd); + + // Swap the buffers. hWnd may override the hWnd used for CreateDevice() +// hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL); + + // Set refresh sync flag + dwFlags = glb.bWaitForRetrace ? 0 : D3DX_UPDATE_NOVSYNC; + // Render and show frame + hr = gld->pD3DXContext->lpVtbl->UpdateFrame(gld->pD3DXContext, dwFlags); + if (FAILED(hr)) + ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: UpdateFrame", hr); + + if (hr == DDERR_SURFACELOST) { + hr = gld->pD3DXContext->lpVtbl->RestoreSurfaces(gld->pD3DXContext); + if (FAILED(hr)) + ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: RestoreSurfaces", hr); + } + +exit_swap: + // Begin a new scene + IDirect3DDevice7_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return (FAILED(hr)) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldGetDisplayMode_DX( + DGL_ctx *ctx, + GLD_displayMode *glddm) +{ +// D3DDISPLAYMODE d3ddm; + D3DX_VIDMODEDESC d3ddm; + HRESULT hr; + GLD_driver_dx7 *lpCtx = NULL; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; + + if ((glddm == NULL) || (ctx == NULL)) + return FALSE; + + lpCtx = ctx->glPriv; + if (lpCtx == NULL) + return FALSE; + + if (lpCtx->pD3D == NULL) + return FALSE; + +// hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + hr = D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm); + if (FAILED(hr)) + return FALSE; + + // Get info from the display format +// _BitsFromDisplayFormat(d3ddm.Format, +// &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + glddm->Width = d3ddm.width; + glddm->Height = d3ddm.height; + glddm->BPP = d3ddm.bpp; + glddm->Refresh = d3ddm.refreshRate; + + return TRUE; +} + +//--------------------------------------------------------------------------- + diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c new file mode 100644 index 00000000000..0a6d9f8555c --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c @@ -0,0 +1,1176 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Driver interface code to Mesa +* +****************************************************************************/ + +//#include <windows.h> +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +extern BOOL dglSwapBuffers(HDC hDC); + +// HACK: Hack the _33 member of the OpenGL perspective projection matrix +const float _fPersp_33 = 1.6f; + +//--------------------------------------------------------------------------- +// Internal functions +//--------------------------------------------------------------------------- + +void _gld_mesa_warning( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal warning mechanism + gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str); +} + +//--------------------------------------------------------------------------- + +void _gld_mesa_fatal( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal fatal-message mechanism + gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str); + + // Mesa calls abort(0) here. + ddlogClose(); + exit(0); +} + +//--------------------------------------------------------------------------- + +D3DSTENCILOP _gldConvertStencilOp( + GLenum StencilOp) +{ + // Used by Stencil: pass, fail and zfail + + switch (StencilOp) { + case GL_KEEP: + return D3DSTENCILOP_KEEP; + case GL_ZERO: + return D3DSTENCILOP_ZERO; + case GL_REPLACE: + return D3DSTENCILOP_REPLACE; + case GL_INCR: + return D3DSTENCILOP_INCRSAT; + case GL_DECR: + return D3DSTENCILOP_DECRSAT; + case GL_INVERT: + return D3DSTENCILOP_INVERT; + case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_INCR; + case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_DECR; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n"); +#endif + + return D3DSTENCILOP_KEEP; +} + +//--------------------------------------------------------------------------- + +D3DCMPFUNC _gldConvertCompareFunc( + GLenum CmpFunc) +{ + // Used for Alpha func, depth func and stencil func. + + switch (CmpFunc) { + case GL_NEVER: + return D3DCMP_NEVER; + case GL_LESS: + return D3DCMP_LESS; + case GL_EQUAL: + return D3DCMP_EQUAL; + case GL_LEQUAL: + return D3DCMP_LESSEQUAL; + case GL_GREATER: + return D3DCMP_GREATER; + case GL_NOTEQUAL: + return D3DCMP_NOTEQUAL; + case GL_GEQUAL: + return D3DCMP_GREATEREQUAL; + case GL_ALWAYS: + return D3DCMP_ALWAYS; + }; + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n"); +#endif + + return D3DCMP_ALWAYS; +} + +//--------------------------------------------------------------------------- + +D3DBLEND _gldConvertBlendFunc( + GLenum blend, + GLenum DefaultBlend) +{ + switch (blend) { + case GL_ZERO: + return D3DBLEND_ZERO; + case GL_ONE: + return D3DBLEND_ONE; + case GL_DST_COLOR: + return D3DBLEND_DESTCOLOR; + case GL_SRC_COLOR: + return D3DBLEND_SRCCOLOR; + case GL_ONE_MINUS_DST_COLOR: + return D3DBLEND_INVDESTCOLOR; + case GL_ONE_MINUS_SRC_COLOR: + return D3DBLEND_INVSRCCOLOR; + case GL_SRC_ALPHA: + return D3DBLEND_SRCALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + return D3DBLEND_INVSRCALPHA; + case GL_DST_ALPHA: + return D3DBLEND_DESTALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return D3DBLEND_INVDESTALPHA; + case GL_SRC_ALPHA_SATURATE: + return D3DBLEND_SRCALPHASAT; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n"); +#endif + + return DefaultBlend; +} + +//--------------------------------------------------------------------------- +// Misc. functions +//--------------------------------------------------------------------------- + +void gld_Noop_DX8( + GLcontext *ctx) +{ +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n"); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_Error_DX8( + GLcontext *ctx) +{ +#ifdef _DEBUG + // Quite useless. +// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n"); +#endif +} + +//--------------------------------------------------------------------------- +// Required Mesa functions +//--------------------------------------------------------------------------- + +static GLboolean gld_set_draw_buffer_DX8( + GLcontext *ctx, + GLenum mode) +{ + (void) ctx; + if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +//--------------------------------------------------------------------------- + +static void gld_set_read_buffer_DX8( + GLcontext *ctx, + GLframebuffer *buffer, + GLenum mode) +{ + /* separate read buffer not supported */ +/* + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(mode == GL_FRONT_LEFT); +*/ +} + +//--------------------------------------------------------------------------- + +void gld_Clear_DX8( + GLcontext *ctx, + GLbitfield mask, + GLboolean all, + GLint x, + GLint y, + GLint width, + GLint height) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DCOLOR Color = 0; + float Z = 0.0f; + DWORD Stencil = 0; + D3DRECT d3dClearRect; + + // TODO: Colourmask + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if (!gld->pDev) + return; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + GLubyte col[4]; + CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]); + dwFlags |= D3DCLEAR_TARGET; + Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]); +// ctx->Color.ClearColor[1], +// ctx->Color.ClearColor[2], +// ctx->Color.ClearColor[3]); + } + + if (mask & DD_DEPTH_BIT) { + // D3D8 will fail the Clear call if we try and clear a + // depth buffer and we haven't created one. + // Also, some apps try and clear a depth buffer, + // when a depth buffer hasn't been requested by the app. + if (ctx->Visual.depthBits == 0) { + mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask + } else { + dwFlags |= D3DCLEAR_ZBUFFER; + Z = ctx->Depth.Clear; + } + } + + if (mask & DD_STENCIL_BIT) { + if (ctx->Visual.stencilBits == 0) { + // No stencil bits in depth buffer + mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask + } else { + dwFlags |= D3DCLEAR_STENCIL; + Stencil = ctx->Stencil.Clear; + } + } + + // Some apps do really weird things with the rect, such as Quake3. + if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) { + all = GL_TRUE; + } + + if (!all) { + // Calculate clear subrect + d3dClearRect.x1 = x; + d3dClearRect.y1 = gldCtx->dwHeight - (y + height); + d3dClearRect.x2 = x + width; + d3dClearRect.y2 = d3dClearRect.y1 + height; + } + + // dwFlags will be zero if there's nothing to clear + if (dwFlags) { + _GLD_DX8_DEV(Clear( + gld->pDev, + all ? 0 : 1, + all ? NULL : &d3dClearRect, + dwFlags, + Color, Z, Stencil)); + } + + if (mask & DD_ACCUM_BIT) { + // Clear accumulation buffer + } +} + +//--------------------------------------------------------------------------- + +// Mesa 5: Parameter change +static void gld_buffer_size_DX8( +// GLcontext *ctx, + GLframebuffer *fb, + GLuint *width, + GLuint *height) +{ +// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + + *width = fb->Width; // gldCtx->dwWidth; + *height = fb->Height; // gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +static void gld_Finish_DX8( + GLcontext *ctx) +{ +} + +//--------------------------------------------------------------------------- + +static void gld_Flush_DX8( + GLcontext *ctx) +{ + GLD_context *gld = GLD_GET_CONTEXT(ctx); + + // TODO: Detect apps that glFlush() then SwapBuffers() ? + + if (gld->EmulateSingle) { + // Emulating a single-buffered context. + // [Direct3D doesn't allow rendering to front buffer] + dglSwapBuffers(gld->hDC); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_STENCIL( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + // Two-sided stencil. New for Mesa 5 + const GLuint uiFace = 0UL; + + struct gl_stencil_attrib *pStencil = &ctx->Stencil; + + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE)); + if (pStencil->Enabled) { + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace]))); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace])); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace])); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace])); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace]))); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace]))); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace]))); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_COLOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DBLEND src; + D3DBLEND dest; + + // Alpha func + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc))); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled)); + + // Blend func + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled)); + src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE); + dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest)); + + // Color mask + if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED; + if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN; + if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE; + if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA; + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_DEPTH( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func))); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_POLYGON( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DFILLMODE d3dFillMode = D3DFILL_SOLID; + D3DCULL d3dCullMode = D3DCULL_NONE; + int iOffset = 0; + + // Fillmode + switch (ctx->Polygon.FrontMode) { + case GL_POINT: + d3dFillMode = D3DFILL_POINT; + break; + case GL_LINE: + d3dFillMode = D3DFILL_WIREFRAME; + break; + case GL_FILL: + d3dFillMode = D3DFILL_SOLID; + break; + } + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode)); + + if (ctx->Polygon.CullFlag) { + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CW; + else + d3dCullMode = D3DCULL_CCW; + break; + case GL_FRONT: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CCW; + else + d3dCullMode = D3DCULL_CW; + break; + case GL_FRONT_AND_BACK: + d3dCullMode = D3DCULL_NONE; + break; + default: + break; + } + } else { + d3dCullMode = D3DCULL_NONE; + } +// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode)); + + // Polygon offset + // ZBIAS ranges from 0 to 16 and can only move towards the viewer + // Mesa5: ctx->Polygon._OffsetAny removed + if (ctx->Polygon.OffsetFill) { + iOffset = (int)ctx->Polygon.OffsetUnits; + if (iOffset < 0) + iOffset = -iOffset; + else + iOffset = 0; // D3D can't push away + } + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZBIAS, iOffset)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_FOG( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DCOLOR d3dFogColour; + D3DFOGMODE d3dFogMode = D3DFOG_LINEAR; + + // TODO: Fog is calculated seperately in the Mesa pipeline + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE)); + return; + + // Fog enable + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled)); + if (!ctx->Fog.Enabled) { + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); + return; // If disabled, don't bother setting any fog state + } + + // Fog colour + d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0], + ctx->Fog.Color[1], + ctx->Fog.Color[2], + ctx->Fog.Color[3]); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour)); + + // Fog density + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density)))); + + // Fog start + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start)))); + + // Fog end + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End)))); + + // Fog mode + switch (ctx->Fog.Mode) { + case GL_LINEAR: + d3dFogMode = D3DFOG_LINEAR; + break; + case GL_EXP: + d3dFogMode = D3DFOG_EXP; + break; + case GL_EXP2: + d3dFogMode = D3DFOG_EXP2; + break; + } + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_LIGHT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + DWORD dwSpecularEnable; + + // Shademode + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); + + // Separate specular colour + if (ctx->Light.Enabled) + dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE; + else + dwSpecularEnable = FALSE; + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_MODELVIEW( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ModelView.m; + // Mesa5: Model-view is now a stack + GLfloat *pM = ctx->ModelviewMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10]; + m._34 = pM[11]; + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14]; + m._44 = pM[15]; + + gld->matModelView = m; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_PROJECTION( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ProjectionMatrix.m; + // Mesa 5: Now a stack + GLfloat *pM = ctx->ProjectionMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10] / _fPersp_33; // / 1.6f; + m._34 = pM[11]; + + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14] / 2.0f; + m._44 = pM[15]; + + gld->matProjection = m; +} + +//--------------------------------------------------------------------------- +/* +void gldFrustumHook_DX8( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Frustum(left, right, bottom, top, nearval, farval); + + _fPersp_33 = farval / (nearval - farval); + +// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval); +} + +//--------------------------------------------------------------------------- + +void gldOrthoHook_DX8( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Ortho(left, right, bottom, top, nearval, farval); + + _fPersp_33 = 1.6f; + +// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval); +} +*/ +//--------------------------------------------------------------------------- + +void gld_NEW_VIEWPORT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DVIEWPORT8 d3dvp; +// GLint x, y; +// GLsizei w, h; + + // Set depth range + _GLD_DX8_DEV(GetViewport(gld->pDev, &d3dvp)); + // D3D can't do Quake1/Quake2 z-trick + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } +/* x = ctx->Viewport.X; + y = ctx->Viewport.Y; + w = ctx->Viewport.Width; + h = ctx->Viewport.Height; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h;*/ + _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp)); + +// gld->fFlipWindowY = (float)gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +__inline BOOL _gldAnyEvalEnabled( + GLcontext *ctx) +{ + struct gl_eval_attrib *eval = &ctx->Eval; + + if ((eval->AutoNormal) || + (eval->Map1Color4) || + (eval->Map1Index) || + (eval->Map1Normal) || + (eval->Map1TextureCoord1) || + (eval->Map1TextureCoord2) || + (eval->Map1TextureCoord3) || + (eval->Map1TextureCoord4) || + (eval->Map1Vertex3) || + (eval->Map1Vertex4) || + (eval->Map2Color4) || + (eval->Map2Index) || + (eval->Map2Normal) || + (eval->Map2TextureCoord1) || + (eval->Map2TextureCoord2) || + (eval->Map2TextureCoord3) || + (eval->Map2TextureCoord4) || + (eval->Map2Vertex3) || + (eval->Map2Vertex4) + ) + return TRUE; + + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL _gldChooseInternalPipeline( + GLcontext *ctx, + GLD_driver_dx8 *gld) +{ +// return TRUE; // DEBUGGING: ALWAYS USE MESA +// return FALSE; // DEBUGGING: ALWAYS USE D3D + + if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE)) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; // Force Mesa TnL + } + + if ((ctx->Light.Enabled) || + (1) || + (ctx->Texture._TexGenEnabled) || + (ctx->Texture._TexMatEnabled) || +// (ctx->Transform._AnyClip) || + (ctx->Scissor.Enabled) || + _gldAnyEvalEnabled(ctx) // Put this last so we can early-out + ) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; + } + + gld->PipelineUsage.qwD3DFVF.QuadPart++; + return FALSE; + +/* // Force Mesa pipeline? + if (glb.dwTnL == GLDS_TNL_MESA) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Test for functionality not exposed in the D3D pathways + if ((ctx->Texture._GenFlags)) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Now decide if vertex shader can be used. + // If two sided lighting is enabled then we must either + // use Mesa TnL or the vertex shader + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) { + // Use Vertex Shader + gld->PipelineUsage.dwD3D2SVS.QuadPart++; + return GLD_PIPELINE_D3D_VS_TWOSIDE; + } else { + // Use Mesa TnL + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + } + + // Must be D3D fixed-function pipeline + gld->PipelineUsage.dwD3DFVF.QuadPart++; + return GLD_PIPELINE_D3D_FVF; +*/ +} + +//--------------------------------------------------------------------------- + +void gld_update_state_DX8( + GLcontext *ctx, + GLuint new_state) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLD_pb_dx8 *gldPB; + + if (!gld || !gld->pDev) + return; + + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + + // SetupIndex will be used in the pipelines for choosing setup function + if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) || + (ctx->Fog.Enabled)) + { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT_EXTRAS; + else + gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS; + } else { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture + else + gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture + } + + gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld); + if (gld->bUseMesaTnL) { + gldPB = &gld->PB2d; + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE)); + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE)); + _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF)); + } else { + gldPB = &gld->PB3d; + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE)); +// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) { +// _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware)); +// _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); +// } else { + _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL)); + _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF)); +// } + } + +#define _GLD_TEST_STATE(a) \ + if (new_state & (a)) { \ + gld##a(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_TEST_STATE_DX8(a) \ + if (new_state & (a)) { \ + gld##a##_DX8(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_IGNORE_STATE(a) new_state &= ~(a); + +// if (!gld->bUseMesaTnL) { + // Not required if Mesa is doing the TnL. + // Problem: If gld->bUseMesaTnL is TRUE when these are signaled, + // then we'll miss updating the D3D TnL pipeline. + // Therefore, don't test for gld->bUseMesaTnL + _GLD_TEST_STATE(_NEW_MODELVIEW); + _GLD_TEST_STATE(_NEW_PROJECTION); +// } + + _GLD_TEST_STATE_DX8(_NEW_TEXTURE); // extern, so guard with _DX8 + _GLD_TEST_STATE(_NEW_COLOR); + _GLD_TEST_STATE(_NEW_DEPTH); + _GLD_TEST_STATE(_NEW_POLYGON); + _GLD_TEST_STATE(_NEW_STENCIL); + _GLD_TEST_STATE(_NEW_FOG); + _GLD_TEST_STATE(_NEW_LIGHT); + _GLD_TEST_STATE(_NEW_VIEWPORT); + + _GLD_IGNORE_STATE(_NEW_TRANSFORM); + + +// Stubs for future use. +/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_STATE(_NEW_ACCUM); + _GLD_TEST_STATE(_NEW_EVAL); + _GLD_TEST_STATE(_NEW_HINT); + _GLD_TEST_STATE(_NEW_LINE); + _GLD_TEST_STATE(_NEW_PIXEL); + _GLD_TEST_STATE(_NEW_POINT); + _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_STATE(_NEW_SCISSOR); + _GLD_TEST_STATE(_NEW_PACKUNPACK); + _GLD_TEST_STATE(_NEW_ARRAY); + _GLD_TEST_STATE(_NEW_RENDERMODE); + _GLD_TEST_STATE(_NEW_BUFFERS); + _GLD_TEST_STATE(_NEW_MULTISAMPLE); +*/ + +// For debugging. +#if 0 +#define _GLD_TEST_UNHANDLED_STATE(a) \ + if (new_state & (a)) { \ + gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \ + } + _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); + _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); + _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); + _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL); + _GLD_TEST_UNHANDLED_STATE(_NEW_POINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR); + _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK); + _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY); + _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE); + _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS); + _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE); +#undef _GLD_UNHANDLED_STATE +#endif + +#undef _GLD_TEST_STATE +} + +//--------------------------------------------------------------------------- +// Viewport +//--------------------------------------------------------------------------- + +void gld_Viewport_DX8( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei w, + GLsizei h) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DVIEWPORT8 d3dvp; + + if (!gld || !gld->pDev) + return; + + // This is a hack. When the app is minimized, Mesa passes + // w=1 and h=1 for viewport dimensions. Without this test + // we get a GPF in gld_wgl_resize_buffers(). + if ((w==1) && (h==1)) + return; + + // Call ResizeBuffersMESA. This function will early-out + // if no resize is needed. + //ctx->Driver.ResizeBuffersMESA(ctx); + // Mesa 5: Changed parameters + ctx->Driver.ResizeBuffers(gldCtx->glBuffer); + +#if 0 + ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h); +#endif + + // ** D3D viewport must not be outside the render target surface ** + // Sanity check the GL viewport dimensions + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h; + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } + + // TODO: DEBUGGING +// d3dvp.MinZ = 0.0f; +// d3dvp.MaxZ = 1.0f; + + _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp)); + +} + +//--------------------------------------------------------------------------- + +extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver); + +// Mesa 5: Parameter change +void gldResizeBuffers_DX8( +// GLcontext *ctx) + GLframebuffer *fb) +{ + GET_CURRENT_CONTEXT(ctx); + dglWglResizeBuffers(ctx, TRUE); +} + +//--------------------------------------------------------------------------- +#ifdef _DEBUG +// This is only for debugging. +// To use, plug into ctx->Driver.Enable pointer below. +void gld_Enable( + GLcontext *ctx, + GLenum e, + GLboolean b) +{ + char buf[1024]; + sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE"); + ddlogMessage(DDLOG_SYSTEM, buf); +} +#endif +//--------------------------------------------------------------------------- +// Driver pointer setup +//--------------------------------------------------------------------------- + +extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum); + +void gldSetupDriverPointers_DX8( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + + // Mandatory functions + ctx->Driver.GetString = _gldGetStringGeneric; + ctx->Driver.UpdateState = gld_update_state_DX8; + ctx->Driver.Clear = gld_Clear_DX8; + ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX8; + ctx->Driver.GetBufferSize = gld_buffer_size_DX8; + ctx->Driver.Finish = gld_Finish_DX8; + ctx->Driver.Flush = gld_Flush_DX8; + ctx->Driver.Error = gld_Error_DX8; + + // Hardware accumulation buffer + ctx->Driver.Accum = NULL; // TODO: gld_Accum; + + // Bitmap functions + ctx->Driver.CopyPixels = gld_CopyPixels_DX8; + ctx->Driver.DrawPixels = gld_DrawPixels_DX8; + ctx->Driver.ReadPixels = gld_ReadPixels_DX8; + ctx->Driver.Bitmap = gld_Bitmap_DX8; + + // Buffer resize + ctx->Driver.ResizeBuffers = gldResizeBuffers_DX8; + + // Texture image functions + ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX8; + ctx->Driver.TexImage1D = gld_TexImage1D_DX8; + ctx->Driver.TexImage2D = gld_TexImage2D_DX8; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX8; + ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX8; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + + ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX8; //NULL; + ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX8; //NULL; + ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX8; //NULL; + ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX8; //NULL; + ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX8; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + // Texture object functions + ctx->Driver.BindTexture = NULL; + ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!; + ctx->Driver.DeleteTexture = gld_DeleteTexture_DX8; + ctx->Driver.PrioritizeTexture = NULL; + + // Imaging functionality + ctx->Driver.CopyColorTable = NULL; + ctx->Driver.CopyColorSubTable = NULL; + ctx->Driver.CopyConvolutionFilter1D = NULL; + ctx->Driver.CopyConvolutionFilter2D = NULL; + + // State changing functions + ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc; + ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc; + ctx->Driver.ClearColor = NULL; //gld_ClearColor; + ctx->Driver.ClearDepth = NULL; //gld_ClearDepth; + ctx->Driver.ClearStencil = NULL; //gld_ClearStencil; + ctx->Driver.ColorMask = NULL; //gld_ColorMask; + ctx->Driver.CullFace = NULL; //gld_CullFace; + ctx->Driver.ClipPlane = NULL; //gld_ClipPlane; + ctx->Driver.FrontFace = NULL; //gld_FrontFace; + ctx->Driver.DepthFunc = NULL; //gld_DepthFunc; + ctx->Driver.DepthMask = NULL; //gld_DepthMask; + ctx->Driver.DepthRange = NULL; + ctx->Driver.Enable = NULL; //gld_Enable; + ctx->Driver.Fogfv = NULL; //gld_Fogfv; + ctx->Driver.Hint = NULL; //gld_Hint; + ctx->Driver.Lightfv = NULL; //gld_Lightfv; + ctx->Driver.LightModelfv = NULL; //gld_LightModelfv; + ctx->Driver.LineStipple = NULL; //gld_LineStipple; + ctx->Driver.LineWidth = NULL; //gld_LineWidth; + ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode; + ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv; + ctx->Driver.PointSize = NULL; //gld_PointSize; + ctx->Driver.PolygonMode = NULL; //gld_PolygonMode; + ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset; + ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple; + ctx->Driver.RenderMode = NULL; //gld_RenderMode; + ctx->Driver.Scissor = NULL; //gld_Scissor; + ctx->Driver.ShadeModel = NULL; //gld_ShadeModel; + ctx->Driver.StencilFunc = NULL; //gld_StencilFunc; + ctx->Driver.StencilMask = NULL; //gld_StencilMask; + ctx->Driver.StencilOp = NULL; //gld_StencilOp; + ctx->Driver.TexGen = NULL; //gld_TexGen; + ctx->Driver.TexEnv = NULL; + ctx->Driver.TexParameter = NULL; + ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix; + ctx->Driver.Viewport = gld_Viewport_DX8; + + _swsetup_Wakeup(ctx); + + tnl->Driver.RunPipeline = _tnl_run_pipeline; + tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX8; + tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; + tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; + + // Hook into glFrustum() and glOrtho() +// ctx->Exec->Frustum = gldFrustumHook_DX8; +// ctx->Exec->Ortho = gldOrthoHook_DX8; + +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h new file mode 100644 index 00000000000..7efec7cae80 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h @@ -0,0 +1,324 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 8.0 header file +* +****************************************************************************/ + +#ifndef _GLD_DX8_H +#define _GLD_DX8_H + +//--------------------------------------------------------------------------- +// Windows includes +//--------------------------------------------------------------------------- + +//#ifndef STRICT +//#define STRICT +//#endif + +//#define WIN32_LEAN_AND_MEAN +//#include <windows.h> +#include <d3d8.h> +#include <d3dx8.h> + +// MS screwed up with the DX8.1 SDK - there's no compile-time +// method of compiling for 8.0 via the 8.1 SDK unless you +// "make sure you don't use any 8.1 interfaces". +// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces. +// +// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95). +// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95). +// +#define D3D_SDK_VERSION_DX8_SUPPORT_WIN95 120 + +// Typedef for obtaining function from d3d8.dll +typedef IDirect3D8* (WINAPI *FNDIRECT3DCREATE8) (UINT); + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +#ifdef _DEBUG +#define _GLD_TEST_HRESULT(h) \ +{ \ + HRESULT _hr = (h); \ + if (FAILED(_hr)) { \ + gldLogError(GLDLOG_ERROR, #h, _hr); \ + } \ +} +#define _GLD_DX8(func) _GLD_TEST_HRESULT(IDirect3D8_##func##) +#define _GLD_DX8_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice8_##func##) +#define _GLD_DX8_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer8_##func##) +#define _GLD_DX8_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture8_##func##) +#else +#define _GLD_DX8(func) IDirect3D8_##func +#define _GLD_DX8_DEV(func) IDirect3DDevice8_##func +#define _GLD_DX8_VB(func) IDirect3DVertexBuffer8_##func +#define _GLD_DX8_TEX(func) IDirect3DTexture8_##func +#endif + +#define SAFE_RELEASE(p) \ +{ \ + if (p) { \ + (p)->lpVtbl->Release(p); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_VB8(p) \ +{ \ + if (p) { \ + IDirect3DVertexBuffer8_Release((p)); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_SURFACE8(p) \ +{ \ + if (p) { \ + IDirect3DSurface8_Release((p)); \ + (p) = NULL; \ + } \ +} + +// Setup index. +enum { + GLD_SI_FLAT = 0, + GLD_SI_SMOOTH = 1, + GLD_SI_FLAT_EXTRAS = 2, + GLD_SI_SMOOTH_EXTRAS = 3, +}; +/* +// Internal pipeline +typedef enum { + GLD_PIPELINE_MESA = 0, // Mesa pipeline + GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline + GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader +} GLD_tnl_pipeline; +*/ +//--------------------------------------------------------------------------- +// Vertex definitions for Fixed-Function pipeline +//--------------------------------------------------------------------------- + +// +// NOTE: If the number of texture units is altered then most of +// the texture code will need to be revised. +// + +#define GLD_MAX_TEXTURE_UNITS_DX8 2 + +// +// 2D vertex transformed by Mesa +// +#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \ + D3DFVF_DIFFUSE | \ + D3DFVF_SPECULAR | \ + D3DFVF_TEX2) +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT sz; // Screen Z (depth) + FLOAT rhw; // Reciprocal homogenous W + DWORD diffuse; // Diffuse colour + DWORD specular; // For separate-specular support + FLOAT t0_u, t0_v; // 1st set of texture coords + FLOAT t1_u, t1_v; // 2nd set of texture coords +} GLD_2D_VERTEX; + + +// +// 3D vertex transformed by Direct3D +// +#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \ + D3DFVF_DIFFUSE | \ + D3DFVF_TEX2) + +typedef struct { + D3DXVECTOR3 Position; // XYZ Vector in object space + D3DCOLOR Diffuse; // Diffuse colour + D3DXVECTOR2 TexUnit0; // Texture unit 0 + D3DXVECTOR2 TexUnit1; // Texture unit 1 +} GLD_3D_VERTEX; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// DX8 Vertex Shader +typedef struct { + DWORD hShader; // If NULL, shader is invalid and cannot be used + BOOL bHardware; // If TRUE then shader was created for hardware, + // otherwise shader was created for software. +} GLD_vertexShader; +*/ +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- + +// This keeps a count of how many times we choose each individual internal +// pathway. Useful for seeing if a certain pathway was ever used by an app, and +// how much each pathway is biased. +// Zero the members at context creation and dump stats at context deletion. +typedef struct { + // Note: DWORD is probably too small + ULARGE_INTEGER qwMesa; // Mesa TnL pipeline + ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline +// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline +} GLD_pipeline_usage; + +// GLDirect Primitive Buffer (points, lines, triangles and quads) +typedef struct { + // Data for IDirect3DDevice8::CreateVertexBuffer() + DWORD dwStride; // Stride of vertex + DWORD dwUsage; // Usage flags + DWORD dwFVF; // Direct3D Flexible Vertex Format + DWORD dwPool; // Pool flags + + IDirect3DVertexBuffer8 *pVB; // Holds points, lines, tris and quads. + + // Point list is assumed to be at start of buffer + DWORD iFirstLine; // Index of start of line list + DWORD iFirstTriangle; // Index of start of triangle list + + BYTE *pPoints; // Pointer to next free point + BYTE *pLines; // Pointer to next free line + BYTE *pTriangles; // Pointer to next free triangle + + DWORD nPoints; // Number of points ready to render + DWORD nLines; // Number of lines ready to render + DWORD nTriangles; // Number of triangles ready to render +} GLD_pb_dx8; + +// GLDirect DX8 driver data +typedef struct { + // GLDirect vars + BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered) + BOOL bDepthStencil; // Depth buffer needed (stencil optional) + D3DFORMAT RenderFormat; // Format of back/front buffer + D3DFORMAT DepthFormat; // Format of depth/stencil +// float fFlipWindowY; // Value for flipping viewport Y coord + + // Direct3D vars + D3DCAPS8 d3dCaps8; + BOOL bHasHWTnL; // Device has Hardware Transform/Light? + IDirect3D8 *pD3D; // Base Direct3D8 interface + IDirect3DDevice8 *pDev; // Direct3D8 Device interface + GLD_pb_dx8 PB2d; // Vertices transformed by Mesa + GLD_pb_dx8 PB3d; // Vertices transformed by Direct3D + D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type + D3DXMATRIX matProjection; // Projection matrix for D3D TnL + D3DXMATRIX matModelView; // Model/View matrix for D3D TnL + int iSetupFunc; // Which setup functions to use + BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL + + // Direct3D vars for two-sided lighting +// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting +// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders + + +// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline + GLD_pipeline_usage PipelineUsage; +} GLD_driver_dx8; + +#define GLD_GET_DX8_DRIVER(c) (GLD_driver_dx8*)(c)->glPriv + +//--------------------------------------------------------------------------- +// Function prototypes +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX8(LPCSTR a); +void gldEnableExtensions_DX8(GLcontext *ctx); +void gldInstallPipeline_DX8(GLcontext *ctx); +void gldSetupDriverPointers_DX8(GLcontext *ctx); +//void gldResizeBuffers_DX8(GLcontext *ctx); +void gldResizeBuffers_DX8(GLframebuffer *fb); + + +// Texture functions + +void gldCopyTexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void gldCopyTexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void gldCopyTexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ); +void gldCopyTexSubImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); +void gldCopyTexSubImage3D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + +void gld_NEW_TEXTURE_DX8(GLcontext *ctx); +void gld_DrawPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels); +void gld_ReadPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest); +void gld_CopyPixels_DX8(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type); +void gld_Bitmap_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap); +const struct gl_texture_format* gld_ChooseTextureFormat_DX8(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType); +void gld_TexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage); +void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage); +void gld_DeleteTexture_DX8(GLcontext *ctx, struct gl_texture_object *tObj); +void gld_ResetLineStipple_DX8(GLcontext *ctx); + +// 2D primitive functions + +void gld_Points2D_DX8(GLcontext *ctx, GLuint first, GLuint last); + +void gld_Line2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1); + +void gld_Triangle2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); + +void gld_Quad2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// 3D primitive functions + +void gld_Points3D_DX8(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Line3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// Primitive functions for Two-sided-lighting Vertex Shader + +void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +#endif diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h new file mode 100644 index 00000000000..f8e92b936e8 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h @@ -0,0 +1,77 @@ +/*==========================================================================; + * + * + * File: dxerr8.h + * Content: DirectX Error Library Include File + * + ****************************************************************************/ + +#ifndef _GLD_DXERR8_H_ +#define _GLD_DXERR8_H_ + + +#include <d3d8.h> + +// +// DXGetErrorString8 +// +// Desc: Converts an DirectX HRESULT to a string +// +// Args: HRESULT hr Can be any error code from +// DPLAY D3D8 D3DX8 DMUSIC DSOUND +// +// Return: Converted string +// +const char* __stdcall DXGetErrorString8A(HRESULT hr); +const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr); + +#ifdef UNICODE + #define DXGetErrorString8 DXGetErrorString8W +#else + #define DXGetErrorString8 DXGetErrorString8A +#endif + + +// +// DXTrace +// +// Desc: Outputs a formatted error message to the debug stream +// +// Args: CHAR* strFile The current file, typically passed in using the +// __FILE__ macro. +// DWORD dwLine The current line number, typically passed in using the +// __LINE__ macro. +// HRESULT hr An HRESULT that will be traced to the debug stream. +// CHAR* strMsg A string that will be traced to the debug stream (may be NULL) +// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info. +// +// Return: The hr that was passed in. +// +//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE ); +//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE ); +HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox); +HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox); + +#ifdef UNICODE + #define DXTrace DXTraceW +#else + #define DXTrace DXTraceA +#endif + + +// +// Helper macros +// +#if defined(DEBUG) | defined(_DEBUG) + #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE ) + #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE ) + #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE ) +#else + #define DXTRACE_MSG(str) (0L) + #define DXTRACE_ERR(str,hr) (hr) + #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr) +#endif + + +#endif + diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c new file mode 100644 index 00000000000..108f12a9d16 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c @@ -0,0 +1,344 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GL extensions +* +****************************************************************************/ + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "../gld_settings.h" + +#include <windows.h> +#define GL_GLEXT_PROTOTYPES +#include <GL/gl.h> +#include <GL/glext.h> + +//#include "ddlog.h" +//#include "gld_dx8.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "dglcontext.h" +#include "extensions.h" + +// For some reason this is not defined in an above header... +extern void _mesa_enable_imaging_extensions(GLcontext *ctx); + +//--------------------------------------------------------------------------- +// Hack for the SGIS_multitexture extension that was removed from Mesa +// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel + + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // To enable, uncomment: + // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + +//--------------------------------------------------------------------------- + +enum { + /* Quake2 GL_SGIS_multitexture */ + GL_SELECTED_TEXTURE_SGIS = 0x835B, + GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C, + GL_MAX_TEXTURES_SGIS = 0x835D, + GL_TEXTURE0_SGIS = 0x835E, + GL_TEXTURE1_SGIS = 0x835F, + GL_TEXTURE2_SGIS = 0x8360, + GL_TEXTURE3_SGIS = 0x8361, + GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363, +}; + +//--------------------------------------------------------------------------- + +void APIENTRY gldSelectTextureSGIS( + GLenum target) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glActiveTextureARB(ARB_target); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fSGIS( + GLenum target, + GLfloat s, + GLfloat t) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fARB(ARB_target, s, t); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fvSGIS( + GLenum target, + const GLfloat *v) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fvARB(ARB_target, v); +} + +//--------------------------------------------------------------------------- +// Extensions +//--------------------------------------------------------------------------- + +typedef struct { + PROC proc; + char *name; +} GLD_extension; + +GLD_extension GLD_extList[] = { +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }, + { NULL, "\0" } +}; + +GLD_extension GLD_multitexList[] = { +/* + { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" }, + { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" }, + { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" }, + { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" }, + { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" }, + { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" }, + { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" }, + { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" }, + { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" }, + { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" }, + { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" }, + { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" }, + { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" }, + { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" }, + { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" }, + { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" }, + { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" }, + { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" }, + { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" }, + { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" }, + { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" }, + { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" }, + { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" }, + { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" }, + { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" }, + { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" }, + { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" }, + { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" }, + { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" }, + { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" }, + { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" }, + { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" }, +*/ + { (PROC)glActiveTextureARB, "glActiveTextureARB" }, + { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" }, + { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" }, + { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" }, + { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" }, + { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" }, + { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" }, + { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" }, + { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" }, + { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" }, + { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" }, + { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" }, + { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" }, + { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" }, + { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" }, + { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" }, + { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" }, + { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" }, + { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" }, + { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" }, + { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" }, + { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" }, + { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" }, + { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" }, + { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" }, + { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" }, + { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" }, + { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" }, + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" }, + { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" }, + { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" }, + { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" }, + { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" }, + { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" }, + + // Descent3 doesn't use correct string, hence this hack + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" }, + + // Quake2 SGIS multitexture + { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + + { NULL, "\0" } +}; + +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX( + LPCSTR a) +{ + int i; + PROC proc = NULL; + + for (i=0; GLD_extList[i].proc; i++) { + if (!strcmp(a, GLD_extList[i].name)) { + proc = GLD_extList[i].proc; + break; + } + } + + if (glb.bMultitexture) { + for (i=0; GLD_multitexList[i].proc; i++) { + if (!strcmp(a, GLD_multitexList[i].name)) { + proc = GLD_multitexList[i].proc; + break; + } + } + } + + gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed"); + + return proc; +} + +//--------------------------------------------------------------------------- + +void gldEnableExtensions_DX8( + GLcontext *ctx) +{ + GLuint i; + + // Mesa enables some extensions by default. + // This table decides which ones we want to switch off again. + + // NOTE: GL_EXT_compiled_vertex_array appears broken. + + const char *gld_disable_extensions[] = { +// "GL_ARB_transpose_matrix", +// "GL_EXT_compiled_vertex_array", +// "GL_EXT_polygon_offset", +// "GL_EXT_rescale_normal", + "GL_EXT_texture3D", +// "GL_NV_texgen_reflection", + NULL + }; + + const char *gld_multitex_extensions[] = { + "GL_ARB_multitexture", // Quake 3 + NULL + }; + + // Quake 2 engines + const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture"; + + const char *gld_enable_extensions[] = { + "GL_EXT_texture_env_add", // Quake 3 + "GL_ARB_texture_env_add", // Quake 3 + NULL + }; + + for (i=0; gld_disable_extensions[i]; i++) { + _mesa_disable_extension(ctx, gld_disable_extensions[i]); + } + + for (i=0; gld_enable_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_enable_extensions[i]); + } + + if (glb.bMultitexture) { + for (i=0; gld_multitex_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_multitex_extensions[i]); + } + + // GL_SGIS_multitexture + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // Fair bit slower on GeForce256, + // Much slower on 3dfx Voodoo5 5500. +// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + + } + + _mesa_enable_imaging_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + _mesa_enable_1_4_extensions(ctx); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c new file mode 100644 index 00000000000..2baea57443c --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c @@ -0,0 +1,77 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Mesa transformation pipeline with GLDirect fastpath +* +****************************************************************************/ + +//#include "../GLDirect.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +extern struct tnl_pipeline_stage _gld_d3d_render_stage; +extern struct tnl_pipeline_stage _gld_mesa_render_stage; + +static const struct tnl_pipeline_stage *gld_pipeline[] = { + &_gld_d3d_render_stage, // Direct3D TnL + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */ + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_point_attenuation_stage, + &_gld_mesa_render_stage, // Mesa TnL, D3D rendering + 0, +}; + +//--------------------------------------------------------------------------- + +void gldInstallPipeline_DX8( + GLcontext *ctx) +{ + // Remove any existing pipeline stages, + // then install GLDirect pipeline stages. + + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, gld_pipeline); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c new file mode 100644 index 00000000000..700b5200862 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c @@ -0,0 +1,1446 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Primitive (points/lines/tris/quads) rendering +* +****************************************************************************/ + +//#include "../GLDirect.h" + +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "swrast/s_trispan.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +// Disable compiler complaints about unreferenced local variables +#pragma warning (disable:4101) + +//--------------------------------------------------------------------------- +// Helper defines for primitives +//--------------------------------------------------------------------------- + +//static const float ooZ = 1.0f / 65536.0f; // One over Z + +#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3])) +#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3])) +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +//--------------------------------------------------------------------------- +// 2D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_2D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_TRIANGLES \ + BOOL bFog = ctx->Fog.Enabled; \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour; \ + GLuint facing = 0; \ + struct vertex_buffer *VB; \ + GLchan (*vbcolor)[4]; \ + GLchan (*vbspec)[4] + +#define GLD_SETUP_GET_SWVERT(s) \ + swv = &ss->verts[##s] + +#define GLD_SETUP_2D_VERTEX \ + pV->x = swv->win[0]; \ + pV->y = GLD_FLIP_Y(swv->win[1]); \ + pV->rhw = swv->win[3] + +#define GLD_SETUP_SMOOTH_COLOUR \ + pV->diffuse = GLD_COLOUR + +#define GLD_SETUP_GET_FLAT_COLOUR \ + dwFlatColour = GLD_COLOUR +#define GLD_SETUP_GET_FLAT_FOG_COLOUR \ + dwFlatColour = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_USE_FLAT_COLOUR \ + pV->diffuse = dwFlatColour + +#define GLD_SETUP_GET_FLAT_SPECULAR \ + dwSpecularColour= GLD_SPECULAR + +#define GLD_SETUP_USE_FLAT_SPECULAR \ + pV->specular = dwSpecularColour + +#define GLD_SETUP_DEPTH \ + pV->sz = swv->win[2] / ctx->DepthMaxF +// pV->z = swv->win[2] * ooZ; + +#define GLD_SETUP_SPECULAR \ + pV->specular = GLD_SPECULAR + +#define GLD_SETUP_FOG \ + pV->diffuse = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_TEX0 \ + pV->t0_u = swv->texcoord[0][0]; \ + pV->t0_v = swv->texcoord[0][1] + +#define GLD_SETUP_TEX1 \ + pV->t1_u = swv->texcoord[1][0]; \ + pV->t1_v = swv->texcoord[1][1] + +#define GLD_SETUP_LIGHTING(v) \ + if (facing == 1) { \ + pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } else { \ + if (bFog) \ + GLD_SETUP_FOG; \ + else \ + GLD_SETUP_SMOOTH_COLOUR; \ + GLD_SETUP_SPECULAR; \ + } + +#define GLD_SETUP_GET_FLAT_LIGHTING(v) \ + if (facing == 1) { \ + dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } + +#define GLD_SETUP_TWOSIDED_LIGHTING \ + /* Two-sided lighting */ \ + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \ + SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \ + SWvertex *v[3]; \ + GLfloat ex,ey,fx,fy,cc; \ + /* Get vars for later */ \ + VB = &TNL_CONTEXT(ctx)->vb; \ + vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \ + if (VB->SecondaryColorPtr[1]) { \ + vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \ + } else { \ + vbspec = NULL; \ + } \ + v[0] = &verts[v0]; \ + v[1] = &verts[v1]; \ + v[2] = &verts[v2]; \ + ex = v[0]->win[0] - v[2]->win[0]; \ + ey = v[0]->win[1] - v[2]->win[1]; \ + fx = v[1]->win[0] - v[2]->win[0]; \ + fy = v[1]->win[1] - v[2]->win[1]; \ + cc = ex*fy - ey*fx; \ + facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \ + } + +//--------------------------------------------------------------------------- +// 3D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_3D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_TRIANGLES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VERTEX(v) \ + p4f = VB->ObjPtr->data; \ + pV->Position.x = p4f[##v][0]; \ + pV->Position.y = p4f[##v][1]; \ + pV->Position.z = p4f[##v][2]; + +#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + + +#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + +#define GLD_SETUP_USE_FLAT_COLOUR_3D \ + pV->Diffuse = dwColor; + +#define GLD_SETUP_TEX0_3D(v) \ + if (VB->TexCoordPtr[0]) { \ + tc = VB->TexCoordPtr[0]->data; \ + pV->TexUnit0.x = tc[##v][0]; \ + pV->TexUnit0.y = tc[##v][1]; \ + } + +#define GLD_SETUP_TEX1_3D(v) \ + if (VB->TexCoordPtr[1]) { \ + tc = VB->TexCoordPtr[1]->data; \ + pV->TexUnit1.x = tc[##v][0]; \ + pV->TexUnit1.y = tc[##v][1]; \ + } + +//--------------------------------------------------------------------------- +// Helper functions +//--------------------------------------------------------------------------- + +__inline DWORD _gldComputeFog( + GLcontext *ctx, + SWvertex *swv) +{ + // Full fog calculation. + // Based on Mesa code. + + GLchan rFog, gFog, bFog; + GLchan fR, fG, fB; + const GLfloat f = swv->fog; + const GLfloat g = 1.0f - f; + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + fR = f * swv->color[0] + g * rFog; + fG = f * swv->color[1] + g * gFog; + fB = f * swv->color[2] + g * bFog; + return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]); +} + +//--------------------------------------------------------------------------- + +void gld_ResetLineStipple_DX8( + GLcontext *ctx) +{ + // TODO: Fake stipple with a 32x32 texture. +} + +//--------------------------------------------------------------------------- +// 2D (post-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points2D_DX8( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_2D_VARS_POINTS; + + unsigned i; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); + GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } else { + GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, swv++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } + + gld->PB2d.pPoints = (BYTE*)pV; + gld->PB2d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_SPECULAR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++;; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatExtras_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v2); + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v2); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothExtras_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatExtras_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v3); + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v3); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothExtras_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v3); + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// 3D (pre-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points3D_DX8( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_3D_VARS_POINTS + + unsigned i; +// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); +// GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_3D_VERTEX(VB->Elts[i]) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } else { +// GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } +/* + for (i=first; i<last; i++, pV++) { + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } +*/ + gld->PB3d.pPoints = (BYTE*)pV; + gld->PB3d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- +// Line functions +//--------------------------------------------------------------------------- + +void gld_Line3DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_GET_FLAT_COLOUR_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line3DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- +// Triangle functions +//--------------------------------------------------------------------------- + +void gld_Triangle3DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + GLD_SETUP_GET_FLAT_COLOUR_3D(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle3DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- +// Quad functions +//--------------------------------------------------------------------------- + +void gld_Quad3DFlat_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_GET_FLAT_COLOUR_3D(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad3DSmooth_DX8( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_SMOOTH_COLOUR_3D(v3) + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// Vertex setup for two-sided-lighting vertex shader +//--------------------------------------------------------------------------- + +/* + +void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last) +{ + // NOTE: Two-sided lighting does not apply to Points +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +*/ diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c new file mode 100644 index 00000000000..f24b3cfb74d --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c @@ -0,0 +1,2046 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Texture / Bitmap functions +* +****************************************************************************/ + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +#include <d3dx8tex.h> + +#include "texformat.h" +#include "colormac.h" +#include "texstore.h" +#include "image.h" +// #include "mem.h" + +//--------------------------------------------------------------------------- + +#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h)) + +//--------------------------------------------------------------------------- +// 1D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + (i) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (i) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (i)) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (i)) + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 2D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + ((t)->Width * (j) + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 3D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// Direct3D texture formats that have no Mesa equivalent +//--------------------------------------------------------------------------- + +const struct gl_texture_format _gld_texformat_X8R8G8B8 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_argb8888, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */ + gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */ + gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X1R5G5B5 = { + MESA_FORMAT_ARGB1555, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb1555, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */ + gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */ + gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X4R4G4B4 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb4444, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */ + gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */ + gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */ +}; + +//--------------------------------------------------------------------------- +// Texture unit constants +//--------------------------------------------------------------------------- + +// List of possible combinations of texture environments. +// Example: GLD_TEXENV_MODULATE_RGBA means +// GL_MODULATE, GL_RGBA base internal format. +#define GLD_TEXENV_DECAL_RGB 0 +#define GLD_TEXENV_DECAL_RGBA 1 +#define GLD_TEXENV_DECAL_ALPHA 2 +#define GLD_TEXENV_REPLACE_RGB 3 +#define GLD_TEXENV_REPLACE_RGBA 4 +#define GLD_TEXENV_REPLACE_ALPHA 5 +#define GLD_TEXENV_MODULATE_RGB 6 +#define GLD_TEXENV_MODULATE_RGBA 7 +#define GLD_TEXENV_MODULATE_ALPHA 8 +#define GLD_TEXENV_BLEND_RGB 9 +#define GLD_TEXENV_BLEND_RGBA 10 +#define GLD_TEXENV_BLEND_ALPHA 11 +#define GLD_TEXENV_ADD_RGB 12 +#define GLD_TEXENV_ADD_RGBA 13 +#define GLD_TEXENV_ADD_ALPHA 14 + +// Per-stage (i.e. per-unit) texture environment +typedef struct { + DWORD ColorArg1; // Colour argument 1 + D3DTEXTUREOP ColorOp; // Colour operation + DWORD ColorArg2; // Colour argument 2 + DWORD AlphaArg1; // Alpha argument 1 + D3DTEXTUREOP AlphaOp; // Alpha operation + DWORD AlphaArg2; // Alpha argument 2 +} GLD_texenv; + +// TODO: Do we really need to set ARG1 and ARG2 every time? +// They seem to always be TEXTURE and CURRENT respectively. + +// C = Colour out +// A = Alpha out +// Ct = Colour from Texture +// Cf = Colour from fragment (diffuse) +// At = Alpha from Texture +// Af = Alpha from fragment (diffuse) +// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND) +const GLD_texenv gldTexEnv[] = { + // DECAL_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af + {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_ALPHA: <undefined> use DECAL_RGB + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + + // REPLACE_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // REPLACE_RGBA: C=Ct, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + // REPLACE_ALPHA: C=Cf, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + + // MODULATE_RGB: C=CfCt, A=Af + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // MODULATE_RGBA: C=CfCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // MODULATE_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // BLEND_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // ADD_RGB: C=Cf+Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // ADD_RGBA: C=Cf+Ct, A=AfAt + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // ADD_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +}; + +//--------------------------------------------------------------------------- + +D3DTEXTUREADDRESS _gldConvertWrap( + GLenum wrap) +{ + return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP; +} + +//--------------------------------------------------------------------------- + +D3DTEXTUREFILTERTYPE _gldConvertMagFilter( + GLenum magfilter) +{ + return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT; +} + +//--------------------------------------------------------------------------- + +void _gldConvertMinFilter( + GLenum minfilter, + D3DTEXTUREFILTERTYPE *min_filter, + D3DTEXTUREFILTERTYPE *mip_filter) +{ + switch (minfilter) { + case GL_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_LINEAR; + break; + } +} + +//--------------------------------------------------------------------------- + +D3DFORMAT _gldGLFormatToD3DFormat( + GLenum internalFormat) +{ + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures + return D3DFMT_L8; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return D3DFMT_L8; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return D3DFMT_A8; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return D3DFMT_X8R8G8B8; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return D3DFMT_A8L8; + case GL_R3_G3_B2: + // TODO: Mesa does not support RGB332 internally + return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2; + case GL_RGB4: + return D3DFMT_X4R4G4B4; + case GL_RGB5: + return D3DFMT_X1R5G5B5; + case 3: + case GL_RGB: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return D3DFMT_R8G8B8; + case GL_RGBA4: + return D3DFMT_A4R4G4B4; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return D3DFMT_A8R8G8B8; + case GL_RGB5_A1: + return D3DFMT_A1R5G5B5; + } + + // Return an acceptable default + return D3DFMT_A8R8G8B8; +} + +//--------------------------------------------------------------------------- + +GLenum _gldDecodeBaseFormat( + IDirect3DTexture8 *pTex) +{ + // Examine Direct3D texture and return base OpenGL internal texture format + // NOTE: We can't use any base format info from Mesa because D3D might have + // used a different texture format when we used D3DXCreateTexture(). + + // Base internal format is one of (Red Book p355): + // GL_ALPHA, + // GL_LUMINANCE, + // GL_LUMINANCE_ALPHA, + // GL_INTENSITY, + // GL_RGB, + // GL_RGBA + + // NOTE: INTENSITY not used (not supported by Direct3D) + // LUMINANCE has same texture functions as RGB + // LUMINANCE_ALPHA has same texture functions as RGBA + + // TODO: cache format instead of using GetLevelDesc() + D3DSURFACE_DESC desc; + _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &desc)); + + switch (desc.Format) { + case D3DFMT_R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_R3G3B2: + case D3DFMT_X4R4G4B4: + case D3DFMT_P8: + case D3DFMT_L8: + return GL_RGB; + case D3DFMT_A8R8G8B8: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8R3G3B2: + case D3DFMT_A8P8: + case D3DFMT_A8L8: + case D3DFMT_A4L4: + return GL_RGBA; + case D3DFMT_A8: + return GL_ALPHA; + // Compressed texture formats. Need to check these... + case D3DFMT_DXT1: + return GL_RGBA; + case D3DFMT_DXT2: + return GL_RGB; + case D3DFMT_DXT3: + return GL_RGBA; + case D3DFMT_DXT4: + return GL_RGB; + case D3DFMT_DXT5: + return GL_RGBA; + } + + // Fell through. Return arbitary default. + return GL_RGBA; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* _gldMesaFormatForD3DFormat( + D3DFORMAT d3dfmt) +{ + switch (d3dfmt) { + case D3DFMT_A8R8G8B8: + return &_mesa_texformat_argb8888; + case D3DFMT_R8G8B8: + return &_mesa_texformat_rgb888; + case D3DFMT_R5G6B5: + return &_mesa_texformat_rgb565; + case D3DFMT_A4R4G4B4: + return &_mesa_texformat_argb4444; + case D3DFMT_A1R5G5B5: + return &_mesa_texformat_argb1555; + case D3DFMT_A8L8: + return &_mesa_texformat_al88; + case D3DFMT_R3G3B2: + return &_mesa_texformat_rgb332; + case D3DFMT_A8: + return &_mesa_texformat_a8; + case D3DFMT_L8: + return &_mesa_texformat_l8; + case D3DFMT_X8R8G8B8: + return &_gld_texformat_X8R8G8B8; + case D3DFMT_X1R5G5B5: + return &_gld_texformat_X1R5G5B5; + case D3DFMT_X4R4G4B4: + return &_gld_texformat_X4R4G4B4; + } + + // If we reach here then we've made an error somewhere else + // by allowing a format that is not supported. + assert(0); + + return NULL; // Shut up compiler warning +} + +//--------------------------------------------------------------------------- +// Copy* functions +//--------------------------------------------------------------------------- + +void gldCopyTexImage1D_DX8( + GLcontext *ctx, + GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexImage2D_DX8( + GLcontext *ctx, + GLenum target, + GLint level, + GLenum internalFormat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage1D_DX8( + GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage2D_DX8( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage3D_DX8( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height ) +{ + // TODO ? +} + +//--------------------------------------------------------------------------- +// Bitmap/Pixel functions +//--------------------------------------------------------------------------- + +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1) + +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT z; // depth value + FLOAT rhw; // reciprocal homogenous W (always 1.0f) + FLOAT tu, tv; // texture coords +} _GLD_IMAGE_VERTEX; + +//--------------------------------------------------------------------------- + +HRESULT _gldDrawPixels( + GLcontext *ctx, + BOOL bChromakey, // Alpha test for glBitmap() images + GLint x, // GL x position + GLint y, // GL y position (needs flipping) + GLsizei width, // Width of input image + GLsizei height, // Height of input image + IDirect3DSurface8 *pImage) +{ + // + // Draw input image as texture implementing PixelZoom and clipping. + // Any fragment operations currently enabled will be used. + // + + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + IDirect3DTexture8 *pTexture; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface8 *pSurface; + _GLD_IMAGE_VERTEX v[4]; + HRESULT hr; + + float ZoomWidth, ZoomHeight; + float ScaleWidth, ScaleHeight; + + // Create a texture to hold image + hr = D3DXCreateTexture( + gld->pDev, + width, height, + 1, // miplevels + 0, // usage + D3DFMT_A8R8G8B8, // format + D3DPOOL_MANAGED, // pool + &pTexture); + if (FAILED(hr)) + return hr; + + hr = IDirect3DTexture8_GetSurfaceLevel(pTexture, 0, &pSurface); + if (FAILED(hr)) { + IDirect3DTexture8_Release(pTexture); + return hr; + } + + // Copy image into texture + hr = D3DXLoadSurfaceFromSurface( + pSurface, NULL, NULL, // Dest surface + pImage, NULL, NULL, // Src surface + D3DX_FILTER_NONE, + 0); + IDirect3DSurface8_Release(pSurface); + if (FAILED(hr)) { + IDirect3DTexture8_Release(pTexture); + return hr; + } + + // + // Set up the quad like this (ascii-art ahead!) + // + // 3--2 + // | | + // 0--1 + // + // + + // Set depth + v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2]; + // Set Reciprocal Homogenous W + v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f; + + // Set texcoords + // Examine texture size - if different to input width and height + // then we'll need to munge the texcoords to fit. + IDirect3DTexture8_GetLevelDesc(pTexture, 0, &d3dsd); + ScaleWidth = (float)width / (float)d3dsd.Width; + ScaleHeight = (float)height / (float)d3dsd.Height; + v[0].tu = 0.0f; v[0].tv = 0.0f; + v[1].tu = ScaleWidth; v[1].tv = 0.0f; + v[2].tu = ScaleWidth; v[2].tv = ScaleHeight; + v[3].tu = 0.0f; v[3].tv = ScaleHeight; + + // Set raster positions + ZoomWidth = (float)width * ctx->Pixel.ZoomX; + ZoomHeight = (float)height * ctx->Pixel.ZoomY; + + v[0].x = x; v[0].y = GLD_FLIP_Y(y); + v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y); + v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight); + v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight); + + // Draw image with full HW acceleration + // NOTE: Be nice to use a State Block for all this state... + IDirect3DDevice8_SetTexture(gld->pDev, 0, pTexture); + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); + IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + IDirect3DDevice8_SetVertexShader(gld->pDev, _GLD_FVF_IMAGE); + + // + // Emulate Chromakey with an Alpha Test. + // [Alpha Test is more widely supported anyway] + // + if (bChromakey) { + // Switch on alpha testing + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE); + // Fragment passes is alpha is greater than reference value + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER); + // Set alpha reference value between Bitmap alpha values of + // zero (transparent) and one (opaque). + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f); + } + + IDirect3DDevice8_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX)); + + // Release texture + IDirect3DDevice8_SetTexture(gld->pDev, 0, NULL); + IDirect3DTexture8_Release(pTexture); + + // Reset state to before we messed it up + FLUSH_VERTICES(ctx, _NEW_ALL); + + return S_OK; +} + +//--------------------------------------------------------------------------- + +void gld_DrawPixels_DX8( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + GLD_context *gldCtx; + GLD_driver_dx8 *gld; + + IDirect3DSurface8 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + + const struct gl_texture_format *MesaFormat; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX8_DRIVER(gldCtx); + + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + &pImage); + if (FAILED(hr)) { + return; + } + + // + // Use Mesa to fill in image + // + + // Lock all of surface + hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pImage); + return; + } + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + + // unpack image, apply transfer ops and store directly in texture + MesaFormat->StoreImage( + ctx, + 2, + GL_RGBA, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, /* dstImageStride */ + format, type, pixels, unpack); + + IDirect3DSurface8_UnlockRect(pImage); + + _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage); + + IDirect3DSurface8_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_ReadPixels_DX8( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *dest) +{ + + GLD_context *gldCtx; + GLD_driver_dx8 *gld; + + IDirect3DSurface8 *pBackbuffer = NULL; + IDirect3DSurface8 *pNativeImage = NULL; + IDirect3DSurface8 *pCanonicalImage = NULL; + + D3DSURFACE_DESC d3dsd; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + struct gl_pixelstore_attrib srcPacking; + int i; + GLint DstRowStride; + const struct gl_texture_format *MesaFormat; + + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + return; + } + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + DstRowStride = _mesa_image_row_stride(pack, width, format, type); + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX8_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice8_GetBackBuffer( + gld->pDev, + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + d3dsd.Format, + &pNativeImage); + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels. + // + // This intermediate surface ensure that we can use CopyRects() + // instead of relying on D3DXLoadSurfaceFromSurface(), which may + // try and lock the backbuffer. This way seems safer. + // + hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pNativeImage, + &ptDst); + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + // Create an RGBA8888 surface + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + &pCanonicalImage); + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + // Convert to RGBA8888 + hr = D3DXLoadSurfaceFromSurface( + pCanonicalImage, // Dest surface + NULL, NULL, // Dest palette, RECT + pNativeImage, // Src surface + NULL, NULL, // Src palette, RECT + D3DX_FILTER_NONE, // Filter + 0); // Colourkey + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + srcPacking.Alignment = 1; + srcPacking.ImageHeight = height; + srcPacking.LsbFirst = GL_FALSE; + srcPacking.RowLength = 0; + srcPacking.SkipImages = 0; + srcPacking.SkipPixels = 0; + srcPacking.SkipRows = 0; + srcPacking.SwapBytes = GL_FALSE; + + // Lock all of image + hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + goto gld_ReadPixels_DX8_return; + } + + // We need to flip the data. Yuck. + // Perhaps Mesa has a span packer we can use in future... + for (i=0; i<height; i++) { + BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0); + BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1)); + MesaFormat->StoreImage( + ctx, + 2, + GL_RGBA, // base format + MesaFormat, // dst format + pDestRow, // dest addr + width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z + DstRowStride, // dst row stride + 0, // dstImageStride + GL_BGRA, // src format + GL_UNSIGNED_BYTE, // src type + pSrcRow, // src addr + &srcPacking); // packing params of source image + } + + IDirect3DSurface8_UnlockRect(pCanonicalImage); + +gld_ReadPixels_DX8_return: + SAFE_RELEASE_SURFACE8(pCanonicalImage); + SAFE_RELEASE_SURFACE8(pNativeImage); + SAFE_RELEASE_SURFACE8(pBackbuffer); +} + +//--------------------------------------------------------------------------- + +void gld_CopyPixels_DX8( + GLcontext *ctx, + GLint srcx, + GLint srcy, + GLsizei width, + GLsizei height, + GLint dstx, + GLint dsty, + GLenum type) +{ + // + // NOTE: Not allowed to copy vidmem to vidmem! + // Therefore we use an intermediate image surface. + // + + GLD_context *gldCtx; + GLD_driver_dx8 *gld; + + IDirect3DSurface8 *pBackbuffer; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface8 *pImage; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + + // Only backbuffer + if (type != GL_COLOR) + return; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX8_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice8_GetBackBuffer( + gld->pDev, + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pBackbuffer); + return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + d3dsd.Format, + &pImage); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pBackbuffer); + return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels + hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pImage, + &ptDst); + IDirect3DSurface8_Release(pBackbuffer); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pImage); + return; + } + + _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage); + + IDirect3DSurface8_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_Bitmap_DX8( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + GLD_context *gldCtx; + GLD_driver_dx8 *gld; + + IDirect3DSurface8 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + BYTE *pTempBitmap; + D3DCOLOR clBitmapOne, clBitmapZero; + D3DCOLOR *pBits; + const GLubyte *src; + int i, j, k; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX8_DRIVER(gldCtx); + + clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero + clBitmapOne = D3DCOLOR_COLORVALUE( + ctx->Current.RasterColor[0], + ctx->Current.RasterColor[1], + ctx->Current.RasterColor[2], + 1.0f); // NOTE: Alpha is One + + hr = IDirect3DDevice8_CreateImageSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + &pImage); + if (FAILED(hr)) { + return; + } + + // Lock all of surface + hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pImage); + return; + } + + pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack); + if (pTempBitmap == NULL) { + IDirect3DSurface8_Release(pImage); + return; + } + + pBits = (D3DCOLOR*)d3dLockedRect.pBits; + + for (i=0; i<height; i++) { + GLubyte byte; + pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch)); + src = (const GLubyte *) _mesa_image_address(2, + &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, + 0, i, 0); + for (j=0; j<(width>>3); j++) { + byte = *src++; + for (k=0; k<8; k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + // Fill remaining bits from bitmap + if (width & 7) { + byte = *src; + for (k=0; k<(width & 7); k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + } + + FREE(pTempBitmap); + +/* + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage( + ctx, + 2, + GL_BITMAP, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack); +*/ + IDirect3DSurface8_UnlockRect(pImage); + + _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage); + + IDirect3DSurface8_Release(pImage); +} + +//--------------------------------------------------------------------------- +// Texture functions +//--------------------------------------------------------------------------- + +void _gldAllocateTexture( + GLcontext *ctx, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + IDirect3DTexture8 *pTex; + D3DFORMAT d3dFormat; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (pTex) { + // Decide whether we can keep existing D3D texture + // by examining top-level surface. + D3DSURFACE_DESC d3dsd; + _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &d3dsd)); + // Release existing texture if not compatible + if ((d3dsd.Width == texImage->Width) || + (d3dsd.Height == texImage->Height)) + { + return; // Keep the existing texture + } + tObj->DriverData = NULL; + _GLD_DX8_TEX(Release(pTex)); + } + + d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat); + D3DXCreateTexture( + gld->pDev, + texImage->Width, + texImage->Height, + // TODO: Re-evaluate mipmapping + (glb.bUseMipmaps) ? D3DX_DEFAULT : 1, + 0, // Usage + d3dFormat, + D3DPOOL_MANAGED, + &pTex); + tObj->DriverData = pTex; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* gld_ChooseTextureFormat_DX8( + GLcontext *ctx, + GLint internalFormat, + GLenum srcFormat, + GLenum srcType) +{ + // [Based on mesa_choose_tex_format()] + // + // We will choose only texture formats that are supported + // by Direct3D. If the hardware doesn't support a particular + // texture format, then the D3DX texture calls that we use + // will automatically use a HW supported format. + // + // The most critical aim is to reduce copying; if we can use + // texture-image data directly then it will be a big performance assist. + // + + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return &_mesa_texformat_a8; // D3DFMT_A8 + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5 + // Mesa will convert this for us later... + // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5 + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return &_mesa_texformat_al88; // D3DFMT_A8L8 + case GL_R3_G3_B2: + return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2 + case GL_RGB4: + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4 + case 3: + case GL_RGB: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_rgb565; + case 4: + case GL_RGBA: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return &_mesa_texformat_argb8888; + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + default: + _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); + return NULL; + } +} + +//--------------------------------------------------------------------------- + +/* +// Safer(?), slower version. +void gld_TexImage2D_DX8( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + RECT rcSrcRect; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + + if (!tObj || !texImage) + return; + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture8_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface8_Release(pSurface); + return; + } + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + SetRect(&rcSrcRect, 0, 0, width, height); + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + NULL, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface8_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexImage2D_DX8( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + // GLQUAKE FIX + // Test for input alpha data with non-alpha internalformat + if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) { + // Input format has alpha, but a non-alpha format has been requested. + texImage->IntFormat = GL_RGBA; + internalFormat = GL_RGBA; + } + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture8_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface8_GetDesc(pSurface, &d3dsd); + + // Lock all of surface + hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage( + ctx, + 2, + texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + IDirect3DSurface8_UnlockRect(pSurface); + IDirect3DSurface8_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + // A 1D texture is a 2D texture with a height of zero + gld_TexImage2D_DX8(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +/* +void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_GET_CONTEXT + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + D3DFORMAT d3dFormat; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + RECT rcSrcRect; + RECT rcDstRect; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= _GLD_DX8_TEX(GetLevelCount(pTex)) + return; // Level does not exist + hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + d3dFormat = _gldGLFormatToD3DFormat(texImage->Format); + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface8_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + // Source rectangle is whole of input image + SetRect(&rcSrcRect, 0, 0, width, height); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + &rcDstRect, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface8_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + IDirect3DTexture8 *pTex; + IDirect3DSurface8 *pSurface; + HRESULT hr; + RECT rcDstRect; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture8*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture8_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface8_GetDesc(pSurface, &d3dsd); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + // Lock sub-rect of surface + hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0); + if (FAILED(hr)) { + IDirect3DSurface8_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, + 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!! + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + + IDirect3DSurface8_UnlockRect(pSurface); + IDirect3DSurface8_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexSubImage1D_DX8( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + gld_TexSubImage2D_DX8(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +void gld_DeleteTexture_DX8( + GLcontext *ctx, + struct gl_texture_object *tObj) +{ + GLD_context *gld = (GLD_context*)(ctx->DriverCtx); + + if (tObj) { + IDirect3DTexture8 *pTex = (IDirect3DTexture8*)tObj->DriverData; + if (pTex) { +/* // Make sure texture is not bound to a stage before releasing it + for (int i=0; i<MAX_TEXTURE_UNITS; i++) { + if (gld->CurrentTexture[i] == pTex) { + gld->pDev->SetTexture(i, NULL); + gld->CurrentTexture[i] = NULL; + } + }*/ + _GLD_DX8_TEX(Release(pTex)); + tObj->DriverData = NULL; + } + } +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetColorOps( + const GLD_driver_dx8 *gld, + GLuint unit, + DWORD ColorArg1, + D3DTEXTUREOP ColorOp, + DWORD ColorArg2) +{ + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2)); +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetAlphaOps( + const GLD_driver_dx8 *gld, + GLuint unit, + DWORD AlphaArg1, + D3DTEXTUREOP AlphaOp, + DWORD AlphaArg2) +{ + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2)); +} + +//--------------------------------------------------------------------------- + +void gldUpdateTextureUnit( + GLcontext *ctx, + GLuint unit, + BOOL bPassThrough) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + D3DTEXTUREFILTERTYPE minfilter; + D3DTEXTUREFILTERTYPE mipfilter; + GLenum BaseFormat; + DWORD dwColorArg0; + int iTexEnv = 0; + GLD_texenv *pTexenv; + + // NOTE: If bPassThrough is FALSE then texture stage can be + // disabled otherwise it must pass-through it's current fragment. + + const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *tObj = pUnit->_Current; + + IDirect3DTexture8 *pTex = NULL; + if (tObj) { + pTex = (IDirect3DTexture8*)tObj->DriverData; + } + + // Enable texturing if unit is enabled and a valid D3D texture exists + // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT + //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) { + if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) { + // Enable texturing + _GLD_DX8_DEV(SetTexture(gld->pDev, unit, pTex)); + } else { + // Disable texturing, then return + _GLD_DX8_DEV(SetTexture(gld->pDev, unit, NULL)); + if (bPassThrough) { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + } else { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + } + return; + } + + // Texture parameters + _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter)); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS))); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + + // Texture priority + _GLD_DX8_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f))); + + // Texture environment + // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops. + // See Page 355 of the Red Book. + BaseFormat = _gldDecodeBaseFormat(pTex); + + switch (BaseFormat) { + case GL_RGB: + iTexEnv = 0; + break; + case GL_RGBA: + iTexEnv = 1; + break; + case GL_ALPHA: + iTexEnv = 2; + break; + } + + switch (pUnit->EnvMode) { + case GL_DECAL: + iTexEnv += 0; + break; + case GL_REPLACE: + iTexEnv += 3; + break; + case GL_MODULATE: + iTexEnv += 6; + break; + case GL_BLEND: + // Set blend colour + dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]); + _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0)); + iTexEnv += 9; + break; + case GL_ADD: + iTexEnv += 12; + break; + } + pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv]; + _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2); + _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_TEXTURE_DX8( + GLcontext *ctx) +{ + // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units + + BOOL bUnit0Enabled; + BOOL bUnit1Enabled; + + if (!ctx) + return; // Sanity check + + if (ctx->Const.MaxTextureUnits == 1) { + gldUpdateTextureUnit(ctx, 0, TRUE); + return; + } + + // + // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!! + // + + // Mesa 5: Texture Units altered + //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE; + //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE; + bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + + // If Unit0 is disabled and Unit1 is enabled then we must pass-though + gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE); + // We can always disable the last texture unit + gldUpdateTextureUnit(ctx, 1, FALSE); + +#ifdef _DEBUG + { + // Find out whether device supports current renderstates + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); +// GLD_context *gld = GLD_GET_CONTEXT(ctx); + + DWORD dwPasses; + _GLD_DX8_DEV(ValidateDevice(gld->pDev, &dwPasses)); +// if (FAILED(hr)) { +// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr); +// } + if (dwPasses != 1) { + gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n"); + } + } +#endif +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c new file mode 100644 index 00000000000..cafbf4f5c50 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c @@ -0,0 +1,249 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect fastpath pipeline stage +* +****************************************************************************/ + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +__inline void _gldSetVertexShaderConstants( + GLcontext *ctx, + GLD_driver_dx8 *gld) +{ + D3DXMATRIX mat, matView, matProj; + GLfloat *pM; + + // Mesa 5: Altered to a Stack + //pM = ctx->ModelView.m; + pM = ctx->ModelviewMatrixStack.Top->m; + matView._11 = pM[0]; + matView._12 = pM[1]; + matView._13 = pM[2]; + matView._14 = pM[3]; + matView._21 = pM[4]; + matView._22 = pM[5]; + matView._23 = pM[6]; + matView._24 = pM[7]; + matView._31 = pM[8]; + matView._32 = pM[9]; + matView._33 = pM[10]; + matView._34 = pM[11]; + matView._41 = pM[12]; + matView._42 = pM[13]; + matView._43 = pM[14]; + matView._44 = pM[15]; + + // Mesa 5: Altered to a Stack + //pM = ctx->ProjectionMatrix.m; + pM = ctx->ProjectionMatrixStack.Top->m; + matProj._11 = pM[0]; + matProj._12 = pM[1]; + matProj._13 = pM[2]; + matProj._14 = pM[3]; + matProj._21 = pM[4]; + matProj._22 = pM[5]; + matProj._23 = pM[6]; + matProj._24 = pM[7]; + matProj._31 = pM[8]; + matProj._32 = pM[9]; + matProj._33 = pM[10]; + matProj._34 = pM[11]; + matProj._41 = pM[12]; + matProj._42 = pM[13]; + matProj._43 = pM[14]; + matProj._44 = pM[15]; + + D3DXMatrixMultiply( &mat, &matView, &matProj ); + D3DXMatrixTranspose( &mat, &mat ); + + _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4)); +} + +//--------------------------------------------------------------------------- + +static GLboolean gld_d3d_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + TNLcontext *tnl; + struct vertex_buffer *VB; + tnl_render_func *tab; + GLint pass; + GLD_pb_dx8 *gldPB = &gld->PB3d; +/* + static int count = 0; + count++; + if (count != 2) + return GL_FALSE; +*/ + // The "check" function should disable this stage, + // but we'll test gld->bUseMesaTnL anyway. + if (gld->bUseMesaTnL) { + // Do nothing in this stage, but continue pipeline + return GL_TRUE; + } + + tnl = TNL_CONTEXT(ctx); + VB = &tnl->vb; + pass = 0; + + tnl->Driver.Render.Start( ctx ); + +#if 0 + // For debugging: Useful to see if an app passes colour data in + // an unusual format. + switch (VB->ColorPtr[0]->Type) { + case GL_FLOAT: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n"); + break; + case GL_UNSIGNED_BYTE: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n"); + break; + default: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n"); + break; + } +#endif + + tnl->Driver.Render.Points = gld_Points3D_DX8; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line3DFlat_DX8; + tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX8; + tnl->Driver.Render.Quad = gld_Quad3DFlat_DX8; + } else { + tnl->Driver.Render.Line = gld_Line3DSmooth_DX8; + tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX8; + tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX8; + } + + _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts); + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) + { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + _GLD_DX8_VB(Unlock(gldPB->pVB)); + + _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride)); + + _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection)); + _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView)); + + if (gldPB->nPoints) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + +//--------------------------------------------------------------------------- + +const struct tnl_pipeline_stage _gld_d3d_render_stage = +{ + "gld_d3d_render_stage", + NULL, + NULL, + NULL, + NULL, + gld_d3d_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c new file mode 100644 index 00000000000..81414a31dde --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c @@ -0,0 +1,449 @@ +/* $Id: gld_vb_mesa_render_dx8.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <[email protected]> + */ + + +/* + * Render whole vertex buffers, including projection of vertices from + * clip space and clipping of primitives. + * + * This file makes calls to project vertices and to the point, line + * and triangle rasterizers via the function pointers: + * + * context->Driver.Render.* + * + */ + + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx8.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +/**********************************************************************/ +/* Clip single primitives */ +/**********************************************************************/ + + +#if defined(USE_IEEE) +#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31)) +//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +#define NEGATIVE(x) (x < 0) +//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#endif + + +#define W(i) coord[i][3] +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 4 +#define TAG(x) x##_4 +#include "tnl/t_vb_cliptmp.h" + + + +/**********************************************************************/ +/* Clip and render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte ormask = c1|c2; \ + if (!ormask) \ + LineFunc( ctx, v1, v2 ); \ + else if (!(c1 & c2 & 0x3f)) \ + clip_line_4( ctx, v1, v2, ormask ); \ +} while (0) + +#define RENDER_TRI( v1, v2, v3 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ + GLubyte ormask = c1|c2|c3; \ + if (!ormask) \ + TriangleFunc( ctx, v1, v2, v3 ); \ + else if (!(c1 & c2 & c3 & 0x3f)) \ + clip_tri_4( ctx, v1, v2, v3, ormask ); \ +} while (0) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte c3 = mask[v3], c4 = mask[v4]; \ + GLubyte ormask = c1|c2|c3|c4; \ + if (!ormask) \ + QuadFunc( ctx, v1, v2, v3, v4 ); \ + else if (!(c1 & c2 & c3 & c4 & 0x3f)) \ + clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ +} while (0) + + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const GLubyte *mask = VB->ClipMask; \ + const GLuint sz = VB->ClipPtr->size; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + const GLboolean stipple = ctx->Line.StippleFlag; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; (void) mask; (void) sz; (void) stipple; + +#define TAG(x) clip_##x##_verts +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + + +/* Elts, with the possibility of clipping. + */ +#undef ELT +#undef TAG +#define ELT(x) elt[x] +#define TAG(x) clip_##x##_elts +#include "tnl/t_vb_rendertmp.h" + +/* TODO: do this for all primitives, verts and elts: + */ +static void clip_elt_triangles( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES]; + struct vertex_buffer *VB = &tnl->vb; + const GLuint * const elt = VB->Elts; + GLubyte *mask = VB->ClipMask; + GLuint last = count-2; + GLuint j; + (void) flags; + + tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES ); + + for (j=start; j < last; j+=3 ) { + GLubyte c1 = mask[elt[j]]; + GLubyte c2 = mask[elt[j+1]]; + GLubyte c3 = mask[elt[j+2]]; + GLubyte ormask = c1|c2|c3; + if (ormask) { + if (start < j) + render_tris( ctx, start, j, 0 ); + if (!(c1&c2&c3&0x3f)) + clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); + start = j+3; + } + } + + if (start < j) + render_tris( ctx, start, j, 0 ); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, no clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ + LineFunc( ctx, v1, v2 ) + +#define RENDER_TRI( v1, v2, v3 ) \ + TriangleFunc( ctx, v1, v2, v3 ) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ + QuadFunc( ctx, v1, v2, v3, v4 ) + +#define TAG(x) _gld_tnl_##x##_verts + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; + +#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx ) +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RENDER_TAB_QUALIFIER +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + +/* Elts, no clipping. + */ +#undef ELT +#define TAG(x) _gld_tnl_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Helper functions for drivers */ +/**********************************************************************/ +/* +void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; +} + +void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} +*/ + + +/**********************************************************************/ +/* Clip and render whole vertex buffers */ +/**********************************************************************/ + +tnl_points_func _gldSetupPoints[4] = { + gld_Points2D_DX8, + gld_Points2D_DX8, + gld_Points2D_DX8, + gld_Points2D_DX8 +}; +tnl_line_func _gldSetupLine[4] = { + gld_Line2DFlat_DX8, + gld_Line2DSmooth_DX8, + gld_Line2DFlat_DX8, + gld_Line2DSmooth_DX8, +}; +tnl_triangle_func _gldSetupTriangle[4] = { + gld_Triangle2DFlat_DX8, + gld_Triangle2DSmooth_DX8, + gld_Triangle2DFlatExtras_DX8, + gld_Triangle2DSmoothExtras_DX8 +}; +tnl_quad_func _gldSetupQuad[4] = { + gld_Quad2DFlat_DX8, + gld_Quad2DSmooth_DX8, + gld_Quad2DFlatExtras_DX8, + gld_Quad2DSmoothExtras_DX8 +}; + +//--------------------------------------------------------------------------- + +static GLboolean _gld_mesa_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + tnl_render_func *tab; + GLint pass = 0; + GLD_pb_dx8 *gldPB; + + /* Allow the drivers to lock before projected verts are built so + * that window coordinates are guarenteed not to change before + * rendering. + */ + ASSERT(tnl->Driver.Render.Start); + + tnl->Driver.Render.Start( ctx ); + + // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets + // stream, indices and shader to default values of NULL or 0. +/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) && + gld->VStwosidelight.hShader && + !ctx->Fog.Enabled) + { + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware); + _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); + gldPB = &gld->PBtwosidelight; + tnl->Driver.Render.Points = gld_Points2DTwoside_DX8; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX8; + tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX8; + tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX8; + } else { + tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX8; + tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX8; + tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX8; + } + } else {*/ + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); + gldPB = &gld->PB2d; + _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF)); + tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc]; + tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc]; + tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc]; + tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc]; +// } + + _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 ); + + if (VB->ClipOrMask) { + tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; + clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles; + } + else { + tab = (VB->Elts ? + tnl->Driver.Render.PrimTabElts : + tnl->Driver.Render.PrimTabVerts); + } + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + +// tnl->Driver.Render.Finish( ctx ); + + _GLD_DX8_VB(Unlock(gldPB->pVB)); + + _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride)); + + if (gldPB->nPoints) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + + + +//--------------------------------------------------------------------------- + +const struct tnl_pipeline_stage _gld_mesa_render_stage = +{ + "gld_mesa_render_stage", + NULL, + NULL, + NULL, + NULL, + _gld_mesa_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c new file mode 100644 index 00000000000..690f68b68f1 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c @@ -0,0 +1,1335 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 8.x WGL (WindowsGL) +* +****************************************************************************/ + +#include "dglcontext.h" +#include "gld_driver.h" +#include "gld_dxerr8.h" +#include "gld_dx8.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +// Copied from dglcontect.c +#define GLDERR_NONE 0 +#define GLDERR_MEM 1 +#define GLDERR_DDRAW 2 +#define GLDERR_D3D 3 +#define GLDERR_BPP 4 +#define GLDERR_DDS 5 +// This external var keeps track of any error +extern int nContextError; + +#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL + +extern void _gld_mesa_warning(GLcontext *, char *); +extern void _gld_mesa_fatal(GLcontext *, char *); + +//--------------------------------------------------------------------------- + +static char szColorDepthWarning[] = +"GLDirect does not support the current desktop\n\ +color depth.\n\n\ +You may need to change the display resolution to\n\ +16 bits per pixel or higher color depth using\n\ +the Windows Display Settings control panel\n\ +before running this OpenGL application.\n"; + +// The only depth-stencil formats currently supported by Direct3D +// Surface Format Depth Stencil Total Bits +// D3DFMT_D32 32 - 32 +// D3DFMT_D15S1 15 1 16 +// D3DFMT_D24S8 24 8 32 +// D3DFMT_D16 16 - 16 +// D3DFMT_D24X8 24 - 32 +// D3DFMT_D24X4S4 24 4 32 + +// This pixel format will be used as a template when compiling the list +// of pixel formats supported by the hardware. Many fields will be +// filled in at runtime. +// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM +static DGL_pixelFormat pfTemplateHW = +{ + { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure + 1, // Structure version - should be 1 + // Flags: + PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface. + PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM) + PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM) + PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing. + PFD_DOUBLEBUFFER | // The buffer is double-buffered. + 0, // Placeholder for easy commenting of above flags + PFD_TYPE_RGBA, // Pixel type RGBA. + 16, // Total colour bitplanes (excluding alpha bitplanes) + 5, 0, // Red bits, shift + 5, 0, // Green bits, shift + 5, 0, // Blue bits, shift + 0, 0, // Alpha bits, shift (destination alpha) + 0, // Accumulator bits (total) + 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha + 0, // Depth bits + 0, // Stencil bits + 0, // Number of auxiliary buffers + 0, // Layer type + 0, // Specifies the number of overlay and underlay planes. + 0, // Layer mask + 0, // Specifies the transparent color or index of an underlay plane. + 0 // Damage mask + }, + D3DFMT_UNKNOWN, // No depth/stencil buffer +}; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- + +// Vertex Shader Declaration +static DWORD dwTwoSidedLightingDecl[] = +{ + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position + D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal + D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color + D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color + D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0 + D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1 + D3DVSD_END() +}; + +// Vertex Shader for two-sided lighting +static char *szTwoSidedLightingVS = +// This is a test shader! +"vs.1.0\n" +"m4x4 oPos,v0,c0\n" +"mov oD0,v2\n" +"mov oD1,v3\n" +"mov oT0,v4\n" +"mov oT1,v5\n" +; + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +typedef struct { + HINSTANCE hD3D8DLL; // Handle to d3d8.dll + FNDIRECT3DCREATE8 fnDirect3DCreate8; // Direct3DCreate8 function prototype + BOOL bDirect3D; // Persistant Direct3D8 exists + BOOL bDirect3DDevice; // Persistant Direct3DDevice8 exists + IDirect3D8 *pD3D; // Persistant Direct3D8 + IDirect3DDevice8 *pDev; // Persistant Direct3DDevice8 +} GLD_dx8_globals; + +// These are "global" to all DX8 contexts. KeithH +static GLD_dx8_globals dx8Globals; + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +BOOL gldGetDXErrorString_DX( + HRESULT hr, + char *buf, + int nBufSize) +{ + // + // Return a string describing the input HRESULT error code + // + + D3DXGetErrorString(hr, buf, nBufSize); + return TRUE; +} + +//--------------------------------------------------------------------------- + +static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType( + IDirect3D8 *pD3D8, + D3DFORMAT SurfaceFormat, + D3DDEVTYPE d3dDevType, + BOOL Windowed) +{ + int i; + HRESULT hr; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE) + return D3DMULTISAMPLE_NONE; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) { + // Find fastest multisample + for (i=2; i<17; i++) { + hr = IDirect3D8_CheckDeviceMultiSampleType( + pD3D8, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } else { + // Find nicest multisample + for (i=16; i>1; i--) { + hr = IDirect3D8_CheckDeviceMultiSampleType( + pD3D8, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } + + // Nothing found - return default + return D3DMULTISAMPLE_NONE; +} + +//--------------------------------------------------------------------------- + +void _gldDestroyPrimitiveBuffer( + GLD_pb_dx8 *gldVB) +{ + SAFE_RELEASE(gldVB->pVB); + + // Sanity check... + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; +} + +//--------------------------------------------------------------------------- + +HRESULT _gldCreatePrimitiveBuffer( + GLcontext *ctx, + GLD_driver_dx8 *lpCtx, + GLD_pb_dx8 *gldVB) +{ + HRESULT hResult; + char *szCreateVertexBufferFailed = "CreateVertexBuffer failed"; + DWORD dwMaxVertices; // Max number of vertices in vertex buffer + DWORD dwVBSize; // Total size of vertex buffer + + // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we + // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize. + // We'll use IMM_SIZE if it's larger (which it should not be). + dwMaxVertices = MAX_ARRAY_LOCK_SIZE; + + // Now calculate how many vertices to allow for in total + // 1 per point, 2 per line, 6 per quad = 9 + dwVBSize = dwMaxVertices * 9 * gldVB->dwStride; + + hResult = IDirect3DDevice8_CreateVertexBuffer( + lpCtx->pDev, + dwVBSize, + gldVB->dwUsage, + gldVB->dwFVF, + gldVB->dwPool, + &gldVB->pVB); + if (FAILED(hResult)) { + ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed); + return hResult; + } + + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; + gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL; + gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB + gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB + + return S_OK; +} + +//--------------------------------------------------------------------------- +// Function: _gldCreateVertexShaders +// Create DX8 Vertex Shaders. +//--------------------------------------------------------------------------- +/* +void _gldCreateVertexShaders( + GLD_driver_dx8 *gld) +{ + DWORD dwFlags; + LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer + HRESULT hr; + +#ifdef _DEBUG + dwFlags = D3DXASM_DEBUG; +#else + dwFlags = 0; // D3DXASM_SKIPVALIDATION; +#endif + + ddlogMessage(DDLOG_INFO, "Creating shaders...\n"); + + // Init the shader handle + gld->VStwosidelight.hShader = 0; + + if (gld->d3dCaps8.MaxStreams == 0) { + // Lame DX8 driver doesn't support streams + // Not fatal, as defaults will be used + ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n"); + return; + } + + // ** THIS DISABLES VERTEX SHADER SUPPORT ** +// return; + // ** THIS DISABLES VERTEX SHADER SUPPORT ** + + // + // Two-sided lighting + // + +#if 0 + // + // DEBUGGING: Load shader from a text file + // + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + hr = D3DXAssembleShaderFromFile( + "twoside.vsh", + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#else + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + // Assemble ascii shader text into shader opcodes + hr = D3DXAssembleShader( + szTwoSidedLightingVS, + strlen(szTwoSidedLightingVS), + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#endif + if (FAILED(hr)) { + ddlogError(DDLOG_WARN, "AssembleShader failed", hr); + SAFE_RELEASE(pVSOpcodeBuffer); + return; + } + +// This is for debugging. Remove to enable vertex shaders in HW +#define _GLD_FORCE_SW_VS 0 + + if (_GLD_FORCE_SW_VS) { + // _GLD_FORCE_SW_VS should be disabled for Final Release + ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n"); + } + + // Try and create shader in hardware. + // NOTE: The D3D Ref device appears to succeed when trying to + // create the device in hardware, but later complains + // when trying to set it with SetVertexShader(). Go figure. + if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) { + // Don't try and create a hardware shader with the Ref device + hr = E_FAIL; // COM error/fail result + } else { + gld->VStwosidelight.bHardware = TRUE; + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + 0); + } + if (FAILED(hr)) { + ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n"); + // Failed. Try and create shader for software processing + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + D3DUSAGE_SOFTWAREPROCESSING); + if (FAILED(hr)) { + gld->VStwosidelight.hShader = 0; // Sanity check + ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr); + return; + } + // Succeeded, but for software processing + gld->VStwosidelight.bHardware = FALSE; + } + + SAFE_RELEASE(pVSOpcodeBuffer); + + ddlogMessage(DDLOG_INFO, "... OK\n"); +} + +//--------------------------------------------------------------------------- + +void _gldDestroyVertexShaders( + GLD_driver_dx8 *gld) +{ + if (gld->VStwosidelight.hShader) { + IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader); + gld->VStwosidelight.hShader = 0; + } +} +*/ +//--------------------------------------------------------------------------- + +LPVOID lpOpaque1 = NULL; +LPVOID lpOpaque2 = NULL; + +BOOL gldCreateDrawable_DX( + DGL_ctx *ctx, +// BOOL bDefaultDriver, + BOOL bDirectDrawPersistant, + BOOL bPersistantBuffers) +{ + // + // bDirectDrawPersistant: applies to IDirect3D8 + // bPersistantBuffers: applies to IDirect3DDevice8 + // + + HRESULT hResult; + GLD_driver_dx8 *lpCtx = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + DWORD dwBehaviourFlags; + D3DADAPTER_IDENTIFIER8 d3dIdent; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + if (ctx->glPriv) { + lpCtx = ctx->glPriv; + // Release any existing interfaces + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + } else { + lpCtx = (GLD_driver_dx8*)malloc(sizeof(GLD_driver_dx8)); + ZeroMemory(lpCtx, sizeof(lpCtx)); + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + // TODO: Check this +// if (bDefaultDriver) +// d3dDevType = D3DDEVTYPE_REF; + + // Use persistant interface if needed + if (bDirectDrawPersistant && dx8Globals.bDirect3D) { + lpCtx->pD3D = dx8Globals.pD3D; + IDirect3D8_AddRef(lpCtx->pD3D); + goto SkipDirectDrawCreate; + } + + // Create Direct3D8 object + lpCtx->pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); + if (lpCtx->pD3D == NULL) { + MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK); + ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface"); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Cache Direct3D interface for subsequent GLRCs + if (bDirectDrawPersistant && !dx8Globals.bDirect3D) { + dx8Globals.pD3D = lpCtx->pD3D; + IDirect3D8_AddRef(dx8Globals.pD3D); + dx8Globals.bDirect3D = TRUE; + } +SkipDirectDrawCreate: + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Get device caps + hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Check for hardware transform & lighting + lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; + + // If this flag is present then we can't default to Mesa + // SW rendering between BeginScene() and EndScene(). + if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { + ddlogMessage(DDLOG_WARN, + "Warning : No 2D allowed during 3D scene.\n"); + } + + // + // Create the Direct3D context + // + + // Re-use original IDirect3DDevice if persistant buffers exist. + // Note that we test for persistant IDirect3D8 as well + // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist) + if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D && dx8Globals.pDev) { + lpCtx->pDev = dx8Globals.pDev; + IDirect3DDevice8_AddRef(dx8Globals.pDev); + goto skip_direct3ddevice_create; + } + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + + // Support for vertical retrace synchronisation. + // Set default presentation interval in case caps bits are missing + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + // FullScreen_PresentationInterval must be default for Windowed mode + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + + // Decide if we can use hardware TnL + dwBehaviourFlags = (lpCtx->bHasHWTnL) ? + D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; + // Add flag to tell D3D to be thread-safe + if (glb.bMultiThreaded) + dwBehaviourFlags |= D3DCREATE_MULTITHREADED; + // Add flag to tell D3D to be FPU-safe + if (!glb.bFastFPU) + dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE; + hResult = IDirect3D8_CreateDevice(lpCtx->pD3D, + glb.dwAdapter, + d3dDevType, + ctx->hWnd, + dwBehaviourFlags, + &d3dpp, + &lpCtx->pDev); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D) { + dx8Globals.pDev = lpCtx->pDev; + dx8Globals.bDirect3DDevice = TRUE; + } + +/* + // See if DDraw interfaces are available (DaveM) + hResult = IDirect3D8_QueryInterface(lpCtx->pDev, + &IID_IDirectDraw7, (LPVOID*)&lpOpaque1); + if (FAILED(hResult) || lpOpaque1 == NULL) { + ddlogMessage(DDLOG_INFO, "DirectDraw QueryInterface unavailable\n"); + } + + hResult = IDirect3DDevice8_QueryInterface(lpCtx->pDev, + &IID_IDirectDrawSurface7, (LPVOID*)&lpOpaque2); + if (FAILED(hResult) || lpOpaque2 == NULL) { + ddlogMessage(DDLOG_INFO, "DirectDrawSurface QueryInterface unavialable\n"); + } +*/ + // Dump some useful stats + hResult = IDirect3D8_GetAdapterIdentifier( + lpCtx->pD3D, + glb.dwAdapter, + D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay + &d3dIdent); + if (SUCCEEDED(hResult)) { + ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); + ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", + d3dIdent.Driver, + HIWORD(d3dIdent.DriverVersion.HighPart), + LOWORD(d3dIdent.DriverVersion.HighPart), + HIWORD(d3dIdent.DriverVersion.LowPart), + LOWORD(d3dIdent.DriverVersion.LowPart)); + ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", + d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); + } + + // Init projection matrix for D3D TnL + D3DXMatrixIdentity(&lpCtx->matProjection); + lpCtx->matModelView = lpCtx->matProjection; +// gld->bUseMesaProjection = TRUE; + +skip_direct3ddevice_create: + + // Create buffers to hold primitives + lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; + lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; + lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); + lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); + if (FAILED(hResult)) + goto return_with_error; + + lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; + lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; + lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); + lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); + if (FAILED(hResult)) + goto return_with_error; + +/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders) + lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX; + lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT; + lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX); + lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight); + if (FAILED(hResult)) + goto return_with_error;*/ + + // Now try and create the DX8 Vertex Shaders +// _gldCreateVertexShaders(lpCtx); + + // Zero the pipeline usage counters + lpCtx->PipelineUsage.qwMesa.QuadPart = +// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = + lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; + + // Assign drawable to GL private + ctx->glPriv = lpCtx; + return TRUE; + +return_with_error: + // Clean up and bail + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL gldResizeDrawable_DX( + DGL_ctx *ctx, + BOOL bDefaultDriver, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + GLD_driver_dx8 *gld = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + HRESULT hResult; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice8_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + if (!bDefaultDriver) + d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software) + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; +// goto return_with_error; + return FALSE; + } + + // Destroy DX8 Vertex Shaders before Reset() +// _gldDestroyVertexShaders(gld); + + // Release POOL_DEFAULT objects before Reset() + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB2d); + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB3d); +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) +// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight); + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + // TODO: Sync to refresh + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + // Get better benchmark results? KeithH +// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED; + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult); + return FALSE; + //goto cleanup_and_return_with_error; + } + + // Explicitly Clear resized surfaces (DaveM) + { + D3DVIEWPORT8 d3dvp1, d3dvp2; + IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp1); + IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp2); + d3dvp1.X = 0; + d3dvp1.Y = 0; + d3dvp1.Width = ctx->dwWidth; + d3dvp1.Height = ctx->dwHeight; + IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp1); + IDirect3DDevice8_Clear(gld->pDev,0,NULL,D3DCLEAR_TARGET,0,0,0); + IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp2); + } + + // + // Recreate POOL_DEFAULT objects + // + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); + } + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d); + } +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) { +// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); +// } + + // Recreate DX8 Vertex Shaders +// _gldCreateVertexShaders(gld); + + // Signal a complete state update + ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL); + + // Begin a new scene + IDirect3DDevice8_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyDrawable_DX( + DGL_ctx *ctx) +{ + GLD_driver_dx8 *lpCtx = NULL; + + // Error if context is NULL. + if (!ctx) + return FALSE; + + // Error if the drawable does not exist. + if (!ctx->glPriv) + return FALSE; + + lpCtx = ctx->glPriv; + +#ifdef _DEBUG + // Dump out stats + ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X", + lpCtx->PipelineUsage.qwMesa.HighPart, + lpCtx->PipelineUsage.qwMesa.LowPart, + lpCtx->PipelineUsage.qwD3DFVF.HighPart, + lpCtx->PipelineUsage.qwD3DFVF.LowPart); +#endif + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + + // Free the private drawable data + free(ctx->glPriv); + ctx->glPriv = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldCreatePrivateGlobals_DX(void) +{ + ZeroMemory(&dx8Globals, sizeof(dx8Globals)); + + // Load d3d8.dll + dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL"); + if (dx8Globals.hD3D8DLL == NULL) + return FALSE; + + // Now try and obtain Direct3DCreate8 + dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8"); + if (dx8Globals.fnDirect3DCreate8 == NULL) { + FreeLibrary(dx8Globals.hD3D8DLL); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyPrivateGlobals_DX(void) +{ + if (dx8Globals.bDirect3DDevice) { + SAFE_RELEASE(dx8Globals.pDev); + dx8Globals.bDirect3DDevice = FALSE; + } + if (dx8Globals.bDirect3D) { + SAFE_RELEASE(dx8Globals.pD3D); + dx8Globals.bDirect3D = FALSE; + } + + FreeLibrary(dx8Globals.hD3D8DLL); + dx8Globals.hD3D8DLL = NULL; + dx8Globals.fnDirect3DCreate8 = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDisplayFormat( + D3DFORMAT fmt, + BYTE *cColorBits, + BYTE *cRedBits, + BYTE *cGreenBits, + BYTE *cBlueBits, + BYTE *cAlphaBits) +{ + switch (fmt) { + case D3DFMT_X1R5G5B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 5; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_R5G6B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 6; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_X8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; + return; + case D3DFMT_A8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 8; + return; + } + + // Should not get here! + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDepthStencilFormat( + D3DFORMAT fmt, + BYTE *cDepthBits, + BYTE *cStencilBits) +{ + // NOTE: GL expects either 32 or 16 as depth bits. + switch (fmt) { + case D3DFMT_D32: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D15S1: + *cDepthBits = 16; + *cStencilBits = 1; + return; + case D3DFMT_D24S8: + *cDepthBits = 32; + *cStencilBits = 8; + return; + case D3DFMT_D16: + *cDepthBits = 16; + *cStencilBits = 0; + return; + case D3DFMT_D24X8: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D24X4S4: + *cDepthBits = 32; + *cStencilBits = 4; + return; + } +} + +//--------------------------------------------------------------------------- + +BOOL gldBuildPixelformatList_DX(void) +{ + D3DDISPLAYMODE d3ddm; + D3DFORMAT fmt[6]; + IDirect3D8 *pD3D = NULL; + HRESULT hr; + int nSupportedFormats = 0; + int i; + DGL_pixelFormat *pPF; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; +// char buf[128]; +// char cat[8]; + + // Direct3D (SW or HW) + // These are arranged so that 'best' pixelformat + // is higher in the list (for ChoosePixelFormat). + const D3DFORMAT DepthStencil[6] = { + D3DFMT_D15S1, + D3DFMT_D16, + D3DFMT_D24X8, + D3DFMT_D24X4S4, + D3DFMT_D24S8, + D3DFMT_D32, + }; + + // Dump DX version + ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 8.0\n"); + + // Release any existing pixelformat list + if (glb.lpPF) { + free(glb.lpPF); + } + + glb.nPixelFormatCount = 0; + glb.lpPF = NULL; + + // + // Pixelformats for Direct3D (SW or HW) rendering + // + + // Get a Direct3D 8.0 interface + pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95); + if (!pD3D) { + return FALSE; + } + + // We will use the display mode format when finding compliant + // rendertarget/depth-stencil surfaces. + hr = IDirect3D8_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) { + IDirect3D8_Release(pD3D); + return FALSE; + } + + // Run through the possible formats and detect supported formats + for (i=0; i<6; i++) { + hr = IDirect3D8_CheckDeviceFormat( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal. + continue; + + // Verify that the depth format is compatible. + hr = IDirect3D8_CheckDepthStencilMatch( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + d3ddm.Format, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal, just means depth-stencil + // format is not compatible with this display mode. + continue; + + fmt[nSupportedFormats++] = DepthStencil[i]; + } + + IDirect3D8_Release(pD3D); + + if (nSupportedFormats == 0) + return FALSE; // Bail: no compliant pixelformats + + // Total count of pixelformats is: + // (nSupportedFormats+1)*2 + glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat)); + glb.nPixelFormatCount = (nSupportedFormats)*2; + if (glb.lpPF == NULL) { + glb.nPixelFormatCount = 0; + return FALSE; + } + + // Get a copy of pointer that we can alter + pPF = glb.lpPF; + + // Cache colour bits from display format + _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + // + // Add single-buffer formats + // + + // Single-buffer, no depth-stencil buffer +/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++;*/ + + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // + // Add double-buffer formats + // + +/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++;*/ + + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // Popup warning message if non RGB color mode + { + // This is a hack. KeithH + HDC hdcDesktop = GetDC(NULL); + DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL); + ReleaseDC(0, hdcDesktop); + if (dwDisplayBitDepth <= 8) { + ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth); + MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING); + } + } + + // Mark list as 'current' + glb.bPixelformatsDirty = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldInitialiseMesa_DX( + DGL_ctx *lpCtx) +{ + GLD_driver_dx8 *gld = NULL; + int MaxTextureSize, TextureLevels; + BOOL bSoftwareTnL; + + if (lpCtx == NULL) + return FALSE; + + gld = lpCtx->glPriv; + if (gld == NULL) + return FALSE; + + if (glb.bMultitexture) { + lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps8.MaxSimultaneousTextures; + // Only support MAX_TEXTURE_UNITS texture units. + // ** If this is altered then the FVF formats must be reviewed **. + if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX8) + lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX8; + } else { + // Multitexture override + lpCtx->glCtx->Const.MaxTextureUnits = 1; + } + + // max texture size + MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth); + if (MaxTextureSize == 0) + MaxTextureSize = 256; // Sanity check + + // + // HACK!! + if (MaxTextureSize > 1024) + MaxTextureSize = 1024; // HACK - CLAMP TO 1024 + // HACK!! + // + + // Got to set MAX_TEXTURE_SIZE as max levels. + // Who thought this stupid idea up? ;) + TextureLevels = 0; + // Calculate power-of-two. + while (MaxTextureSize) { + TextureLevels++; + MaxTextureSize >>= 1; + } + lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8; + + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE); + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE); + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ZENABLE, + (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE); + + // Set the view matrix + { + D3DXMATRIX vm; +#if 1 + D3DXMatrixIdentity(&vm); +#else + D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f); + D3DXVECTOR3 At(0.0f, 0.0f, -1.0f); + D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); + D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up); + vm._31 = -vm._31; + vm._32 = -vm._32; + vm._33 = -vm._33; + vm._34 = -vm._34; +#endif + IDirect3DDevice8_SetTransform(gld->pDev, D3DTS_VIEW, &vm); + } + + if (gld->bHasHWTnL) { + if (glb.dwTnL == GLDS_TNL_DEFAULT) + bSoftwareTnL = FALSE; // HW TnL + else { + bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE; + } + } else { + // No HW TnL, so no choice possible + bSoftwareTnL = TRUE; + } + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL); + +// Dump this in a Release build as well, now. +//#ifdef _DEBUG + ddlogPrintf(DDLOG_INFO, "HW TnL: %s", + gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable"); +//#endif + + gldEnableExtensions_DX8(lpCtx->glCtx); + gldInstallPipeline_DX8(lpCtx->glCtx); + gldSetupDriverPointers_DX8(lpCtx->glCtx); + + // Signal a complete state update + lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL); + + // Start a scene + IDirect3DDevice8_BeginScene(gld->pDev); + lpCtx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldSwapBuffers_DX( + DGL_ctx *ctx, + HDC hDC, + HWND hWnd) +{ + HRESULT hr; + GLD_driver_dx8 *gld = NULL; + + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice8_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + // Swap the buffers. hWnd may override the hWnd used for CreateDevice() + hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL); + + IDirect3DDevice8_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return (FAILED(hr)) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldGetDisplayMode_DX( + DGL_ctx *ctx, + GLD_displayMode *glddm) +{ + D3DDISPLAYMODE d3ddm; + HRESULT hr; + GLD_driver_dx8 *lpCtx = NULL; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; + + if ((glddm == NULL) || (ctx == NULL)) + return FALSE; + + lpCtx = ctx->glPriv; + if (lpCtx == NULL) + return FALSE; + + if (lpCtx->pD3D == NULL) + return FALSE; + + hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) + return FALSE; + + // Get info from the display format + _BitsFromDisplayFormat(d3ddm.Format, + &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + glddm->Width = d3ddm.Width; + glddm->Height = d3ddm.Height; + glddm->BPP = cColorBits; + glddm->Refresh = d3ddm.RefreshRate; + + return TRUE; +} + +//--------------------------------------------------------------------------- + diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c new file mode 100644 index 00000000000..1b01cb1f7f3 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c @@ -0,0 +1,1206 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Driver interface code to Mesa +* +****************************************************************************/ + +//#include <windows.h> +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +extern BOOL dglSwapBuffers(HDC hDC); + +// HACK: Hack the _33 member of the OpenGL perspective projection matrix +const float _fPersp_33 = 1.6f; + +//--------------------------------------------------------------------------- +// Internal functions +//--------------------------------------------------------------------------- + +void _gld_mesa_warning( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal warning mechanism + gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str); +} + +//--------------------------------------------------------------------------- + +void _gld_mesa_fatal( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal fatal-message mechanism + gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str); + + // Mesa calls abort(0) here. + ddlogClose(); + exit(0); +} + +//--------------------------------------------------------------------------- + +D3DSTENCILOP _gldConvertStencilOp( + GLenum StencilOp) +{ + // Used by Stencil: pass, fail and zfail + + switch (StencilOp) { + case GL_KEEP: + return D3DSTENCILOP_KEEP; + case GL_ZERO: + return D3DSTENCILOP_ZERO; + case GL_REPLACE: + return D3DSTENCILOP_REPLACE; + case GL_INCR: + return D3DSTENCILOP_INCRSAT; + case GL_DECR: + return D3DSTENCILOP_DECRSAT; + case GL_INVERT: + return D3DSTENCILOP_INVERT; + case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_INCR; + case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_DECR; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n"); +#endif + + return D3DSTENCILOP_KEEP; +} + +//--------------------------------------------------------------------------- + +D3DCMPFUNC _gldConvertCompareFunc( + GLenum CmpFunc) +{ + // Used for Alpha func, depth func and stencil func. + + switch (CmpFunc) { + case GL_NEVER: + return D3DCMP_NEVER; + case GL_LESS: + return D3DCMP_LESS; + case GL_EQUAL: + return D3DCMP_EQUAL; + case GL_LEQUAL: + return D3DCMP_LESSEQUAL; + case GL_GREATER: + return D3DCMP_GREATER; + case GL_NOTEQUAL: + return D3DCMP_NOTEQUAL; + case GL_GEQUAL: + return D3DCMP_GREATEREQUAL; + case GL_ALWAYS: + return D3DCMP_ALWAYS; + }; + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n"); +#endif + + return D3DCMP_ALWAYS; +} + +//--------------------------------------------------------------------------- + +D3DBLEND _gldConvertBlendFunc( + GLenum blend, + GLenum DefaultBlend) +{ + switch (blend) { + case GL_ZERO: + return D3DBLEND_ZERO; + case GL_ONE: + return D3DBLEND_ONE; + case GL_DST_COLOR: + return D3DBLEND_DESTCOLOR; + case GL_SRC_COLOR: + return D3DBLEND_SRCCOLOR; + case GL_ONE_MINUS_DST_COLOR: + return D3DBLEND_INVDESTCOLOR; + case GL_ONE_MINUS_SRC_COLOR: + return D3DBLEND_INVSRCCOLOR; + case GL_SRC_ALPHA: + return D3DBLEND_SRCALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + return D3DBLEND_INVSRCALPHA; + case GL_DST_ALPHA: + return D3DBLEND_DESTALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return D3DBLEND_INVDESTALPHA; + case GL_SRC_ALPHA_SATURATE: + return D3DBLEND_SRCALPHASAT; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n"); +#endif + + return DefaultBlend; +} + +//--------------------------------------------------------------------------- +// Misc. functions +//--------------------------------------------------------------------------- + +void gld_Noop_DX9( + GLcontext *ctx) +{ +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n"); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_Error_DX9( + GLcontext *ctx) +{ +#ifdef _DEBUG + // Quite useless. +// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n"); +#endif +} + +//--------------------------------------------------------------------------- +// Required Mesa functions +//--------------------------------------------------------------------------- + +static GLboolean gld_set_draw_buffer_DX9( + GLcontext *ctx, + GLenum mode) +{ + (void) ctx; + if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +//--------------------------------------------------------------------------- + +static void gld_set_read_buffer_DX9( + GLcontext *ctx, + GLframebuffer *buffer, + GLenum mode) +{ + /* separate read buffer not supported */ +/* + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(mode == GL_FRONT_LEFT); +*/ +} + +//--------------------------------------------------------------------------- + +void gld_Clear_DX9( + GLcontext *ctx, + GLbitfield mask, + GLboolean all, + GLint x, + GLint y, + GLint width, + GLint height) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DCOLOR Color = 0; + float Z = 0.0f; + DWORD Stencil = 0; + D3DRECT d3dClearRect; + + // TODO: Colourmask + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if (!gld->pDev) + return; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + GLubyte col[4]; + CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]); + dwFlags |= D3DCLEAR_TARGET; + Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]); + } + + if (mask & DD_DEPTH_BIT) { + // D3D8 will fail the Clear call if we try and clear a + // depth buffer and we haven't created one. + // Also, some apps try and clear a depth buffer, + // when a depth buffer hasn't been requested by the app. + if (ctx->Visual.depthBits == 0) { + mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask + } else { + dwFlags |= D3DCLEAR_ZBUFFER; + Z = ctx->Depth.Clear; + } + } + + if (mask & DD_STENCIL_BIT) { + if (ctx->Visual.stencilBits == 0) { + // No stencil bits in depth buffer + mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask + } else { + dwFlags |= D3DCLEAR_STENCIL; + Stencil = ctx->Stencil.Clear; + } + } + + // Some apps do really weird things with the rect, such as Quake3. + if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) { + all = GL_TRUE; + } + + if (!all) { + // Calculate clear subrect + d3dClearRect.x1 = x; + d3dClearRect.y1 = gldCtx->dwHeight - (y + height); + d3dClearRect.x2 = x + width; + d3dClearRect.y2 = d3dClearRect.y1 + height; +// gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height); + } + + // dwFlags will be zero if there's nothing to clear + if (dwFlags) { + _GLD_DX9_DEV(Clear( + gld->pDev, + all ? 0 : 1, + all ? NULL : &d3dClearRect, + dwFlags, + Color, Z, Stencil)); + } + + if (mask & DD_ACCUM_BIT) { + // Clear accumulation buffer + } +} + +//--------------------------------------------------------------------------- + +// Mesa 5: Parameter change +static void gld_buffer_size_DX9( +// GLcontext *ctx, + GLframebuffer *fb, + GLuint *width, + GLuint *height) +{ +// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + + *width = fb->Width; // gldCtx->dwWidth; + *height = fb->Height; // gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +static void gld_Finish_DX9( + GLcontext *ctx) +{ +} + +//--------------------------------------------------------------------------- + +static void gld_Flush_DX9( + GLcontext *ctx) +{ + GLD_context *gld = GLD_GET_CONTEXT(ctx); + + // TODO: Detect apps that glFlush() then SwapBuffers() ? + + if (gld->EmulateSingle) { + // Emulating a single-buffered context. + // [Direct3D doesn't allow rendering to front buffer] + dglSwapBuffers(gld->hDC); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_STENCIL( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Two-sided stencil. New for Mesa 5 + const GLuint uiFace = 0UL; + + struct gl_stencil_attrib *pStencil = &ctx->Stencil; + + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE)); + if (pStencil->Enabled) { + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace]))); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_COLOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DBLEND src; + D3DBLEND dest; + + // Alpha func + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled)); + + // Blend func + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled)); + src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE); + dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest)); + + // Color mask + if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED; + if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN; + if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE; + if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_DEPTH( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_POLYGON( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DFILLMODE d3dFillMode = D3DFILL_SOLID; + D3DCULL d3dCullMode = D3DCULL_NONE; + float fOffset = 0; // Changed from int to float for DX9 + + // Fillmode + switch (ctx->Polygon.FrontMode) { + case GL_POINT: + d3dFillMode = D3DFILL_POINT; + break; + case GL_LINE: + d3dFillMode = D3DFILL_WIREFRAME; + break; + case GL_FILL: + d3dFillMode = D3DFILL_SOLID; + break; + } + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode)); + + if (ctx->Polygon.CullFlag) { + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CW; + else + d3dCullMode = D3DCULL_CCW; + break; + case GL_FRONT: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CCW; + else + d3dCullMode = D3DCULL_CW; + break; + case GL_FRONT_AND_BACK: + d3dCullMode = D3DCULL_NONE; + break; + default: + break; + } + } else { + d3dCullMode = D3DCULL_NONE; + } +// d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode)); + + // Polygon offset + // ZBIAS ranges from 0 to 16 and can only move towards the viewer + // Mesa5: ctx->Polygon._OffsetAny removed + if (ctx->Polygon.OffsetFill) { + fOffset = ctx->Polygon.OffsetUnits; +// if (iOffset < 0.0f) +// iOffset = -iOffset; +// else +// iOffset = 0.0f; // D3D can't push away + } + // NOTE: SetRenderState() required a DWORD, so need to cast + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DEPTHBIAS, *((DWORD*)&fOffset))); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_FOG( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DCOLOR d3dFogColour; + D3DFOGMODE d3dFogMode = D3DFOG_LINEAR; + + // TODO: Fog is calculated seperately in the Mesa pipeline + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE)); + return; + + // Fog enable + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled)); + if (!ctx->Fog.Enabled) { + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); + return; // If disabled, don't bother setting any fog state + } + + // Fog colour + d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0], + ctx->Fog.Color[1], + ctx->Fog.Color[2], + ctx->Fog.Color[3]); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour)); + + // Fog density + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density)))); + + // Fog start + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start)))); + + // Fog end + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End)))); + + // Fog mode + switch (ctx->Fog.Mode) { + case GL_LINEAR: + d3dFogMode = D3DFOG_LINEAR; + break; + case GL_EXP: + d3dFogMode = D3DFOG_EXP; + break; + case GL_EXP2: + d3dFogMode = D3DFOG_EXP2; + break; + } + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_LIGHT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + DWORD dwSpecularEnable; + + // Shademode + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); + + // Separate specular colour + if (ctx->Light.Enabled) + dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE; + else + dwSpecularEnable = FALSE; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_MODELVIEW( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ModelView.m; + // Mesa5: Model-view is now a stack + GLfloat *pM = ctx->ModelviewMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10]; + m._34 = pM[11]; + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14]; + m._44 = pM[15]; + + gld->matModelView = m; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_PROJECTION( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ProjectionMatrix.m; + // Mesa 5: Now a stack + GLfloat *pM = ctx->ProjectionMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10] / _fPersp_33; // / 1.6f; + m._34 = pM[11]; + + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14] / 2.0f; + m._44 = pM[15]; + + gld->matProjection = m; +} + +//--------------------------------------------------------------------------- +/* +void gldFrustumHook_DX9( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Frustum(left, right, bottom, top, nearval, farval); + + _fPersp_33 = farval / (nearval - farval); + +// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval); +} + +//--------------------------------------------------------------------------- + +void gldOrthoHook_DX9( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Ortho(left, right, bottom, top, nearval, farval); + + _fPersp_33 = 1.6f; + +// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval); +} +*/ +//--------------------------------------------------------------------------- + +void gld_NEW_VIEWPORT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DVIEWPORT9 d3dvp; +// GLint x, y; +// GLsizei w, h; + + // Set depth range + _GLD_DX9_DEV(GetViewport(gld->pDev, &d3dvp)); + // D3D can't do Quake1/Quake2 z-trick + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } +/* x = ctx->Viewport.X; + y = ctx->Viewport.Y; + w = ctx->Viewport.Width; + h = ctx->Viewport.Height; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h;*/ + _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp)); + +// gld->fFlipWindowY = (float)gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_SCISSOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Bail if IHV driver cannot scissor + if (!gld->bCanScissor) + return; + + // Set scissor rect + if (ctx->Scissor.Enabled) { + RECT rcRect; + // Keep in mind that RECT's need an extra row and column + rcRect.left = ctx->Scissor.X; + rcRect.right = ctx->Scissor.X + ctx->Scissor.Width; // + 1; + rcRect.top = gldCtx->dwHeight - (ctx->Scissor.Y + ctx->Scissor.Height); + rcRect.bottom = rcRect.top + ctx->Scissor.Height; + IDirect3DDevice9_SetScissorRect(gld->pDev, &rcRect); + } + + // Enable/disable scissor as required + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SCISSORTESTENABLE, ctx->Scissor.Enabled)); +} + +//--------------------------------------------------------------------------- + +__inline BOOL _gldAnyEvalEnabled( + GLcontext *ctx) +{ + struct gl_eval_attrib *eval = &ctx->Eval; + + if ((eval->AutoNormal) || + (eval->Map1Color4) || + (eval->Map1Index) || + (eval->Map1Normal) || + (eval->Map1TextureCoord1) || + (eval->Map1TextureCoord2) || + (eval->Map1TextureCoord3) || + (eval->Map1TextureCoord4) || + (eval->Map1Vertex3) || + (eval->Map1Vertex4) || + (eval->Map2Color4) || + (eval->Map2Index) || + (eval->Map2Normal) || + (eval->Map2TextureCoord1) || + (eval->Map2TextureCoord2) || + (eval->Map2TextureCoord3) || + (eval->Map2TextureCoord4) || + (eval->Map2Vertex3) || + (eval->Map2Vertex4) + ) + return TRUE; + + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL _gldChooseInternalPipeline( + GLcontext *ctx, + GLD_driver_dx9 *gld) +{ +// return TRUE; // DEBUGGING: ALWAYS USE MESA +// return FALSE; // DEBUGGING: ALWAYS USE D3D + + if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE)) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; // Force Mesa TnL + } + + if ((ctx->Light.Enabled) || + (1) || + (ctx->Texture._TexGenEnabled) || + (ctx->Texture._TexMatEnabled) || +// (ctx->Transform._AnyClip) || + (ctx->Scissor.Enabled) || + _gldAnyEvalEnabled(ctx) // Put this last so we can early-out + ) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; + } + + gld->PipelineUsage.qwD3DFVF.QuadPart++; + return FALSE; + +/* // Force Mesa pipeline? + if (glb.dwTnL == GLDS_TNL_MESA) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Test for functionality not exposed in the D3D pathways + if ((ctx->Texture._GenFlags)) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Now decide if vertex shader can be used. + // If two sided lighting is enabled then we must either + // use Mesa TnL or the vertex shader + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) { + // Use Vertex Shader + gld->PipelineUsage.dwD3D2SVS.QuadPart++; + return GLD_PIPELINE_D3D_VS_TWOSIDE; + } else { + // Use Mesa TnL + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + } + + // Must be D3D fixed-function pipeline + gld->PipelineUsage.dwD3DFVF.QuadPart++; + return GLD_PIPELINE_D3D_FVF; +*/ +} + +//--------------------------------------------------------------------------- + +void gld_update_state_DX9( + GLcontext *ctx, + GLuint new_state) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLD_pb_dx9 *gldPB; + + if (!gld || !gld->pDev) + return; + + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + + // SetupIndex will be used in the pipelines for choosing setup function + if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) || + (ctx->Fog.Enabled)) + { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT_EXTRAS; + else + gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS; + } else { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture + else + gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture + } + + gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld); + if (gld->bUseMesaTnL) { + gldPB = &gld->PB2d; + _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, TRUE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE)); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); + } else { + gldPB = &gld->PB3d; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE)); +// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) { +// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware)); +// _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); +// } else { +// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL)); + _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, !gld->bHasHWTnL)); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); +// } + } + +#define _GLD_TEST_STATE(a) \ + if (new_state & (a)) { \ + gld##a(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_TEST_STATE_DX9(a) \ + if (new_state & (a)) { \ + gld##a##_DX9(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_IGNORE_STATE(a) new_state &= ~(a); + +// if (!gld->bUseMesaTnL) { + // Not required if Mesa is doing the TnL. + // Problem: If gld->bUseMesaTnL is TRUE when these are signaled, + // then we'll miss updating the D3D TnL pipeline. + // Therefore, don't test for gld->bUseMesaTnL + _GLD_TEST_STATE(_NEW_MODELVIEW); + _GLD_TEST_STATE(_NEW_PROJECTION); +// } + + _GLD_TEST_STATE_DX9(_NEW_TEXTURE); // extern, so guard with _DX9 + _GLD_TEST_STATE(_NEW_COLOR); + _GLD_TEST_STATE(_NEW_DEPTH); + _GLD_TEST_STATE(_NEW_POLYGON); + _GLD_TEST_STATE(_NEW_STENCIL); + _GLD_TEST_STATE(_NEW_FOG); + _GLD_TEST_STATE(_NEW_LIGHT); + _GLD_TEST_STATE(_NEW_VIEWPORT); + + _GLD_IGNORE_STATE(_NEW_TRANSFORM); + + // Scissor Test: New for DX9 + _GLD_TEST_STATE(_NEW_SCISSOR); + +// Stubs for future use. +/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_STATE(_NEW_ACCUM); + _GLD_TEST_STATE(_NEW_EVAL); + _GLD_TEST_STATE(_NEW_HINT); + _GLD_TEST_STATE(_NEW_LINE); + _GLD_TEST_STATE(_NEW_PIXEL); + _GLD_TEST_STATE(_NEW_POINT); + _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_STATE(_NEW_PACKUNPACK); + _GLD_TEST_STATE(_NEW_ARRAY); + _GLD_TEST_STATE(_NEW_RENDERMODE); + _GLD_TEST_STATE(_NEW_BUFFERS); + _GLD_TEST_STATE(_NEW_MULTISAMPLE); +*/ + +// For debugging. +#if 0 +#define _GLD_TEST_UNHANDLED_STATE(a) \ + if (new_state & (a)) { \ + gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \ + } + _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); + _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); + _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); + _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL); + _GLD_TEST_UNHANDLED_STATE(_NEW_POINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE); +// _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR); + _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK); + _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY); + _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE); + _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS); + _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE); +#undef _GLD_UNHANDLED_STATE +#endif + +#undef _GLD_TEST_STATE +} + +//--------------------------------------------------------------------------- +// Viewport +//--------------------------------------------------------------------------- + +void gld_Viewport_DX9( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei w, + GLsizei h) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DVIEWPORT9 d3dvp; + + if (!gld || !gld->pDev) + return; + + // This is a hack. When the app is minimized, Mesa passes + // w=1 and h=1 for viewport dimensions. Without this test + // we get a GPF in gld_wgl_resize_buffers(). + if ((w==1) && (h==1)) + return; + + // Call ResizeBuffersMESA. This function will early-out + // if no resize is needed. + //ctx->Driver.ResizeBuffersMESA(ctx); + // Mesa 5: Changed parameters + ctx->Driver.ResizeBuffers(gldCtx->glBuffer); + +#if 0 + ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h); +#endif + + // ** D3D viewport must not be outside the render target surface ** + // Sanity check the GL viewport dimensions + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h; + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } + + // TODO: DEBUGGING +// d3dvp.MinZ = 0.0f; +// d3dvp.MaxZ = 1.0f; + + _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp)); + +} + +//--------------------------------------------------------------------------- + +extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver); + +// Mesa 5: Parameter change +void gldResizeBuffers_DX9( +// GLcontext *ctx) + GLframebuffer *fb) +{ + GET_CURRENT_CONTEXT(ctx); + dglWglResizeBuffers(ctx, TRUE); +} + +//--------------------------------------------------------------------------- +#ifdef _DEBUG +// This is only for debugging. +// To use, plug into ctx->Driver.Enable pointer below. +void gld_Enable( + GLcontext *ctx, + GLenum e, + GLboolean b) +{ + char buf[1024]; + sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE"); + ddlogMessage(DDLOG_SYSTEM, buf); +} +#endif +//--------------------------------------------------------------------------- +// Driver pointer setup +//--------------------------------------------------------------------------- + +extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum); + +void gldSetupDriverPointers_DX9( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + + // Mandatory functions + ctx->Driver.GetString = _gldGetStringGeneric; + ctx->Driver.UpdateState = gld_update_state_DX9; + ctx->Driver.Clear = gld_Clear_DX9; + ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX9; + ctx->Driver.GetBufferSize = gld_buffer_size_DX9; + ctx->Driver.Finish = gld_Finish_DX9; + ctx->Driver.Flush = gld_Flush_DX9; + ctx->Driver.Error = gld_Error_DX9; + + // Hardware accumulation buffer + ctx->Driver.Accum = NULL; // TODO: gld_Accum; + + // Bitmap functions + ctx->Driver.CopyPixels = gld_CopyPixels_DX9; + ctx->Driver.DrawPixels = gld_DrawPixels_DX9; + ctx->Driver.ReadPixels = gld_ReadPixels_DX9; + ctx->Driver.Bitmap = gld_Bitmap_DX9; + + // Buffer resize + ctx->Driver.ResizeBuffers = gldResizeBuffers_DX9; + + // Texture image functions + ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX9; + ctx->Driver.TexImage1D = gld_TexImage1D_DX9; + ctx->Driver.TexImage2D = gld_TexImage2D_DX9; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX9; + ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX9; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + + ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX9; //NULL; + ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX9; //NULL; + ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX9; //NULL; + ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX9; //NULL; + ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX9; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + // Texture object functions + ctx->Driver.BindTexture = NULL; + ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!; + ctx->Driver.DeleteTexture = gld_DeleteTexture_DX9; + ctx->Driver.PrioritizeTexture = NULL; + + // Imaging functionality + ctx->Driver.CopyColorTable = NULL; + ctx->Driver.CopyColorSubTable = NULL; + ctx->Driver.CopyConvolutionFilter1D = NULL; + ctx->Driver.CopyConvolutionFilter2D = NULL; + + // State changing functions + ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc; + ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc; + ctx->Driver.ClearColor = NULL; //gld_ClearColor; + ctx->Driver.ClearDepth = NULL; //gld_ClearDepth; + ctx->Driver.ClearStencil = NULL; //gld_ClearStencil; + ctx->Driver.ColorMask = NULL; //gld_ColorMask; + ctx->Driver.CullFace = NULL; //gld_CullFace; + ctx->Driver.ClipPlane = NULL; //gld_ClipPlane; + ctx->Driver.FrontFace = NULL; //gld_FrontFace; + ctx->Driver.DepthFunc = NULL; //gld_DepthFunc; + ctx->Driver.DepthMask = NULL; //gld_DepthMask; + ctx->Driver.DepthRange = NULL; + ctx->Driver.Enable = NULL; //gld_Enable; + ctx->Driver.Fogfv = NULL; //gld_Fogfv; + ctx->Driver.Hint = NULL; //gld_Hint; + ctx->Driver.Lightfv = NULL; //gld_Lightfv; + ctx->Driver.LightModelfv = NULL; //gld_LightModelfv; + ctx->Driver.LineStipple = NULL; //gld_LineStipple; + ctx->Driver.LineWidth = NULL; //gld_LineWidth; + ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode; + ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv; + ctx->Driver.PointSize = NULL; //gld_PointSize; + ctx->Driver.PolygonMode = NULL; //gld_PolygonMode; + ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset; + ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple; + ctx->Driver.RenderMode = NULL; //gld_RenderMode; + ctx->Driver.Scissor = NULL; //gld_Scissor; + ctx->Driver.ShadeModel = NULL; //gld_ShadeModel; + ctx->Driver.StencilFunc = NULL; //gld_StencilFunc; + ctx->Driver.StencilMask = NULL; //gld_StencilMask; + ctx->Driver.StencilOp = NULL; //gld_StencilOp; + ctx->Driver.TexGen = NULL; //gld_TexGen; + ctx->Driver.TexEnv = NULL; + ctx->Driver.TexParameter = NULL; + ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix; + ctx->Driver.Viewport = gld_Viewport_DX9; + + _swsetup_Wakeup(ctx); + + tnl->Driver.RunPipeline = _tnl_run_pipeline; + tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX9; + tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; + tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; + + // Hook into glFrustum() and glOrtho() +// ctx->Exec->Frustum = gldFrustumHook_DX9; +// ctx->Exec->Ortho = gldOrthoHook_DX9; + +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h new file mode 100644 index 00000000000..aec40ac9dd1 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h @@ -0,0 +1,327 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 9.0 header file +* +****************************************************************************/ + +#ifndef _GLD_DX9_H +#define _GLD_DX9_H + +//--------------------------------------------------------------------------- +// Windows includes +//--------------------------------------------------------------------------- + +//#ifndef STRICT +//#define STRICT +//#endif + +//#define WIN32_LEAN_AND_MEAN +//#include <windows.h> +#include <d3d9.h> +#include <d3dx9.h> + +// MS screwed up with the DX8.1 SDK - there's no compile-time +// method of compiling for 8.0 via the 8.1 SDK unless you +// "make sure you don't use any 8.1 interfaces". +// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces. +// +// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95). +// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95). +// +//#define D3D_SDK_VERSION_DX9_SUPPORT_WIN95 120 +//#define D3D_SDK_VERSION_DX91 220 + +// Typedef for obtaining function from d3d8.dll +typedef IDirect3D9* (WINAPI *FNDIRECT3DCREATE9) (UINT); + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +#ifdef _DEBUG +#define _GLD_TEST_HRESULT(h) \ +{ \ + HRESULT _hr = (h); \ + if (FAILED(_hr)) { \ + gldLogError(GLDLOG_ERROR, #h, _hr); \ + } \ +} +#define _GLD_DX9(func) _GLD_TEST_HRESULT(IDirect3D9_##func##) +#define _GLD_DX9_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice9_##func##) +#define _GLD_DX9_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer9_##func##) +#define _GLD_DX9_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture9_##func##) +#else +#define _GLD_DX9(func) IDirect3D9_##func +#define _GLD_DX9_DEV(func) IDirect3DDevice9_##func +#define _GLD_DX9_VB(func) IDirect3DVertexBuffer9_##func +#define _GLD_DX9_TEX(func) IDirect3DTexture9_##func +#endif + +#define SAFE_RELEASE(p) \ +{ \ + if (p) { \ + (p)->lpVtbl->Release(p); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_VB9(p) \ +{ \ + if (p) { \ + IDirect3DVertexBuffer9_Release((p)); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_SURFACE9(p) \ +{ \ + if (p) { \ + IDirect3DSurface9_Release((p)); \ + (p) = NULL; \ + } \ +} + +// Setup index. +enum { + GLD_SI_FLAT = 0, + GLD_SI_SMOOTH = 1, + GLD_SI_FLAT_EXTRAS = 2, + GLD_SI_SMOOTH_EXTRAS = 3, +}; +/* +// Internal pipeline +typedef enum { + GLD_PIPELINE_MESA = 0, // Mesa pipeline + GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline + GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader +} GLD_tnl_pipeline; +*/ +//--------------------------------------------------------------------------- +// Vertex definitions for Fixed-Function pipeline +//--------------------------------------------------------------------------- + +// +// NOTE: If the number of texture units is altered then most of +// the texture code will need to be revised. +// + +#define GLD_MAX_TEXTURE_UNITS_DX9 2 + +// +// 2D vertex transformed by Mesa +// +#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \ + D3DFVF_DIFFUSE | \ + D3DFVF_SPECULAR | \ + D3DFVF_TEX2) +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT sz; // Screen Z (depth) + FLOAT rhw; // Reciprocal homogenous W + DWORD diffuse; // Diffuse colour + DWORD specular; // For separate-specular support + FLOAT t0_u, t0_v; // 1st set of texture coords + FLOAT t1_u, t1_v; // 2nd set of texture coords +} GLD_2D_VERTEX; + + +// +// 3D vertex transformed by Direct3D +// +#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \ + D3DFVF_DIFFUSE | \ + D3DFVF_TEX2) + +typedef struct { + D3DXVECTOR3 Position; // XYZ Vector in object space + D3DCOLOR Diffuse; // Diffuse colour + D3DXVECTOR2 TexUnit0; // Texture unit 0 + D3DXVECTOR2 TexUnit1; // Texture unit 1 +} GLD_3D_VERTEX; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// DX8 Vertex Shader +typedef struct { + DWORD hShader; // If NULL, shader is invalid and cannot be used + BOOL bHardware; // If TRUE then shader was created for hardware, + // otherwise shader was created for software. +} GLD_vertexShader; +*/ +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- + +// This keeps a count of how many times we choose each individual internal +// pathway. Useful for seeing if a certain pathway was ever used by an app, and +// how much each pathway is biased. +// Zero the members at context creation and dump stats at context deletion. +typedef struct { + // Note: DWORD is probably too small + ULARGE_INTEGER qwMesa; // Mesa TnL pipeline + ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline +// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline +} GLD_pipeline_usage; + +// GLDirect Primitive Buffer (points, lines, triangles and quads) +typedef struct { + // Data for IDirect3DDevice9::CreateVertexBuffer() + DWORD dwStride; // Stride of vertex + DWORD dwUsage; // Usage flags + DWORD dwFVF; // Direct3D Flexible Vertex Format + DWORD dwPool; // Pool flags + + IDirect3DVertexBuffer9 *pVB; // Holds points, lines, tris and quads. + + // Point list is assumed to be at start of buffer + DWORD iFirstLine; // Index of start of line list + DWORD iFirstTriangle; // Index of start of triangle list + + BYTE *pPoints; // Pointer to next free point + BYTE *pLines; // Pointer to next free line + BYTE *pTriangles; // Pointer to next free triangle + + DWORD nPoints; // Number of points ready to render + DWORD nLines; // Number of lines ready to render + DWORD nTriangles; // Number of triangles ready to render +} GLD_pb_dx9; + +// GLDirect DX9 driver data +typedef struct { + // GLDirect vars + BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered) + BOOL bDepthStencil; // Depth buffer needed (stencil optional) + D3DFORMAT RenderFormat; // Format of back/front buffer + D3DFORMAT DepthFormat; // Format of depth/stencil +// float fFlipWindowY; // Value for flipping viewport Y coord + + // Direct3D vars + D3DCAPS9 d3dCaps9; + BOOL bHasHWTnL; // Device has Hardware Transform/Light? + IDirect3D9 *pD3D; // Base Direct3D9 interface + IDirect3DDevice9 *pDev; // Direct3D9 Device interface + GLD_pb_dx9 PB2d; // Vertices transformed by Mesa + GLD_pb_dx9 PB3d; // Vertices transformed by Direct3D + D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type + D3DXMATRIX matProjection; // Projection matrix for D3D TnL + D3DXMATRIX matModelView; // Model/View matrix for D3D TnL + int iSetupFunc; // Which setup functions to use + BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL + + // Direct3D vars for two-sided lighting +// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting +// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders + + +// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline + GLD_pipeline_usage PipelineUsage; + + BOOL bCanScissor; // Scissor test - new for DX9 +} GLD_driver_dx9; + +#define GLD_GET_DX9_DRIVER(c) (GLD_driver_dx9*)(c)->glPriv + +//--------------------------------------------------------------------------- +// Function prototypes +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX9(LPCSTR a); +void gldEnableExtensions_DX9(GLcontext *ctx); +void gldInstallPipeline_DX9(GLcontext *ctx); +void gldSetupDriverPointers_DX9(GLcontext *ctx); +//void gldResizeBuffers_DX9(GLcontext *ctx); +void gldResizeBuffers_DX9(GLframebuffer *fb); + + +// Texture functions + +void gldCopyTexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void gldCopyTexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void gldCopyTexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ); +void gldCopyTexSubImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); +void gldCopyTexSubImage3D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + +void gld_NEW_TEXTURE_DX9(GLcontext *ctx); +void gld_DrawPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels); +void gld_ReadPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest); +void gld_CopyPixels_DX9(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type); +void gld_Bitmap_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap); +const struct gl_texture_format* gld_ChooseTextureFormat_DX9(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType); +void gld_TexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage); +void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage); +void gld_DeleteTexture_DX9(GLcontext *ctx, struct gl_texture_object *tObj); +void gld_ResetLineStipple_DX9(GLcontext *ctx); + +// 2D primitive functions + +void gld_Points2D_DX9(GLcontext *ctx, GLuint first, GLuint last); + +void gld_Line2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1); + +void gld_Triangle2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); + +void gld_Quad2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// 3D primitive functions + +void gld_Points3D_DX9(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Line3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// Primitive functions for Two-sided-lighting Vertex Shader + +void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +#endif diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h new file mode 100644 index 00000000000..1d6b7b1c760 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h @@ -0,0 +1,77 @@ +/*==========================================================================; + * + * + * File: dxerr9.h + * Content: DirectX Error Library Include File + * + ****************************************************************************/ + +#ifndef _GLD_DXERR9_H_ +#define _GLD_DXERR9_H_ + + +#include <d3d9.h> + +// +// DXGetErrorString9 +// +// Desc: Converts an DirectX HRESULT to a string +// +// Args: HRESULT hr Can be any error code from +// DPLAY D3D8 D3DX8 DMUSIC DSOUND +// +// Return: Converted string +// +const char* __stdcall DXGetErrorString9A(HRESULT hr); +const WCHAR* __stdcall DXGetErrorString9W(HRESULT hr); + +#ifdef UNICODE + #define DXGetErrorString9 DXGetErrorString9W +#else + #define DXGetErrorString9 DXGetErrorString9A +#endif + + +// +// DXTrace +// +// Desc: Outputs a formatted error message to the debug stream +// +// Args: CHAR* strFile The current file, typically passed in using the +// __FILE__ macro. +// DWORD dwLine The current line number, typically passed in using the +// __LINE__ macro. +// HRESULT hr An HRESULT that will be traced to the debug stream. +// CHAR* strMsg A string that will be traced to the debug stream (may be NULL) +// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info. +// +// Return: The hr that was passed in. +// +//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE ); +//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE ); +HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox); +HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox); + +#ifdef UNICODE + #define DXTrace DXTraceW +#else + #define DXTrace DXTraceA +#endif + + +// +// Helper macros +// +#if defined(DEBUG) | defined(_DEBUG) + #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE ) + #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE ) + #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE ) +#else + #define DXTRACE_MSG(str) (0L) + #define DXTRACE_ERR(str,hr) (hr) + #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr) +#endif + + +#endif + diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c new file mode 100644 index 00000000000..745c987602b --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c @@ -0,0 +1,344 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GL extensions +* +****************************************************************************/ + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "../gld_settings.h" + +#include <windows.h> +#define GL_GLEXT_PROTOTYPES +#include <GL/gl.h> +#include <GL/glext.h> + +//#include "ddlog.h" +//#include "gld_dx8.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "dglcontext.h" +#include "extensions.h" + +// For some reason this is not defined in an above header... +extern void _mesa_enable_imaging_extensions(GLcontext *ctx); + +//--------------------------------------------------------------------------- +// Hack for the SGIS_multitexture extension that was removed from Mesa +// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel + + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // To enable, uncomment: + // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + +//--------------------------------------------------------------------------- + +enum { + /* Quake2 GL_SGIS_multitexture */ + GL_SELECTED_TEXTURE_SGIS = 0x835B, + GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C, + GL_MAX_TEXTURES_SGIS = 0x835D, + GL_TEXTURE0_SGIS = 0x835E, + GL_TEXTURE1_SGIS = 0x835F, + GL_TEXTURE2_SGIS = 0x8360, + GL_TEXTURE3_SGIS = 0x8361, + GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363, +}; + +//--------------------------------------------------------------------------- + +void APIENTRY gldSelectTextureSGIS( + GLenum target) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glActiveTextureARB(ARB_target); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fSGIS( + GLenum target, + GLfloat s, + GLfloat t) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fARB(ARB_target, s, t); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fvSGIS( + GLenum target, + const GLfloat *v) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fvARB(ARB_target, v); +} + +//--------------------------------------------------------------------------- +// Extensions +//--------------------------------------------------------------------------- + +typedef struct { + PROC proc; + char *name; +} GLD_extension; + +GLD_extension GLD_extList[] = { +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }, + { NULL, "\0" } +}; + +GLD_extension GLD_multitexList[] = { +/* + { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" }, + { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" }, + { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" }, + { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" }, + { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" }, + { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" }, + { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" }, + { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" }, + { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" }, + { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" }, + { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" }, + { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" }, + { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" }, + { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" }, + { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" }, + { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" }, + { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" }, + { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" }, + { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" }, + { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" }, + { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" }, + { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" }, + { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" }, + { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" }, + { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" }, + { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" }, + { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" }, + { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" }, + { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" }, + { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" }, + { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" }, + { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" }, +*/ + { (PROC)glActiveTextureARB, "glActiveTextureARB" }, + { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" }, + { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" }, + { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" }, + { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" }, + { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" }, + { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" }, + { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" }, + { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" }, + { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" }, + { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" }, + { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" }, + { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" }, + { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" }, + { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" }, + { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" }, + { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" }, + { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" }, + { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" }, + { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" }, + { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" }, + { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" }, + { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" }, + { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" }, + { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" }, + { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" }, + { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" }, + { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" }, + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" }, + { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" }, + { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" }, + { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" }, + { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" }, + { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" }, + + // Descent3 doesn't use correct string, hence this hack + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" }, + + // Quake2 SGIS multitexture + { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + + { NULL, "\0" } +}; + +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX( + LPCSTR a) +{ + int i; + PROC proc = NULL; + + for (i=0; GLD_extList[i].proc; i++) { + if (!strcmp(a, GLD_extList[i].name)) { + proc = GLD_extList[i].proc; + break; + } + } + + if (glb.bMultitexture) { + for (i=0; GLD_multitexList[i].proc; i++) { + if (!strcmp(a, GLD_multitexList[i].name)) { + proc = GLD_multitexList[i].proc; + break; + } + } + } + + gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed"); + + return proc; +} + +//--------------------------------------------------------------------------- + +void gldEnableExtensions_DX9( + GLcontext *ctx) +{ + GLuint i; + + // Mesa enables some extensions by default. + // This table decides which ones we want to switch off again. + + // NOTE: GL_EXT_compiled_vertex_array appears broken. + + const char *gld_disable_extensions[] = { +// "GL_ARB_transpose_matrix", +// "GL_EXT_compiled_vertex_array", +// "GL_EXT_polygon_offset", +// "GL_EXT_rescale_normal", + "GL_EXT_texture3D", +// "GL_NV_texgen_reflection", + NULL + }; + + const char *gld_multitex_extensions[] = { + "GL_ARB_multitexture", // Quake 3 + NULL + }; + + // Quake 2 engines + const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture"; + + const char *gld_enable_extensions[] = { + "GL_EXT_texture_env_add", // Quake 3 + "GL_ARB_texture_env_add", // Quake 3 + NULL + }; + + for (i=0; gld_disable_extensions[i]; i++) { + _mesa_disable_extension(ctx, gld_disable_extensions[i]); + } + + for (i=0; gld_enable_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_enable_extensions[i]); + } + + if (glb.bMultitexture) { + for (i=0; gld_multitex_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_multitex_extensions[i]); + } + + // GL_SGIS_multitexture + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // Fair bit slower on GeForce256, + // Much slower on 3dfx Voodoo5 5500. +// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + + } + + _mesa_enable_imaging_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + _mesa_enable_1_4_extensions(ctx); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c new file mode 100644 index 00000000000..2b272aa6281 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c @@ -0,0 +1,77 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Mesa transformation pipeline with GLDirect fastpath +* +****************************************************************************/ + +//#include "../GLDirect.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +extern struct tnl_pipeline_stage _gld_d3d_render_stage; +extern struct tnl_pipeline_stage _gld_mesa_render_stage; + +static const struct tnl_pipeline_stage *gld_pipeline[] = { + &_gld_d3d_render_stage, // Direct3D TnL + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */ + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_point_attenuation_stage, + &_gld_mesa_render_stage, // Mesa TnL, D3D rendering + 0, +}; + +//--------------------------------------------------------------------------- + +void gldInstallPipeline_DX9( + GLcontext *ctx) +{ + // Remove any existing pipeline stages, + // then install GLDirect pipeline stages. + + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, gld_pipeline); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c new file mode 100644 index 00000000000..65fd821276e --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c @@ -0,0 +1,1446 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Primitive (points/lines/tris/quads) rendering +* +****************************************************************************/ + +//#include "../GLDirect.h" + +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "swrast/s_trispan.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +// Disable compiler complaints about unreferenced local variables +#pragma warning (disable:4101) + +//--------------------------------------------------------------------------- +// Helper defines for primitives +//--------------------------------------------------------------------------- + +//static const float ooZ = 1.0f / 65536.0f; // One over Z + +#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3])) +#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3])) +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +//--------------------------------------------------------------------------- +// 2D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_2D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_TRIANGLES \ + BOOL bFog = ctx->Fog.Enabled; \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour; \ + GLuint facing = 0; \ + struct vertex_buffer *VB; \ + GLchan (*vbcolor)[4]; \ + GLchan (*vbspec)[4] + +#define GLD_SETUP_GET_SWVERT(s) \ + swv = &ss->verts[##s] + +#define GLD_SETUP_2D_VERTEX \ + pV->x = swv->win[0]; \ + pV->y = GLD_FLIP_Y(swv->win[1]); \ + pV->rhw = swv->win[3] + +#define GLD_SETUP_SMOOTH_COLOUR \ + pV->diffuse = GLD_COLOUR + +#define GLD_SETUP_GET_FLAT_COLOUR \ + dwFlatColour = GLD_COLOUR +#define GLD_SETUP_GET_FLAT_FOG_COLOUR \ + dwFlatColour = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_USE_FLAT_COLOUR \ + pV->diffuse = dwFlatColour + +#define GLD_SETUP_GET_FLAT_SPECULAR \ + dwSpecularColour= GLD_SPECULAR + +#define GLD_SETUP_USE_FLAT_SPECULAR \ + pV->specular = dwSpecularColour + +#define GLD_SETUP_DEPTH \ + pV->sz = swv->win[2] / ctx->DepthMaxF +// pV->z = swv->win[2] * ooZ; + +#define GLD_SETUP_SPECULAR \ + pV->specular = GLD_SPECULAR + +#define GLD_SETUP_FOG \ + pV->diffuse = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_TEX0 \ + pV->t0_u = swv->texcoord[0][0]; \ + pV->t0_v = swv->texcoord[0][1] + +#define GLD_SETUP_TEX1 \ + pV->t1_u = swv->texcoord[1][0]; \ + pV->t1_v = swv->texcoord[1][1] + +#define GLD_SETUP_LIGHTING(v) \ + if (facing == 1) { \ + pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } else { \ + if (bFog) \ + GLD_SETUP_FOG; \ + else \ + GLD_SETUP_SMOOTH_COLOUR; \ + GLD_SETUP_SPECULAR; \ + } + +#define GLD_SETUP_GET_FLAT_LIGHTING(v) \ + if (facing == 1) { \ + dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } + +#define GLD_SETUP_TWOSIDED_LIGHTING \ + /* Two-sided lighting */ \ + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \ + SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \ + SWvertex *v[3]; \ + GLfloat ex,ey,fx,fy,cc; \ + /* Get vars for later */ \ + VB = &TNL_CONTEXT(ctx)->vb; \ + vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \ + if (VB->SecondaryColorPtr[1]) { \ + vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \ + } else { \ + vbspec = NULL; \ + } \ + v[0] = &verts[v0]; \ + v[1] = &verts[v1]; \ + v[2] = &verts[v2]; \ + ex = v[0]->win[0] - v[2]->win[0]; \ + ey = v[0]->win[1] - v[2]->win[1]; \ + fx = v[1]->win[0] - v[2]->win[0]; \ + fy = v[1]->win[1] - v[2]->win[1]; \ + cc = ex*fy - ey*fx; \ + facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \ + } + +//--------------------------------------------------------------------------- +// 3D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_3D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_TRIANGLES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VERTEX(v) \ + p4f = VB->ObjPtr->data; \ + pV->Position.x = p4f[##v][0]; \ + pV->Position.y = p4f[##v][1]; \ + pV->Position.z = p4f[##v][2]; + +#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + + +#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \ + dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + +#define GLD_SETUP_USE_FLAT_COLOUR_3D \ + pV->Diffuse = dwColor; + +#define GLD_SETUP_TEX0_3D(v) \ + if (VB->TexCoordPtr[0]) { \ + tc = VB->TexCoordPtr[0]->data; \ + pV->TexUnit0.x = tc[##v][0]; \ + pV->TexUnit0.y = tc[##v][1]; \ + } + +#define GLD_SETUP_TEX1_3D(v) \ + if (VB->TexCoordPtr[1]) { \ + tc = VB->TexCoordPtr[1]->data; \ + pV->TexUnit1.x = tc[##v][0]; \ + pV->TexUnit1.y = tc[##v][1]; \ + } + +//--------------------------------------------------------------------------- +// Helper functions +//--------------------------------------------------------------------------- + +__inline DWORD _gldComputeFog( + GLcontext *ctx, + SWvertex *swv) +{ + // Full fog calculation. + // Based on Mesa code. + + GLchan rFog, gFog, bFog; + GLchan fR, fG, fB; + const GLfloat f = swv->fog; + const GLfloat g = 1.0 - f; + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + fR = f * swv->color[0] + g * rFog; + fG = f * swv->color[1] + g * gFog; + fB = f * swv->color[2] + g * bFog; + return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]); +} + +//--------------------------------------------------------------------------- + +void gld_ResetLineStipple_DX9( + GLcontext *ctx) +{ + // TODO: Fake stipple with a 32x32 texture. +} + +//--------------------------------------------------------------------------- +// 2D (post-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points2D_DX9( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_2D_VARS_POINTS; + + unsigned i; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); + GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } else { + GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, swv++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } + + gld->PB2d.pPoints = (BYTE*)pV; + gld->PB2d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_SPECULAR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++;; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v2); + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v2); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v3); + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v3); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v3); + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// 3D (pre-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points3D_DX9( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_3D_VARS_POINTS + + unsigned i; +// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); +// GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_3D_VERTEX(VB->Elts[i]) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } else { +// GLD_SETUP_GET_SWVERT(first); + for (i=first; i<last; i++, pV++) { + if (VB->ClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } +/* + for (i=first; i<last; i++, pV++) { + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } +*/ + gld->PB3d.pPoints = (BYTE*)pV; + gld->PB3d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- +// Line functions +//--------------------------------------------------------------------------- + +void gld_Line3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_GET_FLAT_COLOUR_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- +// Triangle functions +//--------------------------------------------------------------------------- + +void gld_Triangle3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + GLD_SETUP_GET_FLAT_COLOUR_3D(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- +// Quad functions +//--------------------------------------------------------------------------- + +void gld_Quad3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_GET_FLAT_COLOUR_3D(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_SMOOTH_COLOUR_3D(v3) + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// Vertex setup for two-sided-lighting vertex shader +//--------------------------------------------------------------------------- + +/* + +void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last) +{ + // NOTE: Two-sided lighting does not apply to Points +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +*/ diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c new file mode 100644 index 00000000000..5a822356164 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c @@ -0,0 +1,2104 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Texture / Bitmap functions +* +****************************************************************************/ + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include <d3dx9tex.h> + +#include "texformat.h" +#include "colormac.h" +#include "texstore.h" +#include "image.h" +// #include "mem.h" + +//--------------------------------------------------------------------------- + +#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h)) + +//--------------------------------------------------------------------------- +// 1D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + (i) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (i) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (i)) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (i)) + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 2D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + ((t)->Width * (j) + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 3D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *)texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + texel[RCOMP] = CHAN_TO_FLOAT(src[0]); + texel[GCOMP] = CHAN_TO_FLOAT(src[1]); + texel[BCOMP] = CHAN_TO_FLOAT(src[2]); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLchan *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_f_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLushort s = *src; + texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); + texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); + texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); + texel[ACOMP] = 1.f; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// Direct3D texture formats that have no Mesa equivalent +//--------------------------------------------------------------------------- + +const struct gl_texture_format _gld_texformat_X8R8G8B8 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + _mesa_texstore_argb8888, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */ + gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */ + gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X1R5G5B5 = { + MESA_FORMAT_ARGB1555, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb1555, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */ + gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */ + gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */ +}; + +const struct gl_texture_format _gld_texformat_X4R4G4B4 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ + GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + _mesa_texstore_argb4444, /* StoreTexImageFunc */ + gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */ + gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */ + gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */ + gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */ + gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */ + gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */ +}; + +//--------------------------------------------------------------------------- +// Texture unit constants +//--------------------------------------------------------------------------- + +// List of possible combinations of texture environments. +// Example: GLD_TEXENV_MODULATE_RGBA means +// GL_MODULATE, GL_RGBA base internal format. +#define GLD_TEXENV_DECAL_RGB 0 +#define GLD_TEXENV_DECAL_RGBA 1 +#define GLD_TEXENV_DECAL_ALPHA 2 +#define GLD_TEXENV_REPLACE_RGB 3 +#define GLD_TEXENV_REPLACE_RGBA 4 +#define GLD_TEXENV_REPLACE_ALPHA 5 +#define GLD_TEXENV_MODULATE_RGB 6 +#define GLD_TEXENV_MODULATE_RGBA 7 +#define GLD_TEXENV_MODULATE_ALPHA 8 +#define GLD_TEXENV_BLEND_RGB 9 +#define GLD_TEXENV_BLEND_RGBA 10 +#define GLD_TEXENV_BLEND_ALPHA 11 +#define GLD_TEXENV_ADD_RGB 12 +#define GLD_TEXENV_ADD_RGBA 13 +#define GLD_TEXENV_ADD_ALPHA 14 + +// Per-stage (i.e. per-unit) texture environment +typedef struct { + DWORD ColorArg1; // Colour argument 1 + D3DTEXTUREOP ColorOp; // Colour operation + DWORD ColorArg2; // Colour argument 2 + DWORD AlphaArg1; // Alpha argument 1 + D3DTEXTUREOP AlphaOp; // Alpha operation + DWORD AlphaArg2; // Alpha argument 2 +} GLD_texenv; + +// TODO: Do we really need to set ARG1 and ARG2 every time? +// They seem to always be TEXTURE and CURRENT respectively. + +// C = Colour out +// A = Alpha out +// Ct = Colour from Texture +// Cf = Colour from fragment (diffuse) +// At = Alpha from Texture +// Af = Alpha from fragment (diffuse) +// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND) +const GLD_texenv gldTexEnv[] = { + // DECAL_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af + {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_ALPHA: <undefined> use DECAL_RGB + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + + // REPLACE_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // REPLACE_RGBA: C=Ct, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + // REPLACE_ALPHA: C=Cf, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + + // MODULATE_RGB: C=CfCt, A=Af + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // MODULATE_RGBA: C=CfCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // MODULATE_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // BLEND_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // ADD_RGB: C=Cf+Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // ADD_RGBA: C=Cf+Ct, A=AfAt + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // ADD_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +}; + +//--------------------------------------------------------------------------- + +D3DTEXTUREADDRESS _gldConvertWrap( + GLenum wrap) +{ + return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP; +} + +//--------------------------------------------------------------------------- + +D3DTEXTUREFILTERTYPE _gldConvertMagFilter( + GLenum magfilter) +{ + return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT; +} + +//--------------------------------------------------------------------------- + +void _gldConvertMinFilter( + GLenum minfilter, + D3DTEXTUREFILTERTYPE *min_filter, + D3DTEXTUREFILTERTYPE *mip_filter) +{ + switch (minfilter) { + case GL_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_LINEAR; + break; + } +} + +//--------------------------------------------------------------------------- + +D3DFORMAT _gldGLFormatToD3DFormat( + GLenum internalFormat) +{ + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures + return D3DFMT_L8; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return D3DFMT_L8; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return D3DFMT_A8; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return D3DFMT_X8R8G8B8; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return D3DFMT_A8L8; + case GL_R3_G3_B2: + // TODO: Mesa does not support RGB332 internally + return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2; + case GL_RGB4: + return D3DFMT_X4R4G4B4; + case GL_RGB5: + return D3DFMT_X1R5G5B5; + case 3: + case GL_RGB: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return D3DFMT_R8G8B8; + case GL_RGBA4: + return D3DFMT_A4R4G4B4; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return D3DFMT_A8R8G8B8; + case GL_RGB5_A1: + return D3DFMT_A1R5G5B5; + } + + // Return an acceptable default + return D3DFMT_A8R8G8B8; +} + +//--------------------------------------------------------------------------- + +GLenum _gldDecodeBaseFormat( + IDirect3DTexture9 *pTex) +{ + // Examine Direct3D texture and return base OpenGL internal texture format + // NOTE: We can't use any base format info from Mesa because D3D might have + // used a different texture format when we used D3DXCreateTexture(). + + // Base internal format is one of (Red Book p355): + // GL_ALPHA, + // GL_LUMINANCE, + // GL_LUMINANCE_ALPHA, + // GL_INTENSITY, + // GL_RGB, + // GL_RGBA + + // NOTE: INTENSITY not used (not supported by Direct3D) + // LUMINANCE has same texture functions as RGB + // LUMINANCE_ALPHA has same texture functions as RGBA + + // TODO: cache format instead of using GetLevelDesc() + D3DSURFACE_DESC desc; + _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc)); + + switch (desc.Format) { + case D3DFMT_R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_R3G3B2: + case D3DFMT_X4R4G4B4: + case D3DFMT_P8: + case D3DFMT_L8: + return GL_RGB; + case D3DFMT_A8R8G8B8: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8R3G3B2: + case D3DFMT_A8P8: + case D3DFMT_A8L8: + case D3DFMT_A4L4: + return GL_RGBA; + case D3DFMT_A8: + return GL_ALPHA; + // Compressed texture formats. Need to check these... + case D3DFMT_DXT1: + return GL_RGBA; + case D3DFMT_DXT2: + return GL_RGB; + case D3DFMT_DXT3: + return GL_RGBA; + case D3DFMT_DXT4: + return GL_RGB; + case D3DFMT_DXT5: + return GL_RGBA; + } + + // Fell through. Return arbitary default. + return GL_RGBA; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* _gldMesaFormatForD3DFormat( + D3DFORMAT d3dfmt) +{ + switch (d3dfmt) { + case D3DFMT_A8R8G8B8: + return &_mesa_texformat_argb8888; + case D3DFMT_R8G8B8: + return &_mesa_texformat_rgb888; + case D3DFMT_R5G6B5: + return &_mesa_texformat_rgb565; + case D3DFMT_A4R4G4B4: + return &_mesa_texformat_argb4444; + case D3DFMT_A1R5G5B5: + return &_mesa_texformat_argb1555; + case D3DFMT_A8L8: + return &_mesa_texformat_al88; + case D3DFMT_R3G3B2: + return &_mesa_texformat_rgb332; + case D3DFMT_A8: + return &_mesa_texformat_a8; + case D3DFMT_L8: + return &_mesa_texformat_l8; + case D3DFMT_X8R8G8B8: + return &_gld_texformat_X8R8G8B8; + case D3DFMT_X1R5G5B5: + return &_gld_texformat_X1R5G5B5; + case D3DFMT_X4R4G4B4: + return &_gld_texformat_X4R4G4B4; + } + + // If we reach here then we've made an error somewhere else + // by allowing a format that is not supported. + assert(0); + + return NULL; // Shut up compiler warning +} + +//--------------------------------------------------------------------------- +// Copy* functions +//--------------------------------------------------------------------------- + +void gldCopyTexImage1D_DX9( + GLcontext *ctx, + GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLenum internalFormat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage1D_DX9( + GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage3D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height ) +{ + // TODO ? +} + +//--------------------------------------------------------------------------- +// Bitmap/Pixel functions +//--------------------------------------------------------------------------- + +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1) + +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT z; // depth value + FLOAT rhw; // reciprocal homogenous W (always 1.0f) + FLOAT tu, tv; // texture coords +} _GLD_IMAGE_VERTEX; + +//--------------------------------------------------------------------------- + +HRESULT _gldDrawPixels( + GLcontext *ctx, + BOOL bChromakey, // Alpha test for glBitmap() images + GLint x, // GL x position + GLint y, // GL y position (needs flipping) + GLsizei width, // Width of input image + GLsizei height, // Height of input image + IDirect3DSurface9 *pImage) +{ + // + // Draw input image as texture implementing PixelZoom and clipping. + // Any fragment operations currently enabled will be used. + // + + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTexture; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface9 *pSurface; + _GLD_IMAGE_VERTEX v[4]; + HRESULT hr; + + float ZoomWidth, ZoomHeight; + float ScaleWidth, ScaleHeight; + + // Create a texture to hold image + hr = D3DXCreateTexture( + gld->pDev, + width, height, + 1, // miplevels + 0, // usage + D3DFMT_A8R8G8B8, // format + D3DPOOL_MANAGED, // pool + &pTexture); + if (FAILED(hr)) + return hr; + + hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface); + if (FAILED(hr)) { + IDirect3DTexture9_Release(pTexture); + return hr; + } + + // Copy image into texture + hr = D3DXLoadSurfaceFromSurface( + pSurface, NULL, NULL, // Dest surface + pImage, NULL, NULL, // Src surface + D3DX_FILTER_NONE, + 0); + IDirect3DSurface9_Release(pSurface); + if (FAILED(hr)) { + IDirect3DTexture9_Release(pTexture); + return hr; + } + + // + // Set up the quad like this (ascii-art ahead!) + // + // 3--2 + // | | + // 0--1 + // + // + + // Set depth + v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2]; + // Set Reciprocal Homogenous W + v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f; + + // Set texcoords + // Examine texture size - if different to input width and height + // then we'll need to munge the texcoords to fit. + IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd); + ScaleWidth = (float)width / (float)d3dsd.Width; + ScaleHeight = (float)height / (float)d3dsd.Height; + v[0].tu = 0.0f; v[0].tv = 0.0f; + v[1].tu = ScaleWidth; v[1].tv = 0.0f; + v[2].tu = ScaleWidth; v[2].tv = ScaleHeight; + v[3].tu = 0.0f; v[3].tv = ScaleHeight; + + // Set raster positions + ZoomWidth = (float)width * ctx->Pixel.ZoomX; + ZoomHeight = (float)height * ctx->Pixel.ZoomY; + + v[0].x = x; v[0].y = GLD_FLIP_Y(y); + v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y); + v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight); + v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight); + + // Draw image with full HW acceleration + // NOTE: Be nice to use a State Block for all this state... + IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE); + +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + IDirect3DDevice9_SetVertexShader(gld->pDev, NULL); + IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE); + + // + // Emulate Chromakey with an Alpha Test. + // [Alpha Test is more widely supported anyway] + // + if (bChromakey) { + // Switch on alpha testing + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE); + // Fragment passes is alpha is greater than reference value + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER); + // Set alpha reference value between Bitmap alpha values of + // zero (transparent) and one (opaque). + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f); + } + + IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX)); + + // Release texture + IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL); + IDirect3DTexture9_Release(pTexture); + + // Reset state to before we messed it up + FLUSH_VERTICES(ctx, _NEW_ALL); + + return S_OK; +} + +//--------------------------------------------------------------------------- + +void gld_DrawPixels_DX9( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + + const struct gl_texture_format *MesaFormat; + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + + // Mesa does not currently handle this format. + if (format == GL_BGR) + return; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + return; + } + + // + // Use Mesa to fill in image + // + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + // unpack image, apply transfer ops and store directly in texture + MesaFormat->StoreImage( + ctx, + 2, + GL_RGBA, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, /* dstImageStride */ + format, type, pixels, unpack); + + IDirect3DSurface9_UnlockRect(pImage); + + _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_ReadPixels_DX9( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *dest) +{ + + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pBackbuffer = NULL; + IDirect3DSurface9 *pNativeImage = NULL; + IDirect3DSurface9 *pCanonicalImage = NULL; + + D3DSURFACE_DESC d3dsd; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + struct gl_pixelstore_attrib srcPacking; + int i; + GLint DstRowStride; + const struct gl_texture_format *MesaFormat; + + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + return; + } + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + DstRowStride = _mesa_image_row_stride(pack, width, format, type); + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice9_GetBackBuffer( + gld->pDev, + 0, // First swapchain + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + d3dsd.Format, + D3DPOOL_SCRATCH, + &pNativeImage, + NULL); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels. + // + // This intermediate surface ensure that we can use CopyRects() + // instead of relying on D3DXLoadSurfaceFromSurface(), which may + // try and lock the backbuffer. This way seems safer. + // + // CopyRects has been removed for DX9. + // +/* hr = IDirect3DDevice9_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pNativeImage, + &ptDst);*/ + hr = D3DXLoadSurfaceFromSurface( + pNativeImage, // Dest surface + NULL, // Dest palette + &rcSrc, // Dest rect + pBackbuffer, // Src surface + NULL, // Src palette + &rcSrc, // Src rect + D3DX_FILTER_NONE, // Filter + 0 // Colorkey (0=no colorkey) + ); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Create an RGBA8888 surface + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pCanonicalImage, + NULL); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Convert to RGBA8888 + hr = D3DXLoadSurfaceFromSurface( + pCanonicalImage, // Dest surface + NULL, NULL, // Dest palette, RECT + pNativeImage, // Src surface + NULL, NULL, // Src palette, RECT + D3DX_FILTER_NONE, // Filter + 0); // Colourkey + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + srcPacking.Alignment = 1; + srcPacking.ImageHeight = height; + srcPacking.LsbFirst = GL_FALSE; + srcPacking.RowLength = 0; + srcPacking.SkipImages = 0; + srcPacking.SkipPixels = 0; + srcPacking.SkipRows = 0; + srcPacking.SwapBytes = GL_FALSE; + + // Lock all of image + hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // We need to flip the data. Yuck. + // Perhaps Mesa has a span packer we can use in future... + for (i=0; i<height; i++) { + BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0); + BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1)); + MesaFormat->StoreImage( + ctx, + 2, + GL_RGBA, // base format + MesaFormat, // dst format + pDestRow, // dest addr + width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z + DstRowStride, // dst row stride + 0, // dstImageStride + GL_BGRA, // src format + GL_UNSIGNED_BYTE, // src type + pSrcRow, // src addr + &srcPacking); // packing params of source image + } + + IDirect3DSurface9_UnlockRect(pCanonicalImage); + +gld_ReadPixels_DX9_return: + SAFE_RELEASE_SURFACE9(pCanonicalImage); + SAFE_RELEASE_SURFACE9(pNativeImage); + SAFE_RELEASE_SURFACE9(pBackbuffer); +} + +//--------------------------------------------------------------------------- + +void gld_CopyPixels_DX9( + GLcontext *ctx, + GLint srcx, + GLint srcy, + GLsizei width, + GLsizei height, + GLint dstx, + GLint dsty, + GLenum type) +{ + // + // NOTE: Not allowed to copy vidmem to vidmem! + // Therefore we use an intermediate image surface. + // + + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pBackbuffer; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface9 *pImage; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + + // Only backbuffer + if (type != GL_COLOR) + return; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice9_GetBackBuffer( + gld->pDev, + 0, // First swapchain + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pBackbuffer); + return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + d3dsd.Format, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pBackbuffer); + return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels +/* hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pImage, + &ptDst);*/ + hr = D3DXLoadSurfaceFromSurface( + pImage, // Dest surface + NULL, // Dest palette + &rcSrc, // Dest rect + pBackbuffer, // Src surface + NULL, // Src palette + &rcSrc, // Src rect + D3DX_FILTER_NONE, // Filter + 0 // Colorkey (0=no colorkey) + ); + IDirect3DSurface9_Release(pBackbuffer); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_Bitmap_DX9( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + BYTE *pTempBitmap; + D3DCOLOR clBitmapOne, clBitmapZero; + D3DCOLOR *pBits; + const GLubyte *src; + int i, j, k; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + // A NULL bitmap is valid, but merely advances the raster position + if ((bitmap == NULL) || (width == 0) || (height == 0)) + return; + + clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero + clBitmapOne = D3DCOLOR_COLORVALUE( + ctx->Current.RasterColor[0], + ctx->Current.RasterColor[1], + ctx->Current.RasterColor[2], + 1.0f); // NOTE: Alpha is One + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + return; + } + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack); + if (pTempBitmap == NULL) { + IDirect3DSurface9_Release(pImage); + return; + } + + pBits = (D3DCOLOR*)d3dLockedRect.pBits; + + for (i=0; i<height; i++) { + GLubyte byte; + pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch)); + src = (const GLubyte *) _mesa_image_address(2, + &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, + 0, i, 0); + for (j=0; j<(width>>3); j++) { + byte = *src++; + for (k=0; k<8; k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + // Fill remaining bits from bitmap + if (width & 7) { + byte = *src; + for (k=0; k<(width & 7); k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + } + + FREE(pTempBitmap); + +/* + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage( + ctx, + 2, + GL_BITMAP, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack); +*/ + IDirect3DSurface9_UnlockRect(pImage); + + _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- +// Texture functions +//--------------------------------------------------------------------------- + +void _gldAllocateTexture( + GLcontext *ctx, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + D3DFORMAT d3dFormat; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (pTex) { + // Decide whether we can keep existing D3D texture + // by examining top-level surface. + D3DSURFACE_DESC d3dsd; + _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd)); + // Release existing texture if not compatible + if ((d3dsd.Width == texImage->Width) || + (d3dsd.Height == texImage->Height)) + { + return; // Keep the existing texture + } + tObj->DriverData = NULL; + _GLD_DX9_TEX(Release(pTex)); + } + + d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat); + D3DXCreateTexture( + gld->pDev, + texImage->Width, + texImage->Height, + // TODO: Re-evaluate mipmapping + (glb.bUseMipmaps) ? D3DX_DEFAULT : 1, + 0, // Usage + d3dFormat, + D3DPOOL_MANAGED, + &pTex); + tObj->DriverData = pTex; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* gld_ChooseTextureFormat_DX9( + GLcontext *ctx, + GLint internalFormat, + GLenum srcFormat, + GLenum srcType) +{ + // [Based on mesa_choose_tex_format()] + // + // We will choose only texture formats that are supported + // by Direct3D. If the hardware doesn't support a particular + // texture format, then the D3DX texture calls that we use + // will automatically use a HW supported format. + // + // The most critical aim is to reduce copying; if we can use + // texture-image data directly then it will be a big performance assist. + // + + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return &_mesa_texformat_a8; // D3DFMT_A8 + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5 + // Mesa will convert this for us later... + // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5 + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return &_mesa_texformat_al88; // D3DFMT_A8L8 + case GL_R3_G3_B2: + return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2 + case GL_RGB4: + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4 + case 3: + case GL_RGB: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_rgb565; + case 4: + case GL_RGBA: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return &_mesa_texformat_argb8888; + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + default: + _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); + return NULL; + } +} + +//--------------------------------------------------------------------------- + +/* +// Safer(?), slower version. +void gld_TexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + RECT rcSrcRect; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + + if (!tObj || !texImage) + return; + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface9_Release(pSurface); + return; + } + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + SetRect(&rcSrcRect, 0, 0, width, height); + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + NULL, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface9_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + // GLQUAKE FIX + // Test for input alpha data with non-alpha internalformat + if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) { + // Input format has alpha, but a non-alpha format has been requested. + texImage->IntFormat = GL_RGBA; + internalFormat = GL_RGBA; + } + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface9_GetDesc(pSurface, &d3dsd); + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage( + ctx, + 2, + texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + IDirect3DSurface9_UnlockRect(pSurface); + IDirect3DSurface9_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + // A 1D texture is a 2D texture with a height of zero + gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +/* +void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_GET_CONTEXT + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + D3DFORMAT d3dFormat; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + RECT rcSrcRect; + RECT rcDstRect; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= _GLD_DX9_TEX(GetLevelCount(pTex)) + return; // Level does not exist + hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + d3dFormat = _gldGLFormatToD3DFormat(texImage->Format); + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store in tempImage + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + // Source rectangle is whole of input image + SetRect(&rcSrcRect, 0, 0, width, height); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + &rcDstRect, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface9_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + HRESULT hr; + RECT rcDstRect; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface9_GetDesc(pSurface, &d3dsd); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + // Lock sub-rect of surface + hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, + 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!! + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + + IDirect3DSurface9_UnlockRect(pSurface); + IDirect3DSurface9_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +void gld_DeleteTexture_DX9( + GLcontext *ctx, + struct gl_texture_object *tObj) +{ + GLD_context *gld = (GLD_context*)(ctx->DriverCtx); + + if (tObj) { + IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData; + if (pTex) { +/* // Make sure texture is not bound to a stage before releasing it + for (int i=0; i<MAX_TEXTURE_UNITS; i++) { + if (gld->CurrentTexture[i] == pTex) { + gld->pDev->SetTexture(i, NULL); + gld->CurrentTexture[i] = NULL; + } + }*/ + _GLD_DX9_TEX(Release(pTex)); + tObj->DriverData = NULL; + } + } +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetColorOps( + const GLD_driver_dx9 *gld, + GLuint unit, + DWORD ColorArg1, + D3DTEXTUREOP ColorOp, + DWORD ColorArg2) +{ + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2)); +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetAlphaOps( + const GLD_driver_dx9 *gld, + GLuint unit, + DWORD AlphaArg1, + D3DTEXTUREOP AlphaOp, + DWORD AlphaArg2) +{ + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2)); +} + +//--------------------------------------------------------------------------- + +void gldUpdateTextureUnit( + GLcontext *ctx, + GLuint unit, + BOOL bPassThrough) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DTEXTUREFILTERTYPE minfilter; + D3DTEXTUREFILTERTYPE mipfilter; + GLenum BaseFormat; + DWORD dwColorArg0; + int iTexEnv = 0; + GLD_texenv *pTexenv; + + // NOTE: If bPassThrough is FALSE then texture stage can be + // disabled otherwise it must pass-through it's current fragment. + + const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *tObj = pUnit->_Current; + + IDirect3DTexture9 *pTex = NULL; + if (tObj) { + pTex = (IDirect3DTexture9*)tObj->DriverData; + } + + // Enable texturing if unit is enabled and a valid D3D texture exists + // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT + //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) { + if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) { + // Enable texturing + _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex)); + } else { + // Disable texturing, then return + _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL)); + if (bPassThrough) { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + } else { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + } + return; + } + + // Texture parameters + _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter)); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter)); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS))); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter)); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter)); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + + // Texture priority + _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f))); + + // Texture environment + // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops. + // See Page 355 of the Red Book. + BaseFormat = _gldDecodeBaseFormat(pTex); + + switch (BaseFormat) { + case GL_RGB: + iTexEnv = 0; + break; + case GL_RGBA: + iTexEnv = 1; + break; + case GL_ALPHA: + iTexEnv = 2; + break; + } + + switch (pUnit->EnvMode) { + case GL_DECAL: + iTexEnv += 0; + break; + case GL_REPLACE: + iTexEnv += 3; + break; + case GL_MODULATE: + iTexEnv += 6; + break; + case GL_BLEND: + // Set blend colour + dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0)); + iTexEnv += 9; + break; + case GL_ADD: + iTexEnv += 12; + break; + } + pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv]; + _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2); + _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_TEXTURE_DX9( + GLcontext *ctx) +{ + // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units + + BOOL bUnit0Enabled; + BOOL bUnit1Enabled; + + if (!ctx) + return; // Sanity check + + if (ctx->Const.MaxTextureUnits == 1) { + gldUpdateTextureUnit(ctx, 0, TRUE); + return; + } + + // + // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!! + // + + // Mesa 5: Texture Units altered + //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE; + //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE; + bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + + // If Unit0 is disabled and Unit1 is enabled then we must pass-though + gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE); + // We can always disable the last texture unit + gldUpdateTextureUnit(ctx, 1, FALSE); + +#ifdef _DEBUG +#if 0 + { + // Find out whether device supports current renderstates + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); +// GLD_context *gld = GLD_GET_CONTEXT(ctx); + + DWORD dwPasses; + _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses)); +// if (FAILED(hr)) { +// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr); +// } + if (dwPasses != 1) { + gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n"); + } + } +#endif +#endif +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c new file mode 100644 index 00000000000..4fa6bcaf1ab --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c @@ -0,0 +1,263 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect fastpath pipeline stage +* +****************************************************************************/ + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +__inline void _gldSetVertexShaderConstants( + GLcontext *ctx, + GLD_driver_dx9 *gld) +{ + D3DXMATRIX mat, matView, matProj; + GLfloat *pM; + + // Mesa 5: Altered to a Stack + //pM = ctx->ModelView.m; + pM = ctx->ModelviewMatrixStack.Top->m; + matView._11 = pM[0]; + matView._12 = pM[1]; + matView._13 = pM[2]; + matView._14 = pM[3]; + matView._21 = pM[4]; + matView._22 = pM[5]; + matView._23 = pM[6]; + matView._24 = pM[7]; + matView._31 = pM[8]; + matView._32 = pM[9]; + matView._33 = pM[10]; + matView._34 = pM[11]; + matView._41 = pM[12]; + matView._42 = pM[13]; + matView._43 = pM[14]; + matView._44 = pM[15]; + + // Mesa 5: Altered to a Stack + //pM = ctx->ProjectionMatrix.m; + pM = ctx->ProjectionMatrixStack.Top->m; + matProj._11 = pM[0]; + matProj._12 = pM[1]; + matProj._13 = pM[2]; + matProj._14 = pM[3]; + matProj._21 = pM[4]; + matProj._22 = pM[5]; + matProj._23 = pM[6]; + matProj._24 = pM[7]; + matProj._31 = pM[8]; + matProj._32 = pM[9]; + matProj._33 = pM[10]; + matProj._34 = pM[11]; + matProj._41 = pM[12]; + matProj._42 = pM[13]; + matProj._43 = pM[14]; + matProj._44 = pM[15]; + + D3DXMatrixMultiply( &mat, &matView, &matProj ); + D3DXMatrixTranspose( &mat, &mat ); + + _GLD_DX9_DEV(SetVertexShaderConstantF(gld->pDev, 0, (float*)&mat, 4)); +} + +//--------------------------------------------------------------------------- + +static GLboolean gld_d3d_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl; + struct vertex_buffer *VB; + tnl_render_func *tab; + GLint pass; + GLD_pb_dx9 *gldPB = &gld->PB3d; +/* + static int count = 0; + count++; + if (count != 2) + return GL_FALSE; +*/ + // The "check" function should disable this stage, + // but we'll test gld->bUseMesaTnL anyway. + if (gld->bUseMesaTnL) { + // Do nothing in this stage, but continue pipeline + return GL_TRUE; + } + + tnl = TNL_CONTEXT(ctx); + VB = &tnl->vb; + pass = 0; + + tnl->Driver.Render.Start( ctx ); + +#if 0 + // For debugging: Useful to see if an app passes colour data in + // an unusual format. + switch (VB->ColorPtr[0]->Type) { + case GL_FLOAT: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n"); + break; + case GL_UNSIGNED_BYTE: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n"); + break; + default: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n"); + break; + } +#endif + + tnl->Driver.Render.Points = gld_Points3D_DX9; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line3DFlat_DX9; + tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX9; + tnl->Driver.Render.Quad = gld_Quad3DFlat_DX9; + } else { + tnl->Driver.Render.Line = gld_Line3DSmooth_DX9; + tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX9; + tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX9; + } + + _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts); + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) + { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + _GLD_DX9_VB(Unlock(gldPB->pVB)); + + _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride)); + + _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection)); + _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView)); + + if (gldPB->nPoints) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + +//--------------------------------------------------------------------------- + +static void gld_d3d_render_stage_check( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + // Is this thread safe? + stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE; + return; +} + + +//--------------------------------------------------------------------------- + +const struct tnl_pipeline_stage _gld_d3d_render_stage = +{ + "gld_d3d_render_stage", + NULL, + NULL, + NULL, + NULL, + gld_d3d_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c new file mode 100644 index 00000000000..372be2fb569 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c @@ -0,0 +1,444 @@ +/* $Id: gld_vb_mesa_render_dx9.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <[email protected]> + */ + + +/* + * Render whole vertex buffers, including projection of vertices from + * clip space and clipping of primitives. + * + * This file makes calls to project vertices and to the point, line + * and triangle rasterizers via the function pointers: + * + * context->Driver.Render.* + * + */ + + +//--------------------------------------------------------------------------- + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" +//#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +/**********************************************************************/ +/* Clip single primitives */ +/**********************************************************************/ + + +#if defined(USE_IEEE) +#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31)) +//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +#define NEGATIVE(x) (x < 0) +//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#endif + + +#define W(i) coord[i][3] +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 4 +#define TAG(x) x##_4 +#include "tnl/t_vb_cliptmp.h" + + + +/**********************************************************************/ +/* Clip and render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte ormask = c1|c2; \ + if (!ormask) \ + LineFunc( ctx, v1, v2 ); \ + else if (!(c1 & c2 & 0x3f)) \ + clip_line_4( ctx, v1, v2, ormask ); \ +} while (0) + +#define RENDER_TRI( v1, v2, v3 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ + GLubyte ormask = c1|c2|c3; \ + if (!ormask) \ + TriangleFunc( ctx, v1, v2, v3 ); \ + else if (!(c1 & c2 & c3 & 0x3f)) \ + clip_tri_4( ctx, v1, v2, v3, ormask ); \ +} while (0) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte c3 = mask[v3], c4 = mask[v4]; \ + GLubyte ormask = c1|c2|c3|c4; \ + if (!ormask) \ + QuadFunc( ctx, v1, v2, v3, v4 ); \ + else if (!(c1 & c2 & c3 & c4 & 0x3f)) \ + clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ +} while (0) + + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const GLubyte *mask = VB->ClipMask; \ + const GLuint sz = VB->ClipPtr->size; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + const GLboolean stipple = ctx->Line.StippleFlag; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; (void) mask; (void) sz; (void) stipple; + +#define TAG(x) clip_##x##_verts +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + + +/* Elts, with the possibility of clipping. + */ +#undef ELT +#undef TAG +#define ELT(x) elt[x] +#define TAG(x) clip_##x##_elts +#include "tnl/t_vb_rendertmp.h" + +/* TODO: do this for all primitives, verts and elts: + */ +static void clip_elt_triangles( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES]; + struct vertex_buffer *VB = &tnl->vb; + const GLuint * const elt = VB->Elts; + GLubyte *mask = VB->ClipMask; + GLuint last = count-2; + GLuint j; + (void) flags; + + tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES ); + + for (j=start; j < last; j+=3 ) { + GLubyte c1 = mask[elt[j]]; + GLubyte c2 = mask[elt[j+1]]; + GLubyte c3 = mask[elt[j+2]]; + GLubyte ormask = c1|c2|c3; + if (ormask) { + if (start < j) + render_tris( ctx, start, j, 0 ); + if (!(c1&c2&c3&0x3f)) + clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); + start = j+3; + } + } + + if (start < j) + render_tris( ctx, start, j, 0 ); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, no clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ + LineFunc( ctx, v1, v2 ) + +#define RENDER_TRI( v1, v2, v3 ) \ + TriangleFunc( ctx, v1, v2, v3 ) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ + QuadFunc( ctx, v1, v2, v3, v4 ) + +#define TAG(x) _gld_tnl_##x##_verts + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ + const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; + +#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx ) +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RENDER_TAB_QUALIFIER +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + +/* Elts, no clipping. + */ +#undef ELT +#define TAG(x) _gld_tnl_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Helper functions for drivers */ +/**********************************************************************/ +/* +void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; +} + +void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} +*/ + + +/**********************************************************************/ +/* Clip and render whole vertex buffers */ +/**********************************************************************/ + +tnl_points_func _gldSetupPoints[4] = { + gld_Points2D_DX9, + gld_Points2D_DX9, + gld_Points2D_DX9, + gld_Points2D_DX9 +}; +tnl_line_func _gldSetupLine[4] = { + gld_Line2DFlat_DX9, + gld_Line2DSmooth_DX9, + gld_Line2DFlat_DX9, + gld_Line2DSmooth_DX9, +}; +tnl_triangle_func _gldSetupTriangle[4] = { + gld_Triangle2DFlat_DX9, + gld_Triangle2DSmooth_DX9, + gld_Triangle2DFlatExtras_DX9, + gld_Triangle2DSmoothExtras_DX9 +}; +tnl_quad_func _gldSetupQuad[4] = { + gld_Quad2DFlat_DX9, + gld_Quad2DSmooth_DX9, + gld_Quad2DFlatExtras_DX9, + gld_Quad2DSmoothExtras_DX9 +}; + +//--------------------------------------------------------------------------- + +static GLboolean _gld_mesa_render_stage_run( + GLcontext *ctx, + struct tnl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + tnl_render_func *tab; + GLint pass = 0; + GLD_pb_dx9 *gldPB; + + /* Allow the drivers to lock before projected verts are built so + * that window coordinates are guarenteed not to change before + * rendering. + */ + ASSERT(tnl->Driver.Render.Start); + + tnl->Driver.Render.Start( ctx ); + + // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets + // stream, indices and shader to default values of NULL or 0. +/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) && + gld->VStwosidelight.hShader && + !ctx->Fog.Enabled) + { + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); + gldPB = &gld->PBtwosidelight; + tnl->Driver.Render.Points = gld_Points2DTwoside_DX9; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX9; + tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX9; + tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX9; + } else { + tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX9; + tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX9; + tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX9; + } + } else {*/ +// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); + IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, TRUE); + gldPB = &gld->PB2d; + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); + tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc]; + tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc]; + tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc]; + tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc]; +// } + + _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 ); + + if (VB->ClipOrMask) { + tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; + clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles; + } + else { + tab = (VB->Elts ? + tnl->Driver.Render.PrimTabElts : + tnl->Driver.Render.PrimTabVerts); + } + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_END) ; i += length) { + flags = VB->Primitive[i].mode; + length= VB->Primitive[i].count; + ASSERT(length || (flags & PRIM_END)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + +// tnl->Driver.Render.Finish( ctx ); + + _GLD_DX9_VB(Unlock(gldPB->pVB)); + + _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride)); + + if (gldPB->nPoints) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + + + +const struct tnl_pipeline_stage _gld_mesa_render_stage = +{ + "gld_mesa_render_stage", + NULL, + NULL, + NULL, + NULL, + _gld_mesa_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c new file mode 100644 index 00000000000..dc465c54185 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c @@ -0,0 +1,1345 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: GLDirect Direct3D 8.x WGL (WindowsGL) +* +****************************************************************************/ + +#include "dglcontext.h" +#include "gld_driver.h" +#include "gld_dxerr9.h" +#include "gld_dx9.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +// Copied from dglcontect.c +#define GLDERR_NONE 0 +#define GLDERR_MEM 1 +#define GLDERR_DDRAW 2 +#define GLDERR_D3D 3 +#define GLDERR_BPP 4 +#define GLDERR_DDS 5 +// This external var keeps track of any error +extern int nContextError; + +#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL + +extern void _gld_mesa_warning(GLcontext *, char *); +extern void _gld_mesa_fatal(GLcontext *, char *); + +//--------------------------------------------------------------------------- + +static char szColorDepthWarning[] = +"GLDirect does not support the current desktop\n\ +color depth.\n\n\ +You may need to change the display resolution to\n\ +16 bits per pixel or higher color depth using\n\ +the Windows Display Settings control panel\n\ +before running this OpenGL application.\n"; + +// The only depth-stencil formats currently supported by Direct3D +// Surface Format Depth Stencil Total Bits +// D3DFMT_D32 32 - 32 +// D3DFMT_D15S1 15 1 16 +// D3DFMT_D24S8 24 8 32 +// D3DFMT_D16 16 - 16 +// D3DFMT_D24X8 24 - 32 +// D3DFMT_D24X4S4 24 4 32 + +// This pixel format will be used as a template when compiling the list +// of pixel formats supported by the hardware. Many fields will be +// filled in at runtime. +// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM +static DGL_pixelFormat pfTemplateHW = +{ + { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure + 1, // Structure version - should be 1 + // Flags: + PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface. + PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM) + PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM) + PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing. + PFD_DOUBLEBUFFER | // The buffer is double-buffered. + 0, // Placeholder for easy commenting of above flags + PFD_TYPE_RGBA, // Pixel type RGBA. + 16, // Total colour bitplanes (excluding alpha bitplanes) + 5, 0, // Red bits, shift + 5, 0, // Green bits, shift + 5, 0, // Blue bits, shift + 0, 0, // Alpha bits, shift (destination alpha) + 0, // Accumulator bits (total) + 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha + 0, // Depth bits + 0, // Stencil bits + 0, // Number of auxiliary buffers + 0, // Layer type + 0, // Specifies the number of overlay and underlay planes. + 0, // Layer mask + 0, // Specifies the transparent color or index of an underlay plane. + 0 // Damage mask + }, + D3DFMT_UNKNOWN, // No depth/stencil buffer +}; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// Vertex Shader Declaration +static DWORD dwTwoSidedLightingDecl[] = +{ + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position + D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal + D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color + D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color + D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0 + D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1 + D3DVSD_END() +}; + +// Vertex Shader for two-sided lighting +static char *szTwoSidedLightingVS = +// This is a test shader! +"vs.1.0\n" +"m4x4 oPos,v0,c0\n" +"mov oD0,v2\n" +"mov oD1,v3\n" +"mov oT0,v4\n" +"mov oT1,v5\n" +; +*/ +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +typedef struct { + HINSTANCE hD3D9DLL; // Handle to d3d9.dll + FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype + BOOL bDirect3D; // Persistant Direct3D9 exists + BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists + IDirect3D9 *pD3D; // Persistant Direct3D9 + IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9 +} GLD_dx9_globals; + +// These are "global" to all DX9 contexts. KeithH +static GLD_dx9_globals dx9Globals; + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +BOOL gldGetDXErrorString_DX( + HRESULT hr, + char *buf, + int nBufSize) +{ + // + // Return a string describing the input HRESULT error code + // + + const char *pStr = DXGetErrorString9(hr); + + if (pStr == NULL) + return FALSE; + + if (strlen(pStr) > nBufSize) + strncpy(buf, pStr, nBufSize); + else + strcpy(buf, pStr); + +// D3DXGetErrorString(hr, buf, nBufSize); + + return TRUE; +} + +//--------------------------------------------------------------------------- + +static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType( + IDirect3D9 *pD3D9, + D3DFORMAT SurfaceFormat, + D3DDEVTYPE d3dDevType, + BOOL Windowed) +{ + int i; + HRESULT hr; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE) + return D3DMULTISAMPLE_NONE; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) { + // Find fastest multisample + for (i=2; i<17; i++) { + hr = IDirect3D9_CheckDeviceMultiSampleType( + pD3D9, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i, + NULL); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } else { + // Find nicest multisample + for (i=16; i>1; i--) { + hr = IDirect3D9_CheckDeviceMultiSampleType( + pD3D9, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i, + NULL); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } + + // Nothing found - return default + return D3DMULTISAMPLE_NONE; +} + +//--------------------------------------------------------------------------- + +void _gldDestroyPrimitiveBuffer( + GLD_pb_dx9 *gldVB) +{ + SAFE_RELEASE(gldVB->pVB); + + // Sanity check... + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; +} + +//--------------------------------------------------------------------------- + +HRESULT _gldCreatePrimitiveBuffer( + GLcontext *ctx, + GLD_driver_dx9 *lpCtx, + GLD_pb_dx9 *gldVB) +{ + HRESULT hResult; + char *szCreateVertexBufferFailed = "CreateVertexBuffer failed"; + DWORD dwMaxVertices; // Max number of vertices in vertex buffer + DWORD dwVBSize; // Total size of vertex buffer + + // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we + // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize. + // We'll use IMM_SIZE if it's larger (which it should not be). + dwMaxVertices = MAX_ARRAY_LOCK_SIZE; + + // Now calculate how many vertices to allow for in total + // 1 per point, 2 per line, 6 per quad = 9 + dwVBSize = dwMaxVertices * 9 * gldVB->dwStride; + + hResult = IDirect3DDevice9_CreateVertexBuffer( + lpCtx->pDev, + dwVBSize, + gldVB->dwUsage, + gldVB->dwFVF, + gldVB->dwPool, + &gldVB->pVB, + NULL); + if (FAILED(hResult)) { + ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed); + return hResult; + } + + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; + gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL; + gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB + gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB + + return S_OK; +} + +//--------------------------------------------------------------------------- +// Function: _gldCreateVertexShaders +// Create DX9 Vertex Shaders. +//--------------------------------------------------------------------------- +/* +void _gldCreateVertexShaders( + GLD_driver_dx9 *gld) +{ + DWORD dwFlags; + LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer + HRESULT hr; + +#ifdef _DEBUG + dwFlags = D3DXASM_DEBUG; +#else + dwFlags = 0; // D3DXASM_SKIPVALIDATION; +#endif + + ddlogMessage(DDLOG_INFO, "Creating shaders...\n"); + + // Init the shader handle + gld->VStwosidelight.hShader = 0; + + if (gld->d3dCaps8.MaxStreams == 0) { + // Lame DX8 driver doesn't support streams + // Not fatal, as defaults will be used + ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n"); + return; + } + + // ** THIS DISABLES VERTEX SHADER SUPPORT ** +// return; + // ** THIS DISABLES VERTEX SHADER SUPPORT ** + + // + // Two-sided lighting + // + +#if 0 + // + // DEBUGGING: Load shader from a text file + // + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + hr = D3DXAssembleShaderFromFile( + "twoside.vsh", + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#else + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + // Assemble ascii shader text into shader opcodes + hr = D3DXAssembleShader( + szTwoSidedLightingVS, + strlen(szTwoSidedLightingVS), + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#endif + if (FAILED(hr)) { + ddlogError(DDLOG_WARN, "AssembleShader failed", hr); + SAFE_RELEASE(pVSOpcodeBuffer); + return; + } + +// This is for debugging. Remove to enable vertex shaders in HW +#define _GLD_FORCE_SW_VS 0 + + if (_GLD_FORCE_SW_VS) { + // _GLD_FORCE_SW_VS should be disabled for Final Release + ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n"); + } + + // Try and create shader in hardware. + // NOTE: The D3D Ref device appears to succeed when trying to + // create the device in hardware, but later complains + // when trying to set it with SetVertexShader(). Go figure. + if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) { + // Don't try and create a hardware shader with the Ref device + hr = E_FAIL; // COM error/fail result + } else { + gld->VStwosidelight.bHardware = TRUE; + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + 0); + } + if (FAILED(hr)) { + ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n"); + // Failed. Try and create shader for software processing + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + D3DUSAGE_SOFTWAREPROCESSING); + if (FAILED(hr)) { + gld->VStwosidelight.hShader = 0; // Sanity check + ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr); + return; + } + // Succeeded, but for software processing + gld->VStwosidelight.bHardware = FALSE; + } + + SAFE_RELEASE(pVSOpcodeBuffer); + + ddlogMessage(DDLOG_INFO, "... OK\n"); +} + +//--------------------------------------------------------------------------- + +void _gldDestroyVertexShaders( + GLD_driver_dx9 *gld) +{ + if (gld->VStwosidelight.hShader) { + IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader); + gld->VStwosidelight.hShader = 0; + } +} +*/ +//--------------------------------------------------------------------------- + +BOOL gldCreateDrawable_DX( + DGL_ctx *ctx, +// BOOL bDefaultDriver, + BOOL bDirectDrawPersistant, + BOOL bPersistantBuffers) +{ + // + // bDirectDrawPersistant: applies to IDirect3D9 + // bPersistantBuffers: applies to IDirect3DDevice9 + // + + HRESULT hResult; + GLD_driver_dx9 *lpCtx = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + DWORD dwBehaviourFlags; + D3DADAPTER_IDENTIFIER9 d3dIdent; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + if (ctx->glPriv) { + lpCtx = ctx->glPriv; + // Release any existing interfaces + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + } else { + lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9)); + ZeroMemory(lpCtx, sizeof(lpCtx)); + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + // TODO: Check this +// if (bDefaultDriver) +// d3dDevType = D3DDEVTYPE_REF; + + // Use persistant interface if needed + if (bDirectDrawPersistant && dx9Globals.bDirect3D) { + lpCtx->pD3D = dx9Globals.pD3D; + IDirect3D9_AddRef(lpCtx->pD3D); + goto SkipDirectDrawCreate; + } + + // Create Direct3D9 object + lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION); + if (lpCtx->pD3D == NULL) { + MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK); + ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface"); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Cache Direct3D interface for subsequent GLRCs + if (bDirectDrawPersistant && !dx9Globals.bDirect3D) { + dx9Globals.pD3D = lpCtx->pD3D; + IDirect3D9_AddRef(dx9Globals.pD3D); + dx9Globals.bDirect3D = TRUE; + } +SkipDirectDrawCreate: + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Get device caps + hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Check for hardware transform & lighting + lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; + +/* + // + // GONE FOR DX9? + // + // If this flag is present then we can't default to Mesa + // SW rendering between BeginScene() and EndScene(). + if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { + ddlogMessage(DDLOG_WARN, + "Warning : No 2D allowed during 3D scene.\n"); + } +*/ + + // + // Create the Direct3D context + // + + // Re-use original IDirect3DDevice if persistant buffers exist. + // Note that we test for persistant IDirect3D9 as well + // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist) + if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) { + lpCtx->pDev = dx9Globals.pDev; + IDirect3DDevice9_AddRef(dx9Globals.pDev); + goto skip_direct3ddevice_create; + } + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 2; //1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + + // Support for vertical retrace synchronisation. + // Set default presentation interval in case caps bits are missing + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + // PresentationInterval Windowed mode is optional now in DX9 (DaveM) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } + + // Decide if we can use hardware TnL + dwBehaviourFlags = (lpCtx->bHasHWTnL) ? + D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; + // Add flag to tell D3D to be thread-safe + if (glb.bMultiThreaded) + dwBehaviourFlags |= D3DCREATE_MULTITHREADED; + // Add flag to tell D3D to be FPU-safe + if (!glb.bFastFPU) + dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE; + hResult = IDirect3D9_CreateDevice(lpCtx->pD3D, + glb.dwAdapter, + d3dDevType, + ctx->hWnd, + dwBehaviourFlags, + &d3dpp, + &lpCtx->pDev); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) { + dx9Globals.pDev = lpCtx->pDev; + dx9Globals.bDirect3DDevice = TRUE; + } + + // Dump some useful stats + hResult = IDirect3D9_GetAdapterIdentifier( + lpCtx->pD3D, + glb.dwAdapter, + 0, // No WHQL detection (avoid few seconds delay) + &d3dIdent); + if (SUCCEEDED(hResult)) { + ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); + ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", + d3dIdent.Driver, + HIWORD(d3dIdent.DriverVersion.HighPart), + LOWORD(d3dIdent.DriverVersion.HighPart), + HIWORD(d3dIdent.DriverVersion.LowPart), + LOWORD(d3dIdent.DriverVersion.LowPart)); + ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", + d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); + } + + // Test to see if IHV driver exposes Scissor Test (new for DX9) + lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST; + ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No"); + + // Init projection matrix for D3D TnL + D3DXMatrixIdentity(&lpCtx->matProjection); + lpCtx->matModelView = lpCtx->matProjection; +// gld->bUseMesaProjection = TRUE; + +skip_direct3ddevice_create: + + // Create buffers to hold primitives + lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; + lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; + lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); + lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); + if (FAILED(hResult)) + goto return_with_error; + + lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; + lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; + lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); + lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC | +//DaveM D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); + if (FAILED(hResult)) + goto return_with_error; + +/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders) + lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX; + lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT; + lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX); + lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight); + if (FAILED(hResult)) + goto return_with_error;*/ + + // Now try and create the DX9 Vertex Shaders +// _gldCreateVertexShaders(lpCtx); + + // Zero the pipeline usage counters + lpCtx->PipelineUsage.qwMesa.QuadPart = +// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = + lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; + + // Assign drawable to GL private + ctx->glPriv = lpCtx; + return TRUE; + +return_with_error: + // Clean up and bail + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL gldResizeDrawable_DX( + DGL_ctx *ctx, + BOOL bDefaultDriver, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + GLD_driver_dx9 *gld = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + HRESULT hResult; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice9_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + if (!bDefaultDriver) + d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software) + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; +// goto return_with_error; + return FALSE; + } + + // Destroy DX9 Vertex Shaders before Reset() +// _gldDestroyVertexShaders(gld); + + // Release POOL_DEFAULT objects before Reset() + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB2d); + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB3d); +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) +// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight); + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + // TODO: Sync to refresh + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + // Get better benchmark results? KeithH +// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED; + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult); + return FALSE; + //goto cleanup_and_return_with_error; + } + + // + // Recreate POOL_DEFAULT objects + // + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); + } + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d); + } +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) { +// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); +// } + + // Recreate DX9 Vertex Shaders +// _gldCreateVertexShaders(gld); + + // Signal a complete state update + ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL); + + // Begin a new scene + IDirect3DDevice9_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyDrawable_DX( + DGL_ctx *ctx) +{ + GLD_driver_dx9 *lpCtx = NULL; + + // Error if context is NULL. + if (!ctx) + return FALSE; + + // Error if the drawable does not exist. + if (!ctx->glPriv) + return FALSE; + + lpCtx = ctx->glPriv; + +#ifdef _DEBUG + // Dump out stats + ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X", + lpCtx->PipelineUsage.qwMesa.HighPart, + lpCtx->PipelineUsage.qwMesa.LowPart, + lpCtx->PipelineUsage.qwD3DFVF.HighPart, + lpCtx->PipelineUsage.qwD3DFVF.LowPart); +#endif + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + + // Free the private drawable data + free(ctx->glPriv); + ctx->glPriv = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldCreatePrivateGlobals_DX(void) +{ + ZeroMemory(&dx9Globals, sizeof(dx9Globals)); + + // Load d3d9.dll + dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL"); + if (dx9Globals.hD3D9DLL == NULL) + return FALSE; + + // Now try and obtain Direct3DCreate9 + dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9"); + if (dx9Globals.fnDirect3DCreate9 == NULL) { + FreeLibrary(dx9Globals.hD3D9DLL); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyPrivateGlobals_DX(void) +{ + if (dx9Globals.bDirect3DDevice) { + SAFE_RELEASE(dx9Globals.pDev); + dx9Globals.bDirect3DDevice = FALSE; + } + if (dx9Globals.bDirect3D) { + SAFE_RELEASE(dx9Globals.pD3D); + dx9Globals.bDirect3D = FALSE; + } + + FreeLibrary(dx9Globals.hD3D9DLL); + dx9Globals.hD3D9DLL = NULL; + dx9Globals.fnDirect3DCreate9 = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDisplayFormat( + D3DFORMAT fmt, + BYTE *cColorBits, + BYTE *cRedBits, + BYTE *cGreenBits, + BYTE *cBlueBits, + BYTE *cAlphaBits) +{ + switch (fmt) { + case D3DFMT_X1R5G5B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 5; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_R5G6B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 6; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_X8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; + return; + case D3DFMT_A8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 8; + return; + } + + // Should not get here! + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDepthStencilFormat( + D3DFORMAT fmt, + BYTE *cDepthBits, + BYTE *cStencilBits) +{ + // NOTE: GL expects either 32 or 16 as depth bits. + switch (fmt) { + case D3DFMT_D32: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D15S1: + *cDepthBits = 16; + *cStencilBits = 1; + return; + case D3DFMT_D24S8: + *cDepthBits = 32; + *cStencilBits = 8; + return; + case D3DFMT_D16: + *cDepthBits = 16; + *cStencilBits = 0; + return; + case D3DFMT_D24X8: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D24X4S4: + *cDepthBits = 32; + *cStencilBits = 4; + return; + } +} + +//--------------------------------------------------------------------------- + +BOOL gldBuildPixelformatList_DX(void) +{ + D3DDISPLAYMODE d3ddm; + D3DFORMAT fmt[6]; + IDirect3D9 *pD3D = NULL; + HRESULT hr; + int nSupportedFormats = 0; + int i; + DGL_pixelFormat *pPF; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; +// char buf[128]; +// char cat[8]; + + // Direct3D (SW or HW) + // These are arranged so that 'best' pixelformat + // is higher in the list (for ChoosePixelFormat). + const D3DFORMAT DepthStencil[6] = { +// New order: increaing Z, then increasing stencil + D3DFMT_D15S1, + D3DFMT_D16, + D3DFMT_D24X4S4, + D3DFMT_D24X8, + D3DFMT_D24S8, + D3DFMT_D32, + }; + + // Dump DX version + ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n"); + + // Release any existing pixelformat list + if (glb.lpPF) { + free(glb.lpPF); + } + + glb.nPixelFormatCount = 0; + glb.lpPF = NULL; + + // + // Pixelformats for Direct3D (SW or HW) rendering + // + + // Get a Direct3D 9.0 interface + pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION); + if (!pD3D) { + return FALSE; + } + + // We will use the display mode format when finding compliant + // rendertarget/depth-stencil surfaces. + hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) { + IDirect3D9_Release(pD3D); + return FALSE; + } + + // Run through the possible formats and detect supported formats + for (i=0; i<6; i++) { + hr = IDirect3D9_CheckDeviceFormat( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal. + continue; + + // Verify that the depth format is compatible. + hr = IDirect3D9_CheckDepthStencilMatch( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + d3ddm.Format, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal, just means depth-stencil + // format is not compatible with this display mode. + continue; + + fmt[nSupportedFormats++] = DepthStencil[i]; + } + + IDirect3D9_Release(pD3D); + + if (nSupportedFormats == 0) + return FALSE; // Bail: no compliant pixelformats + + // Total count of pixelformats is: + // (nSupportedFormats+1)*2 + // UPDATED: nSupportedFormats*2 + glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat)); + glb.nPixelFormatCount = nSupportedFormats*2; + if (glb.lpPF == NULL) { + glb.nPixelFormatCount = 0; + return FALSE; + } + + // Get a copy of pointer that we can alter + pPF = glb.lpPF; + + // Cache colour bits from display format + _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + // + // Add single-buffer formats + // +/* + // NOTE: No longer returning pixelformats that don't contain depth + // Single-buffer, no depth-stencil buffer + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++; +*/ + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // + // Add double-buffer formats + // + + // NOTE: No longer returning pixelformats that don't contain depth +/* + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++; +*/ + for (i=0; i<nSupportedFormats; i++, pPF++) { + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // Popup warning message if non RGB color mode + { + // This is a hack. KeithH + HDC hdcDesktop = GetDC(NULL); + DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL); + ReleaseDC(0, hdcDesktop); + if (dwDisplayBitDepth <= 8) { + ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth); + MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING); + } + } + + // Mark list as 'current' + glb.bPixelformatsDirty = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldInitialiseMesa_DX( + DGL_ctx *lpCtx) +{ + GLD_driver_dx9 *gld = NULL; + int MaxTextureSize, TextureLevels; + BOOL bSoftwareTnL; + + if (lpCtx == NULL) + return FALSE; + + gld = lpCtx->glPriv; + if (gld == NULL) + return FALSE; + + if (glb.bMultitexture) { + lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures; + // Only support MAX_TEXTURE_UNITS texture units. + // ** If this is altered then the FVF formats must be reviewed **. + if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9) + lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9; + } else { + // Multitexture override + lpCtx->glCtx->Const.MaxTextureUnits = 1; + } + + // max texture size + MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth); + if (MaxTextureSize == 0) + MaxTextureSize = 256; // Sanity check + + // + // HACK!! + if (MaxTextureSize > 1024) + MaxTextureSize = 1024; // HACK - CLAMP TO 1024 + // HACK!! + // + + // Got to set MAX_TEXTURE_SIZE as max levels. + // Who thought this stupid idea up? ;) + TextureLevels = 0; + // Calculate power-of-two. + while (MaxTextureSize) { + TextureLevels++; + MaxTextureSize >>= 1; + } + lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8; + + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE, + (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE); + + // Set the view matrix + { + D3DXMATRIX vm; +#if 1 + D3DXMatrixIdentity(&vm); +#else + D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f); + D3DXVECTOR3 At(0.0f, 0.0f, -1.0f); + D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); + D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up); + vm._31 = -vm._31; + vm._32 = -vm._32; + vm._33 = -vm._33; + vm._34 = -vm._34; +#endif + IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm); + } + + if (gld->bHasHWTnL) { + if (glb.dwTnL == GLDS_TNL_DEFAULT) + bSoftwareTnL = FALSE; // HW TnL + else { + bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE; + } + } else { + // No HW TnL, so no choice possible + bSoftwareTnL = TRUE; + } +// IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL); + IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL); + +// Dump this in a Release build as well, now. +//#ifdef _DEBUG + ddlogPrintf(DDLOG_INFO, "HW TnL: %s", + gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable"); +//#endif + + gldEnableExtensions_DX9(lpCtx->glCtx); + gldInstallPipeline_DX9(lpCtx->glCtx); + gldSetupDriverPointers_DX9(lpCtx->glCtx); + + // Signal a complete state update + lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL); + + // Start a scene + IDirect3DDevice9_BeginScene(gld->pDev); + lpCtx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldSwapBuffers_DX( + DGL_ctx *ctx, + HDC hDC, + HWND hWnd) +{ + HRESULT hr; + GLD_driver_dx9 *gld = NULL; + + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice9_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + // Swap the buffers. hWnd may override the hWnd used for CreateDevice() + hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL); + +exit_swap: + + IDirect3DDevice9_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + +// Debugging code +#ifdef _DEBUG +// ddlogMessage(GLDLOG_WARN, "SwapBuffers\n"); +#endif + + return (FAILED(hr)) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldGetDisplayMode_DX( + DGL_ctx *ctx, + GLD_displayMode *glddm) +{ + D3DDISPLAYMODE d3ddm; + HRESULT hr; + GLD_driver_dx9 *lpCtx = NULL; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; + + if ((glddm == NULL) || (ctx == NULL)) + return FALSE; + + lpCtx = ctx->glPriv; + if (lpCtx == NULL) + return FALSE; + + if (lpCtx->pD3D == NULL) + return FALSE; + + hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) + return FALSE; + + // Get info from the display format + _BitsFromDisplayFormat(d3ddm.Format, + &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + glddm->Width = d3ddm.Width; + glddm->Height = d3ddm.Height; + glddm->BPP = cColorBits; + glddm->Refresh = d3ddm.RefreshRate; + + return TRUE; +} + +//--------------------------------------------------------------------------- + diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c index 1eb19ca84b0..3000cd07d2f 100644 --- a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c +++ b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c @@ -1,4 +1,4 @@ -/* $Id: gld_debug_clip.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */ +/* $Id: gld_debug_clip.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c index 00c428bd262..8b7523ff5f3 100644 --- a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c +++ b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c @@ -1,4 +1,4 @@ -/* $Id: gld_debug_norm.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */ +/* $Id: gld_debug_norm.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c index d6e64b8ffdf..5cbea2617ea 100644 --- a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c +++ b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c @@ -1,4 +1,4 @@ -/* $Id: gld_debug_xform.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */ +/* $Id: gld_debug_xform.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */ /* * Mesa 3-D graphics library diff --git a/src/mesa/drivers/windows/gldirect/gldirect.rc b/src/mesa/drivers/windows/gldirect/gldirect.rc new file mode 100644 index 00000000000..ba09631538a --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/gldirect.rc @@ -0,0 +1,43 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: Windows Resource Compiler +* Environment: Windows 95 +* +****************************************************************************/ + +#ifndef WORKSHOP_INVOKED + #include <windows.h> +#endif + +#define FILE_DESCRIPTION "SciTech GLDirect" +#define ORIG_FILENAME "opengl32.dll" +#define FILE_TYPE VFT_DLL + +#include "gldirect/gldver.ver" diff --git a/src/mesa/drivers/windows/gldirect/mesasw/colors.h b/src/mesa/drivers/windows/gldirect/mesasw/colors.h new file mode 100644 index 00000000000..5660907aa51 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/mesasw/colors.h @@ -0,0 +1,523 @@ +/* File name : colors.h + * Version : 2.3 + * + * Header file for display driver for Mesa 2.3 under + * Windows95 and WindowsNT + * This file defines macros and global variables needed + * for converting color format + * + * Copyright (C) 1996- Li Wei + * Address : Institute of Artificial Intelligence + * : & Robotics + * : Xi'an Jiaotong University + * Email : [email protected] + * Web page : http://sun.aiar.xjtu.edu.cn + * + * This file and its associations are partially based on the + * Windows NT driver for Mesa, written by Mark Leaming + * ([email protected]). + */ + +/* $Log: ddcolors.h 1997/6/14 by Li Wei([email protected]) + * Macros for pixel format defined + */ + +/* + * $Log: colors.h,v $ + * Revision 1.1 2004-04-20 11:13:11 alanh + * add SciTech's GLDirect driver for Windows. + * + * This code is donated to Mesa which allows the usage of + * a Direct3D layer (DX7, DX8, DX9 or complete software fallback). + * + * No build system exists for this code yet, that will come..... + * + * Revision 1.1.1.1 1999/08/19 00:55:42 jtg + * Imported sources + * + * Revision 1.2 1999/01/03 03:08:57 brianp + * Ted Jump's changes + * + * Revision 1.1 1999/01/03 03:08:12 brianp + * Initial revision + * + * Revision 2.0.2 1997/4/30 15:58:00 CST by Li Wei([email protected]) + * Add LUTs need for dithering + */ + +/* + * $Log: colors.h,v $ + * Revision 1.1 2004-04-20 11:13:11 alanh + * add SciTech's GLDirect driver for Windows. + * + * This code is donated to Mesa which allows the usage of + * a Direct3D layer (DX7, DX8, DX9 or complete software fallback). + * + * No build system exists for this code yet, that will come..... + * + * Revision 1.1.1.1 1999/08/19 00:55:42 jtg + * Imported sources + * + * Revision 1.2 1999/01/03 03:08:57 brianp + * Ted Jump's changes + * + * Revision 1.1 1999/01/03 03:08:12 brianp + * Initial revision + * + * Revision 2.0.1 1997/4/29 15:52:00 CST by Li Wei([email protected]) + * Add BGR8 Macro + */ + +/* + * $Log: colors.h,v $ + * Revision 1.1 2004-04-20 11:13:11 alanh + * add SciTech's GLDirect driver for Windows. + * + * This code is donated to Mesa which allows the usage of + * a Direct3D layer (DX7, DX8, DX9 or complete software fallback). + * + * No build system exists for this code yet, that will come..... + * + * Revision 1.1.1.1 1999/08/19 00:55:42 jtg + * Imported sources + * + * Revision 1.2 1999/01/03 03:08:57 brianp + * Ted Jump's changes + * + * Revision 1.1 1999/01/03 03:08:12 brianp + * Initial revision + * + * Revision 2.0 1996/11/15 10:55:00 CST by Li Wei([email protected]) + * Initial revision + */ +/* Values for wmesa->pixelformat: */ + +#define PF_8A8B8G8R 3 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */ +#define PF_8R8G8B 4 /* 32-bit TrueColor: 8-R, 8-G, 8-B */ +#define PF_5R6G5B 5 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */ +#define PF_DITHER8 6 /* Dithered RGB using a lookup table */ +#define PF_LOOKUP 7 /* Undithered RGB using a lookup table */ +#define PF_GRAYSCALE 10 /* Grayscale or StaticGray */ +#define PF_BADFORMAT 11 +#define PF_INDEX8 12 + +char ColorMap16[] = { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, +0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, +0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, +0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A, +0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B, +0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, +0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D, +0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E, +0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, +0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14, +0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, +0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, +0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, +0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A, +0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B, +0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C, +0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D, +0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E, +0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F}; + +#define BGR8(r,g,b) (unsigned)(((BYTE)(b & 0xc0 | (g & 0xe0)>>2 | (r & 0xe0)>>5))) +#ifdef DDRAW +#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(g&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[r])) << 11))) +#else +#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(ColorMap16[g]) << 5)) | (((WORD)(BYTE)(ColorMap16[r])) << 10))) +#endif +#define BGR24(r,g,b) (unsigned long)(((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) << 8) +#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) + + + +/* + * If pixelformat==PF_8A8B8G8R: + */ +#define PACK_8A8B8G8R( R, G, B, A ) \ + ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) ) + + +/* + * If pixelformat==PF_8R8G8B: + */ +#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) ) + + +/* + * If pixelformat==PF_5R6G5B: + */ + + +#ifdef DDRAW +#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(G&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[R])) << 11))) +#else +#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(ColorMap16[G]) << 5)) | (((WORD)(BYTE)(ColorMap16[R])) << 10))) +#endif +/*---------------------------------------------------------------------------- + +Division lookup tables. These tables compute 0-255 divided by 51 and +modulo 51. These tables could approximate gamma correction. + +*/ + +char unsigned const aDividedBy51Rounded[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +}; + +char unsigned const aDividedBy51[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, +}; + +char unsigned const aModulo51[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, +}; + +/*---------------------------------------------------------------------------- + +Multiplication LUTs. These compute 0-5 times 6 and 36. + +*/ + +char unsigned const aTimes6[6] = +{ + 0, 6, 12, 18, 24, 30 +}; + +char unsigned const aTimes36[6] = +{ + 0, 36, 72, 108, 144, 180 +}; + + +/*---------------------------------------------------------------------------- + +Dither matrices for 8 bit to 2.6 bit halftones. + +*/ + +char unsigned const aHalftone16x16[256] = +{ + 0, 44, 9, 41, 3, 46, 12, 43, 1, 44, 10, 41, 3, 46, 12, 43, + 34, 16, 25, 19, 37, 18, 28, 21, 35, 16, 26, 19, 37, 18, 28, 21, + 38, 6, 47, 3, 40, 9, 50, 6, 38, 7, 47, 4, 40, 9, 49, 6, + 22, 28, 13, 31, 25, 31, 15, 34, 22, 29, 13, 32, 24, 31, 15, 34, + 2, 46, 12, 43, 1, 45, 10, 42, 2, 45, 11, 42, 1, 45, 11, 42, + 37, 18, 27, 21, 35, 17, 26, 20, 36, 17, 27, 20, 36, 17, 26, 20, + 40, 8, 49, 5, 38, 7, 48, 4, 39, 8, 48, 5, 39, 7, 48, 4, + 24, 30, 15, 33, 23, 29, 13, 32, 23, 30, 14, 33, 23, 29, 14, 32, + 2, 46, 12, 43, 0, 44, 10, 41, 3, 47, 12, 44, 0, 44, 10, 41, + 37, 18, 27, 21, 35, 16, 25, 19, 37, 19, 28, 22, 35, 16, 25, 19, + 40, 9, 49, 5, 38, 7, 47, 4, 40, 9, 50, 6, 38, 6, 47, 3, + 24, 30, 15, 34, 22, 29, 13, 32, 25, 31, 15, 34, 22, 28, 13, 31, + 1, 45, 11, 42, 2, 46, 11, 42, 1, 45, 10, 41, 2, 46, 11, 43, + 36, 17, 26, 20, 36, 17, 27, 21, 35, 16, 26, 20, 36, 18, 27, 21, + 39, 8, 48, 4, 39, 8, 49, 5, 38, 7, 48, 4, 39, 8, 49, 5, + 23, 29, 14, 33, 24, 30, 14, 33, 23, 29, 13, 32, 24, 30, 14, 33, +}; + +char unsigned const aHalftone8x8[64] = +{ + 0, 38, 9, 47, 2, 40, 11, 50, + 25, 12, 35, 22, 27, 15, 37, 24, + 6, 44, 3, 41, 8, 47, 5, 43, + 31, 19, 28, 15, 34, 21, 31, 18, + 1, 39, 11, 49, 0, 39, 10, 48, + 27, 14, 36, 23, 26, 13, 35, 23, + 7, 46, 4, 43, 7, 45, 3, 42, + 33, 20, 30, 17, 32, 19, 29, 16, +}; + +char unsigned const aHalftone4x4_1[16] = +{ + 0, 25, 6, 31, + 38, 12, 44, 19, + 9, 35, 3, 28, + 47, 22, 41, 15 +}; + +char unsigned const aHalftone4x4_2[16] = +{ + 41, 3, 9, 28, + 35, 15, 22, 47, + 6, 25, 38, 0, + 19, 44, 31, 12 +}; + +/*************************************************************************** + aWinGHalftoneTranslation + + Translates a 2.6 bit-per-pixel halftoned representation into the + slightly rearranged WinG Halftone Palette. +*/ + +char unsigned const aWinGHalftoneTranslation[216] = +{ + 0, + 29, + 30, + 31, + 32, + 249, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 250, + 250, + 57, + 58, + 59, + 251, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 250, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 227, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 151, + 120, + 121, + 122, + 123, + 124, + 228, + 125, + 126, + 229, + 133, + 162, + 135, + 131, + 132, + 137, + 166, + 134, + 140, + 130, + 136, + 143, + 138, + 139, + 174, + 141, + 142, + 177, + 129, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 157, + 152, + 153, + 154, + 155, + 156, + 192, + 158, + 159, + 160, + 161, + 196, + 163, + 164, + 165, + 127, + 199, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 207, + 175, + 176, + 210, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 224, + 193, + 194, + 195, + 252, + 252, + 197, + 198, + 128, + 253, + 252, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 230, + 208, + 209, + 231, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 254, + 223, + 232, + 225, + 226, + 255, +};
\ No newline at end of file diff --git a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c new file mode 100644 index 00000000000..0f11b4fe513 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c @@ -0,0 +1,1719 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Mesa Software WGL (WindowsGL) +* +****************************************************************************/ + +#include <windows.h> +#define GL_GLEXT_PROTOTYPES +#include <GL/gl.h> +#include <GL/glext.h> + +#include "glheader.h" +#include "colors.h" +#include "context.h" +#include "colormac.h" +#include "dd.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "texstore.h" +#include "teximage.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "swrast/s_trispan.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "dglcontext.h" +#include "gld_driver.h" + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +DGL_pixelFormat pfTemplateMesaSW = +{ + { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure + 1, // Structure version - should be 1 + // Flags: + PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface. + PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM) + PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM) + PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing. + PFD_DOUBLEBUFFER | // The buffer is double-buffered. + 0, // Placeholder for easy commenting of above flags + PFD_TYPE_RGBA, // Pixel type RGBA. + 32, // Total colour bitplanes (excluding alpha bitplanes) + 8, 0, // Red bits, shift + 8, 8, // Green bits, shift + 8, 16, // Blue bits, shift + 8, 24, // Alpha bits, shift (destination alpha) + 64, // Accumulator bits (total) + 16, 16, 16, 16, // Accumulator bits: Red, Green, Blue, Alpha + 16, // Depth bits + 8, // Stencil bits + 0, // Number of auxiliary buffers + 0, // Layer type + 0, // Specifies the number of overlay and underlay planes. + 0, // Layer mask + 0, // Specifies the transparent color or index of an underlay plane. + 0 // Damage mask + }, + 0, // Unused +}; + +//--------------------------------------------------------------------------- +// Extensions +//--------------------------------------------------------------------------- + +typedef struct { + PROC proc; + char *name; +} GLD_extension; + +static GLD_extension GLD_extList[] = { +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }, + { NULL, "\0" } +}; + +//--------------------------------------------------------------------------- +// WMesa Internal Functions +//--------------------------------------------------------------------------- + +#define PAGE_FILE 0xffffffff + +#define REDBITS 0x03 +#define REDSHIFT 0x00 +#define GREENBITS 0x03 +#define GREENSHIFT 0x03 +#define BLUEBITS 0x02 +#define BLUESHIFT 0x06 + +typedef struct _dibSection { + HDC hDC; + HANDLE hFileMap; + BOOL fFlushed; + LPVOID base; +} WMDIBSECTION, *PWMDIBSECTION; + +typedef struct wmesa_context { + HWND Window; + HDC hDC; + HPALETTE hPalette; + HPALETTE hOldPalette; + HPEN hPen; + HPEN hOldPen; + HCURSOR hOldCursor; + COLORREF crColor; + // 3D projection stuff + RECT drawRect; + UINT uiDIBoffset; + // OpenGL stuff + HPALETTE hGLPalette; + GLuint width; + GLuint height; + GLuint ScanWidth; + GLboolean db_flag; //* double buffered? + GLboolean rgb_flag; //* RGB mode? + GLboolean dither_flag; //* use dither when 256 color mode for RGB? + GLuint depth; //* bits per pixel (1, 8, 24, etc) + ULONG pixel; // current color index or RGBA pixel value + ULONG clearpixel; //* pixel for clearing the color buffers + PBYTE ScreenMem; // WinG memory + BITMAPINFO *IndexFormat; + HPALETTE hPal; // Current Palette + HPALETTE hPalHalfTone; + + + WMDIBSECTION dib; + BITMAPINFO bmi; + HBITMAP hbmDIB; + HBITMAP hOldBitmap; + HBITMAP Old_Compat_BM; + HBITMAP Compat_BM; // Bitmap for double buffering + PBYTE pbPixels; + int nColors; + BYTE cColorBits; + int pixelformat; + + RECT rectOffScreen; + RECT rectSurface; +// HWND hwnd; + DWORD pitch; + PBYTE addrOffScreen; + + // We always double-buffer, for performance reasons, but + // we need to know which of SwapBuffers() or glFlush() to + // handle. If we're emulating, then we update on Flush(), + // otherwise we update on SwapBufers(). KeithH + BOOL bEmulateSingleBuffer; +} WMesaContext, *PWMC; + +#define GLD_GET_WMESA_DRIVER(c) (WMesaContext*)(c)->glPriv + +// TODO: +GLint stereo_flag = 0 ; + +/* If we are double-buffering, we want to get the DC for the + * off-screen DIB, otherwise the DC for the window. + */ +#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC ) +#define DD_RELEASEDC + +#define FLIP(Y) (Current->height-(Y)-1) + +struct DISPLAY_OPTIONS { + int stereo; + int fullScreen; + int mode; + int bpp; +}; + +struct DISPLAY_OPTIONS displayOptions; + +//--------------------------------------------------------------------------- + +static unsigned char threeto8[8] = { + 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377 +}; + +static unsigned char twoto8[4] = { + 0, 0x55, 0xaa, 0xff +}; + +static unsigned char oneto8[2] = { + 0, 255 +}; + +//--------------------------------------------------------------------------- + +BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline) +{ + char unsigned redtemp, greentemp, bluetemp, paletteindex; + + //*** now, look up each value in the halftone matrix + //*** using an 8x8 ordered dither. + redtemp = aDividedBy51[red] + + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 + + scanline%8]); + greentemp = aDividedBy51[(char unsigned)green] + + (aModulo51[green] > aHalftone8x8[ + (pixel%8)*8 + scanline%8]); + bluetemp = aDividedBy51[(char unsigned)blue] + + (aModulo51[blue] > aHalftone8x8[ + (pixel%8)*8 +scanline%8]); + + //*** recombine the halftoned rgb values into a palette index + paletteindex = + redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; + + //*** and translate through the wing halftone palette + //*** translation vector to give the correct value. + return aWinGHalftoneTranslation[paletteindex]; +} + +//--------------------------------------------------------------------------- + +static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift) +{ + unsigned char val; + + val = i >> shift; + switch (nbits) { + + case 1: + val &= 0x1; + return oneto8[val]; + + case 2: + val &= 0x3; + return twoto8[val]; + + case 3: + val &= 0x7; + return threeto8[val]; + + default: + return 0; + } +} + +//--------------------------------------------------------------------------- + + +void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b) +{ + WMesaContext *Current = pwc; + + // Test for invalid scanline parameter. KeithH + if ((iScanLine < 0) || (iScanLine >= pwc->height)) + return; + + if (Current->db_flag) { + LPBYTE lpb = pwc->pbPixels; + UINT nBypp = pwc->cColorBits >> 3; + UINT nOffset = iPixel % nBypp; + + lpb += pwc->ScanWidth * iScanLine; + lpb += iPixel * nBypp; + + if(nBypp == 1){ + if(pwc->dither_flag) + *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel); + else + *lpb = BGR8(r,g,b); + } + else if(nBypp == 2) + *((LPWORD)lpb) = BGR16(r,g,b); + else if (nBypp == 3) + *((LPDWORD)lpb) = BGR24(r,g,b); + else if (nBypp == 4) + *((LPDWORD)lpb) = BGR32(r,g,b); + } + else{ + SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b)); + } +} + +//--------------------------------------------------------------------------- + +void wmCreateDIBSection( + HDC hDC, + PWMC pwc, // handle of device context + CONST BITMAPINFO *pbmi, // bitmap size, format, and color data + UINT iUsage // color data type indicator: RGB values or palette indices + ) +{ + DWORD dwSize = 0; + DWORD dwScanWidth; + UINT nBypp = pwc->cColorBits / 8; + HDC hic; + + dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3); + + pwc->ScanWidth =pwc->pitch = dwScanWidth; + + if (stereo_flag) + pwc->ScanWidth = 2* pwc->pitch; + + dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height); + + pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + dwSize, + NULL); + + if (!pwc->dib.hFileMap) + return; + + pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap, + FILE_MAP_ALL_ACCESS, + 0, + 0, + 0); + + if(!pwc->dib.base){ + CloseHandle(pwc->dib.hFileMap); + return; + } + + + CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO)); + + hic = CreateIC("display", NULL, NULL, NULL); + pwc->dib.hDC = CreateCompatibleDC(hic); + + + pwc->hbmDIB = CreateDIBSection(hic, + &(pwc->bmi), + (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS), + &(pwc->pbPixels), + pwc->dib.hFileMap, + 0); + pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels; + pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB); + + DeleteDC(hic); + + return; + +} + +//--------------------------------------------------------------------------- + +void wmCreatePalette( PWMC pwdc ) +{ + /* Create a compressed and re-expanded 3:3:2 palette */ + int i; + LOGPALETTE *pPal; + BYTE rb, rs, gb, gs, bb, bs; + + pwdc->nColors = 0x100; + + pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + + pwdc->nColors * sizeof(PALETTEENTRY)); + memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) ); + + pPal->palVersion = 0x300; + + rb = REDBITS; + rs = REDSHIFT; + gb = GREENBITS; + gs = GREENSHIFT; + bb = BLUEBITS; + bs = BLUESHIFT; + + if (pwdc->db_flag) { + + /* Need to make two palettes: one for the screen DC and one for the DIB. */ + pPal->palNumEntries = pwdc->nColors; + for (i = 0; i < pwdc->nColors; i++) { + pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); + pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); + pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); + pPal->palPalEntry[i].peFlags = 0; + } + pwdc->hGLPalette = CreatePalette( pPal ); + pwdc->hPalette = CreatePalette( pPal ); + } + + else { + pPal->palNumEntries = pwdc->nColors; + for (i = 0; i < pwdc->nColors; i++) { + pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs ); + pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs ); + pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs ); + pPal->palPalEntry[i].peFlags = 0; + } + pwdc->hGLPalette = CreatePalette( pPal ); + } + + free(pPal); + +} + +//--------------------------------------------------------------------------- + +/* This function sets the color table of a DIB section + * to match that of the destination DC + */ +BOOL wmSetDibColors(PWMC pwc) +{ + RGBQUAD *pColTab, *pRGB; + PALETTEENTRY *pPal, *pPE; + int i, nColors; + BOOL bRet=TRUE; + DWORD dwErr=0; + + /* Build a color table in the DIB that maps to the + * selected palette in the DC. + */ + nColors = 1 << pwc->cColorBits; + pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY)); + memset( pPal, 0, nColors * sizeof(PALETTEENTRY) ); + GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal ); + pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD)); + for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) { + pRGB->rgbRed = pPE->peRed; + pRGB->rgbGreen = pPE->peGreen; + pRGB->rgbBlue = pPE->peBlue; + } + if(pwc->db_flag) + bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab ); + + if(!bRet) + dwErr = GetLastError(); + + free( pColTab ); + free( pPal ); + + return bRet; +} + +//--------------------------------------------------------------------------- + +static void wmSetPixelFormat( PWMC wc, HDC hDC) +{ + if(wc->rgb_flag) + wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); + else + wc->cColorBits = 8; + switch(wc->cColorBits){ + case 8: + if(wc->dither_flag != GL_TRUE) + wc->pixelformat = PF_INDEX8; + else + wc->pixelformat = PF_DITHER8; + break; + case 16: + wc->pixelformat = PF_5R6G5B; + break; + case 32: + wc->pixelformat = PF_8R8G8B; + break; + default: + wc->pixelformat = PF_BADFORMAT; + } +} + +//--------------------------------------------------------------------------- + +/* + * This function creates the DIB section that is used for combined + * GL and GDI calls + */ +BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize) +{ + HDC hdc = pwc->hDC; + LPBITMAPINFO pbmi = &(pwc->bmi); + int iUsage; + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biWidth = lxSize; + pbmi->bmiHeader.biHeight= -lySize; + pbmi->bmiHeader.biPlanes = 1; + if(pwc->rgb_flag) + pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL); + else + pbmi->bmiHeader.biBitCount = 8; + 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; + + iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS; + + pwc->cColorBits = pbmi->bmiHeader.biBitCount; + pwc->ScanWidth = pwc->pitch = lxSize; + pwc->width = lxSize; + pwc->height = lySize; + + wmCreateDIBSection(hdc, pwc, pbmi, iUsage); + + if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) { + wmCreatePalette( pwc ); + wmSetDibColors( pwc ); + } + wmSetPixelFormat(pwc, pwc->hDC); + return TRUE; +} + +//--------------------------------------------------------------------------- + +/* + * Free up the dib section that was created + */ +BOOL wmDeleteBackingStore(PWMC pwc) +{ + SelectObject(pwc->dib.hDC, pwc->hOldBitmap); + DeleteDC(pwc->dib.hDC); + DeleteObject(pwc->hbmDIB); + UnmapViewOfFile(pwc->dib.base); + CloseHandle(pwc->dib.hFileMap); + return TRUE; +} + +//--------------------------------------------------------------------------- + +/* + * Blit memory DC to screen DC + */ +BOOL wmFlush(PWMC pwc, HDC hDC) +{ + BOOL bRet = 0; + DWORD dwErr = 0; + +// Now using bEmulateSingleBuffer in the calling function. KeithH + +// if(pwc->db_flag){ + bRet = BitBlt(hDC, 0, 0, pwc->width, pwc->height, + pwc->dib.hDC, 0, 0, SRCCOPY); +// } + + return bRet; + +} + +//--------------------------------------------------------------------------- +// Support Functions +//--------------------------------------------------------------------------- + +static void flush(GLcontext* ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); +/* + if((Current->rgb_flag &&!(Current->db_flag)) + ||(!Current->rgb_flag)) + { + wmFlush(Current, Current->hDC); + } +*/ + // Only flush if we're not in double-buffer mode. KeithH + // The demo fractal.c calls glutSwapBuffers() then glFlush()! + if (Current->bEmulateSingleBuffer) { + wmFlush(Current, Current->hDC); + } +} + + +//--------------------------------------------------------------------------- + + +/* + * Set the color index used to clear the color buffer. + */ +static void clear_index(GLcontext* ctx, GLuint index) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + Current->clearpixel = index; +} + + + +//--------------------------------------------------------------------------- + +/* + * Set the color used to clear the color buffer. + */ +//static void clear_color( GLcontext* ctx, const GLchan color[4] ) +// Changed for Mesa 5.x. KeithH +static void clear_color( + GLcontext* ctx, + const GLfloat color[4]) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLubyte col[4]; + 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->clearpixel = RGB(col[0], col[1], col[2]); +} + + +//--------------------------------------------------------------------------- + + +/* + * 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. + * We also only clear the color buffers if the color masks are all 1's. + * Otherwise, we let swrast do it. + */ + +static clear(GLcontext* ctx, GLbitfield mask, + GLboolean all, GLint x, GLint y, GLint width, GLint height) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + DWORD dwColor; + WORD wColor; + BYTE bColor; + LPDWORD lpdw = (LPDWORD)Current->pbPixels; + LPWORD lpw = (LPWORD)Current->pbPixels; + LPBYTE lpb = Current->pbPixels; + int lines; + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if (all){ + x=y=0; + width=Current->width; + height=Current->height; + } + + + /* sanity check - can't have right(stereo) buffers */ + assert((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT)) == 0); + + /* clear alpha */ + if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_RIGHT_BIT)) && + ctx->DrawBuffer->UseSoftwareAlphaBuffers && + ctx->Color.ColorMask[ACOMP]) { + _swrast_clear_alpha_buffers( ctx ); + } + + if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { + if (mask & DD_BACK_LEFT_BIT) { + /* Double-buffering - clear back buffer */ + UINT nBypp = Current->cColorBits / 8; + int i = 0; + int iSize = 0; + + assert(Current->db_flag==GL_TRUE); /* we'd better be double buffer */ + if(nBypp ==1 ){ + iSize = Current->width/4; + bColor = BGR8(GetRValue(Current->clearpixel), + GetGValue(Current->clearpixel), + GetBValue(Current->clearpixel)); + wColor = MAKEWORD(bColor,bColor); + dwColor = MAKELONG(wColor, wColor); + } + if(nBypp == 2){ + iSize = Current->width / 2; + wColor = BGR16(GetRValue(Current->clearpixel), + GetGValue(Current->clearpixel), + GetBValue(Current->clearpixel)); + dwColor = MAKELONG(wColor, wColor); + } + else if(nBypp == 4){ + iSize = Current->width; + dwColor = BGR32(GetRValue(Current->clearpixel), + GetGValue(Current->clearpixel), + GetBValue(Current->clearpixel)); + } + + /* clear a line */ + while(i < iSize){ + *lpdw = dwColor; + lpdw++; + i++; + } + + /* This is the 24bit case */ + if (nBypp == 3) { + iSize = Current->width *3/4; + dwColor = BGR24(GetRValue(Current->clearpixel), + GetGValue(Current->clearpixel), + GetBValue(Current->clearpixel)); + while(i < iSize){ + *lpdw = dwColor; + lpb += nBypp; + lpdw = (LPDWORD)lpb; + i++; + } + } + + i = 0; + if (stereo_flag) + lines = height /2; + else + lines = height; + /* copy cleared line to other lines in buffer */ + do { + memcpy(lpb, Current->pbPixels, iSize*4); + lpb += Current->ScanWidth; + i++; + } + while (i<lines-1); + mask &= ~DD_BACK_LEFT_BIT; + } /* double-buffer */ + + if (mask & DD_FRONT_LEFT_BIT) { + /* single-buffer */ + HDC DC=DD_GETDC; + HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel); + HBRUSH Brush=CreateSolidBrush(Current->clearpixel); + HPEN Old_Pen=SelectObject(DC,Pen); + HBRUSH Old_Brush=SelectObject(DC,Brush); + Rectangle(DC,x,y,x+width,y+height); + SelectObject(DC,Old_Pen); + SelectObject(DC,Old_Brush); + DeleteObject(Pen); + DeleteObject(Brush); + DD_RELEASEDC; + mask &= ~DD_FRONT_LEFT_BIT; + } /* single-buffer */ + } /* if masks are all 1's */ + + /* Call swrast if there is anything left to clear (like DEPTH) */ + if (mask) + _swrast_Clear( ctx, mask, all, x, y, width, height ); +} + + +//--------------------------------------------------------------------------- + + +static void enable( GLcontext* ctx, GLenum pname, GLboolean enable ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + + if (!Current) + return; + + if (pname == GL_DITHER) { + if(enable == GL_FALSE){ + Current->dither_flag = GL_FALSE; + if(Current->cColorBits == 8) + Current->pixelformat = PF_INDEX8; + } + else{ + if (Current->rgb_flag && Current->cColorBits == 8){ + Current->pixelformat = PF_DITHER8; + Current->dither_flag = GL_TRUE; + } + else + Current->dither_flag = GL_FALSE; + } + } +} + +//--------------------------------------------------------------------------- + +static GLboolean set_draw_buffer( GLcontext* ctx, GLenum mode ) +{ + /* TODO: this could be better */ + if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +//--------------------------------------------------------------------------- + + +static void set_read_buffer(GLcontext *ctx, GLframebuffer *colorBuffer, + GLenum buffer ) +{ + /* XXX todo */ + return; +} + + +//--------------------------------------------------------------------------- + + +/* Return characteristics of the output buffer. */ +//static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height ) +// Altered for Mesa 5.x. KeithH +static void buffer_size( + GLframebuffer *buffer, + GLuint *width, + GLuint *height) +{ + // For some reason the context is not passed into this function. + // Therefore we have to explicitly retrieve it. + GET_CURRENT_CONTEXT(ctx); + + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + int New_Size; + RECT CR; + + GetClientRect(Current->Window,&CR); + + *width=CR.right; + *height=CR.bottom; + + New_Size=((*width)!=Current->width) || ((*height)!=Current->height); + + if (New_Size){ + Current->width=*width; + Current->height=*height; + Current->ScanWidth=Current->width; + if ((Current->ScanWidth%sizeof(long))!=0) + Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long))); + + if (Current->db_flag){ + if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){ + wmDeleteBackingStore(Current); + wmCreateBackingStore(Current, Current->width, Current->height); + } + } + + } +} + + + +/**********************************************************************/ +/***** Accelerated point, line, polygon rendering *****/ +/**********************************************************************/ + +/* Accelerated routines are not implemented in 4.0. See OSMesa for ideas. */ + +static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last ) +{ +} + +//--------------------------------------------------------------------------- + +/* Return pointer to accelerated points function */ +extern tnl_points_func choose_points_function( GLcontext* ctx ) +{ + return NULL; +} + +//--------------------------------------------------------------------------- + +static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, + GLuint v1, GLuint pv ) +{ +} + +//--------------------------------------------------------------------------- + +static tnl_line_func choose_line_function( GLcontext* ctx ) +{ +} + + +/**********************************************************************/ +/***** Span-based pixel drawing *****/ +/**********************************************************************/ + + +/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */ +static void write_ci32_span( const GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLuint index[], + const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) + if (mask[i]) + Mem[i]=index[i]; +} + + +//--------------------------------------------------------------------------- + +/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */ +static void write_ci8_span( const GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLubyte index[], + const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) + if (mask[i]) + Mem[i]=index[i]; +} + + +//--------------------------------------------------------------------------- + + +/* + * Write a horizontal span of pixels with a boolean mask. The current + * color index is used for all pixels. + */ +static void write_mono_ci_span(const GLcontext* ctx, + GLuint n,GLint x,GLint y, + GLuint colorIndex, const GLubyte mask[]) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) + if (mask[i]) + Mem[i]=colorIndex; +} + +//--------------------------------------------------------------------------- + +/* + * To improve the performance of this routine, frob the data into an actual + * scanline and call bitblt on the complete scan line instead of SetPixel. + */ + +/* Write a horizontal span of RGBA color pixels with a boolean mask. */ +static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, + const GLubyte rgba[][4], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + PWMC pwc = Current; + + if (pwc->rgb_flag==GL_TRUE) + { + GLuint i; + HDC DC=DD_GETDC; + y=FLIP(y); + if (mask) { + for (i=0; i<n; i++) + if (mask[i]) + wmSetPixel(pwc, y, x + i, + rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); + } + else { + for (i=0; i<n; i++) + wmSetPixel(pwc, y, x + i, + rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + DD_RELEASEDC; + } + else + { + GLuint i; + BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; i<n; i++) + if (mask[i]) + Mem[i] = GetNearestPaletteIndex(Current->hPal, + RGB(rgba[i][RCOMP], + rgba[i][GCOMP], + rgba[i][BCOMP])); + } + else { + for (i=0; i<n; i++) + Mem[i] = GetNearestPaletteIndex(Current->hPal, + 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( const GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLubyte rgb[][3], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + PWMC pwc = Current; + + if (pwc->rgb_flag==GL_TRUE) + { + GLuint i; + HDC DC=DD_GETDC; + y=FLIP(y); + if (mask) { + for (i=0; i<n; i++) + if (mask[i]) + wmSetPixel(pwc, y, x + i, + rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]); + } + else { + for (i=0; i<n; i++) + wmSetPixel(pwc, y, x + i, + rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ); + } + DD_RELEASEDC; + } + else + { + GLuint i; + BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x; + y = FLIP(y); + if (mask) { + for (i=0; i<n; i++) + if (mask[i]) + Mem[i] = GetNearestPaletteIndex(Current->hPal, + RGB(rgb[i][RCOMP], + rgb[i][GCOMP], + rgb[i][BCOMP])); + } + else { + for (i=0; i<n; i++) + Mem[i] = GetNearestPaletteIndex(Current->hPal, + 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( const GLcontext* ctx, + GLuint n, GLint x, GLint y, + const GLchan color[4], const GLubyte mask[]) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + ULONG pixel = RGB( color[RCOMP], color[GCOMP], color[BCOMP] ); + GLuint i; + HDC DC=DD_GETDC; + PWMC pwc = Current; + assert(Current->rgb_flag==GL_TRUE); + y=FLIP(y); + if(Current->rgb_flag==GL_TRUE){ + for (i=0; i<n; i++) + if (mask[i]) + wmSetPixel(pwc,y,x+i,color[RCOMP], color[GCOMP], color[BCOMP]); + } + else { + for (i=0; i<n; i++) + if (mask[i]) + SetPixel(DC, y, x+i, pixel); + } + DD_RELEASEDC; +} + + + +/**********************************************************************/ +/***** Array-based pixel drawing *****/ +/**********************************************************************/ + + +/* Write an array of 32-bit index pixels with a boolean mask. */ +static void write_ci32_pixels( const GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLuint index[], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) { + if (mask[i]) { + BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; + *Mem = index[i]; + } + } +} + + +//--------------------------------------------------------------------------- + + +/* + * Write an array of pixels with a boolean mask. The current color + * index is used for all pixels. + */ +static void write_mono_ci_pixels( const GLcontext* ctx, + GLuint n, + const GLint x[], const GLint y[], + GLuint colorIndex, const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) { + if (mask[i]) { + BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]; + *Mem = colorIndex; + } + } +} + + +//--------------------------------------------------------------------------- + + +/* Write an array of RGBA pixels with a boolean mask. */ +static void write_rgba_pixels( const GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + const GLubyte rgba[][4], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + PWMC pwc = Current; + HDC DC=DD_GETDC; + assert(Current->rgb_flag==GL_TRUE); + for (i=0; i<n; i++) + if (mask[i]) + wmSetPixel(pwc, FLIP(y[i]), x[i], + rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); + DD_RELEASEDC; +} + + +//--------------------------------------------------------------------------- + + +/* + * Write an array of pixels with a boolean mask. The current color + * is used for all pixels. + */ +static void write_mono_rgba_pixels( const GLcontext* ctx, + GLuint n, + const GLint x[], const GLint y[], + const GLchan color[4], + const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + PWMC pwc = Current; + HDC DC=DD_GETDC; + assert(Current->rgb_flag==GL_TRUE); + for (i=0; i<n; i++) + if (mask[i]) + wmSetPixel(pwc, FLIP(y[i]),x[i],color[RCOMP], + color[GCOMP], color[BCOMP]); + DD_RELEASEDC; +} + +/**********************************************************************/ +/***** Read spans/arrays of pixels *****/ +/**********************************************************************/ + +/* Read a horizontal span of color-index pixels. */ +static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y, + GLuint index[]) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) + index[i]=Mem[i]; +} + +//--------------------------------------------------------------------------- + +/* Read an array of color index pixels. */ +static void read_ci32_pixels( const GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + GLuint indx[], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + assert(Current->rgb_flag==GL_FALSE); + for (i=0; i<n; i++) { + if (mask[i]) { + indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]); + } + } +} + +//--------------------------------------------------------------------------- + +/* Read a horizontal span of color pixels. */ +static void read_rgba_span( const GLcontext* ctx, + GLuint n, GLint x, GLint y, + GLubyte rgba[][4] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + UINT i; + COLORREF Color; + HDC DC=DD_GETDC; + assert(Current->rgb_flag==GL_TRUE); + y = Current->height - y - 1; + for (i=0; i<n; i++) { + Color=GetPixel(DC,x+i,y); + rgba[i][RCOMP] = GetRValue(Color); + rgba[i][GCOMP] = GetGValue(Color); + rgba[i][BCOMP] = GetBValue(Color); + rgba[i][ACOMP] = 255; + } + DD_RELEASEDC; +} + +//--------------------------------------------------------------------------- + +/* Read an array of color pixels. */ +static void read_rgba_pixels( const GLcontext* ctx, + GLuint n, const GLint x[], const GLint y[], + GLubyte rgba[][4], const GLubyte mask[] ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx); + GLuint i; + COLORREF Color; + HDC DC=DD_GETDC; + assert(Current->rgb_flag==GL_TRUE); + for (i=0; i<n; i++) { + if (mask[i]) { + GLint y2 = Current->height - y[i] - 1; + Color=GetPixel(DC,x[i],y2); + rgba[i][RCOMP] = GetRValue(Color); + rgba[i][GCOMP] = GetGValue(Color); + rgba[i][BCOMP] = GetBValue(Color); + rgba[i][ACOMP] = 255; + } + } + DD_RELEASEDC; +} + +//--------------------------------------------------------------------------- + +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 ); +} + +//--------------------------------------------------------------------------- + +static void wmesa_viewport( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei w, + GLsizei h) +{ +// ctx->Driver.ResizeBuffersMESA(ctx); +} + +//--------------------------------------------------------------------------- + +static void wmesa_update_state_first_time( + GLcontext *ctx, + GLuint new_state) +{ + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* + * XXX these function pointers could be initialized just once during + * context creation since they don't depend on any state changes. + * kws - This is true - this function gets called a lot and it + * would be good to minimize setting all this when not needed. + */ + // Good idea, so I'll do it. KeithH. :-) + + ctx->Driver.GetString = _gldGetStringGeneric; + ctx->Driver.UpdateState = wmesa_update_state; + ctx->Driver.DrawBuffer = set_draw_buffer; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + ctx->Driver.GetBufferSize = buffer_size; + + ctx->Driver.Viewport = wmesa_viewport; + + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.Clear = clear; + + ctx->Driver.Flush = flush; + ctx->Driver.ClearIndex = clear_index; + ctx->Driver.ClearColor = clear_color; + ctx->Driver.Enable = enable; + + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + + ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + // Does not apply for Mesa 5.x + //ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat; + //ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size; + //ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage; + + swdd->SetBuffer = set_read_buffer; + + + /* Pixel/span writing functions: */ + swdd->WriteRGBASpan = write_rgba_span; + swdd->WriteRGBSpan = write_rgb_span; + swdd->WriteMonoRGBASpan = write_mono_rgba_span; + swdd->WriteRGBAPixels = write_rgba_pixels; + swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels; + swdd->WriteCI32Span = write_ci32_span; + swdd->WriteCI8Span = write_ci8_span; + swdd->WriteMonoCISpan = write_mono_ci_span; + swdd->WriteCI32Pixels = write_ci32_pixels; + swdd->WriteMonoCIPixels = write_mono_ci_pixels; + + swdd->ReadCI32Span = read_ci32_span; + swdd->ReadRGBASpan = read_rgba_span; + swdd->ReadCI32Pixels = read_ci32_pixels; + swdd->ReadRGBAPixels = read_rgba_pixels; + + + tnl->Driver.RunPipeline = _tnl_run_pipeline; + + wmesa_update_state(ctx, new_state); +} + +//--------------------------------------------------------------------------- +// Driver interface functions +//--------------------------------------------------------------------------- + +BOOL gldCreateDrawable_MesaSW( + DGL_ctx *pCtx, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + WMesaContext *c; + GLboolean true_color_flag; + GLboolean rgb_flag = GL_TRUE; + GLboolean db_flag = GL_TRUE; + + if (pCtx == NULL) + return FALSE; + + c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context)); + if (!c) + return FALSE; + + pCtx->glPriv = c; + + c->hDC = pCtx->hDC; + c->Window = pCtx->hWnd; + + true_color_flag = GetDeviceCaps(pCtx->hDC, BITSPIXEL) > 8; + + +#ifdef DITHER + if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){ + c->dither_flag = GL_TRUE; + c->hPalHalfTone = WinGCreateHalftonePalette(); + } + else + c->dither_flag = GL_FALSE; +#else + c->dither_flag = GL_FALSE; +#endif + + + if (rgb_flag==GL_FALSE) + { + c->rgb_flag = GL_FALSE; +#if 0 + /* Old WinG stuff???? */ + c->db_flag = db_flag =GL_TRUE; /* WinG requires double buffering */ + printf("Single buffer is not supported in color index mode, ", + "setting to double buffer.\n"); +#endif + } + else + { + c->rgb_flag = GL_TRUE; + } + +// db_flag = pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? GL_TRUE : GL_FALSE; + db_flag = GL_TRUE; // Force double-buffer + if (db_flag) { + c->db_flag = 1; + /* Double buffered */ + { + wmCreateBackingStore(c, pCtx->dwWidth, pCtx->dwHeight); + + } + } else { + /* Single Buffered */ + if (c->rgb_flag) + c->db_flag = 0; + } + + c->bEmulateSingleBuffer = (pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER) + ? FALSE : TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldResizeDrawable_MesaSW( + DGL_ctx *ctx, + BOOL bDefaultDriver, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + WMesaContext *c; + + if (ctx == NULL) + return FALSE; + + c = ctx->glPriv; + if (c == NULL) + return FALSE; + + c->hDC = ctx->hDC; + c->Window = ctx->hWnd; +// c->width = ctx->dwWidth; +// c->height = ctx->dwHeight; + + if (c->db_flag) { + wmDeleteBackingStore(c); + wmCreateBackingStore(c, ctx->dwWidth, ctx->dwHeight); + } + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyDrawable_MesaSW( + DGL_ctx *ctx) +{ + WMesaContext *c; + + if (ctx == NULL) + return FALSE; + + c = ctx->glPriv; + if (c == NULL) + return FALSE; + + if (c->hPalHalfTone != NULL) + DeleteObject(c->hPalHalfTone); + + if (c->db_flag) + wmDeleteBackingStore(c); + + free(c); + + ctx->glPriv = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldCreatePrivateGlobals_MesaSW(void) +{ + // Mesa Software driver needs no private globals + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyPrivateGlobals_MesaSW(void) +{ + // Mesa Software driver needs no private globals + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldBuildPixelformatList_MesaSW(void) +{ + // Release any existing pixelformat list + if (glb.lpPF) { + free(glb.lpPF); + } + + glb.nPixelFormatCount = 0; + glb.lpPF = NULL; + + glb.lpPF = (DGL_pixelFormat *)calloc(2, sizeof(DGL_pixelFormat)); + if (glb.lpPF == NULL) + return FALSE; + // Single-buffered + memcpy(&glb.lpPF[0], &pfTemplateMesaSW, sizeof(DGL_pixelFormat)); + glb.lpPF[0].pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + // Double-buffered + memcpy(&glb.lpPF[1], &pfTemplateMesaSW, sizeof(DGL_pixelFormat)); + glb.nPixelFormatCount = 2; + + // Mark list as 'current' + glb.bPixelformatsDirty = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldInitialiseMesa_MesaSW( + DGL_ctx *gld) +{ + GLcontext *ctx; + + if (gld == NULL) + return FALSE; + + ctx = gld->glCtx; + + // Set max texture size to 256 + ctx->Const.MaxTextureLevels = 8; + + // Multitexture enable/disable + ctx->Const.MaxTextureUnits = (glb.bMultitexture) ? MAX_TEXTURE_UNITS : 1; + + /* Initialize the software rasterizer and helper modules.*/ + + // Added this to force max texture diminsion to 256. KeithH + ctx->Const.MaxTextureLevels = 8; + + _mesa_enable_sw_extensions(ctx); + _mesa_enable_imaging_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + +// _swrast_CreateContext( ctx ); +// _ac_CreateContext( ctx ); +// _tnl_CreateContext( ctx ); +// _swsetup_CreateContext( ctx ); + + _swsetup_Wakeup( ctx ); + + wmesa_update_state_first_time(ctx, ~0); + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldSwapBuffers_MesaSW( + DGL_ctx *ctx, + HDC hDC, + HWND hWnd) +{ + WMesaContext *c; + + if (ctx == NULL) + return FALSE; + + c = ctx->glPriv; + if (c == NULL) + return FALSE; + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + + // Altered to respect bEmulateSingleBuffer. KeithH +// if (c->db_flag) + if (!c->bEmulateSingleBuffer) + wmFlush(c, hDC); + + return TRUE; +} + +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_MesaSW( + LPCSTR a) +{ + int i; + PROC proc = NULL; + + for (i=0; GLD_extList[i].proc; i++) { + if (!strcmp(a, GLD_extList[i].name)) { + proc = GLD_extList[i].proc; + break; + } + } + + gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed"); + + return proc; +} + +//--------------------------------------------------------------------------- + +BOOL gldGetDisplayMode_MesaSW( + DGL_ctx *ctx, + GLD_displayMode *glddm) +{ + HDC hdcDesktop; + + if (glddm == NULL) + return FALSE; + + // + // A bit hacky... KeithH + // + + hdcDesktop = GetDC(NULL); + glddm->Width = GetDeviceCaps(hdcDesktop, HORZRES); + glddm->Height = GetDeviceCaps(hdcDesktop, VERTRES); + glddm->BPP = GetDeviceCaps(hdcDesktop, BITSPIXEL); + glddm->Refresh = 0; + ReleaseDC(0, hdcDesktop); + + return TRUE; +} + +//--------------------------------------------------------------------------- + diff --git a/src/mesa/drivers/windows/gldirect/opengl32.ref b/src/mesa/drivers/windows/gldirect/opengl32.ref new file mode 100644 index 00000000000..2f71faf2167 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/opengl32.ref @@ -0,0 +1,495 @@ +;**************************************************************************** +;* +;* Mesa 3-D graphics library +;* Direct3D Driver Interface +;* +;* ======================================================================== +;* +;* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +;* +;* Permission is hereby granted, free of charge, to any person obtaining a +;* copy of this software and associated documentation files (the "Software"), +;* to deal in the Software without restriction, including without limitation +;* the rights to use, copy, modify, merge, publish, distribute, sublicense, +;* and/or sell copies of the Software, and to permit persons to whom the +;* Software is furnished to do so, subject to the following conditions: +;* +;* The above copyright notice and this permission notice shall be included +;* in all copies or substantial portions of the Software. +;* +;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +;* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +;* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +;* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +;* SOFTWARE. +;* +;* ====================================================================== +;* +;* Language: ANSI C +;* Environment: Windows 9x/2000/XP/XBox (Win32) +;* +;* Description: DLL Module definition file +;* +;****************************************************************************/ + +DESCRIPTION 'GLDirect' + +VERSION 3.0 + +EXPORTS + glAccum + glAlphaFunc + glAreTexturesResident + glArrayElement + glBegin + glBindTexture + glBitmap + glBlendFunc + glCallList + glCallLists + glClear + glClearAccum + glClearIndex + glClearColor + glClearDepth + glClearStencil + glClipPlane + glColor3b + glColor3d + glColor3f + glColor3i + glColor3s + glColor3ub + glColor3ui + glColor3us + glColor4b + glColor4d + glColor4f + glColor4i + glColor4s + glColor4ub + glColor4ui + glColor4us + glColor3bv + glColor3dv + glColor3fv + glColor3iv + glColor3sv + glColor3ubv + glColor3uiv + glColor3usv + glColor4bv + glColor4dv + glColor4fv + glColor4iv + glColor4sv + glColor4ubv + glColor4uiv + glColor4usv + glColorMask + glColorMaterial + glColorPointer + glColorTableEXT + glColorSubTableEXT + glCopyPixels + glCopyTexImage1D + glCopyTexImage2D + glCopyTexSubImage1D + glCopyTexSubImage2D + glCullFace + glDepthFunc + glDepthMask + glDepthRange + glDeleteLists + glDeleteTextures + glDisable + glDisableClientState + glDrawArrays + glDrawBuffer + glDrawElements + glDrawPixels + glEnable + glEnableClientState + glEnd + glEndList + glEvalCoord1d + glEvalCoord1f + glEvalCoord1dv + glEvalCoord1fv + glEvalCoord2d + glEvalCoord2f + glEvalCoord2dv + glEvalCoord2fv + glEvalPoint1 + glEvalPoint2 + glEvalMesh1 + glEdgeFlag + glEdgeFlagv + glEdgeFlagPointer + glEvalMesh2 + glFeedbackBuffer + glFinish + glFlush + glFogf + glFogi + glFogfv + glFogiv + glFrontFace + glFrustum + glGenLists + glGenTextures + glGetBooleanv + glGetClipPlane + glGetColorTableEXT + glGetColorTableParameterivEXT + glGetColorTableParameterfvEXT + glGetDoublev + glGetError + glGetFloatv + glGetIntegerv + glGetLightfv + glGetLightiv + glGetMapdv + glGetMapfv + glGetMapiv + glGetMaterialfv + glGetMaterialiv + glGetPixelMapfv + glGetPixelMapuiv + glGetPixelMapusv + glGetPointerv + glGetPolygonStipple + glGetString + glGetTexEnvfv + glGetTexEnviv + glGetTexGeniv + glGetTexGendv + glGetTexGenfv + glGetTexImage + glGetTexLevelParameterfv + glGetTexLevelParameteriv + glGetTexParameterfv + glGetTexParameteriv + glHint + glIndexd + glIndexf + glIndexi + glIndexs + glIndexub + glIndexdv + glIndexfv + glIndexiv + glIndexsv + glIndexubv + glIndexMask + glIndexPointer + glInterleavedArrays + glInitNames + glIsList + glIsTexture + glLightf + glLighti + glLightfv + glLightiv + glLightModelf + glLightModeli + glLightModelfv + glLightModeliv + glLineWidth + glLineStipple + glListBase + glLoadIdentity + glLoadMatrixd + glLoadMatrixf + glLoadName + glLogicOp + glMap1d + glMap1f + glMap2d + glMap2f + glMapGrid1d + glMapGrid1f + glMapGrid2d + glMapGrid2f + glMaterialf + glMateriali + glMaterialfv + glMaterialiv + glMatrixMode + glMultMatrixd + glMultMatrixf + glNewList + glNormal3b + glNormal3d + glNormal3f + glNormal3i + glNormal3s + glNormal3bv + glNormal3dv + glNormal3fv + glNormal3iv + glNormal3sv + glNormalPointer + glOrtho + glPassThrough + glPixelMapfv + glPixelMapuiv + glPixelMapusv + glPixelStoref + glPixelStorei + glPixelTransferf + glPixelTransferi + glPixelZoom + glPointSize + glPolygonMode + glPolygonOffset + glPolygonOffsetEXT + glPolygonStipple + glPopAttrib + glPopClientAttrib + glPopMatrix + glPopName + glPrioritizeTextures + glPushMatrix + glRasterPos2d + glRasterPos2f + glRasterPos2i + glRasterPos2s + glRasterPos3d + glRasterPos3f + glRasterPos3i + glRasterPos3s + glRasterPos4d + glRasterPos4f + glRasterPos4i + glRasterPos4s + glRasterPos2dv + glRasterPos2fv + glRasterPos2iv + glRasterPos2sv + glRasterPos3dv + glRasterPos3fv + glRasterPos3iv + glRasterPos3sv + glRasterPos4dv + glRasterPos4fv + glRasterPos4iv + glRasterPos4sv + glReadBuffer + glReadPixels + glRectd + glRectf + glRecti + glRects + glRectdv + glRectfv + glRectiv + glRectsv + glScissor + glIsEnabled + glPushAttrib + glPushClientAttrib + glPushName + glRenderMode + glRotated + glRotatef + glSelectBuffer + glScaled + glScalef + glShadeModel + glStencilFunc + glStencilMask + glStencilOp + glTexCoord1d + glTexCoord1f + glTexCoord1i + glTexCoord1s + glTexCoord2d + glTexCoord2f + glTexCoord2i + glTexCoord2s + glTexCoord3d + glTexCoord3f + glTexCoord3i + glTexCoord3s + glTexCoord4d + glTexCoord4f + glTexCoord4i + glTexCoord4s + glTexCoord1dv + glTexCoord1fv + glTexCoord1iv + glTexCoord1sv + glTexCoord2dv + glTexCoord2fv + glTexCoord2iv + glTexCoord2sv + glTexCoord3dv + glTexCoord3fv + glTexCoord3iv + glTexCoord3sv + glTexCoord4dv + glTexCoord4fv + glTexCoord4iv + glTexCoord4sv + glTexCoordPointer + glTexGend + glTexGenf + glTexGeni + glTexGendv + glTexGeniv + glTexGenfv + glTexEnvf + glTexEnvi + glTexEnvfv + glTexEnviv + glTexImage1D + glTexImage2D + glTexParameterf + glTexParameteri + glTexParameterfv + glTexParameteriv + glTexSubImage1D + glTexSubImage2D + glTranslated + glTranslatef + glVertex2d + glVertex2f + glVertex2i + glVertex2s + glVertex3d + glVertex3f + glVertex3i + glVertex3s + glVertex4d + glVertex4f + glVertex4i + glVertex4s + glVertex2dv + glVertex2fv + glVertex2iv + glVertex2sv + glVertex3dv + glVertex3fv + glVertex3iv + glVertex3sv + glVertex4dv + glVertex4fv + glVertex4iv + glVertex4sv + glVertexPointer + glViewport + + glBlendEquationEXT + glBlendColorEXT + glVertexPointerEXT + glNormalPointerEXT + glColorPointerEXT + glIndexPointerEXT + glTexCoordPointerEXT + glEdgeFlagPointerEXT + glGetPointervEXT + glArrayElementEXT + glDrawArraysEXT + glBindTextureEXT + glDeleteTexturesEXT + glGenTexturesEXT + glPrioritizeTexturesEXT + glCopyTexSubImage3DEXT + glTexImage3DEXT + glTexSubImage3DEXT + + glWindowPos4fMESA + glWindowPos2iMESA + glWindowPos2sMESA + glWindowPos2fMESA + glWindowPos2dMESA + glWindowPos2ivMESA + glWindowPos2svMESA + glWindowPos2fvMESA + glWindowPos2dvMESA + glWindowPos3iMESA + glWindowPos3sMESA + glWindowPos3fMESA + glWindowPos3dMESA + glWindowPos3ivMESA + glWindowPos3svMESA + glWindowPos3fvMESA + glWindowPos3dvMESA + glWindowPos4iMESA + glWindowPos4sMESA + glWindowPos4dMESA + glWindowPos4ivMESA + glWindowPos4svMESA + glWindowPos4fvMESA + glWindowPos4dvMESA + glResizeBuffersMESA + + wglCopyContext + wglCreateContext + wglCreateLayerContext + wglDeleteContext + wglDescribeLayerPlane + wglGetCurrentContext + wglGetCurrentDC + wglGetLayerPaletteEntries + wglGetProcAddress + wglMakeCurrent + wglRealizeLayerPalette + wglSetLayerPaletteEntries + wglShareLists + wglSwapLayerBuffers + wglUseFontBitmapsA + wglUseFontBitmapsW + wglUseFontOutlinesA + wglUseFontOutlinesW + +;These functions are identical and therefore share the same addresses + ChoosePixelFormat = wglChoosePixelFormat + DescribePixelFormat = wglDescribePixelFormat + GetPixelFormat = wglGetPixelFormat + SetPixelFormat = wglSetPixelFormat + SwapBuffers = wglSwapBuffers + + wglChoosePixelFormat + wglDescribePixelFormat + wglGetPixelFormat + wglSetPixelFormat + wglSwapBuffers + + glActiveTextureARB + glClientActiveTextureARB + glMultiTexCoord1dARB + glMultiTexCoord1dvARB + glMultiTexCoord1fARB + glMultiTexCoord1fvARB + glMultiTexCoord1iARB + glMultiTexCoord1ivARB + glMultiTexCoord1sARB + glMultiTexCoord1svARB + glMultiTexCoord2dARB + glMultiTexCoord2dvARB + glMultiTexCoord2fARB + glMultiTexCoord2fvARB + glMultiTexCoord2iARB + glMultiTexCoord2ivARB + glMultiTexCoord2sARB + glMultiTexCoord2svARB + glMultiTexCoord3dARB + glMultiTexCoord3dvARB + glMultiTexCoord3fARB + glMultiTexCoord3fvARB + glMultiTexCoord3iARB + glMultiTexCoord3ivARB + glMultiTexCoord3sARB + glMultiTexCoord3svARB + glMultiTexCoord4dARB + glMultiTexCoord4dvARB + glMultiTexCoord4fARB + glMultiTexCoord4fvARB + glMultiTexCoord4iARB + glMultiTexCoord4ivARB + glMultiTexCoord4sARB + glMultiTexCoord4svARB diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c index 2f20b162a7f..2a44e126f78 100644 --- a/src/mesa/drivers/x11/xm_buffer.c +++ b/src/mesa/drivers/x11/xm_buffer.c @@ -48,7 +48,7 @@ static GLboolean xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); /* just clear these to be sure we don't accidentally use them */ xrb->origin1 = NULL; @@ -74,7 +74,7 @@ static GLboolean xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); /* same as front buffer */ (void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height); diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index 516b238d6eb..d339ac6bc39 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -302,11 +302,12 @@ clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb, const XMesaContext xmesa = XMESA_CONTEXT(ctx); if (all) { - GLint i, c16 = (xrb->ximage->bytes_per_line>>4)<<4; + const GLuint c16 = xrb->ximage->bytes_per_line & ~0xf; + GLuint i; GLubyte *ptr = (GLubyte *) xrb->ximage->data; for (i = 0; i < xrb->Base.Height; i++) { - GLint j; - GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; + GLuint j; + const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; if (i&1) { sptr += 16; } @@ -329,7 +330,7 @@ clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb, ptr[15] = sptr[15]; ptr += 16; } - for (; j < xrb->ximage->bytes_per_line; j++) { + for (; j < (GLuint) xrb->ximage->bytes_per_line; j++) { *ptr = sptr[j&15]; ptr++; } @@ -530,14 +531,15 @@ clear_buffers( GLcontext *ctx, GLbitfield mask, if (ctx->DrawBuffer->Name == 0) { /* this is a window system framebuffer */ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; - XMesaBuffer b = (XMesaBuffer) ctx->DrawBuffer; + XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer); /* we can't handle color or index masking */ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { if (mask & BUFFER_BIT_FRONT_LEFT) { /* clear front color buffer */ - if (b->frontxrb == (struct xmesa_renderbuffer *) - ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer) { + struct gl_renderbuffer *frontRb + = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + if (b->frontxrb == xmesa_renderbuffer(frontRb)) { /* renderbuffer is not wrapped - great! */ b->frontxrb->clearFunc(ctx, b->frontxrb, all, x, y, width, height); @@ -549,8 +551,9 @@ clear_buffers( GLcontext *ctx, GLbitfield mask, } if (mask & BUFFER_BIT_BACK_LEFT) { /* clear back color buffer */ - if (b->backxrb == (struct xmesa_renderbuffer *) - ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer) { + struct gl_renderbuffer *backRb + = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer; + if (b->backxrb == xmesa_renderbuffer(backRb)) { /* renderbuffer is not wrapped - great! */ b->backxrb->clearFunc(ctx, b->backxrb, all, x, y, width, height); @@ -600,7 +603,7 @@ xmesa_DrawPixels_8R8G8B( GLcontext *ctx, const GLvoid *pixels ) { struct xmesa_renderbuffer *xrb - = (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + = (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped; const XMesaContext xmesa = XMESA_CONTEXT(ctx); const SWcontext *swrast = SWRAST_CONTEXT( ctx ); @@ -997,18 +1000,18 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state ) * renderbuffer span/clear funcs. */ if (new_state & (_NEW_COLOR | _NEW_PIXEL | _NEW_BUFFERS)) { + XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); struct xmesa_renderbuffer *front_xrb, *back_xrb; - front_xrb = XMESA_BUFFER(ctx->DrawBuffer)->frontxrb; + front_xrb = xmbuf->frontxrb; if (front_xrb) { xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat, xmesa->xm_visual->BitsPerPixel); front_xrb->clearFunc = clear_pixmap; } - back_xrb = XMESA_BUFFER(ctx->DrawBuffer)->backxrb; + back_xrb = xmbuf->backxrb; if (back_xrb) { - XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat, xmesa->xm_visual->BitsPerPixel); if (xmbuf->backxrb->pixmap) { @@ -1151,10 +1154,15 @@ update_framebuffer_size(GLcontext *ctx) * 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. + * That problem led to the GLX_MESA_resize_buffers extension. */ static void xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h) { + (void) x; + (void) y; + (void) w; + (void) h; update_framebuffer_size(ctx); } diff --git a/src/mesa/drivers/x11/xm_line.c b/src/mesa/drivers/x11/xm_line.c index f60ffa65eb9..c3105425159 100644 --- a/src/mesa/drivers/x11/xm_line.c +++ b/src/mesa/drivers/x11/xm_line.c @@ -117,8 +117,11 @@ void xmesa_choose_point( GLcontext *ctx ) /**********************************************************************/ +#if CHAN_BITS == 8 + + #define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \ - (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped + xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped) /* @@ -533,6 +536,7 @@ void xmesa_choose_point( GLcontext *ctx ) + #ifndef XFree86Server /** * Draw fast, XOR line with XDrawLine in front color buffer. @@ -547,8 +551,7 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaGC gc = xmesa->xm_buffer->gc; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) - ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + GET_XRB(xrb); unsigned long pixel = xmesa_color_to_pixel(ctx, vert1->color[0], vert1->color[1], vert1->color[2], vert1->color[3], @@ -567,6 +570,9 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) #endif /* XFree86Server */ +#endif /* CHAN_BITS == 8 */ + + /** * Return pointer to line drawing function, or NULL if we should use a * swrast fallback. @@ -574,11 +580,15 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) static swrast_line_func get_line_func(GLcontext *ctx) { +#if CHAN_BITS == 8 XMesaContext xmesa = XMESA_CONTEXT(ctx); SWcontext *swrast = SWRAST_CONTEXT(ctx); int depth = GET_VISUAL_DEPTH(xmesa->xm_visual); struct xmesa_renderbuffer *xrb; + if (CHAN_BITS != 8) + return NULL; + if ((ctx->DrawBuffer->_ColorDrawBufferMask[0] & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0) return (swrast_line_func) NULL; @@ -589,8 +599,7 @@ get_line_func(GLcontext *ctx) if (ctx->Line.StippleFlag) return (swrast_line_func) NULL; if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL; - xrb = (struct xmesa_renderbuffer *) - ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped; + xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped); if (xrb->ximage && swrast->_RasterMask==DEPTH_BIT @@ -663,6 +672,7 @@ get_line_func(GLcontext *ctx) } #endif /* XFree86Server */ +#endif /* CHAN_BITS == 8 */ return (swrast_line_func) NULL; } diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c index 664f365df96..ff0557800ae 100644 --- a/src/mesa/drivers/x11/xm_span.c +++ b/src/mesa/drivers/x11/xm_span.c @@ -21,7 +21,6 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $XFree86: xc/extras/Mesa/src/X/xm_span.c,v 1.3 2002/02/27 21:07:54 tsi Exp $ */ #include "glxheader.h" #include "colormac.h" @@ -176,7 +175,8 @@ static unsigned long read_pixel( XMesaDisplay *dpy, const void *values, const GLubyte mask[] -/* NOTE: if mask==NULL, draw all pixels */ +#define GET_XRB(XRB) \ + struct xmesa_renderbuffer *XRB = xmesa_renderbuffer(rb) /* @@ -186,7 +186,7 @@ static void put_row_TRUECOLOR_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = XMESA_BUFFER(ctx->DrawBuffer)->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -223,7 +223,7 @@ static void put_row_rgb_TRUECOLOR_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -258,7 +258,7 @@ static void put_row_TRUEDITHER_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -293,7 +293,7 @@ static void put_row_rgb_TRUEDITHER_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -328,7 +328,7 @@ static void put_row_8A8B8G8R_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -362,7 +362,7 @@ static void put_row_rgb_8A8B8G8R_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -395,7 +395,7 @@ static void put_row_8A8R8G8B_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -429,7 +429,7 @@ static void put_row_rgb_8A8R8G8B_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -462,7 +462,7 @@ static void put_row_8R8G8B_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -495,7 +495,7 @@ static void put_row_8R8G8B24_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -591,7 +591,7 @@ static void put_row_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -623,7 +623,7 @@ static void put_row_rgb_8R8G8B24_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -724,7 +724,7 @@ static void put_row_5R6G5B_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -757,7 +757,7 @@ static void put_row_DITHER_5R6G5B_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -792,7 +792,7 @@ static void put_row_rgb_5R6G5B_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -825,7 +825,7 @@ static void put_row_rgb_DITHER_5R6G5B_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -860,7 +860,7 @@ static void put_row_DITHER_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -893,7 +893,7 @@ static void put_row_rgb_DITHER_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -926,7 +926,7 @@ static void put_row_1BIT_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -961,7 +961,7 @@ static void put_row_rgb_1BIT_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -996,7 +996,7 @@ static void put_row_HPCR_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1029,7 +1029,7 @@ static void put_row_rgb_HPCR_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1061,7 +1061,7 @@ static void put_row_LOOKUP_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1093,7 +1093,7 @@ static void put_row_rgb_LOOKUP_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1125,7 +1125,7 @@ static void put_row_GRAYSCALE_pixmap( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1156,7 +1156,7 @@ static void put_row_rgb_GRAYSCALE_pixmap( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -1186,7 +1186,7 @@ static void put_row_TRUECOLOR_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -1217,7 +1217,7 @@ static void put_row_rgb_TRUECOLOR_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -1248,7 +1248,7 @@ static void put_row_TRUEDITHER_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -1279,7 +1279,7 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -1309,9 +1309,10 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS ) static void put_row_8A8B8G8R_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); + (void) ctx; if (mask) { for (i=0;i<n;i++) { if (mask[i]) { @@ -1334,7 +1335,7 @@ static void put_row_8A8B8G8R_ximage( PUT_ROW_ARGS ) static void put_row_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { @@ -1358,7 +1359,7 @@ static void put_row_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS ) static void put_row_8A8R8G8B_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { @@ -1383,7 +1384,7 @@ static void put_row_8A8R8G8B_ximage( PUT_ROW_ARGS ) static void put_row_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { @@ -1408,7 +1409,7 @@ static void put_row_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS ) static void put_row_8R8G8B_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { @@ -1432,7 +1433,7 @@ static void put_row_8R8G8B_ximage( PUT_ROW_ARGS ) static void put_row_8R8G8B24_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y ); if (mask) { @@ -1583,7 +1584,7 @@ static void put_row_8R8G8B24_ximage( PUT_ROW_ARGS ) static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLuint *ptr = PIXEL_ADDR4(xrb, x, y); if (mask) { @@ -1608,7 +1609,7 @@ static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS ) static void put_row_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y); if (mask) { @@ -1640,7 +1641,7 @@ static void put_row_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS ) static void put_row_5R6G5B_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLushort *ptr = PIXEL_ADDR2(xrb, x, y); if (mask) { @@ -1680,7 +1681,7 @@ static void put_row_5R6G5B_ximage( PUT_ROW_ARGS ) static void put_row_DITHER_5R6G5B_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; register GLushort *ptr = PIXEL_ADDR2(xrb, x, y); @@ -1722,7 +1723,7 @@ static void put_row_DITHER_5R6G5B_ximage( PUT_ROW_ARGS ) static void put_row_rgb_5R6G5B_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLushort *ptr = PIXEL_ADDR2(xrb, x, y); if (mask) { @@ -1762,7 +1763,7 @@ static void put_row_rgb_5R6G5B_ximage( RGB_SPAN_ARGS ) static void put_row_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; register GLushort *ptr = PIXEL_ADDR2(xrb, x, y ); @@ -1803,7 +1804,7 @@ static void put_row_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS ) static void put_row_DITHER_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; int yy = YFLIP(xrb, y); @@ -1830,7 +1831,7 @@ static void put_row_DITHER_ximage( PUT_ROW_ARGS ) static void put_row_rgb_DITHER_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; int yy = YFLIP(xrb, y); @@ -1858,7 +1859,7 @@ static void put_row_rgb_DITHER_ximage( RGB_SPAN_ARGS ) static void put_row_DITHER8_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); XDITHER_SETUP(y); @@ -1880,7 +1881,7 @@ static void put_row_DITHER8_ximage( PUT_ROW_ARGS ) static void put_row_rgb_DITHER8_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); XDITHER_SETUP(y); @@ -1909,7 +1910,7 @@ static void put_row_1BIT_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; SETUP_1BIT; @@ -1936,7 +1937,7 @@ static void put_row_rgb_1BIT_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; SETUP_1BIT; @@ -1962,7 +1963,7 @@ static void put_row_rgb_1BIT_ximage( RGB_SPAN_ARGS ) static void put_row_HPCR_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); @@ -1988,7 +1989,7 @@ static void put_row_HPCR_ximage( PUT_ROW_ARGS ) static void put_row_rgb_HPCR_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); @@ -2014,7 +2015,7 @@ static void put_row_rgb_HPCR_ximage( RGB_SPAN_ARGS ) static void put_row_LOOKUP_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; LOOKUP_SETUP; @@ -2041,7 +2042,7 @@ static void put_row_LOOKUP_ximage( PUT_ROW_ARGS ) static void put_row_rgb_LOOKUP_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; LOOKUP_SETUP; @@ -2068,7 +2069,7 @@ static void put_row_rgb_LOOKUP_ximage( RGB_SPAN_ARGS ) static void put_row_LOOKUP8_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); LOOKUP_SETUP; @@ -2091,7 +2092,7 @@ static void put_row_LOOKUP8_ximage( PUT_ROW_ARGS ) static void put_row_rgb_LOOKUP8_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); LOOKUP_SETUP; @@ -2119,7 +2120,7 @@ static void put_row_rgb_LOOKUP8_ximage( RGB_SPAN_ARGS ) static void put_row_GRAYSCALE_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -2145,7 +2146,7 @@ static void put_row_GRAYSCALE_ximage( PUT_ROW_ARGS ) static void put_row_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -2171,7 +2172,7 @@ static void put_row_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS ) static void put_row_GRAYSCALE8_ximage( PUT_ROW_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); if (mask) { @@ -2196,7 +2197,7 @@ static void put_row_GRAYSCALE8_ximage( PUT_ROW_ARGS ) static void put_row_rgb_GRAYSCALE8_ximage( RGB_SPAN_ARGS ) { const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); if (mask) { @@ -2235,7 +2236,7 @@ static void put_values_TRUECOLOR_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2258,7 +2259,7 @@ static void put_values_TRUEDITHER_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2281,7 +2282,7 @@ static void put_values_8A8B8G8R_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2302,7 +2303,7 @@ static void put_values_8A8R8G8B_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2323,7 +2324,7 @@ static void put_values_8R8G8B_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2344,7 +2345,7 @@ static void put_values_8R8G8B24_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2365,7 +2366,7 @@ static void put_values_5R6G5B_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2386,7 +2387,7 @@ static void put_values_DITHER_5R6G5B_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2409,7 +2410,7 @@ static void put_values_DITHER_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2432,7 +2433,7 @@ static void put_values_1BIT_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2455,7 +2456,7 @@ static void put_values_HPCR_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2477,7 +2478,7 @@ static void put_values_LOOKUP_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2499,7 +2500,7 @@ static void put_values_GRAYSCALE_pixmap( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2520,7 +2521,7 @@ static void put_values_TRUECOLOR_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; for (i=0;i<n;i++) { @@ -2540,7 +2541,7 @@ static void put_values_TRUEDITHER_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; for (i=0;i<n;i++) { @@ -2559,7 +2560,7 @@ static void put_values_TRUEDITHER_ximage( PUT_VALUES_ARGS ) static void put_values_8A8B8G8R_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2575,7 +2576,7 @@ static void put_values_8A8B8G8R_ximage( PUT_VALUES_ARGS ) static void put_values_8A8R8G8B_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2592,7 +2593,7 @@ static void put_values_8A8R8G8B_ximage( PUT_VALUES_ARGS ) static void put_values_8R8G8B_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2609,7 +2610,7 @@ static void put_values_8R8G8B_ximage( PUT_VALUES_ARGS ) static void put_values_8R8G8B24_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2628,7 +2629,7 @@ static void put_values_8R8G8B24_ximage( PUT_VALUES_ARGS ) static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2645,7 +2646,7 @@ static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS ) static void put_values_DITHER_5R6G5B_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; for (i=0;i<n;i++) { @@ -2663,7 +2664,7 @@ static void put_values_DITHER_5R6G5B_ximage( PUT_VALUES_ARGS ) static void put_values_DITHER_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; DITHER_SETUP; @@ -2682,7 +2683,7 @@ static void put_values_DITHER_ximage( PUT_VALUES_ARGS ) static void put_values_DITHER8_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; DITHER_SETUP; for (i=0;i<n;i++) { @@ -2701,7 +2702,7 @@ static void put_values_1BIT_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; SETUP_1BIT; @@ -2720,7 +2721,7 @@ static void put_values_1BIT_ximage( PUT_VALUES_ARGS ) static void put_values_HPCR_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLuint i; for (i=0;i<n;i++) { @@ -2738,7 +2739,7 @@ static void put_values_HPCR_ximage( PUT_VALUES_ARGS ) static void put_values_LOOKUP_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; LOOKUP_SETUP; @@ -2756,7 +2757,7 @@ static void put_values_LOOKUP_ximage( PUT_VALUES_ARGS ) static void put_values_LOOKUP8_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; LOOKUP_SETUP; for (i=0;i<n;i++) { @@ -2774,7 +2775,7 @@ static void put_values_LOOKUP8_ximage( PUT_VALUES_ARGS ) static void put_values_GRAYSCALE_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; for (i=0;i<n;i++) { @@ -2792,7 +2793,7 @@ static void put_values_GRAYSCALE_ximage( PUT_VALUES_ARGS ) static void put_values_GRAYSCALE8_ximage( PUT_VALUES_ARGS ) { const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; for (i=0;i<n;i++) { if (mask[i]) { @@ -2822,7 +2823,7 @@ static void put_values_GRAYSCALE8_ximage( PUT_VALUES_ARGS ) static void put_mono_row_pixmap( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; @@ -2863,7 +2864,7 @@ put_mono_row_ci_pixmap( PUT_MONO_ROW_ARGS ) { GLuint colorIndex = *((GLuint *) value); XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -2899,7 +2900,7 @@ put_mono_row_ci_pixmap( PUT_MONO_ROW_ARGS ) static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; @@ -2924,7 +2925,7 @@ static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS ) static void put_mono_row_DITHER_pixmap( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; @@ -2948,7 +2949,7 @@ static void put_mono_row_DITHER_pixmap( PUT_MONO_ROW_ARGS ) static void put_mono_row_1BIT_pixmap( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; @@ -2972,7 +2973,7 @@ static void put_mono_row_1BIT_pixmap( PUT_MONO_ROW_ARGS ) static void put_mono_row_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaImage *img = xrb->ximage; register GLuint i; @@ -2991,7 +2992,7 @@ static void put_mono_row_ci_ximage( PUT_MONO_ROW_ARGS ) { const GLuint colorIndex = *((GLuint *) value); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -3009,7 +3010,7 @@ put_mono_row_ci_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_TRUEDITHER_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaImage *img = xrb->ximage; const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; @@ -3031,7 +3032,7 @@ static void put_mono_row_TRUEDITHER_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_8A8B8G8R_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaContext xmesa = XMESA_CONTEXT(ctx); GLuint i, *ptr; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], @@ -3050,7 +3051,7 @@ static void put_mono_row_8A8B8G8R_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_8A8R8G8B_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); GLuint i, *ptr; XMesaContext xmesa = XMESA_CONTEXT(ctx); const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], @@ -3070,7 +3071,7 @@ static void put_mono_row_8A8R8G8B_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_8R8G8B_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLuint pixel = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]); GLuint *ptr = PIXEL_ADDR4(xrb, x, y ); GLuint i; @@ -3088,7 +3089,7 @@ static void put_mono_row_8R8G8B_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_8R8G8B24_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP]; const GLubyte g = color[GCOMP]; const GLubyte b = color[BCOMP]; @@ -3110,7 +3111,7 @@ static void put_mono_row_8R8G8B24_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_DITHER_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; XMesaImage *img = xrb->ximage; int yy = YFLIP(xrb, y); @@ -3130,7 +3131,7 @@ static void put_mono_row_DITHER_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_DITHER8_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); register GLuint i; @@ -3149,7 +3150,7 @@ static void put_mono_row_DITHER8_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_LOOKUP8_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); GLubyte pixel; @@ -3170,7 +3171,7 @@ static void put_mono_row_1BIT_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; XMesaImage *img = xrb->ximage; register GLuint i; @@ -3190,7 +3191,7 @@ static void put_mono_row_1BIT_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_HPCR_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y); @@ -3209,7 +3210,7 @@ static void put_mono_row_HPCR_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_GRAYSCALE8_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]); GLubyte *ptr = (GLubyte *) PIXEL_ADDR1(xrb, x, y); GLuint i; @@ -3228,7 +3229,7 @@ static void put_mono_row_GRAYSCALE8_ximage( PUT_MONO_ROW_ARGS ) static void put_mono_row_DITHER_5R6G5B_ximage( PUT_MONO_ROW_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); register GLushort *ptr = PIXEL_ADDR2(xrb, x, y ); const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; @@ -3261,7 +3262,7 @@ static void put_mono_values_pixmap( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3283,7 +3284,7 @@ put_mono_values_ci_pixmap( PUT_MONO_VALUES_ARGS ) { const GLuint colorIndex = *((GLuint *) value); const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3305,7 +3306,7 @@ static void put_mono_values_TRUEDITHER_pixmap( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3330,7 +3331,7 @@ static void put_mono_values_DITHER_pixmap( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3353,7 +3354,7 @@ static void put_mono_values_1BIT_pixmap( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3376,7 +3377,7 @@ static void put_mono_values_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP], @@ -3393,7 +3394,7 @@ static void put_mono_values_ci_ximage( PUT_MONO_VALUES_ARGS ) { const GLuint colorIndex = *((GLuint *) value); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; for (i=0;i<n;i++) { @@ -3411,7 +3412,7 @@ static void put_mono_values_TRUEDITHER_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; @@ -3432,7 +3433,7 @@ static void put_mono_values_TRUEDITHER_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_8A8B8G8R_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLuint p = PACK_8A8B8G8R(color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); register GLuint i; @@ -3450,7 +3451,7 @@ static void put_mono_values_8A8B8G8R_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_8A8R8G8B_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLuint p = PACK_8A8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]); register GLuint i; @@ -3468,7 +3469,7 @@ static void put_mono_values_8A8R8G8B_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_8R8G8B_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; const GLuint p = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]); for (i=0;i<n;i++) { @@ -3486,7 +3487,7 @@ static void put_mono_values_8R8G8B_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_8R8G8B24_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; for (i=0;i<n;i++) { @@ -3506,7 +3507,7 @@ static void put_mono_values_8R8G8B24_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_DITHER_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; XMesaImage *img = xrb->ximage; register GLuint i; @@ -3525,7 +3526,7 @@ static void put_mono_values_DITHER_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_DITHER8_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; DITHER_SETUP; @@ -3544,7 +3545,7 @@ static void put_mono_values_DITHER8_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_LOOKUP8_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; GLubyte pixel; LOOKUP_SETUP; @@ -3566,7 +3567,7 @@ static void put_mono_values_1BIT_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; XMesaImage *img = xrb->ximage; register GLuint i; @@ -3586,7 +3587,7 @@ static void put_mono_values_1BIT_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_HPCR_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; @@ -3605,7 +3606,7 @@ static void put_mono_values_HPCR_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_GRAYSCALE8_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); register GLuint i; register GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]); for (i=0;i<n;i++) { @@ -3623,7 +3624,7 @@ static void put_mono_values_GRAYSCALE8_ximage( PUT_MONO_VALUES_ARGS ) static void put_mono_values_DITHER_5R6G5B_ximage( PUT_MONO_VALUES_ARGS ) { const GLubyte *color = (const GLubyte *) value; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; register GLuint i; @@ -3648,7 +3649,7 @@ static void put_row_ci_pixmap( PUT_ROW_ARGS ) { const GLuint *index = (GLuint *) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3677,7 +3678,7 @@ static void put_row_ci_pixmap( PUT_ROW_ARGS ) static void put_row_ci_ximage( PUT_ROW_ARGS ) { const GLuint *index = (const GLuint *) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; y = YFLIP(xrb, y); @@ -3707,7 +3708,7 @@ static void put_values_ci_pixmap( PUT_VALUES_ARGS ) { const GLuint *index = (const GLuint *) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaDrawable buffer = xrb->drawable; XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc; @@ -3727,7 +3728,7 @@ static void put_values_ci_pixmap( PUT_VALUES_ARGS ) static void put_values_ci_ximage( PUT_VALUES_ARGS ) { const GLuint *index = (const GLuint *) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaImage *img = xrb->ximage; register GLuint i; for (i=0;i<n;i++) { @@ -3799,7 +3800,7 @@ get_row_ci(GLcontext *ctx, struct gl_renderbuffer *rb, { GLuint *index = (GLuint *) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); GLuint i; y = YFLIP(xrb, y); @@ -3856,7 +3857,7 @@ get_row_rgba(GLcontext *ctx, struct gl_renderbuffer *rb, { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer); if (xrb->pixmap) { @@ -4258,7 +4259,7 @@ get_values_ci(GLcontext *ctx, struct gl_renderbuffer *rb, { GLuint *indx = (GLuint *) values; const XMesaContext xmesa = XMESA_CONTEXT(ctx); - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); GLuint i; if (xrb->pixmap) { for (i=0;i<n;i++) { @@ -4281,7 +4282,7 @@ get_values_rgba(GLcontext *ctx, struct gl_renderbuffer *rb, GLuint n, const GLint x[], const GLint y[], void *values) { GLubyte (*rgba)[4] = (GLubyte (*)[4]) values; - struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb; + GET_XRB(xrb); const XMesaContext xmesa = XMESA_CONTEXT(ctx); XMesaDisplay *dpy = xmesa->xm_visual->display; XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer); diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c index 61e8986a9b2..289ce11be62 100644 --- a/src/mesa/drivers/x11/xm_tri.c +++ b/src/mesa/drivers/x11/xm_tri.c @@ -45,7 +45,7 @@ #define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \ - (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped + xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped) /**********************************************************************/ @@ -53,6 +53,8 @@ /**********************************************************************/ +#if CHAN_BITS == 8 + /* * XImage, smooth, depth-buffered, PF_TRUECOLOR triangle. */ @@ -1307,8 +1309,10 @@ #include "swrast/s_tritemp.h" +#endif /* CHAN_BITS == 8 */ -#ifdef DEBUG + +#if defined(DEBUG) && CHAN_BITS == 8 extern void _xmesa_print_triangle_func( swrast_tri_func triFunc ); void _xmesa_print_triangle_func( swrast_tri_func triFunc ) { @@ -1441,19 +1445,24 @@ get_triangle_func(GLcontext *ctx) triFuncName = NULL; #endif +#if CHAN_BITS == 8 + /* trivial fallback tests */ if ((ctx->DrawBuffer->_ColorDrawBufferMask[0] & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0) return (swrast_tri_func) NULL; - if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; - if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; - if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; - if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_tri_func) NULL; + if (ctx->RenderMode != GL_RENDER) + return (swrast_tri_func) NULL; + if (ctx->Polygon.SmoothFlag) + return (swrast_tri_func) NULL; + if (ctx->Texture._EnabledUnits) + return (swrast_tri_func) NULL; + if (swrast->_RasterMask & MULTI_DRAW_BIT) + return (swrast_tri_func) NULL; if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) - return (swrast_tri_func) NULL; + return (swrast_tri_func) NULL; - xrb = (struct xmesa_renderbuffer *) - ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped; + xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped); if (xrb->ximage) { if ( ctx->Light.ShadeModel==GL_SMOOTH @@ -1607,13 +1616,10 @@ get_triangle_func(GLcontext *ctx) return (swrast_tri_func) NULL; } } - - return (swrast_tri_func) NULL; - } - else { - /* draw to pixmap */ - return (swrast_tri_func) NULL; } +#endif /* CHAN_BITS == 8 */ + + return (swrast_tri_func) NULL; } diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h index 9d4e6946090..bcac0557b98 100644 --- a/src/mesa/drivers/x11/xmesaP.h +++ b/src/mesa/drivers/x11/xmesaP.h @@ -480,12 +480,14 @@ extern const int xmesa_kernel1[16]; /* * Return pointer to XMesaContext corresponding to a Mesa GLcontext. * Since we're using structure containment, it's just a cast!. + * XXX should use inlined function for better type safety. */ #define XMESA_CONTEXT(MESACTX) ((XMesaContext) (MESACTX)) /* * Return pointer to XMesaBuffer corresponding to a Mesa GLframebuffer. * Since we're using structure containment, it's just a cast!. + * XXX should use inlined function for better type safety. */ #define XMESA_BUFFER(MESABUFF) ((XMesaBuffer) (MESABUFF)) @@ -520,6 +522,16 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb, enum pixel_format pixelformat, GLint depth); +/** + * Using a function instead of an ordinary cast is safer. + */ +static INLINE struct xmesa_renderbuffer * +xmesa_renderbuffer(struct gl_renderbuffer *rb) +{ + return (struct xmesa_renderbuffer *) rb; +} + + /* Plugged into the software rasterizer. Try to use internal * swrast-style point, line and triangle functions. */ |