aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c')
-rw-r--r--nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c1430
1 files changed, 1430 insertions, 0 deletions
diff --git a/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c b/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c
new file mode 100644
index 000000000..d7c847709
--- /dev/null
+++ b/nx-X11/extras/Mesa_6.4.2/src/mesa/drivers/dos/dmesa.c
@@ -0,0 +1,1430 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 1999-2004 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.
+ */
+
+/*
+ * DOS/DJGPP device driver v1.7 for Mesa
+ *
+ * Copyright (c) 2003 - Daniel Borca
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "imports.h"
+#ifndef FX
+#include "bufferobj.h"
+#include "buffers.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+#include "video.h"
+#else /* FX */
+#include "GL/fxmesa.h"
+#endif /* FX */
+
+#include "GL/dmesa.h"
+
+
+#define SWTC 0 /* SW texture compression */
+
+
+/*
+ * In C++ terms, this class derives from the GLvisual class.
+ * Add system-specific fields to it.
+ */
+struct dmesa_visual {
+ GLvisual gl_visual;
+ GLboolean sw_alpha; /* use Mesa's alpha buffer? */
+ int z_buffer; /* Z=buffer: 0=no, 1=SW, -1=HW */
+};
+
+/*
+ * In C++ terms, this class derives from the GLframebuffer class.
+ * Add system-specific fields to it.
+ */
+struct dmesa_buffer {
+ GLframebuffer gl_buffer; /* The depth, stencil, accum, etc buffers */
+ void *the_window; /* your window handle, etc */
+
+ int xpos, ypos; /* position */
+ int width, height; /* size in pixels */
+};
+
+/*
+ * In C++ terms, this class derives from the GLcontext class.
+ * Add system-specific fields to it.
+ */
+struct dmesa_context {
+ GLcontext gl_ctx; /* the core library context */
+ DMesaVisual visual;
+ DMesaBuffer buffer;
+ GLuint ClearColor;
+ GLuint ClearIndex;
+ /* etc... */
+};
+
+
+#ifndef FX
+/****************************************************************************
+ * Read/Write pixels
+ ***************************************************************************/
+#define FLIP(y) (dmesa->buffer->height - (y) - 1)
+#define FLIP2(y) (_b_ - (y))
+
+#define DSTRIDE dmesa->buffer->width
+
+/****************************************************************************
+ * RGB[A]
+ ***************************************************************************/
+static void
+write_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, vl_mixrgba(rgba[i]));
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, vl_mixrgba(rgba[i]));
+ }
+ }
+}
+
+
+static void
+write_rgb_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, vl_mixrgb(rgb[i]));
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, vl_mixrgb(rgb[i]));
+ }
+ }
+}
+
+
+static void
+write_mono_rgba_span (const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset, rgba = vl_mixrgba(color);
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, rgba);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, rgba);
+ }
+ }
+}
+
+
+static void
+read_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ /* read all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_getrgba(offset, rgba[i]);
+ }
+}
+
+
+static void
+write_rgba_pixels (const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1;
+
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], vl_mixrgba(rgba[i]));
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], vl_mixrgba(rgba[i]));
+ }
+ }
+}
+
+
+static void
+write_mono_rgba_pixels (const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLchan color[4], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1, rgba = vl_mixrgba(color);
+
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], rgba);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], rgba);
+ }
+ }
+}
+
+
+static void
+read_rgba_pixels (const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1;
+
+ if (mask) {
+ /* read some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ vl_getrgba(FLIP2(y[i])*_w_ + x[i], rgba[i]);
+ }
+ }
+ } else {
+ /* read all pixels */
+ for (i = 0; i < n; i++) {
+ vl_getrgba(FLIP2(y[i])*_w_ + x[i], rgba[i]);
+ }
+ }
+}
+
+
+/****************************************************************************
+ * Index
+ ***************************************************************************/
+static void
+write_index_span (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, index[i]);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, index[i]);
+ }
+ }
+}
+
+
+static void
+write_index8_span (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, index[i]);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, index[i]);
+ }
+ }
+}
+
+
+static void
+write_mono_index_span (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y,
+ GLuint colorIndex, const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++, offset++) {
+ if (mask[i]) {
+ vl_putpixel(offset, colorIndex);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ vl_putpixel(offset, colorIndex);
+ }
+ }
+}
+
+
+static void
+read_index_span (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, GLint x, GLint y, GLuint index[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, offset;
+
+ offset = DSTRIDE * FLIP(y) + x;
+ /* read all pixels */
+ for (i = 0; i < n; i++, offset++) {
+ index[i] = vl_getpixel(offset);
+ }
+}
+
+
+static void
+write_index_pixels (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1;
+
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], index[i]);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], index[i]);
+ }
+ }
+}
+
+
+static void
+write_mono_index_pixels (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1;
+
+ if (mask) {
+ /* draw some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], colorIndex);
+ }
+ }
+ } else {
+ /* draw all pixels */
+ for (i = 0; i < n; i++) {
+ vl_putpixel(FLIP2(y[i])*_w_ + x[i], colorIndex);
+ }
+ }
+}
+
+
+static void
+read_index_pixels (const GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint index[], const GLubyte mask[])
+{
+ const DMesaContext dmesa = (DMesaContext)ctx;
+ GLuint i, _w_ = DSTRIDE, _b_ = dmesa->buffer->height - 1;
+
+ if (mask) {
+ /* read some pixels */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ index[i] = vl_getpixel(FLIP2(y[i])*_w_ + x[i]);
+ }
+ }
+ } else {
+ /* read all pixels */
+ for (i = 0; i < n; i++) {
+ index[i] = vl_getpixel(FLIP2(y[i])*_w_ + x[i]);
+ }
+ }
+}
+
+
+/****************************************************************************
+ * Z-buffer
+ ***************************************************************************/
+
+
+/****************************************************************************
+ * Optimized triangle rendering
+ ***************************************************************************/
+
+/*
+ * NON-depth-buffered flat triangle.
+ */
+#define NAME tri_rgb_flat
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx;\
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width; \
+ GLuint rgb = vl_mixrgb(v2->color);
+
+#define RENDER_SPAN(span) \
+ GLuint i, offset = FLIP2(span.y)*_w_ + span.x;\
+ for (i = 0; i < span.end; i++, offset++) { \
+ vl_putpixel(offset, rgb); \
+ }
+
+#include "swrast/s_tritemp.h"
+
+
+/*
+ * Z-less flat triangle.
+ */
+#define NAME tri_rgb_flat_zless
+
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx; \
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width; \
+ GLuint rgb = vl_mixrgb(v2->color);
+
+#define RENDER_SPAN(span) \
+ GLuint i, offset = FLIP2(span.y)*_w_ + span.x;\
+ for (i = 0; i < span.end; i++, offset++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z);\
+ if (z < zRow[i]) { \
+ vl_putpixel(offset, rgb); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+
+#include "swrast/s_tritemp.h"
+
+
+/*
+ * NON-depth-buffered iterated triangle.
+ */
+#define NAME tri_rgb_iter
+
+#define INTERP_RGB 1
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx;\
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width;
+
+#define RENDER_SPAN(span) \
+ GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
+ for (i = 0; i < span.end; i++, offset++) { \
+ vl_putpixel(offset, vl_mixfix(span.red, span.green, span.blue)); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+
+#include "swrast/s_tritemp.h"
+
+
+/*
+ * Z-less iterated triangle.
+ */
+#define NAME tri_rgb_iter_zless
+
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx;\
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width;
+
+#define RENDER_SPAN(span) \
+ GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
+ for (i = 0; i < span.end; i++, offset++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ vl_putpixel(offset, vl_mixfix(span.red, span.green, span.blue));\
+ zRow[i] = z; \
+ } \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ span.z += span.zStep; \
+ }
+
+#include "swrast/s_tritemp.h"
+
+
+/*
+ * Analyze context state to see if we can provide a fast triangle function
+ * Otherwise, return NULL.
+ */
+static swrast_tri_func
+dmesa_choose_tri_function (GLcontext *ctx)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if ((ctx->RenderMode != GL_RENDER)
+ || (ctx->Polygon.SmoothFlag)
+ || (ctx->Polygon.StippleFlag)
+ || (ctx->Texture._EnabledUnits)
+ || (swrast->_RasterMask & MULTI_DRAW_BIT)
+ || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)) {
+ return (swrast_tri_func)NULL;
+ }
+
+ if (swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
+ return (ctx->Light.ShadeModel==GL_SMOOTH) ? tri_rgb_iter_zless : tri_rgb_flat_zless;
+ }
+
+ if (swrast->_RasterMask==0) { /* no depth test */
+ return (ctx->Light.ShadeModel==GL_SMOOTH) ? tri_rgb_iter : tri_rgb_flat;
+ }
+
+ return (swrast_tri_func)NULL;
+}
+
+
+/* Override for the swrast triangle-selection function. Try to use one
+ * of our internal triangle functions, otherwise fall back to the
+ * standard swrast functions.
+ */
+static void
+dmesa_choose_tri (GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (!(swrast->Triangle=dmesa_choose_tri_function(ctx))) {
+ _swrast_choose_triangle(ctx);
+ }
+}
+
+
+/****************************************************************************
+ * Optimized line rendering
+ ***************************************************************************/
+
+/*
+ * NON-depth-buffered flat line.
+ */
+#define NAME line_rgb_flat
+
+#define INTERP_XY 1
+#define CLIP_HACK 1
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx;\
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width; \
+ GLuint rgb = vl_mixrgb(vert1->color);
+
+#define PLOT(X,Y) vl_putpixel(FLIP2(Y) * _w_ + X, rgb);
+
+#include "swrast/s_linetemp.h"
+
+
+/*
+ * Z-less flat line.
+ */
+#define NAME line_rgb_flat_zless
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define CLIP_HACK 1
+
+#define SETUP_CODE \
+ const DMesaContext dmesa = (DMesaContext)ctx;\
+ GLuint _b_ = dmesa->buffer->height - 1; \
+ GLuint _w_ = dmesa->buffer->width; \
+ GLuint rgb = vl_mixrgb(vert1->color);
+
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ vl_putpixel(FLIP2(Y) * _w_ + X, rgb); \
+ }
+
+#include "swrast/s_linetemp.h"
+
+
+/*
+ * NON-depth-buffered iterated line.
+ */
+#define line_rgb_iter NULL
+
+
+/*
+ * Z-less iterated line.
+ */
+#define line_rgb_iter_zless NULL
+
+
+/*
+ * Analyze context state to see if we can provide a fast line function
+ * Otherwise, return NULL.
+ */
+static swrast_line_func
+dmesa_choose_line_function (GLcontext *ctx)
+{
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if ((ctx->RenderMode != GL_RENDER)
+ || (ctx->Line.SmoothFlag)
+ || (ctx->Texture._EnabledUnits)
+ || (ctx->Line.StippleFlag)
+ || (swrast->_RasterMask & MULTI_DRAW_BIT)
+ || (ctx->Line.Width!=1.0F)) {
+ return (swrast_line_func)NULL;
+ }
+
+ if (swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
+ return (ctx->Light.ShadeModel==GL_SMOOTH) ? line_rgb_iter_zless : line_rgb_flat_zless;
+ }
+
+ if (swrast->_RasterMask==0) { /* no depth test */
+ return (ctx->Light.ShadeModel==GL_SMOOTH) ? line_rgb_iter : line_rgb_flat;
+ }
+
+ return (swrast_line_func)NULL;
+}
+
+
+/* Override for the swrast line-selection function. Try to use one
+ * of our internal line functions, otherwise fall back to the
+ * standard swrast functions.
+ */
+static void
+dmesa_choose_line (GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (!(swrast->Line=dmesa_choose_line_function(ctx))) {
+ _swrast_choose_line(ctx);
+ }
+}
+
+
+/****************************************************************************
+ * Miscellaneous device driver funcs
+ ***************************************************************************/
+static const struct gl_texture_format *
+choose_tex_format (GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type)
+{
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_ARB:
+ return &_mesa_texformat_rgb;
+ case GL_COMPRESSED_RGBA_ARB:
+ return &_mesa_texformat_rgba;
+ default:
+ return _mesa_choose_tex_format(ctx, internalFormat, format, type);
+ }
+}
+
+
+static void
+clear_index (GLcontext *ctx, GLuint index)
+{
+ ((DMesaContext)ctx)->ClearIndex = index;
+}
+
+
+static void
+clear_color (GLcontext *ctx, const GLfloat color[4])
+{
+ 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]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], color[3]);
+ ((DMesaContext)ctx)->ClearColor = vl_mixrgba(col);
+}
+
+
+static void
+clear (GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height)
+{
+ const DMesaContext c = (DMesaContext)ctx;
+ const GLuint *colorMask = (GLuint *)&ctx->Color.ColorMask;
+
+ /*
+ * Clear the specified region of the buffers indicated by 'mask'
+ * using the clear color or index as specified by one of the two
+ * functions above.
+ * If all==GL_TRUE, clear whole buffer, else just clear region defined
+ * by x,y,width,height
+ */
+
+ /* we can't handle color or index masking */
+ if ((*colorMask == 0xffffffff) && (ctx->Color.IndexMask == 0xffffffff)) {
+ if (mask & DD_BACK_LEFT_BIT) {
+ int color = ((GLvisual *)(c->visual))->rgbMode ? c->ClearColor : c->ClearIndex;
+
+ if (all) {
+ vl_clear(color);
+ } else {
+ vl_rect(x, c->buffer->height - y - height, width, height, color);
+ }
+
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+ }
+
+ if (mask) {
+ _swrast_Clear(ctx, mask, all, x, y, width, height);
+ }
+}
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks. This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void
+set_buffer (GLcontext *ctx, GLframebuffer *colorBuffer, GLuint bufferBit)
+{
+ /*
+ * XXX todo - examine bufferBit and set read/write pointers
+ */
+ /* Normally, we would have
+ * ctx->Driver.ReadBuffer == set_read_buffer
+ * ctx->Driver.DrawBuffer == set_draw_buffer
+ * and make sure set_draw_buffer calls _swrast_DrawBuffer,
+ * which in turn will call this routine via dd->SetBuffer.
+ */
+}
+
+
+/*
+ * Return the width and height of the current buffer.
+ * If anything special has to been done when the buffer/window is
+ * resized, do it now.
+ */
+static void
+get_buffer_size (GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ DMesaBuffer b = (DMesaBuffer)buffer;
+
+ *width = b->width;
+ *height = b->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 const GLubyte *
+get_string (GLcontext *ctx, GLenum name)
+{
+ switch (name) {
+ case GL_RENDERER:
+ return (const GLubyte *)"Mesa DJGPP";
+ default:
+ return NULL;
+ }
+}
+
+
+static void
+finish (GLcontext *ctx)
+{
+ /*
+ * XXX todo - OPTIONAL FUNCTION: implements glFinish if possible
+ */
+}
+
+
+static void
+flush (GLcontext *ctx)
+{
+ /*
+ * XXX todo - OPTIONAL FUNCTION: implements glFlush if possible
+ */
+}
+
+
+/****************************************************************************
+ * State
+ ***************************************************************************/
+#define DMESA_NEW_LINE (_NEW_LINE | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define DMESA_NEW_TRIANGLE (_NEW_POLYGON | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+/* Extend the software rasterizer with our line and triangle
+ * functions.
+ */
+static void
+dmesa_register_swrast_functions (GLcontext *ctx)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ swrast->choose_line = dmesa_choose_line;
+ swrast->choose_triangle = dmesa_choose_tri;
+
+ swrast->invalidate_line |= DMESA_NEW_LINE;
+ swrast->invalidate_triangle |= DMESA_NEW_TRIANGLE;
+}
+
+
+static void
+dmesa_update_state (GLcontext *ctx, GLuint new_state)
+{
+ /* Propagate statechange information to swrast and swrast_setup
+ * modules. The DMesa driver has no internal GL-dependent state.
+ */
+ _swrast_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+}
+
+
+/* Initialize the device driver function table with the functions
+ * we implement in this driver.
+ */
+static void
+dmesa_init_driver_functions (DMesaVisual visual,
+ struct dd_function_table *driver)
+{
+ driver->UpdateState = dmesa_update_state;
+ driver->GetString = get_string;
+ driver->GetBufferSize = get_buffer_size;
+ driver->Viewport = viewport;
+ driver->Flush = flush;
+ driver->Finish = finish;
+ driver->Clear = clear;
+ driver->ClearColor = clear_color;
+ driver->ClearIndex = clear_index;
+#if SWTC
+ driver->ChooseTextureFormat = choose_tex_format;
+#endif
+}
+
+
+/* Setup pointers and other driver state that is constant for the life
+ * of a context.
+ */
+static void
+dmesa_init_pointers (GLcontext *ctx)
+{
+ struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference(ctx);
+
+ dd->SetBuffer = set_buffer;
+
+ /* The span functions should be in `dmesa_update_state', but I'm
+ * pretty sure they will never change during the life of the Visual
+ */
+
+ /* Index span/pixel functions */
+ dd->WriteCI32Span = write_index_span;
+ dd->WriteCI8Span = write_index8_span;
+ dd->WriteMonoCISpan = write_mono_index_span;
+ dd->WriteCI32Pixels = write_index_pixels;
+ dd->WriteMonoCIPixels = write_mono_index_pixels;
+ dd->ReadCI32Span = read_index_span;
+ dd->ReadCI32Pixels = read_index_pixels;
+
+ /* RGB(A) span/pixel functions */
+ dd->WriteRGBASpan = write_rgba_span;
+ dd->WriteRGBSpan = write_rgb_span;
+ dd->WriteMonoRGBASpan = write_mono_rgba_span;
+ dd->WriteRGBAPixels = write_rgba_pixels;
+ dd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ dd->ReadRGBASpan = read_rgba_span;
+ dd->ReadRGBAPixels = read_rgba_pixels;
+}
+#endif /* FX */
+
+
+/****************************************************************************
+ * DMesa Public API Functions
+ ***************************************************************************/
+
+/*
+ * The exact arguments to this function will depend on your window system
+ */
+DMesaVisual
+DMesaCreateVisual (GLint width,
+ GLint height,
+ GLint colDepth,
+ GLint refresh,
+ GLboolean dbFlag,
+ GLboolean rgbFlag,
+ GLint alphaSize,
+ GLint depthSize,
+ GLint stencilSize,
+ GLint accumSize)
+{
+ DMesaVisual v;
+ GLint redBits, greenBits, blueBits, alphaBits, indexBits;
+ GLboolean sw_alpha;
+
+ alphaBits = 0;
+
+ if (!rgbFlag) {
+ indexBits = 8;
+ redBits = 0;
+ greenBits = 0;
+ blueBits = 0;
+ } else {
+ indexBits = 0;
+ switch (colDepth) {
+ case 8:
+ redBits = 8;
+ greenBits = 8;
+ blueBits = 8;
+ break;
+ case 15:
+ alphaBits = 1;
+ redBits = 5;
+ greenBits = 5;
+ blueBits = 5;
+ break;
+ case 16:
+ redBits = 5;
+ greenBits = 6;
+ blueBits = 5;
+ break;
+ case 32:
+ alphaBits = 8;
+ case 24:
+ redBits = 8;
+ greenBits = 8;
+ blueBits = 8;
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ /* Okay,
+ * `alphaBits' is what we can provide
+ * `alphaSize' is what app requests
+ *
+ * Note that alpha buffering is required only if destination alpha is used
+ * in alpha blending; alpha blending modes that do not use destination alpha
+ * can be used w/o alpha buffer.
+ *
+ * We will use whatever ALPHA app requests. Later, in `CreateBuffer' we'll
+ * instruct Mesa to use its own ALPHA buffer, by passing a non-FALSE value
+ * for ALPHA to `_mesa_initialize_framebuffer'.
+ *
+ * Basically, 32bit modes provide ALPHA storage, but can we rely on this?
+ */
+ alphaBits = alphaSize;
+ sw_alpha = (alphaBits > 0);
+
+#ifndef FX
+ if (!dbFlag) {
+ return NULL;
+ }
+ if ((colDepth=vl_video_init(width, height, colDepth, rgbFlag, refresh)) <= 0) {
+ return NULL;
+ }
+#else /* FX */
+ if (!rgbFlag) {
+ return NULL;
+ } else {
+ char *env;
+
+ if ((env = getenv("MESA_FX_INFO")) && (env[0] == 'r')) {
+ freopen("MESA.LOG", "w", stderr);
+ }
+
+ if (refresh && (((env = getenv("FX_GLIDE_REFRESH")) == NULL) || !atoi(env))) {
+ /* if we are passed non-zero value for refresh, we need to override
+ * default refresh rate. However, if FX_GLIDE_REFRESH is already set
+ * to 0, we won't override it, because it has a special meaning for
+ * DJGPP Glide3x (switch via VESA, using BIOS default refresh).
+ */
+ char tmp[32];
+ sprintf(tmp, "FX_GLIDE_REFRESH=%u", refresh);
+ putenv(tmp);
+ }
+ }
+#endif /* FX */
+
+ if ((v=(DMesaVisual)CALLOC_STRUCT(dmesa_visual)) != NULL) {
+ /* Create core visual */
+ _mesa_initialize_visual((GLvisual *)v,
+ rgbFlag, /* rgb */
+ dbFlag,
+ GL_FALSE, /* stereo */
+ redBits,
+ greenBits,
+ blueBits,
+ alphaBits,
+ indexBits, /* indexBits */
+ depthSize,
+ stencilSize,
+ accumSize, /* accumRed */
+ accumSize, /* accumGreen */
+ accumSize, /* accumBlue */
+ alphaBits?accumSize:0, /* accumAlpha */
+ 1); /* numSamples */
+
+#ifndef FX
+ v->sw_alpha = sw_alpha;
+ v->z_buffer = (depthSize > 0) ? 1 : 0;
+#endif
+ }
+
+ return v;
+}
+
+
+void
+DMesaDestroyVisual (DMesaVisual v)
+{
+#ifndef FX
+ vl_video_exit();
+#endif
+ _mesa_destroy_visual((GLvisual *)v);
+}
+
+
+DMesaBuffer
+DMesaCreateBuffer (DMesaVisual visual,
+ GLint xpos, GLint ypos,
+ GLint width, GLint height)
+{
+#ifndef FX
+ DMesaBuffer b;
+
+ if ((b=(DMesaBuffer)CALLOC_STRUCT(dmesa_buffer)) != NULL) {
+ _mesa_initialize_framebuffer((GLframebuffer *)b,
+ (GLvisual *)visual,
+ visual->z_buffer == 1,
+ ((GLvisual *)visual)->stencilBits > 0,
+ ((GLvisual *)visual)->accumRedBits > 0,
+ visual->sw_alpha);
+ b->xpos = xpos;
+ b->ypos = ypos;
+ b->width = width;
+ b->height = height;
+ }
+
+ return b;
+#else /* FX */
+
+ GLvisual *v = (GLvisual *)visual;
+ int i = 0, fx_attrib[32];
+
+ if (v->doubleBufferMode) fx_attrib[i++] = FXMESA_DOUBLEBUFFER;
+ if (v->depthBits > 0) { fx_attrib[i++] = FXMESA_DEPTH_SIZE; fx_attrib[i++] = v->depthBits; }
+ if (v->stencilBits > 0) { fx_attrib[i++] = FXMESA_STENCIL_SIZE; fx_attrib[i++] = v->stencilBits; }
+ if (v->accumRedBits > 0) { fx_attrib[i++] = FXMESA_ACCUM_SIZE; fx_attrib[i++] = v->accumRedBits; }
+ if (v->alphaBits) { fx_attrib[i++] = FXMESA_ALPHA_SIZE; fx_attrib[i++] = v->alphaBits; }
+ fx_attrib[i++] = FXMESA_COLORDEPTH;
+ fx_attrib[i++] = v->redBits + v->greenBits + v->blueBits;
+ fx_attrib[i] = FXMESA_NONE;
+
+ return (DMesaBuffer)fxMesaCreateBestContext(-1, width, height, fx_attrib);
+#endif /* FX */
+}
+
+
+void
+DMesaDestroyBuffer (DMesaBuffer b)
+{
+#ifndef FX
+ if (b->the_window != NULL) {
+ free(b->the_window);
+ }
+ _mesa_destroy_framebuffer((GLframebuffer *)b);
+#else
+ fxMesaDestroyContext((fxMesaContext)b);
+#endif
+}
+
+
+DMesaContext
+DMesaCreateContext (DMesaVisual visual, DMesaContext share)
+{
+ GLcontext *c;
+#ifndef FX
+ TNLcontext *tnl;
+ struct dd_function_table functions;
+
+ if ((c=(GLcontext *)CALLOC_STRUCT(dmesa_context)) != NULL) {
+ /* Initialize device driver function table */
+ _mesa_init_driver_functions(&functions);
+ /* override with our functions */
+ dmesa_init_driver_functions(visual, &functions);
+
+ _mesa_initialize_context(c,
+ (GLvisual *)visual,
+ (GLcontext *)share,
+ &functions,
+ (void *)c);
+
+ _mesa_enable_sw_extensions(c);
+ _mesa_enable_1_3_extensions(c);
+ _mesa_enable_1_4_extensions(c);
+ _mesa_enable_1_5_extensions(c);
+ _mesa_enable_2_0_extensions(c);
+#if SWTC
+ if (c->Mesa_DXTn) {
+ _mesa_enable_extension(c, "GL_EXT_texture_compression_s3tc");
+ _mesa_enable_extension(c, "GL_S3_s3tc");
+ }
+ _mesa_enable_extension(c, "GL_3DFX_texture_compression_FXT1");
+#endif
+
+ /* you probably have to do a bunch of other initializations here. */
+ ((DMesaContext)c)->visual = visual;
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext(c);
+ _ac_CreateContext(c);
+ _tnl_CreateContext(c);
+ _swsetup_CreateContext(c);
+ /* tnl setup */
+ tnl = TNL_CONTEXT(c);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ /* swrast setup */
+ if (((GLvisual *)visual)->rgbMode) dmesa_register_swrast_functions(c);
+ dmesa_init_pointers(c);
+ _swsetup_Wakeup(c);
+ }
+
+#else /* FX */
+ c = (GLcontext *)0xdeadbeef;
+#endif /* FX */
+
+ return (DMesaContext)c;
+}
+
+
+void
+DMesaDestroyContext (DMesaContext c)
+{
+#ifndef FX
+ if (c) {
+ _swsetup_DestroyContext((GLcontext *)c);
+ _swrast_DestroyContext((GLcontext *)c);
+ _tnl_DestroyContext((GLcontext *)c);
+ _ac_DestroyContext((GLcontext *)c);
+ _mesa_destroy_context((GLcontext *)c);
+ }
+#endif
+}
+
+
+GLboolean
+DMesaMoveBuffer (GLint xpos, GLint ypos)
+{
+#ifndef FX
+ GET_CURRENT_CONTEXT(ctx);
+ DMesaBuffer b = ((DMesaContext)ctx)->buffer;
+
+ if (vl_sync_buffer(&b->the_window, xpos, ypos, b->width, b->height) == 0) {
+ b->xpos = xpos;
+ b->ypos = ypos;
+ return GL_TRUE;
+ }
+#endif
+
+ return GL_FALSE;
+}
+
+
+GLboolean
+DMesaResizeBuffer (GLint width, GLint height)
+{
+#ifndef FX
+ GET_CURRENT_CONTEXT(ctx);
+ DMesaBuffer b = ((DMesaContext)ctx)->buffer;
+
+ if (vl_sync_buffer(&b->the_window, b->xpos, b->ypos, width, height) == 0) {
+ b->width = width;
+ b->height = height;
+ return GL_TRUE;
+ }
+#endif
+
+ return GL_FALSE;
+}
+
+
+/*
+ * Make the specified context and buffer the current one.
+ */
+GLboolean
+DMesaMakeCurrent (DMesaContext c, DMesaBuffer b)
+{
+#ifndef FX
+ if ((c != NULL) && (b != NULL)) {
+ if (vl_sync_buffer(&b->the_window, b->xpos, b->ypos, b->width, b->height) != 0) {
+ return GL_FALSE;
+ }
+
+ c->buffer = b;
+
+ _mesa_make_current((GLcontext *)c, (GLframebuffer *)b);
+ }
+ else {
+ /* Detach */
+ _mesa_make_current(NULL, NULL);
+ }
+
+#else
+ fxMesaMakeCurrent((fxMesaContext)b);
+#endif
+
+ return GL_TRUE;
+}
+
+
+void
+DMesaSwapBuffers (DMesaBuffer b)
+{
+ /* copy/swap back buffer to front if applicable */
+#ifndef FX
+ GET_CURRENT_CONTEXT(ctx);
+ _mesa_notifySwapBuffers(ctx);
+ vl_flip();
+#else
+ fxMesaSwapBuffers();
+#endif
+}
+
+
+void
+DMesaSetCI (int ndx, GLfloat red, GLfloat green, GLfloat blue)
+{
+#ifndef FX
+ vl_setCI(ndx, red, green, blue);
+#endif
+}
+
+
+DMesaContext
+DMesaGetCurrentContext (void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+#ifndef FX
+#else
+ if (ctx != NULL) {
+ ctx = (GLcontext *)0xdeadbeef;
+ }
+#endif
+
+ return (DMesaContext)ctx;
+}
+
+
+DMesaBuffer
+DMesaGetCurrentBuffer (void)
+{
+ const DMesaContext dmesa = DMesaGetCurrentContext();
+
+ if (dmesa == NULL) {
+ return NULL;
+ }
+
+#ifndef FX
+ return dmesa->buffer;
+#else
+ return (DMesaBuffer)fxMesaGetCurrentContext();
+#endif
+}
+
+
+DMesaProc
+DMesaGetProcAddress (const char *name)
+{
+ DMesaProc p = (DMesaProc)_glapi_get_proc_address(name);
+
+ /* TODO: handle DMesa* namespace
+ if (p == NULL) {
+ }
+ */
+
+ return p;
+}
+
+
+int
+DMesaGetIntegerv (GLenum pname, GLint *params)
+{
+ switch (pname) {
+ case DMESA_GET_SCREEN_SIZE:
+ #ifndef FX
+ vl_get(VL_GET_SCREEN_SIZE, params);
+ #else
+ fxGetScreenGeometry(&params[0], &params[1]);
+ #endif
+ break;
+ case DMESA_GET_DRIVER_CAPS:
+ #ifndef FX
+ params[0] = DMESA_DRIVER_SWDB_BIT;
+ #else
+ params[0] = DMESA_DRIVER_LLWO_BIT;
+ #endif
+ break;
+ case DMESA_GET_VIDEO_MODES:
+ #ifndef FX
+ return vl_get(VL_GET_VIDEO_MODES, params);
+ #else
+ return -1; /* TODO */
+ #endif
+ case DMESA_GET_BUFFER_ADDR: {
+ #ifndef FX
+ DMesaContext c = (DMesaContext)DMesaGetCurrentContext();
+ if (c != NULL) {
+ DMesaBuffer b = c->buffer;
+ if (b != NULL) {
+ params[0] = (GLint)b->the_window;
+ }
+ }
+ break;
+ #else
+ return -1;
+ #endif
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+#if SWTC && (((__DJGPP__ << 8) | __DJGPP_MINOR__) >= 0x204)
+#include <sys/dxe.h>
+
+extern_asm(___dj_assert);
+extern_asm(_free);
+extern_asm(_malloc);
+extern_asm(_memset);
+
+DXE_EXPORT_TABLE_AUTO (___dxe_eta___dxtn)
+ DXE_EXPORT_ASM (___dj_assert)
+ DXE_EXPORT_ASM (_free)
+ DXE_EXPORT_ASM (_malloc)
+ DXE_EXPORT_ASM (_memset)
+DXE_EXPORT_END
+#endif