aboutsummaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/beos/GLView.cpp1452
-rw-r--r--src/mesa/drivers/beos/Makefile195
-rw-r--r--src/mesa/drivers/common/descrip.mms37
-rw-r--r--src/mesa/drivers/common/driverfuncs.c211
-rw-r--r--src/mesa/drivers/common/driverfuncs.h32
-rw-r--r--src/mesa/drivers/dos/blit.S210
-rw-r--r--src/mesa/drivers/dos/dmesa.c1384
-rw-r--r--src/mesa/drivers/dos/dpmi.c148
-rw-r--r--src/mesa/drivers/dos/internal.h130
-rw-r--r--src/mesa/drivers/dos/null.c227
-rw-r--r--src/mesa/drivers/dos/null.h41
-rw-r--r--src/mesa/drivers/dos/vesa.c533
-rw-r--r--src/mesa/drivers/dos/vesa.h47
-rw-r--r--src/mesa/drivers/dos/vga.c252
-rw-r--r--src/mesa/drivers/dos/vga.h42
-rw-r--r--src/mesa/drivers/dos/video.c659
-rw-r--r--src/mesa/drivers/dos/video.h65
-rw-r--r--src/mesa/drivers/dos/virtual.S495
-rw-r--r--src/mesa/drivers/dri/common/depthtmp.h220
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c1693
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h568
-rw-r--r--src/mesa/drivers/dri/common/glcontextmodes.c496
-rw-r--r--src/mesa/drivers/dri/common/glcontextmodes.h52
-rw-r--r--src/mesa/drivers/dri/common/mm.c196
-rw-r--r--src/mesa/drivers/dri/common/mm.h82
-rw-r--r--src/mesa/drivers/dri/common/mmio.h61
-rw-r--r--src/mesa/drivers/dri/common/mmx.h560
-rw-r--r--src/mesa/drivers/dri/common/spantmp.h305
-rw-r--r--src/mesa/drivers/dri/common/stenciltmp.h147
-rw-r--r--src/mesa/drivers/dri/common/texmem.c1278
-rw-r--r--src/mesa/drivers/dri/common/texmem.h310
-rw-r--r--src/mesa/drivers/dri/common/utils.c531
-rw-r--r--src/mesa/drivers/dri/common/utils.h71
-rw-r--r--src/mesa/drivers/dri/common/vblank.c349
-rw-r--r--src/mesa/drivers/dri/common/vblank.h69
-rw-r--r--src/mesa/drivers/dri/common/xmlconfig.c1002
-rw-r--r--src/mesa/drivers/dri/common/xmlconfig.h124
-rw-r--r--src/mesa/drivers/dri/common/xmlpool.h297
-rw-r--r--src/mesa/drivers/fbdev/glfbdev.c791
-rw-r--r--src/mesa/drivers/ggi/default/genkgi.conf.in4
-rw-r--r--src/mesa/drivers/ggi/default/genkgi_mode.c97
-rw-r--r--src/mesa/drivers/ggi/default/genkgi_visual.c190
-rw-r--r--src/mesa/drivers/ggi/default/linear.c409
-rw-r--r--src/mesa/drivers/ggi/default/linear_15.c36
-rw-r--r--src/mesa/drivers/ggi/default/linear_16.c36
-rw-r--r--src/mesa/drivers/ggi/default/linear_24.c36
-rw-r--r--src/mesa/drivers/ggi/default/linear_32.c36
-rw-r--r--src/mesa/drivers/ggi/default/linear_8.c36
-rw-r--r--src/mesa/drivers/ggi/default/stubs.c512
-rw-r--r--src/mesa/drivers/ggi/display/fbdev.conf.in4
-rw-r--r--src/mesa/drivers/ggi/display/fbdev_mode.c130
-rw-r--r--src/mesa/drivers/ggi/display/fbdev_visual.c138
-rw-r--r--src/mesa/drivers/ggi/ggimesa.c696
-rw-r--r--src/mesa/drivers/ggi/ggimesa.conf.in13
-rw-r--r--src/mesa/drivers/ggi/include/ggi/mesa/debug.h260
-rw-r--r--src/mesa/drivers/ggi/include/ggi/mesa/display_fbdev.h20
-rw-r--r--src/mesa/drivers/ggi/include/ggi/mesa/ggimesa.h84
-rw-r--r--src/mesa/drivers/ggi/include/ggi/mesa/ggimesa_int.h44
-rw-r--r--src/mesa/drivers/glide/fx.rc39
-rw-r--r--src/mesa/drivers/glide/fxapi.c946
-rw-r--r--src/mesa/drivers/glide/fxdd.c2200
-rw-r--r--src/mesa/drivers/glide/fxddspan.c659
-rw-r--r--src/mesa/drivers/glide/fxddtex.c1849
-rw-r--r--src/mesa/drivers/glide/fxdrv.h772
-rw-r--r--src/mesa/drivers/glide/fxg.c2309
-rw-r--r--src/mesa/drivers/glide/fxg.h382
-rw-r--r--src/mesa/drivers/glide/fxglidew.c269
-rw-r--r--src/mesa/drivers/glide/fxglidew.h228
-rw-r--r--src/mesa/drivers/glide/fxopengl.def938
-rw-r--r--src/mesa/drivers/glide/fxsetup.c2176
-rw-r--r--src/mesa/drivers/glide/fxsetup.h850
-rw-r--r--src/mesa/drivers/glide/fxtexman.c866
-rw-r--r--src/mesa/drivers/glide/fxtris.c1647
-rw-r--r--src/mesa/drivers/glide/fxvb.c834
-rw-r--r--src/mesa/drivers/glide/fxvbtmp.h369
-rw-r--r--src/mesa/drivers/glide/fxwgl.c1123
-rw-r--r--src/mesa/drivers/glide/glide3x_dxe.c176
-rw-r--r--src/mesa/drivers/osmesa/Makefile.win39
-rw-r--r--src/mesa/drivers/osmesa/descrip.mms41
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c1307
-rw-r--r--src/mesa/drivers/osmesa/osmesa.def13
-rw-r--r--src/mesa/drivers/osmesa/osmesa.dsp119
-rw-r--r--src/mesa/drivers/svga/svgamesa.c513
-rw-r--r--src/mesa/drivers/svga/svgamesa15.c217
-rw-r--r--src/mesa/drivers/svga/svgamesa15.h43
-rw-r--r--src/mesa/drivers/svga/svgamesa16.c215
-rw-r--r--src/mesa/drivers/svga/svgamesa16.h44
-rw-r--r--src/mesa/drivers/svga/svgamesa24.c239
-rw-r--r--src/mesa/drivers/svga/svgamesa24.h44
-rw-r--r--src/mesa/drivers/svga/svgamesa32.c220
-rw-r--r--src/mesa/drivers/svga/svgamesa32.h44
-rw-r--r--src/mesa/drivers/svga/svgamesa8.c191
-rw-r--r--src/mesa/drivers/svga/svgamesa8.h44
-rw-r--r--src/mesa/drivers/svga/svgapix.h71
-rw-r--r--src/mesa/drivers/verite/.gdbinit41
-rw-r--r--src/mesa/drivers/verite/README5
-rw-r--r--src/mesa/drivers/verite/libv3d.c400
-rw-r--r--src/mesa/drivers/verite/libv3d.h138
-rw-r--r--src/mesa/drivers/verite/rlgl.c982
-rw-r--r--src/mesa/drivers/verite/rlgl.h194
-rw-r--r--src/mesa/drivers/verite/verite3dio.h107
-rw-r--r--src/mesa/drivers/verite/vrapi.c319
-rw-r--r--src/mesa/drivers/verite/vrdd.c382
-rw-r--r--src/mesa/drivers/verite/vrdrv.h125
-rw-r--r--src/mesa/drivers/verite/vrperf.h161
-rw-r--r--src/mesa/drivers/verite/vrspan.c202
-rw-r--r--src/mesa/drivers/verite/vrtex.c501
-rw-r--r--src/mesa/drivers/verite/vrtris.c1085
-rw-r--r--src/mesa/drivers/windows/gdi/colors.h539
-rw-r--r--src/mesa/drivers/windows/gdi/gdi.dsp137
-rw-r--r--src/mesa/drivers/windows/gdi/mesa.def1057
-rw-r--r--src/mesa/drivers/windows/gdi/wgl.c639
-rw-r--r--src/mesa/drivers/windows/gdi/wmesa.c3353
-rw-r--r--src/mesa/drivers/windows/gdi/wmesadef.h175
-rw-r--r--src/mesa/drivers/windows/gldirect/ddlog.c192
-rw-r--r--src/mesa/drivers/windows/gldirect/ddlog.h109
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.c2213
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.h281
-rw-r--r--src/mesa/drivers/windows/gldirect/dglglobals.c149
-rw-r--r--src/mesa/drivers/windows/gldirect/dglglobals.h198
-rw-r--r--src/mesa/drivers/windows/gldirect/dglmacros.h91
-rw-r--r--src/mesa/drivers/windows/gldirect/dglpf.c620
-rw-r--r--src/mesa/drivers/windows/gldirect/dglpf.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dglwgl.c2958
-rw-r--r--src/mesa/drivers/windows/gldirect/dglwgl.h102
-rw-r--r--src/mesa/drivers/windows/gldirect/dll_main.c816
-rw-r--r--src/mesa/drivers/windows/gldirect/dllmain.h64
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_clip.c40
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_norm.c40
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_xform.c42
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_dispatch.c73
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_driver.c279
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_driver.h90
-rw-r--r--src/mesa/drivers/windows/gldirect/gldlame8.c181
-rw-r--r--src/mesa/drivers/windows/gldirect/opengl32.def488
-rw-r--r--src/mesa/drivers/windows/gldirect/pixpack.h108
-rw-r--r--src/mesa/drivers/windows/icd/icd.c347
-rw-r--r--src/mesa/drivers/windows/icd/icdlist.h336
-rw-r--r--src/mesa/drivers/windows/icd/mesa.def110
-rw-r--r--src/mesa/drivers/x11/descrip.mms50
-rw-r--r--src/mesa/drivers/x11/fakeglx.c2929
-rw-r--r--src/mesa/drivers/x11/glxapi.c1343
-rw-r--r--src/mesa/drivers/x11/glxapi.h236
-rw-r--r--src/mesa/drivers/x11/glxheader.h71
-rw-r--r--src/mesa/drivers/x11/realglx.c185
-rw-r--r--src/mesa/drivers/x11/realglx.h326
-rw-r--r--src/mesa/drivers/x11/xfonts.c377
-rw-r--r--src/mesa/drivers/x11/xfonts.h41
-rw-r--r--src/mesa/drivers/x11/xm_api.c2676
-rw-r--r--src/mesa/drivers/x11/xm_dd.c1220
-rw-r--r--src/mesa/drivers/x11/xm_line.c617
-rw-r--r--src/mesa/drivers/x11/xm_span.c4777
-rw-r--r--src/mesa/drivers/x11/xm_tri.c1609
-rw-r--r--src/mesa/drivers/x11/xmesaP.h531
154 files changed, 77713 insertions, 0 deletions
diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp
new file mode 100644
index 0000000..69f4cf9
--- /dev/null
+++ b/src/mesa/drivers/beos/GLView.cpp
@@ -0,0 +1,1452 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+
+extern "C" {
+
+#include "glheader.h"
+#include "buffers.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstore.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 "drivers/common/driverfuncs.h"
+
+} // extern "C"
+
+#include <interface/Screen.h>
+#include <GLView.h>
+
+// BeOS component ordering for B_RGBA32 bitmap format
+#if B_HOST_IS_LENDIAN
+ #define BE_RCOMP 2
+ #define BE_GCOMP 1
+ #define BE_BCOMP 0
+ #define BE_ACOMP 3
+
+ #define PACK_B_RGBA32(color) (color[BCOMP] | (color[GCOMP] << 8) | \
+ (color[RCOMP] << 16) | (color[ACOMP] << 24))
+
+ #define PACK_B_RGB32(color) (color[BCOMP] | (color[GCOMP] << 8) | \
+ (color[RCOMP] << 16) | 0xFF000000)
+#else
+ // Big Endian B_RGBA32 bitmap format
+ #define BE_RCOMP 1
+ #define BE_GCOMP 2
+ #define BE_BCOMP 3
+ #define BE_ACOMP 0
+
+ #define PACK_B_RGBA32(color) (color[ACOMP] | (color[RCOMP] << 8) | \
+ (color[GCOMP] << 16) | (color[BCOMP] << 24))
+
+ #define PACK_B_RGB32(color) ((color[RCOMP] << 8) | (color[GCOMP] << 16) | \
+ (color[BCOMP] << 24) | 0xFF000000)
+#endif
+
+#define FLIP(coord) (LIBGGI_MODE(ggi_ctx->ggi_visual)->visible.y-(coord) - 1)
+
+//
+// This object hangs off of the BGLView object. We have to use
+// Be's BGLView class as-is to maintain binary compatibility (we
+// can't add new members to it). Instead we just put all our data
+// in this class and use BGLVIew::m_gc to point to it.
+//
+class MesaDriver
+{
+friend class BGLView;
+public:
+ MesaDriver();
+ ~MesaDriver();
+ void Init(BGLView * bglview, GLcontext * c, GLvisual * v, GLframebuffer * b);
+
+ void LockGL();
+ void UnlockGL();
+ void SwapBuffers() const;
+ void CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const;
+ void Draw(BRect updateRect) const;
+
+private:
+ MesaDriver(const MesaDriver &rhs); // copy constructor illegal
+ MesaDriver &operator=(const MesaDriver &rhs); // assignment oper. illegal
+
+ GLcontext * m_glcontext;
+ GLvisual * m_glvisual;
+ GLframebuffer * m_glframebuffer;
+
+ BGLView * m_bglview;
+ BBitmap * m_bitmap;
+
+ GLchan m_clear_color[4]; // buffer clear color
+ GLuint m_clear_index; // buffer clear color index
+ GLint m_bottom; // used for flipping Y coords
+ GLuint m_width;
+ GLuint m_height;
+
+ // Mesa Device Driver functions
+ static void UpdateState(GLcontext *ctx, GLuint new_state);
+ static void ClearIndex(GLcontext *ctx, GLuint index);
+ static void ClearColor(GLcontext *ctx, const GLfloat color[4]);
+ static void Clear(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height);
+ static void ClearFront(GLcontext *ctx, GLboolean all, GLint x, GLint y,
+ GLint width, GLint height);
+ static void ClearBack(GLcontext *ctx, GLboolean all, GLint x, GLint y,
+ GLint width, GLint height);
+ static void Index(GLcontext *ctx, GLuint index);
+ static void Color(GLcontext *ctx, GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a);
+ static void SetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+ GLenum mode);
+ static void GetBufferSize(GLframebuffer * framebuffer, GLuint *width,
+ GLuint *height);
+ static const GLubyte * GetString(GLcontext *ctx, GLenum name);
+
+ // Front-buffer functions
+ static void WriteRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteRGBSpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[]);
+ static void WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[]);
+ static void WriteRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[]);
+ static void WriteCI32SpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteCI8SpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[]);
+ static void WriteMonoCISpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLuint colorIndex, const GLubyte mask[]);
+ static void WriteCI32PixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteMonoCIPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[]);
+ static void ReadCI32SpanFront(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[]);
+ static void ReadRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4]);
+ static void ReadCI32PixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[]);
+ static void ReadRGBAPixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[]);
+
+ // Back buffer functions
+ static void WriteRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteRGBSpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[]);
+ static void WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[]);
+ static void WriteRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[]);
+ static void WriteCI32SpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteCI8SpanBack(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[]);
+ static void WriteMonoCISpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLuint colorIndex,
+ const GLubyte mask[]);
+ static void WriteCI32PixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteMonoCIPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[]);
+ static void ReadCI32SpanBack(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[]);
+ static void ReadRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4]);
+ static void ReadCI32PixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[]);
+ static void ReadRGBAPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[]);
+
+};
+
+//------------------------------------------------------------------
+// Public interface methods
+//------------------------------------------------------------------
+
+
+//
+// Input: rect - initial rectangle
+// name - window name
+// resizingMode - example: B_FOLLOW_NONE
+// mode - usually 0 ?
+// options - Bitwise-OR of BGL_* tokens
+//
+BGLView::BGLView(BRect rect, char *name,
+ ulong resizingMode, ulong mode,
+ ulong options)
+ : BView(rect, name, resizingMode, mode | B_WILL_DRAW | B_FRAME_EVENTS) // | B_FULL_UPDATE_ON_RESIZE)
+{
+ // We don't support single buffering (yet): double buffering forced.
+ options |= BGL_DOUBLE;
+
+ const GLboolean rgbFlag = ((options & BGL_INDEX) == 0);
+ const GLboolean alphaFlag = ((options & BGL_ALPHA) == BGL_ALPHA);
+ const GLboolean dblFlag = ((options & BGL_DOUBLE) == BGL_DOUBLE);
+ const GLboolean stereoFlag = false;
+ const GLint depth = (options & BGL_DEPTH) ? 16 : 0;
+ const GLint stencil = (options & BGL_STENCIL) ? 8 : 0;
+ const GLint accum = (options & BGL_ACCUM) ? 16 : 0;
+ const GLint index = (options & BGL_INDEX) ? 32 : 0;
+ const GLint red = rgbFlag ? 8 : 0;
+ const GLint green = rgbFlag ? 8 : 0;
+ const GLint blue = rgbFlag ? 8 : 0;
+ const GLint alpha = alphaFlag ? 8 : 0;
+
+ m_options = options | BGL_INDIRECT;
+
+ struct dd_function_table functions;
+
+ if (!rgbFlag) {
+ fprintf(stderr, "Mesa Warning: color index mode not supported\n");
+ }
+
+ // Allocate auxiliary data object
+ MesaDriver * md = new MesaDriver();
+
+ // examine option flags and create gl_context struct
+ GLvisual * visual = _mesa_create_visual( rgbFlag,
+ dblFlag,
+ stereoFlag,
+ red, green, blue, alpha,
+ index,
+ depth,
+ stencil,
+ accum, accum, accum, accum,
+ 1
+ );
+
+ // Initialize device driver function table
+ _mesa_init_driver_functions(&functions);
+
+ functions.GetString = md->GetString;
+ functions.UpdateState = md->UpdateState;
+ functions.GetBufferSize = md->GetBufferSize;
+ functions.Clear = md->Clear;
+ functions.ClearIndex = md->ClearIndex;
+ functions.ClearColor = md->ClearColor;
+
+ // create core context
+ GLcontext *ctx = _mesa_create_context(visual, NULL, &functions, md);
+ if (! ctx) {
+ _mesa_destroy_visual(visual);
+ delete md;
+ return;
+ }
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+ _mesa_enable_1_5_extensions(ctx);
+
+
+ // create core framebuffer
+ GLframebuffer * buffer = _mesa_create_framebuffer(visual,
+ depth > 0 ? GL_TRUE : GL_FALSE,
+ stencil > 0 ? GL_TRUE: GL_FALSE,
+ accum > 0 ? GL_TRUE : GL_FALSE,
+ alphaFlag
+ );
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext(ctx);
+ _ac_CreateContext(ctx);
+ _tnl_CreateContext(ctx);
+ _swsetup_CreateContext(ctx);
+ _swsetup_Wakeup(ctx);
+
+ md->Init(this, ctx, visual, buffer );
+
+ // Hook aux data into BGLView object
+ m_gc = md;
+
+ // some stupid applications (Quake2) don't even think about calling LockGL()
+ // before using glGetString and friends... so make sure there is at least a
+ // valid context.
+ if (!_mesa_get_current_context()) {
+ LockGL();
+ // not needed, we don't have a looper yet: UnlockLooper();
+ }
+
+}
+
+
+BGLView::~BGLView()
+{
+ // printf("BGLView destructor\n");
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ delete md;
+}
+
+void BGLView::LockGL()
+{
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ md->LockGL();
+}
+
+void BGLView::UnlockGL()
+{
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ md->UnlockGL();
+}
+
+void BGLView::SwapBuffers()
+{
+ SwapBuffers(false);
+}
+
+void BGLView::SwapBuffers(bool vSync)
+{
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ md->SwapBuffers();
+
+ if (vSync) {
+ BScreen screen(Window());
+ screen.WaitForRetrace();
+ }
+}
+
+
+
+
+#if 0
+void BGLView::CopySubBufferMESA(GLint x, GLint y, GLuint width, GLuint height)
+{
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ md->CopySubBuffer(x, y, width, height);
+}
+#endif
+
+BView * BGLView::EmbeddedView()
+{
+ // TODO
+ return NULL;
+}
+
+status_t BGLView::CopyPixelsOut(BPoint source, BBitmap *dest)
+{
+ // TODO
+ printf("BGLView::CopyPixelsOut() not implemented yet!\n");
+ return B_UNSUPPORTED;
+}
+
+
+status_t BGLView::CopyPixelsIn(BBitmap *source, BPoint dest)
+{
+ // TODO
+ printf("BGLView::CopyPixelsIn() not implemented yet!\n");
+ return B_UNSUPPORTED;
+}
+
+void BGLView::ErrorCallback(unsigned long errorCode) // Mesa's GLenum is not ulong but uint!
+{
+ char msg[32];
+ sprintf(msg, "GL: Error code $%04lx.", errorCode);
+ // debugger(msg);
+ printf("%s\n", msg);
+ return;
+}
+
+void BGLView::Draw(BRect updateRect)
+{
+ // printf("BGLView::Draw()\n");
+ MesaDriver * md = (MesaDriver *) m_gc;
+ assert(md);
+ md->Draw(updateRect);
+}
+
+void BGLView::AttachedToWindow()
+{
+ BView::AttachedToWindow();
+
+ // don't paint window background white when resized
+ SetViewColor(B_TRANSPARENT_32_BIT);
+}
+
+void BGLView::AllAttached()
+{
+ BView::AllAttached();
+// printf("BGLView AllAttached\n");
+}
+
+void BGLView::DetachedFromWindow()
+{
+ BView::DetachedFromWindow();
+}
+
+void BGLView::AllDetached()
+{
+ BView::AllDetached();
+// printf("BGLView AllDetached");
+}
+
+void BGLView::FrameResized(float width, float height)
+{
+ return BView::FrameResized(width, height);
+}
+
+status_t BGLView::Perform(perform_code d, void *arg)
+{
+ return BView::Perform(d, arg);
+}
+
+
+status_t BGLView::Archive(BMessage *data, bool deep) const
+{
+ return BView::Archive(data, deep);
+}
+
+void BGLView::MessageReceived(BMessage *msg)
+{
+ BView::MessageReceived(msg);
+}
+
+void BGLView::SetResizingMode(uint32 mode)
+{
+ BView::SetResizingMode(mode);
+}
+
+void BGLView::Show()
+{
+// printf("BGLView Show\n");
+ BView::Show();
+}
+
+void BGLView::Hide()
+{
+// printf("BGLView Hide\n");
+ BView::Hide();
+}
+
+BHandler *BGLView::ResolveSpecifier(BMessage *msg, int32 index,
+ BMessage *specifier, int32 form,
+ const char *property)
+{
+ return BView::ResolveSpecifier(msg, index, specifier, form, property);
+}
+
+status_t BGLView::GetSupportedSuites(BMessage *data)
+{
+ return BView::GetSupportedSuites(data);
+}
+
+void BGLView::DirectConnected( direct_buffer_info *info )
+{
+#if 0
+ if (! m_direct_connected && m_direct_connection_disabled)
+ return;
+
+ direct_info_locker->Lock();
+ switch(info->buffer_state & B_DIRECT_MODE_MASK) {
+ case B_DIRECT_START:
+ m_direct_connected = true;
+ case B_DIRECT_MODIFY:
+ // Get clipping information
+ if (m_clip_list)
+ free(m_clip_list);
+ m_clip_list_count = info->clip_list_count;
+ m_clip_list = (clipping_rect *) malloc(m_clip_list_count*sizeof(clipping_rect));
+ if (m_clip_list) {
+ memcpy(m_clip_list, info->clip_list, m_clip_list_count*sizeof(clipping_rect));
+ fBits = (uint8 *) info->bits;
+ fRowBytes = info->bytes_per_row;
+ fFormat = info->pixel_format;
+ fBounds = info->window_bounds;
+ fDirty = true;
+ }
+ break;
+ case B_DIRECT_STOP:
+ fConnected = false;
+ break;
+ }
+ direct_info_locker->Unlock();
+#endif
+}
+
+void BGLView::EnableDirectMode( bool enabled )
+{
+ // TODO
+}
+
+
+
+//---- private methods ----------
+
+void BGLView::_ReservedGLView1() {}
+void BGLView::_ReservedGLView2() {}
+void BGLView::_ReservedGLView3() {}
+void BGLView::_ReservedGLView4() {}
+void BGLView::_ReservedGLView5() {}
+void BGLView::_ReservedGLView6() {}
+void BGLView::_ReservedGLView7() {}
+void BGLView::_ReservedGLView8() {}
+
+#if 0
+BGLView::BGLView(const BGLView &v)
+ : BView(v)
+{
+ // XXX not sure how this should work
+ printf("Warning BGLView::copy constructor not implemented\n");
+}
+#endif
+
+
+BGLView &BGLView::operator=(const BGLView &v)
+{
+ printf("Warning BGLView::operator= not implemented\n");
+ return *this;
+}
+
+void BGLView::dither_front()
+{
+ // no-op
+}
+
+bool BGLView::confirm_dither()
+{
+ // no-op
+ return false;
+}
+
+void BGLView::draw(BRect r)
+{
+ // XXX no-op ???
+}
+
+/* Direct Window stuff */
+void BGLView::drawScanline( int x1, int x2, int y, void *data )
+{
+ // no-op
+}
+
+void BGLView::scanlineHandler(struct rasStateRec *state,
+ GLint x1, GLint x2)
+{
+ // no-op
+}
+
+void BGLView::lock_draw()
+{
+ // no-op
+}
+
+void BGLView::unlock_draw()
+{
+ // no-op
+}
+
+bool BGLView::validateView()
+{
+ // no-op
+ return true;
+}
+
+// #pragma mark -
+
+MesaDriver::MesaDriver()
+{
+ m_glcontext = NULL;
+ m_glvisual = NULL;
+ m_glframebuffer = NULL;
+ m_bglview = NULL;
+ m_bitmap = NULL;
+
+ m_clear_color[BE_RCOMP] = 0;
+ m_clear_color[BE_GCOMP] = 0;
+ m_clear_color[BE_BCOMP] = 0;
+ m_clear_color[BE_ACOMP] = 0;
+
+ m_clear_index = 0;
+}
+
+
+MesaDriver::~MesaDriver()
+{
+ _mesa_destroy_visual(m_glvisual);
+ _mesa_destroy_framebuffer(m_glframebuffer);
+ _mesa_destroy_context(m_glcontext);
+
+}
+
+
+void MesaDriver::Init(BGLView * bglview, GLcontext * ctx, GLvisual * visual, GLframebuffer * framebuffer)
+{
+ m_bglview = bglview;
+ m_glcontext = ctx;
+ m_glvisual = visual;
+ m_glframebuffer = framebuffer;
+
+ MesaDriver * md = (MesaDriver *) ctx->DriverCtx;
+ struct swrast_device_driver * swdd = _swrast_GetDeviceDriverReference( ctx );
+ TNLcontext * tnl = TNL_CONTEXT(ctx);
+
+ assert(md->m_glcontext == ctx );
+
+ // Use default TCL pipeline
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ swdd->SetBuffer = this->SetBuffer;
+}
+
+
+void MesaDriver::LockGL()
+{
+ m_bglview->LockLooper();
+
+ UpdateState(m_glcontext, 0);
+ _mesa_make_current(m_glcontext, m_glframebuffer);
+}
+
+
+void MesaDriver::UnlockGL()
+{
+ if (m_bglview->Looper()->IsLocked())
+ m_bglview->UnlockLooper();
+ // Could call _mesa_make_current(NULL, NULL) but it would just
+ // hinder performance
+}
+
+
+void MesaDriver::SwapBuffers() const
+{
+ _mesa_notifySwapBuffers(m_glcontext);
+
+ if (m_bitmap) {
+ m_bglview->LockLooper();
+ m_bglview->DrawBitmap(m_bitmap);
+ m_bglview->UnlockLooper();
+ };
+}
+
+
+void MesaDriver::CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const
+{
+ if (m_bitmap) {
+ // Source bitmap and view's bitmap are same size.
+ // Source and dest rectangle are the same.
+ // Note (x,y) = (0,0) is the lower-left corner, have to flip Y
+ BRect srcAndDest;
+ srcAndDest.left = x;
+ srcAndDest.right = x + width - 1;
+ srcAndDest.bottom = m_bottom - y;
+ srcAndDest.top = srcAndDest.bottom - height + 1;
+ m_bglview->DrawBitmap(m_bitmap, srcAndDest, srcAndDest);
+ }
+}
+
+
+void MesaDriver::Draw(BRect updateRect) const
+{
+ if (m_bitmap)
+ m_bglview->DrawBitmap(m_bitmap, updateRect, updateRect);
+}
+
+
+void MesaDriver::UpdateState( GLcontext *ctx, GLuint new_state )
+{
+ struct swrast_device_driver * swdd = _swrast_GetDeviceDriverReference( ctx );
+
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ if (ctx->Color.DrawBuffer == GL_FRONT) {
+ /* read/write front buffer */
+ swdd->WriteRGBASpan = MesaDriver::WriteRGBASpanFront;
+ swdd->WriteRGBSpan = MesaDriver::WriteRGBSpanFront;
+ swdd->WriteRGBAPixels = MesaDriver::WriteRGBAPixelsFront;
+ swdd->WriteMonoRGBASpan = MesaDriver::WriteMonoRGBASpanFront;
+ swdd->WriteMonoRGBAPixels = MesaDriver::WriteMonoRGBAPixelsFront;
+ swdd->WriteCI32Span = MesaDriver::WriteCI32SpanFront;
+ swdd->WriteCI8Span = MesaDriver::WriteCI8SpanFront;
+ swdd->WriteMonoCISpan = MesaDriver::WriteMonoCISpanFront;
+ swdd->WriteCI32Pixels = MesaDriver::WriteCI32PixelsFront;
+ swdd->WriteMonoCIPixels = MesaDriver::WriteMonoCIPixelsFront;
+ swdd->ReadRGBASpan = MesaDriver::ReadRGBASpanFront;
+ swdd->ReadRGBAPixels = MesaDriver::ReadRGBAPixelsFront;
+ swdd->ReadCI32Span = MesaDriver::ReadCI32SpanFront;
+ swdd->ReadCI32Pixels = MesaDriver::ReadCI32PixelsFront;
+ }
+ else {
+ /* read/write back buffer */
+ swdd->WriteRGBASpan = MesaDriver::WriteRGBASpanBack;
+ swdd->WriteRGBSpan = MesaDriver::WriteRGBSpanBack;
+ swdd->WriteRGBAPixels = MesaDriver::WriteRGBAPixelsBack;
+ swdd->WriteMonoRGBASpan = MesaDriver::WriteMonoRGBASpanBack;
+ swdd->WriteMonoRGBAPixels = MesaDriver::WriteMonoRGBAPixelsBack;
+ swdd->WriteCI32Span = MesaDriver::WriteCI32SpanBack;
+ swdd->WriteCI8Span = MesaDriver::WriteCI8SpanBack;
+ swdd->WriteMonoCISpan = MesaDriver::WriteMonoCISpanBack;
+ swdd->WriteCI32Pixels = MesaDriver::WriteCI32PixelsBack;
+ swdd->WriteMonoCIPixels = MesaDriver::WriteMonoCIPixelsBack;
+ swdd->ReadRGBASpan = MesaDriver::ReadRGBASpanBack;
+ swdd->ReadRGBAPixels = MesaDriver::ReadRGBAPixelsBack;
+ swdd->ReadCI32Span = MesaDriver::ReadCI32SpanBack;
+ swdd->ReadCI32Pixels = MesaDriver::ReadCI32PixelsBack;
+ }
+}
+
+
+void MesaDriver::ClearIndex(GLcontext *ctx, GLuint index)
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ md->m_clear_index = index;
+}
+
+
+void MesaDriver::ClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_RCOMP], color[0]);
+ CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_GCOMP], color[1]);
+ CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_BCOMP], color[2]);
+ CLAMPED_FLOAT_TO_CHAN(md->m_clear_color[BE_ACOMP], color[3]);
+ assert(md->m_bglview);
+}
+
+
+void MesaDriver::Clear(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height)
+{
+ if (mask & DD_FRONT_LEFT_BIT)
+ ClearFront(ctx, all, x, y, width, height);
+ if (mask & DD_BACK_LEFT_BIT)
+ ClearBack(ctx, all, x, y, width, height);
+
+ mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+
+ return;
+}
+
+
+void MesaDriver::ClearFront(GLcontext *ctx,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height)
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+
+ bglview->SetHighColor(md->m_clear_color[BE_RCOMP],
+ md->m_clear_color[BE_GCOMP],
+ md->m_clear_color[BE_BCOMP],
+ md->m_clear_color[BE_ACOMP]);
+ bglview->SetLowColor(md->m_clear_color[BE_RCOMP],
+ md->m_clear_color[BE_GCOMP],
+ md->m_clear_color[BE_BCOMP],
+ md->m_clear_color[BE_ACOMP]);
+ if (all) {
+ BRect b = bglview->Bounds();
+ bglview->FillRect(b);
+ }
+ else {
+ // XXX untested
+ BRect b;
+ b.left = x;
+ b.right = x + width;
+ b.bottom = md->m_height - y - 1;
+ b.top = b.bottom - height;
+ bglview->FillRect(b);
+ }
+
+ // restore drawing color
+#if 0
+ bglview->SetHighColor(md->mColor[BE_RCOMP],
+ md->mColor[BE_GCOMP],
+ md->mColor[BE_BCOMP],
+ md->mColor[BE_ACOMP]);
+ bglview->SetLowColor(md->mColor[BE_RCOMP],
+ md->mColor[BE_GCOMP],
+ md->mColor[BE_BCOMP],
+ md->mColor[BE_ACOMP]);
+#endif
+}
+
+
+void MesaDriver::ClearBack(GLcontext *ctx,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height)
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ BBitmap *bitmap = md->m_bitmap;
+ assert(bitmap);
+ GLuint *start = (GLuint *) bitmap->Bits();
+ const GLuint *clearPixelPtr = (const GLuint *) md->m_clear_color;
+ const GLuint clearPixel = B_LENDIAN_TO_HOST_INT32(*clearPixelPtr);
+
+ if (all) {
+ const int numPixels = md->m_width * md->m_height;
+ if (clearPixel == 0) {
+ memset(start, 0, numPixels * 4);
+ }
+ else {
+ for (int i = 0; i < numPixels; i++) {
+ start[i] = clearPixel;
+ }
+ }
+ }
+ else {
+ // XXX untested
+ start += y * md->m_width + x;
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ start[j] = clearPixel;
+ }
+ start += md->m_width;
+ }
+ }
+}
+
+
+void MesaDriver::SetBuffer(GLcontext *ctx, GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* TODO */
+ (void) ctx;
+ (void) buffer;
+ (void) mode;
+}
+
+void MesaDriver::GetBufferSize(GLframebuffer * framebuffer, GLuint *width,
+ GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (!ctx)
+ return;
+
+ MesaDriver * md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+
+ BRect b = bglview->Bounds();
+ *width = (GLuint) b.IntegerWidth() + 1; // (b.right - b.left + 1);
+ *height = (GLuint) b.IntegerHeight() + 1; // (b.bottom - b.top + 1);
+ md->m_bottom = (GLint) b.bottom;
+
+ if (ctx->Visual.doubleBufferMode) {
+ if (*width != md->m_width || *height != md->m_height) {
+ // allocate new size of back buffer bitmap
+ if (md->m_bitmap)
+ delete md->m_bitmap;
+ BRect rect(0.0, 0.0, *width - 1, *height - 1);
+ md->m_bitmap = new BBitmap(rect, B_RGBA32);
+ }
+ }
+ else
+ {
+ md->m_bitmap = NULL;
+ }
+
+ md->m_width = *width;
+ md->m_height = *height;
+}
+
+
+const GLubyte *MesaDriver::GetString(GLcontext *ctx, GLenum name)
+{
+ switch (name) {
+ case GL_RENDERER:
+ return (const GLubyte *) "Mesa BGLView (software)";
+ default:
+ // Let core library handle all other cases
+ return NULL;
+ }
+}
+
+
+// Plot a pixel. (0,0) is upper-left corner
+// This is only used when drawing to the front buffer.
+inline void Plot(BGLView *bglview, int x, int y)
+{
+ // XXX There's got to be a better way!
+ BPoint p(x, y), q(x+1, y);
+ bglview->StrokeLine(p, q);
+}
+
+
+void MesaDriver::WriteRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ int flippedY = md->m_bottom - y;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void MesaDriver::WriteRGBSpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ int flippedY = md->m_bottom - y;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void MesaDriver::WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ int flippedY = md->m_bottom - y;
+ bglview->SetHighColor(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void MesaDriver::WriteRGBAPixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x[i], md->m_bottom - y[i]);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x[i], md->m_bottom - y[i]);
+ }
+ }
+}
+
+
+void MesaDriver::WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BGLView *bglview = md->m_bglview;
+ assert(bglview);
+ // plot points using current color
+ bglview->SetHighColor(color[RCOMP], color[GCOMP], color[BCOMP]);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ Plot(bglview, x[i], md->m_bottom - y[i]);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ Plot(bglview, x[i], md->m_bottom - y[i]);
+ }
+ }
+}
+
+
+void MesaDriver::WriteCI32SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ printf("WriteCI32SpanFront() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteCI8SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ printf("WriteCI8SpanFront() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteMonoCISpanFront( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ printf("WriteMonoCISpanFront() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::WriteCI32PixelsFront( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ printf("WriteCI32PixelsFront() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteMonoCIPixelsFront( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ printf("WriteMonoCIPixelsFront() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadCI32SpanFront( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ printf("ReadCI32SpanFront() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadRGBASpanFront( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLubyte rgba[][4] )
+{
+ printf("ReadRGBASpanFront() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadCI32PixelsFront( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ printf("ReadCI32PixelsFront() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadRGBAPixelsFront( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ printf("ReadRGBAPixelsFront() not implemented yet!\n");
+ // TODO
+}
+
+
+
+
+void MesaDriver::WriteRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BBitmap *bitmap = md->m_bitmap;
+
+ assert(bitmap);
+
+ int row = md->m_bottom - y;
+ uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4;
+ uint32 * pixel = (uint32 *) ptr;
+
+ if (mask) {
+ while(n--) {
+ if (*mask++)
+ *pixel = PACK_B_RGBA32(rgba[0]);
+ pixel++;
+ rgba++;
+ };
+ } else {
+ while(n--) {
+ *pixel++ = PACK_B_RGBA32(rgba[0]);
+ rgba++;
+ };
+ };
+ }
+
+
+void MesaDriver::WriteRGBSpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgb[][3],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BBitmap *bitmap = md->m_bitmap;
+
+ assert(bitmap);
+
+ int row = md->m_bottom - y;
+ uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4;
+ uint32 * pixel = (uint32 *) ptr;
+
+ if (mask) {
+ while(n--) {
+ if (*mask++)
+ *pixel = PACK_B_RGB32(rgb[0]);
+ pixel++;
+ rgb++;
+ };
+ } else {
+ while(n--) {
+ *pixel++ = PACK_B_RGB32(rgb[0]);
+ rgb++;
+ };
+ };
+}
+
+
+
+
+void MesaDriver::WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BBitmap *bitmap = md->m_bitmap;
+
+ assert(bitmap);
+
+ int row = md->m_bottom - y;
+ uint8 * ptr = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + x * 4;
+ uint32 * pixel = (uint32 *) ptr;
+ uint32 pixel_color = PACK_B_RGBA32(color);
+
+ if (mask) {
+ while(n--) {
+ if (*mask++)
+ *pixel = pixel_color;
+ pixel++;
+ };
+ } else {
+ while(n--) {
+ *pixel++ = pixel_color;
+ };
+ };
+}
+
+
+void MesaDriver::WriteRGBAPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BBitmap *bitmap = md->m_bitmap;
+
+ assert(bitmap);
+#if 0
+ while(n--) {
+ if (*mask++) {
+ int row = md->m_bottom - *y;
+ uint8 * pixel = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + *x * 4;
+ *((uint32 *) pixel) = PACK_B_RGBA32(rgba[0]);
+ };
+ x++;
+ y++;
+ rgba++;
+ };
+#else
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ }
+ }
+#endif
+}
+
+
+void MesaDriver::WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[])
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ BBitmap *bitmap = md->m_bitmap;
+
+ assert(bitmap);
+
+ uint32 pixel_color = PACK_B_RGBA32(color);
+#if 0
+ while(n--) {
+ if (*mask++) {
+ int row = md->m_bottom - *y;
+ uint8 * pixel = (uint8 *) bitmap->Bits() + (row * bitmap->BytesPerRow()) + *x * 4;
+
+ *((uint32 *) pixel) = pixel_color;
+ };
+ x++;
+ y++;
+ };
+#else
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ GLubyte * ptr = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ *((uint32 *) ptr) = pixel_color;
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ GLubyte * ptr = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ *((uint32 *) ptr) = pixel_color;
+ }
+ }
+#endif
+}
+
+
+void MesaDriver::WriteCI32SpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ printf("WriteCI32SpanBack() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteCI8SpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ printf("WriteCI8SpanBack() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteMonoCISpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ printf("WriteMonoCISpanBack() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::WriteCI32PixelsBack( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ printf("WriteCI32PixelsBack() not implemented yet!\n");
+ // TODO
+}
+
+void MesaDriver::WriteMonoCIPixelsBack( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ printf("WriteMonoCIPixelsBack() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadCI32SpanBack( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ printf("ReadCI32SpanBack() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadRGBASpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLubyte rgba[][4] )
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ const BBitmap *bitmap = md->m_bitmap;
+ assert(bitmap);
+ int row = md->m_bottom - y;
+ const GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + (row * bitmap->BytesPerRow()) + x * 4;
+
+ for (GLuint i = 0; i < n; i++) {
+ rgba[i][RCOMP] = pixel[BE_RCOMP];
+ rgba[i][GCOMP] = pixel[BE_GCOMP];
+ rgba[i][BCOMP] = pixel[BE_BCOMP];
+ rgba[i][ACOMP] = pixel[BE_ACOMP];
+ pixel += 4;
+ }
+}
+
+
+void MesaDriver::ReadCI32PixelsBack( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ printf("ReadCI32PixelsBack() not implemented yet!\n");
+ // TODO
+}
+
+
+void MesaDriver::ReadRGBAPixelsBack( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ MesaDriver *md = (MesaDriver *) ctx->DriverCtx;
+ const BBitmap *bitmap = md->m_bitmap;
+ assert(bitmap);
+
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ rgba[i][RCOMP] = pixel[BE_RCOMP];
+ rgba[i][GCOMP] = pixel[BE_GCOMP];
+ rgba[i][BCOMP] = pixel[BE_BCOMP];
+ rgba[i][ACOMP] = pixel[BE_ACOMP];
+ };
+ };
+ } else {
+ for (GLuint i = 0; i < n; i++) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + ((md->m_bottom - y[i]) * bitmap->BytesPerRow()) + x[i] * 4;
+ rgba[i][RCOMP] = pixel[BE_RCOMP];
+ rgba[i][GCOMP] = pixel[BE_GCOMP];
+ rgba[i][BCOMP] = pixel[BE_BCOMP];
+ rgba[i][ACOMP] = pixel[BE_ACOMP];
+ };
+ };
+}
+
+
+
diff --git a/src/mesa/drivers/beos/Makefile b/src/mesa/drivers/beos/Makefile
new file mode 100644
index 0000000..3b1038b
--- /dev/null
+++ b/src/mesa/drivers/beos/Makefile
@@ -0,0 +1,195 @@
+# src/mesa/drivers/beos/Makefile
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+include $(TOP)/src/mesa/sources
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+# To switch back to old Mesa GLU implementation (but why do
+# you want this!), uncomment this next line:
+
+# GLU_DIR = $(TOP)/src/glu/mesa
+ifeq ($(GLU_DIR),)
+ # By default, we build the SGI GLU implementation
+ GLU_DIR = $(TOP)/src/glu/sgi
+endif
+
+ifeq ($(GLU_DIR), $(TOP)/src/glu/mesa)
+ GLU_MODULES = \
+ $(GLU_DIR)/glu.o \
+ $(GLU_DIR)/mipmap.o \
+ $(GLU_DIR)/nurbs.o \
+ $(GLU_DIR)/nurbscrv.o \
+ $(GLU_DIR)/nurbssrf.o \
+ $(GLU_DIR)/nurbsutl.o \
+ $(GLU_DIR)/polytest.o \
+ $(GLU_DIR)/project.o \
+ $(GLU_DIR)/quadric.o \
+ $(GLU_DIR)/tess.o \
+ $(GLU_DIR)/tesselat.o
+else
+ GLU_MODULES = \
+ $(GLU_DIR)/libutil/error.o \
+ $(GLU_DIR)/libutil/glue.o \
+ $(GLU_DIR)/libutil/mipmap.o \
+ $(GLU_DIR)/libutil/project.o \
+ $(GLU_DIR)/libutil/quad.o \
+ $(GLU_DIR)/libutil/registry.o \
+ $(GLU_DIR)/libtess/dict.o \
+ $(GLU_DIR)/libtess/geom.o \
+ $(GLU_DIR)/libtess/memalloc.o \
+ $(GLU_DIR)/libtess/mesh.o \
+ $(GLU_DIR)/libtess/normal.o \
+ $(GLU_DIR)/libtess/priorityq.o \
+ $(GLU_DIR)/libtess/render.o \
+ $(GLU_DIR)/libtess/sweep.o \
+ $(GLU_DIR)/libtess/tess.o \
+ $(GLU_DIR)/libtess/tessmono.o \
+ $(GLU_DIR)/libnurbs/interface/bezierEval.o \
+ $(GLU_DIR)/libnurbs/interface/bezierPatch.o \
+ $(GLU_DIR)/libnurbs/interface/bezierPatchMesh.o \
+ $(GLU_DIR)/libnurbs/interface/glcurveval.o \
+ $(GLU_DIR)/libnurbs/interface/glinterface.o \
+ $(GLU_DIR)/libnurbs/interface/glrenderer.o \
+ $(GLU_DIR)/libnurbs/interface/glsurfeval.o \
+ $(GLU_DIR)/libnurbs/interface/incurveeval.o \
+ $(GLU_DIR)/libnurbs/interface/insurfeval.o \
+ $(GLU_DIR)/libnurbs/internals/arc.o \
+ $(GLU_DIR)/libnurbs/internals/arcsorter.o \
+ $(GLU_DIR)/libnurbs/internals/arctess.o \
+ $(GLU_DIR)/libnurbs/internals/backend.o \
+ $(GLU_DIR)/libnurbs/internals/basiccrveval.o \
+ $(GLU_DIR)/libnurbs/internals/basicsurfeval.o \
+ $(GLU_DIR)/libnurbs/internals/bin.o \
+ $(GLU_DIR)/libnurbs/internals/bufpool.o \
+ $(GLU_DIR)/libnurbs/internals/cachingeval.o \
+ $(GLU_DIR)/libnurbs/internals/ccw.o \
+ $(GLU_DIR)/libnurbs/internals/coveandtiler.o \
+ $(GLU_DIR)/libnurbs/internals/curve.o \
+ $(GLU_DIR)/libnurbs/internals/curvelist.o \
+ $(GLU_DIR)/libnurbs/internals/curvesub.o \
+ $(GLU_DIR)/libnurbs/internals/dataTransform.o \
+ $(GLU_DIR)/libnurbs/internals/displaylist.o \
+ $(GLU_DIR)/libnurbs/internals/flist.o \
+ $(GLU_DIR)/libnurbs/internals/flistsorter.o \
+ $(GLU_DIR)/libnurbs/internals/hull.o \
+ $(GLU_DIR)/libnurbs/internals/intersect.o \
+ $(GLU_DIR)/libnurbs/internals/knotvector.o \
+ $(GLU_DIR)/libnurbs/internals/mapdesc.o \
+ $(GLU_DIR)/libnurbs/internals/mapdescv.o \
+ $(GLU_DIR)/libnurbs/internals/maplist.o \
+ $(GLU_DIR)/libnurbs/internals/mesher.o \
+ $(GLU_DIR)/libnurbs/internals/monoTriangulationBackend.o \
+ $(GLU_DIR)/libnurbs/internals/monotonizer.o \
+ $(GLU_DIR)/libnurbs/internals/mycode.o \
+ $(GLU_DIR)/libnurbs/internals/nurbsinterfac.o \
+ $(GLU_DIR)/libnurbs/internals/nurbstess.o \
+ $(GLU_DIR)/libnurbs/internals/patch.o \
+ $(GLU_DIR)/libnurbs/internals/patchlist.o \
+ $(GLU_DIR)/libnurbs/internals/quilt.o \
+ $(GLU_DIR)/libnurbs/internals/reader.o \
+ $(GLU_DIR)/libnurbs/internals/renderhints.o \
+ $(GLU_DIR)/libnurbs/internals/slicer.o \
+ $(GLU_DIR)/libnurbs/internals/sorter.o \
+ $(GLU_DIR)/libnurbs/internals/splitarcs.o \
+ $(GLU_DIR)/libnurbs/internals/subdivider.o \
+ $(GLU_DIR)/libnurbs/internals/tobezier.o \
+ $(GLU_DIR)/libnurbs/internals/trimline.o \
+ $(GLU_DIR)/libnurbs/internals/trimregion.o \
+ $(GLU_DIR)/libnurbs/internals/trimvertpool.o \
+ $(GLU_DIR)/libnurbs/internals/uarray.o \
+ $(GLU_DIR)/libnurbs/internals/varray.o \
+ $(GLU_DIR)/libnurbs/nurbtess/directedLine.o \
+ $(GLU_DIR)/libnurbs/nurbtess/gridWrap.o \
+ $(GLU_DIR)/libnurbs/nurbtess/monoChain.o \
+ $(GLU_DIR)/libnurbs/nurbtess/monoPolyPart.o \
+ $(GLU_DIR)/libnurbs/nurbtess/monoTriangulation.o \
+ $(GLU_DIR)/libnurbs/nurbtess/partitionX.o \
+ $(GLU_DIR)/libnurbs/nurbtess/partitionY.o \
+ $(GLU_DIR)/libnurbs/nurbtess/polyDBG.o \
+ $(GLU_DIR)/libnurbs/nurbtess/polyUtil.o \
+ $(GLU_DIR)/libnurbs/nurbtess/primitiveStream.o \
+ $(GLU_DIR)/libnurbs/nurbtess/quicksort.o \
+ $(GLU_DIR)/libnurbs/nurbtess/rectBlock.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampleComp.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampleCompBot.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampleCompRight.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampleCompTop.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampleMonoPoly.o \
+ $(GLU_DIR)/libnurbs/nurbtess/sampledLine.o \
+ $(GLU_DIR)/libnurbs/nurbtess/searchTree.o
+endif
+
+INCLUDES = \
+ -I../common \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/array_cache \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/math \
+ -I$(TOP)/src/mesa/shader \
+ -I$(TOP)/src/mesa/swrast \
+ -I$(TOP)/src/mesa/swrast_setup \
+ -I$(TOP)/src/mesa/tnl \
+ -I$(TOP)/src/mesa/tnl_dd \
+ -I$(TOP)/src/mesa/x86 \
+ -I. \
+ -I- \
+ -I$(TOP)/include
+
+DRIVER_SOURCES = \
+ GLView.cpp \
+ ../common/driverfuncs.c \
+ $(addprefix ../../, $(GLAPI_SOURCES))
+
+ifeq ($(CPU), x86)
+ DRIVER_SOURCES += $(addprefix ../../, $(X86_API))
+else
+ # No GL API PPC optimization yet
+endif
+
+DRIVER_OBJECTS = $(DRIVER_SOURCES:.c=.o)
+DRIVER_OBJECTS := $(DRIVER_OBJECTS:.S=.o)
+
+OBJECTS := $(DRIVER_OBJECTS:.cpp=.o)
+
+
+# Rules
+
+.c.o:
+ $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
+
+.S.o:
+ $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
+
+
+default: depend $(LIB_DIR) $(LIB_DIR)/$(GL_LIB_NAME)
+
+$(MESA_MODULES):
+ cd $(TOP)/src/mesa; $(MAKE) mesa.a ;
+
+$(GLU_MODULES):
+ cd $(GLU_DIR); $(MAKE) $(subst $(GLU_DIR)/,,$(GLU_MODULES)) ;
+
+$(LIB_DIR):
+ mkdir $(LIB_DIR)
+
+$(LIB_DIR)/$(GL_LIB_NAME): $(OBJECTS) $(MESA_MODULES) $(GLU_MODULES)
+ @$(TOP)/bin/mklib -o $(GL_LIB) -install $(LIB_DIR) -major $(MESA_MAJOR) -minor $(MESA_MINOR) -patch $(MESA_TINY) \
+ $(MKLIB_OPTIONS) $(GL_LIB_DEPS) $(OBJECTS) $(MESA_MODULES) $(GLU_MODULES)
+
+# $(GLU_OBJECTS):
+# cd $(GLU_DIR); $(MAKE) $< ;
+
+depend: $(DRIVER_SOURCES) $(GLU_SOURCES)
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) $(DRIVER_SOURCES) $(GLU_SOURCES) > /dev/null 2>&1
+
+clean:
+ rm -f depend $(OBJECTS)
+
+include depend
diff --git a/src/mesa/drivers/common/descrip.mms b/src/mesa/drivers/common/descrip.mms
new file mode 100644
index 0000000..aa4b8ae
--- /dev/null
+++ b/src/mesa/drivers/common/descrip.mms
@@ -0,0 +1,37 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
+# Last revision : 16 June 2003
+
+.first
+ define gl [----.include.gl]
+ define math [--.math]
+ define swrast [--.swrast]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi],[--.shader]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)
+
+SOURCES = driverfuncs.c
+
+OBJECTS =driverfuncs.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+driverfuncs.obj : driverfuncs.c
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
new file mode 100644
index 0000000..a51f650
--- /dev/null
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -0,0 +1,211 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "buffers.h"
+#include "context.h"
+#include "program.h"
+#include "texcompress.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "texstore.h"
+#include "bufferobj.h"
+
+#include "driverfuncs.h"
+#include "swrast/swrast.h"
+
+
+
+/**
+ * Plug in default functions for all pointers in the dd_function_table
+ * structure.
+ * Device drivers should call this function and then plug in any
+ * functions which it wants to override.
+ * Some functions (pointers) MUST be implemented by all drivers (REQUIRED).
+ *
+ * \param table the dd_function_table to initialize
+ */
+void
+_mesa_init_driver_functions(struct dd_function_table *driver)
+{
+ _mesa_bzero(driver, sizeof(*driver));
+
+ driver->GetString = NULL; /* REQUIRED! */
+ driver->UpdateState = NULL; /* REQUIRED! */
+ driver->GetBufferSize = NULL; /* REQUIRED! */
+ driver->ResizeBuffers = _swrast_alloc_buffers;
+ driver->Error = NULL;
+
+ driver->Finish = NULL;
+ driver->Flush = NULL;
+
+ /* framebuffer/image functions */
+ driver->Clear = _swrast_Clear;
+ driver->Accum = _swrast_Accum;
+ driver->DrawPixels = _swrast_DrawPixels;
+ driver->ReadPixels = _swrast_ReadPixels;
+ driver->CopyPixels = _swrast_CopyPixels;
+ driver->Bitmap = _swrast_Bitmap;
+
+ /* Texture functions */
+ driver->ChooseTextureFormat = _mesa_choose_tex_format;
+ driver->TexImage1D = _mesa_store_teximage1d;
+ driver->TexImage2D = _mesa_store_teximage2d;
+ driver->TexImage3D = _mesa_store_teximage3d;
+ driver->TexSubImage1D = _mesa_store_texsubimage1d;
+ driver->TexSubImage2D = _mesa_store_texsubimage2d;
+ driver->TexSubImage3D = _mesa_store_texsubimage3d;
+ driver->CopyTexImage1D = _swrast_copy_teximage1d;
+ driver->CopyTexImage2D = _swrast_copy_teximage2d;
+ driver->CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ driver->CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ driver->CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ driver->TestProxyTexImage = _mesa_test_proxy_teximage;
+ driver->CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+ driver->CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+ driver->CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+ driver->CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+ driver->CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+ driver->CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+ driver->CompressedTextureSize = _mesa_compressed_texture_size;
+ driver->BindTexture = NULL;
+ driver->NewTextureObject = _mesa_new_texture_object;
+ driver->DeleteTexture = _mesa_delete_texture_object;
+ driver->NewTextureImage = _mesa_new_texture_image;
+ driver->IsTextureResident = NULL;
+ driver->PrioritizeTexture = NULL;
+ driver->ActiveTexture = NULL;
+ driver->UpdateTexturePalette = NULL;
+
+ /* imaging */
+ driver->CopyColorTable = _swrast_CopyColorTable;
+ driver->CopyColorSubTable = _swrast_CopyColorSubTable;
+ driver->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ driver->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ /* Vertex/fragment programs */
+ driver->BindProgram = NULL;
+ driver->NewProgram = _mesa_new_program;
+ driver->DeleteProgram = _mesa_delete_program;
+
+ /* simple state commands */
+ driver->AlphaFunc = NULL;
+ driver->BlendColor = NULL;
+ driver->BlendEquationSeparate = NULL;
+ driver->BlendFuncSeparate = NULL;
+ driver->ClearColor = NULL;
+ driver->ClearDepth = NULL;
+ driver->ClearIndex = NULL;
+ driver->ClearStencil = NULL;
+ driver->ClipPlane = NULL;
+ driver->ColorMask = NULL;
+ driver->ColorMaterial = NULL;
+ driver->CullFace = NULL;
+ driver->DrawBuffer = _swrast_DrawBuffer;
+ driver->FrontFace = NULL;
+ driver->DepthFunc = NULL;
+ driver->DepthMask = NULL;
+ driver->DepthRange = NULL;
+ driver->Enable = NULL;
+ driver->Fogfv = NULL;
+ driver->Hint = NULL;
+ driver->IndexMask = NULL;
+ driver->Lightfv = NULL;
+ driver->LightModelfv = NULL;
+ driver->LineStipple = NULL;
+ driver->LineWidth = NULL;
+ driver->LogicOpcode = NULL;
+ driver->PointParameterfv = NULL;
+ driver->PointSize = NULL;
+ driver->PolygonMode = NULL;
+ driver->PolygonOffset = NULL;
+ driver->PolygonStipple = NULL;
+ driver->ReadBuffer = NULL;
+ driver->RenderMode = NULL;
+ driver->Scissor = NULL;
+ driver->ShadeModel = NULL;
+ driver->StencilFunc = NULL;
+ driver->StencilMask = NULL;
+ driver->StencilOp = NULL;
+ driver->ActiveStencilFace = NULL;
+ driver->TexGen = NULL;
+ driver->TexEnv = NULL;
+ driver->TexParameter = NULL;
+ driver->TextureMatrix = NULL;
+ driver->Viewport = NULL;
+
+ /* vertex arrays */
+ driver->VertexPointer = NULL;
+ driver->NormalPointer = NULL;
+ driver->ColorPointer = NULL;
+ driver->FogCoordPointer = NULL;
+ driver->IndexPointer = NULL;
+ driver->SecondaryColorPointer = NULL;
+ driver->TexCoordPointer = NULL;
+ driver->EdgeFlagPointer = NULL;
+ driver->VertexAttribPointer = NULL;
+ driver->LockArraysEXT = NULL;
+ driver->UnlockArraysEXT = NULL;
+
+ /* state queries */
+ driver->GetBooleanv = NULL;
+ driver->GetDoublev = NULL;
+ driver->GetFloatv = NULL;
+ driver->GetIntegerv = NULL;
+ driver->GetPointerv = NULL;
+
+#if FEATURE_ARB_vertex_buffer_object
+ driver->NewBufferObject = _mesa_new_buffer_object;
+ driver->DeleteBuffer = _mesa_delete_buffer_object;
+ driver->BindBuffer = NULL;
+ driver->BufferData = _mesa_buffer_data;
+ driver->BufferSubData = _mesa_buffer_subdata;
+ driver->GetBufferSubData = _mesa_buffer_get_subdata;
+ driver->MapBuffer = _mesa_buffer_map;
+ driver->UnmapBuffer = NULL;
+#endif
+
+ /* T&L stuff */
+ driver->NeedValidate = GL_FALSE;
+ driver->ValidateTnlModule = NULL;
+ driver->CurrentExecPrimitive = 0;
+ driver->CurrentSavePrimitive = 0;
+ driver->NeedFlush = 0;
+ driver->SaveNeedFlush = 0;
+
+ driver->FlushVertices = NULL;
+ driver->SaveFlushVertices = NULL;
+ driver->NotifySaveBegin = NULL;
+ driver->LightingSpaceChange = NULL;
+ driver->MakeCurrent = NULL;
+
+ /* display list */
+ driver->NewList = NULL;
+ driver->EndList = NULL;
+ driver->BeginCallList = NULL;
+ driver->EndCallList = NULL;
+}
diff --git a/src/mesa/drivers/common/driverfuncs.h b/src/mesa/drivers/common/driverfuncs.h
new file mode 100644
index 0000000..64f56d9
--- /dev/null
+++ b/src/mesa/drivers/common/driverfuncs.h
@@ -0,0 +1,32 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+#ifndef DRIVERFUNCS_H
+#define DRIVERFUNCS_H
+
+extern void
+_mesa_init_driver_functions(struct dd_function_table *driver);
+
+#endif
diff --git a/src/mesa/drivers/dos/blit.S b/src/mesa/drivers/dos/blit.S
new file mode 100644
index 0000000..d0a5a72
--- /dev/null
+++ b/src/mesa/drivers/dos/blit.S
@@ -0,0 +1,210 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.4 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include "x86/assyntax.h"
+
+
+ FILE("blit.S")
+
+/*
+ * extern unsigned int vesa_gran_mask, vesa_gran_shift;
+ * extern int vl_video_selector;
+
+ * extern void *vl_current_draw_buffer;
+ * extern int vl_current_stride, vl_current_height;
+ * extern int vl_current_offset, vl_current_delta;
+ */
+EXTERN _vesa_gran_mask, _vesa_gran_shift
+EXTERN _vl_video_selector
+
+EXTERN _vl_current_draw_buffer
+EXTERN _vl_current_stride, _vl_current_height
+EXTERN _vl_current_offset, _vl_current_delta
+
+ SEG_TEXT
+ USE32
+
+/* Desc: VESA bank switching routine (BIOS)
+ *
+ * In : EBX=0, EDX = bank number
+ * Out : -
+ *
+ * Note: thrashes EAX
+ */
+ ALIGNTEXT32
+_vesa_swbankBIOS:
+ MOV_W (CONST(0x4f05), AX)
+ INT (CONST(0x10))
+ RET
+
+ ALIGNTEXT8
+ GLOBL _vesa_swbank
+_vesa_swbank: D_LONG _vesa_swbankBIOS
+
+/* Desc: void vesa_b_dump_virtual (void);
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _vesa_b_dump_virtual
+_vesa_b_dump_virtual:
+ CLD
+ PUSH_SR (ES)
+ PUSH_L (EBX)
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ PUSH_L (EBP)
+ MOV_SR (CONTENT(_vl_video_selector), ES)
+ MOV_L (CONTENT(_vl_current_draw_buffer), ESI)
+ MOV_L (CONTENT(_vl_current_offset), EDI)
+ MOV_L (CONTENT(_vesa_gran_shift), ECX)
+ MOV_L (CONTENT(_vesa_gran_mask), EBP)
+ MOV_L (EDI, EDX)
+ XOR_L (EBX, EBX)
+ AND_L (EBP, EDI)
+ SHR_L (CL, EDX)
+ INC_L (EBP)
+ CALL (VARINDIRECT(_vesa_swbank))
+ MOV_L (CONTENT(_vl_current_stride), ECX)
+ MOV_L (CONTENT(_vl_current_height), EAX)
+ MOV_L (CONTENT(_vl_current_delta), EBX)
+ SHR_L (CONST(2), ECX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ CMP_L (EBP, EDI)
+ jb 2f
+ PUSH_L (EAX)
+ PUSH_L (EBX)
+ INC_L (EDX)
+ XOR_L (EBX, EBX)
+ CALL (VARINDIRECT(_vesa_swbank))
+ POP_L (EBX)
+ POP_L (EAX)
+ SUB_L (EBP, EDI)
+ ALIGNTEXT4
+ 2:
+ MOVS_L
+ DEC_L (ECX)
+ jnz 1b
+ POP_L (ECX)
+ ADD_L (EBX, EDI)
+ DEC_L (EAX)
+ jnz 0b
+ POP_L (EBP)
+ POP_L (EDI)
+ POP_L (ESI)
+ POP_L (EBX)
+ POP_SR (ES)
+ RET
+
+/* Desc: void vesa_l_dump_virtual (void);
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _vesa_l_dump_virtual
+_vesa_l_dump_virtual:
+ CLD
+ PUSH_SR (ES)
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_SR (CONTENT(_vl_video_selector), ES)
+ MOV_L (CONTENT(_vl_current_draw_buffer), ESI)
+ MOV_L (CONTENT(_vl_current_offset), EDI)
+ MOV_L (CONTENT(_vl_current_stride), ECX)
+ MOV_L (CONTENT(_vl_current_height), EDX)
+ MOV_L (CONTENT(_vl_current_delta), EAX)
+ SHR_L (CONST(2), ECX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ REP MOVS_L
+ POP_L (ECX)
+ ADD_L (EAX, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EDI)
+ POP_L (ESI)
+ POP_SR (ES)
+ RET
+
+/* Desc: void vesa_l_dump_virtual_mmx (void);
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _vesa_l_dump_virtual_mmx
+_vesa_l_dump_virtual_mmx:
+#ifdef USE_MMX_ASM
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_SR (CONTENT(_vl_video_selector), FS)
+ MOV_L (CONTENT(_vl_current_draw_buffer), ESI)
+ MOV_L (CONTENT(_vl_current_offset), EDI)
+ MOV_L (CONTENT(_vl_current_stride), ECX)
+ MOV_L (CONTENT(_vl_current_height), EDX)
+ MOV_L (CONTENT(_vl_current_delta), EAX)
+ SHR_L (CONST(3), ECX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ MOVQ (REGIND(ESI), MM0)
+ ADD_L (CONST(8), ESI)
+ SEGFS
+ MOVQ (MM0, REGIND(EDI))
+ ADD_L (CONST(8), EDI)
+ DEC_L (ECX)
+ jnz 1b
+ POP_L (ECX)
+ ADD_L (EAX, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EDI)
+ POP_L (ESI)
+ EMMS
+#endif
+ RET
diff --git a/src/mesa/drivers/dos/dmesa.c b/src/mesa/drivers/dos/dmesa.c
new file mode 100644
index 0000000..78abb2f
--- /dev/null
+++ b/src/mesa/drivers/dos/dmesa.c
@@ -0,0 +1,1384 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.6 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 "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"
+
+
+
+/*
+ * 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, 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, 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,
+ 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, 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,
+ 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,
+ 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,
+ 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 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 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->Flush = flush;
+ driver->Finish = finish;
+ driver->Clear = clear;
+ driver->ClearColor = clear_color;
+ driver->ClearIndex = clear_index;
+}
+
+
+
+/* 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);
+
+ /* 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);
+ if (((GLcontext *)c)->Viewport.Width == 0) {
+ /* initialize viewport to window size */
+ _mesa_Viewport(0, 0, b->width, b->height);
+ }
+ } 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;
+ }
+ }
+ }
+ #else
+ return -1;
+ #endif
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/mesa/drivers/dos/dpmi.c b/src/mesa/drivers/dos/dpmi.c
new file mode 100644
index 0000000..f9943ea
--- /dev/null
+++ b/src/mesa/drivers/dos/dpmi.c
@@ -0,0 +1,148 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.4 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include <dpmi.h>
+
+#include "internal.h"
+
+
+
+#ifndef MAX
+#define MAX(x, y) (((x)<(y))?(y):(x))
+#endif
+
+
+
+/* _create_linear_mapping:
+ * Maps a physical address range into linear memory.
+ */
+int _create_linear_mapping (unsigned long *linear, unsigned long physaddr, int size)
+{
+ __dpmi_meminfo meminfo;
+
+ if (physaddr >= 0x100000) {
+ /* map into linear memory */
+ meminfo.address = physaddr;
+ meminfo.size = size;
+ if (__dpmi_physical_address_mapping(&meminfo) != 0)
+ return -1;
+
+ *linear = meminfo.address;
+ } else {
+ /* exploit 1 -> 1 physical to linear mapping in low megabyte */
+ *linear = physaddr;
+ }
+
+ return 0;
+}
+
+
+
+/* _remove_linear_mapping:
+ * Frees the DPMI resources being used to map a linear address range.
+ */
+void _remove_linear_mapping (unsigned long *linear)
+{
+ __dpmi_meminfo meminfo;
+
+ if (*linear) {
+ if (*linear >= 0x100000) {
+ meminfo.address = *linear;
+ __dpmi_free_physical_address_mapping(&meminfo);
+ }
+
+ *linear = 0;
+ }
+}
+
+
+
+/* _create_selector:
+ * Allocates a selector to access a region of linear memory.
+ */
+int _create_selector (int *segment, unsigned long base, int size)
+{
+ /* allocate an ldt descriptor */
+ if ((*segment=__dpmi_allocate_ldt_descriptors(1)) < 0) {
+ *segment = 0;
+ return -1;
+ }
+
+ /* create the linear mapping */
+ if (_create_linear_mapping(&base, base, size)) {
+ __dpmi_free_ldt_descriptor(*segment);
+ *segment = 0;
+ return -1;
+ }
+
+ /* set the descriptor base and limit */
+ __dpmi_set_segment_base_address(*segment, base);
+ __dpmi_set_segment_limit(*segment, MAX(size-1, 0xFFFF));
+
+ return 0;
+}
+
+
+
+/* _remove_selector:
+ * Frees a DPMI segment selector.
+ */
+void _remove_selector (int *segment)
+{
+ if (*segment) {
+ unsigned long base;
+ __dpmi_get_segment_base_address(*segment, &base);
+ _remove_linear_mapping(&base);
+ __dpmi_free_ldt_descriptor(*segment);
+ *segment = 0;
+ }
+}
+
+
+
+/* Desc: retrieve CPU MMX capability
+ *
+ * In : -
+ * Out : FALSE if CPU cannot do MMX
+ *
+ * Note: -
+ */
+int _can_mmx (void)
+{
+#ifdef USE_MMX_ASM
+ extern int _mesa_x86_cpu_features;
+ return (_mesa_x86_cpu_features & 0x00800000);
+#else
+ return 0;
+#endif
+}
diff --git a/src/mesa/drivers/dos/internal.h b/src/mesa/drivers/dos/internal.h
new file mode 100644
index 0000000..fd47dbb
--- /dev/null
+++ b/src/mesa/drivers/dos/internal.h
@@ -0,0 +1,130 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.5 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef INTERNAL_H_included
+#define INTERNAL_H_included
+
+#include "../main/mtypes.h"
+
+/*
+ * general purpose defines, etc.
+ */
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#define __PACKED__ __attribute__((packed))
+
+typedef unsigned char word8;
+typedef unsigned short word16;
+typedef unsigned long word32;
+
+#define _16_ *(word16 *)&
+#define _32_ *(word32 *)&
+
+
+
+/*
+ * video mode structure
+ */
+typedef struct vl_mode {
+ int xres, yres;
+ int bpp;
+
+ int mode;
+ int scanlen;
+
+ int sel;
+ int gran;
+} vl_mode;
+
+
+
+/*
+ * video driver structure
+ */
+typedef struct {
+ vl_mode *(*init) (void);
+ int (*entermode) (vl_mode *p, int refresh);
+ void (*blit) (void);
+ void (*setCI_f) (int index, float red, float green, float blue);
+ void (*setCI_i) (int index, int red, int green, int blue);
+ int (*get) (int pname, int *params);
+ void (*restore) (void);
+ void (*fini) (void);
+} vl_driver;
+
+
+
+/*
+ * memory mapping
+ */
+int _create_linear_mapping (unsigned long *linear, unsigned long physaddr, int size);
+void _remove_linear_mapping (unsigned long *linear);
+int _create_selector (int *segment, unsigned long base, int size);
+void _remove_selector (int *segment);
+
+/*
+ * system routines
+ */
+int _can_mmx (void);
+
+/*
+ * asm routines to deal with virtual buffering
+ */
+extern void v_clear8 (int color);
+#define v_clear15 v_clear16
+extern void v_clear16 (int color);
+extern void v_clear24 (int color);
+extern void v_clear32 (int color);
+
+extern void v_clear8_mmx (int color);
+#define v_clear15_mmx v_clear16_mmx
+extern void v_clear16_mmx (int color);
+extern void v_clear24_mmx (int color);
+extern void v_clear32_mmx (int color);
+
+extern void v_rect8 (int x, int y, int width, int height, int color);
+#define v_rect15 v_rect16
+extern void v_rect16 (int x, int y, int width, int height, int color);
+extern void v_rect24 (int x, int y, int width, int height, int color);
+extern void v_rect32 (int x, int y, int width, int height, int color);
+
+extern void v_putpixel8 (unsigned int offset, int color);
+#define v_putpixel15 v_putpixel16
+extern void v_putpixel16 (unsigned int offset, int color);
+extern void v_putpixel24 (unsigned int offset, int color);
+extern void v_putpixel32 (unsigned int offset, int color);
+
+#endif
diff --git a/src/mesa/drivers/dos/null.c b/src/mesa/drivers/dos/null.c
new file mode 100644
index 0000000..746de23
--- /dev/null
+++ b/src/mesa/drivers/dos/null.c
@@ -0,0 +1,227 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999 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.6 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include <stdlib.h>
+#include <sys/segments.h>
+
+#include "video.h"
+#include "null.h"
+
+
+
+static vl_mode *modes;
+
+#define null_color_precision 8
+
+
+
+
+static void null_blit_nop (void)
+{
+}
+
+
+
+/* Desc: Attempts to detect NUL, check video modes and create selectors.
+ *
+ * In : -
+ * Out : mode array
+ *
+ * Note: -
+ */
+static vl_mode *null_init (void)
+{
+ static int m[][2] = {
+ { 320, 200 },
+ { 320, 240 },
+ { 400, 300 },
+ { 512, 384 },
+ { 640, 400 },
+ { 640, 480 },
+ { 800, 600 },
+ { 1024, 768 },
+ { 1280, 1024 },
+ { 1600, 1200 }
+ };
+ static int b[] = {
+ 8,
+ 15,
+ 16,
+ 24,
+ 32
+ };
+ const unsigned int m_count = sizeof(m) / sizeof(m[0]);
+ const unsigned int b_count = sizeof(b) / sizeof(b[0]);
+
+ unsigned int i, j, k;
+
+ if (modes == NULL) {
+ modes = malloc(sizeof(vl_mode) * (1 + m_count * b_count));
+
+ if (modes != NULL) {
+ for (k = 0, i = 0; i < m_count; i++) {
+ for (j = 0; j < b_count; j++, k++) {
+ modes[k].xres = m[i][0];
+ modes[k].yres = m[i][1];
+ modes[k].bpp = b[j];
+ modes[k].mode = 0x4000;
+ modes[k].scanlen = m[i][0] * ((b[j] + 7) / 8);
+ modes[k].sel = -1;
+ modes[k].gran = -1;
+ }
+ }
+ modes[k].xres = -1;
+ modes[k].yres = -1;
+ modes[k].bpp = -1;
+ modes[k].mode = 0xffff;
+ modes[k].scanlen = -1;
+ modes[k].sel = -1;
+ modes[k].gran = -1;
+ }
+ }
+
+ return modes;
+}
+
+
+
+/* Desc: Frees all resources allocated by NUL init code.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void null_fini (void)
+{
+ if (modes != NULL) {
+ free(modes);
+ modes = NULL;
+ }
+}
+
+
+
+/* Desc: Attempts to enter specified video mode.
+ *
+ * In : ptr to mode structure, refresh rate
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+static int null_entermode (vl_mode *p, int refresh)
+{
+ NUL.blit = null_blit_nop;
+
+ return 0;
+
+ (void)(p && refresh); /* silence compiler warning */
+}
+
+
+
+/* Desc: Restores to the mode prior to first call to null_entermode.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void null_restore (void)
+{
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses integer values
+ */
+static void null_setCI_i (int index, int red, int green, int blue)
+{
+ (void)(index && red && green && blue); /* silence compiler warning */
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses normalized values
+ */
+static void null_setCI_f (int index, float red, float green, float blue)
+{
+ float max = (1 << null_color_precision) - 1;
+
+ null_setCI_i(index, (int)(red * max), (int)(green * max), (int)(blue * max));
+}
+
+
+
+/* Desc: state retrieval
+ *
+ * In : parameter name, ptr to storage
+ * Out : 0 if request successfully processed
+ *
+ * Note: -
+ */
+static int null_get (int pname, int *params)
+{
+ switch (pname) {
+ default:
+ params[0] = params[0]; /* silence compiler warning */
+ return -1;
+ }
+ return 0;
+}
+
+
+
+/*
+ * the driver
+ */
+vl_driver NUL = {
+ null_init,
+ null_entermode,
+ NULL,
+ null_setCI_f,
+ null_setCI_i,
+ null_get,
+ null_restore,
+ null_fini
+};
diff --git a/src/mesa/drivers/dos/null.h b/src/mesa/drivers/dos/null.h
new file mode 100644
index 0000000..a38accc
--- /dev/null
+++ b/src/mesa/drivers/dos/null.h
@@ -0,0 +1,41 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.6 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef NULL_H_included
+#define NULL_H_included
+
+#include "internal.h"
+
+extern vl_driver NUL;
+
+#endif
diff --git a/src/mesa/drivers/dos/vesa.c b/src/mesa/drivers/dos/vesa.c
new file mode 100644
index 0000000..dee3ebf
--- /dev/null
+++ b/src/mesa/drivers/dos/vesa.c
@@ -0,0 +1,533 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999 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.5 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include <dpmi.h>
+#include <pc.h>
+#include <stdlib.h>
+#include <stubinfo.h>
+#include <sys/exceptn.h>
+#include <sys/segments.h>
+#include <sys/farptr.h>
+#include <sys/movedata.h>
+
+#include "video.h"
+#include "vesa.h"
+
+
+
+static vl_mode modes[128];
+
+static word16 vesa_ver;
+static int banked_selector, linear_selector;
+static int oldmode = -1;
+
+static int vesa_color_precision = 6;
+
+static word16 *vesa_pmcode;
+unsigned int vesa_gran_mask, vesa_gran_shift;
+
+
+
+/*
+ * VESA info
+ */
+#define V_SIGN 0
+#define V_MINOR 4
+#define V_MAJOR 5
+#define V_OEM_OFS 6
+#define V_OEM_SEG 8
+#define V_MODE_OFS 14
+#define V_MODE_SEG 16
+#define V_MEMORY 18
+
+/*
+ * mode info
+ */
+#define M_ATTR 0
+#define M_GRAN 4
+#define M_SCANLEN 16
+#define M_XRES 18
+#define M_YRES 20
+#define M_BPP 25
+#define M_RED 31
+#define M_GREEN 33
+#define M_BLUE 35
+#define M_PHYS_PTR 40
+
+/*
+ * VESA 3.0 CRTC timings structure
+ */
+typedef struct CRTCInfoBlock {
+ unsigned short HorizontalTotal;
+ unsigned short HorizontalSyncStart;
+ unsigned short HorizontalSyncEnd;
+ unsigned short VerticalTotal;
+ unsigned short VerticalSyncStart;
+ unsigned short VerticalSyncEnd;
+ unsigned char Flags;
+ unsigned long PixelClock; /* units of Hz */
+ unsigned short RefreshRate; /* units of 0.01 Hz */
+ unsigned char reserved[40];
+} __PACKED__ CRTCInfoBlock;
+
+#define HNEG (1 << 2)
+#define VNEG (1 << 3)
+#define DOUBLESCAN (1 << 0)
+
+
+
+/* Desc: Attempts to detect VESA, check video modes and create selectors.
+ *
+ * In : -
+ * Out : mode array
+ *
+ * Note: -
+ */
+static vl_mode *vesa_init (void)
+{
+ __dpmi_regs r;
+ word16 *p;
+ vl_mode *q;
+ char vesa_info[512], tmp[512];
+ int maxsize = 0;
+ word32 linearfb = 0;
+
+ if (vesa_ver) {
+ return modes;
+ }
+
+ _farpokel(_stubinfo->ds_selector, 0, 0x32454256);
+ r.x.ax = 0x4f00;
+ r.x.di = 0;
+ r.x.es = _stubinfo->ds_segment;
+ __dpmi_int(0x10, &r);
+ movedata(_stubinfo->ds_selector, 0, _my_ds(), (unsigned)vesa_info, 512);
+ if ((r.x.ax!=0x004f) || ((_32_ vesa_info[V_SIGN])!=0x41534556)) {
+ return NULL;
+ }
+
+ p = (word16 *)(((_16_ vesa_info[V_MODE_SEG])<<4) + (_16_ vesa_info[V_MODE_OFS]));
+ q = modes;
+ do {
+ if ((q->mode=_farpeekw(__djgpp_dos_sel, (unsigned long)(p++)))==0xffff) {
+ break;
+ }
+
+ r.x.ax = 0x4f01;
+ r.x.cx = q->mode;
+ r.x.di = 512;
+ r.x.es = _stubinfo->ds_segment;
+ __dpmi_int(0x10, &r);
+ movedata(_stubinfo->ds_selector, 512, _my_ds(), (unsigned)tmp, 256);
+ switch (tmp[M_BPP]) {
+ case 16:
+ q->bpp = tmp[M_RED] + tmp[M_GREEN] + tmp[M_BLUE];
+ break;
+ case 8:
+ case 15:
+ case 24:
+ case 32:
+ q->bpp = tmp[M_BPP];
+ break;
+ default:
+ q->bpp = 0;
+ }
+ if ((r.x.ax==0x004f) && ((tmp[M_ATTR]&0x11)==0x11) && q->bpp) {
+ q->xres = _16_ tmp[M_XRES];
+ q->yres = _16_ tmp[M_YRES];
+ q->scanlen = _16_ tmp[M_SCANLEN];
+ q->gran = (_16_ tmp[M_GRAN])<<10;
+ if (tmp[M_ATTR]&0x80) {
+ vl_mode *q1 = q + 1;
+ *q1 = *q++;
+ linearfb = _32_ tmp[M_PHYS_PTR];
+ q->mode |= 0x4000;
+ }
+ if (maxsize<(q->scanlen*q->yres)) {
+ maxsize = q->scanlen*q->yres;
+ }
+ q++;
+ }
+ } while (TRUE);
+
+ if (q==modes) {
+ return NULL;
+ }
+ if (linearfb) {
+ maxsize = (maxsize + 0xfffUL) & ~0xfffUL;
+ if (_create_selector(&linear_selector, linearfb, maxsize)) {
+ return NULL;
+ }
+ }
+ if (_create_selector(&banked_selector, 0xa0000, modes[0].gran)) {
+ _remove_selector(&linear_selector);
+ return NULL;
+ }
+
+ for (q=modes; q->mode!=0xffff; q++) {
+ q->sel = (q->mode&0x4000) ? linear_selector : banked_selector;
+ }
+
+ if (vesa_info[V_MAJOR] >= 2) {
+ r.x.ax = 0x4f0a;
+ r.x.bx = 0;
+ __dpmi_int(0x10, &r);
+ if (r.x.ax == 0x004f) {
+ vesa_pmcode = (word16 *)malloc(r.x.cx);
+ if (vesa_pmcode != NULL) {
+ movedata(__djgpp_dos_sel, (r.x.es << 4) + r.x.di, _my_ds(), (unsigned)vesa_pmcode, r.x.cx);
+ if (vesa_pmcode[3]) {
+ p = (word16 *)((long)vesa_pmcode + vesa_pmcode[3]);
+ while (*p++ != 0xffff) {
+ }
+ } else {
+ p = NULL;
+ }
+ if (p && (*p != 0xffff)) {
+ free(vesa_pmcode);
+ vesa_pmcode = NULL;
+ } else {
+ vesa_swbank = (void *)((long)vesa_pmcode + vesa_pmcode[0]);
+ }
+ }
+ }
+ }
+
+ vesa_ver = _16_ vesa_info[V_MINOR];
+ return modes;
+}
+
+
+
+/* Desc: Frees all resources allocated by VESA init code.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void vesa_fini (void)
+{
+ if (vesa_ver) {
+ _remove_selector(&linear_selector);
+ _remove_selector(&banked_selector);
+ if (vesa_pmcode != NULL) {
+ free(vesa_pmcode);
+ vesa_pmcode = NULL;
+ }
+ }
+}
+
+
+
+/* Desc: Uses VESA 3.0 function 0x4F0B to find the closest pixel clock to the requested value.
+ *
+ * In : mode, clock
+ * Out : desired clock
+ *
+ * Note: -
+ */
+static unsigned long _closest_pixclk (int mode_no, unsigned long vclk)
+{
+ __dpmi_regs r;
+
+ r.x.ax = 0x4F0B;
+ r.h.bl = 0;
+ r.d.ecx = vclk;
+ r.x.dx = mode_no;
+ __dpmi_int(0x10, &r);
+
+ return (r.x.ax==0x004f) ? r.d.ecx : 0;
+}
+
+
+
+/* Desc: Calculates CRTC mode timings.
+ *
+ * In : crtc block, geometry, adjust
+ * Out :
+ *
+ * Note:
+ */
+static void _crtc_timing (CRTCInfoBlock *crtc, int xres, int yres, int xadjust, int yadjust)
+{
+ int HTotal, VTotal;
+ int HDisp, VDisp;
+ int HSS, VSS;
+ int HSE, VSE;
+ int HSWidth, VSWidth;
+ int SS, SE;
+ int doublescan = FALSE;
+
+ if (yres < 400) {
+ doublescan = TRUE;
+ yres *= 2;
+ }
+
+ HDisp = xres;
+ HTotal = (int)(HDisp * 1.27) & ~0x7;
+ HSWidth = (int)((HTotal - HDisp) / 5) & ~0x7;
+ HSS = HDisp + 16;
+ HSE = HSS + HSWidth;
+ VDisp = yres;
+ VTotal = VDisp * 1.07;
+ VSWidth = (VTotal / 100) + 1;
+ VSS = VDisp + ((int)(VTotal - VDisp) / 5) + 1;
+ VSE = VSS + VSWidth;
+
+ SS = HSS + xadjust;
+ SE = HSE + xadjust;
+
+ if (xadjust < 0) {
+ if (SS < (HDisp + 8)) {
+ SS = HDisp + 8;
+ SE = SS + HSWidth;
+ }
+ } else {
+ if ((HTotal - 24) < SE) {
+ SE = HTotal - 24;
+ SS = SE - HSWidth;
+ }
+ }
+
+ HSS = SS;
+ HSE = SE;
+
+ SS = VSS + yadjust;
+ SE = VSE + yadjust;
+
+ if (yadjust < 0) {
+ if (SS < (VDisp + 3)) {
+ SS = VDisp + 3;
+ SE = SS + VSWidth;
+ }
+ } else {
+ if ((VTotal - 4) < SE) {
+ SE = VTotal - 4;
+ SS = SE - VSWidth;
+ }
+ }
+
+ VSS = SS;
+ VSE = SE;
+
+ crtc->HorizontalTotal = HTotal;
+ crtc->HorizontalSyncStart = HSS;
+ crtc->HorizontalSyncEnd = HSE;
+ crtc->VerticalTotal = VTotal;
+ crtc->VerticalSyncStart = VSS;
+ crtc->VerticalSyncEnd = VSE;
+ crtc->Flags = HNEG | VNEG;
+
+ if (doublescan)
+ crtc->Flags |= DOUBLESCAN;
+}
+
+
+
+/* Desc: Attempts to enter specified video mode.
+ *
+ * In : ptr to mode structure, refresh rate
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+static int vesa_entermode (vl_mode *p, int refresh)
+{
+ __dpmi_regs r;
+
+ if (p->mode & 0x4000) {
+ VESA.blit = _can_mmx() ? vesa_l_dump_virtual_mmx : vesa_l_dump_virtual;
+ } else {
+ VESA.blit = vesa_b_dump_virtual;
+ { int n; for (vesa_gran_shift=0, n=p->gran; n; vesa_gran_shift++, n>>=1) ; }
+ vesa_gran_mask = (1<<(--vesa_gran_shift)) - 1;
+ if ((unsigned)p->gran != (vesa_gran_mask+1)) {
+ return !0;
+ }
+ }
+
+ if (oldmode == -1) {
+ r.x.ax = 0x4f03;
+ __dpmi_int(0x10, &r);
+ oldmode = r.x.bx;
+ }
+
+ r.x.ax = 0x4f02;
+ r.x.bx = p->mode;
+
+ if (refresh && ((vesa_ver>>8) >= 3)) {
+ /* VESA 3.0 stuff for controlling the refresh rate */
+ CRTCInfoBlock crtc;
+ unsigned long vclk;
+ double f0;
+
+ _crtc_timing(&crtc, p->xres, p->yres, 0, 0);
+
+ vclk = (double)crtc.HorizontalTotal * crtc.VerticalTotal * refresh;
+ vclk = _closest_pixclk(p->mode, vclk);
+
+ if (vclk != 0) {
+ f0 = (double)vclk / (crtc.HorizontalTotal * crtc.VerticalTotal);
+ /*_current_refresh_rate = (int)(f0 + 0.5);*/
+
+ crtc.PixelClock = vclk;
+ crtc.RefreshRate = refresh * 100;
+
+ movedata(_my_ds(), (unsigned)&crtc, _stubinfo->ds_selector, 0, sizeof(crtc));
+
+ r.x.di = 0;
+ r.x.es = _stubinfo->ds_segment;
+ r.x.bx |= 0x0800;
+ }
+ }
+
+ __dpmi_int(0x10, &r);
+ if (r.x.ax != 0x004f) {
+ return !0;
+ }
+
+ if (p->bpp == 8) {
+ r.x.ax = 0x4f08;
+ r.x.bx = 0x0800;
+ __dpmi_int(0x10, &r);
+ if (r.x.ax == 0x004f) {
+ r.x.ax = 0x4f08;
+ r.h.bl = 0x01;
+ __dpmi_int(0x10, &r);
+ vesa_color_precision = r.h.bh;
+ }
+ }
+
+ return 0;
+}
+
+
+
+/* Desc: Restores to the mode prior to first call to vesa_entermode.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void vesa_restore (void)
+{
+ __dpmi_regs r;
+
+ if (oldmode != -1) {
+ r.x.ax = 0x4f02;
+ r.x.bx = oldmode;
+ __dpmi_int(0x10, &r);
+ oldmode = -1;
+ }
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses integer values
+ */
+static void vesa_setCI_i (int index, int red, int green, int blue)
+{
+#if 0
+ __asm("\n\
+ movw $0x1010, %%ax \n\
+ movb %1, %%dh \n\
+ movb %2, %%ch \n\
+ int $0x10 \n\
+ "::"b"(index), "m"(red), "m"(green), "c"(blue):"%eax", "%edx");
+#else
+ outportb(0x03C8, index);
+ outportb(0x03C9, red);
+ outportb(0x03C9, green);
+ outportb(0x03C9, blue);
+#endif
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses normalized values
+ */
+static void vesa_setCI_f (int index, float red, float green, float blue)
+{
+ float max = (1 << vesa_color_precision) - 1;
+
+ vesa_setCI_i(index, (int)(red * max), (int)(green * max), (int)(blue * max));
+}
+
+
+
+/* Desc: state retrieval
+ *
+ * In : parameter name, ptr to storage
+ * Out : 0 if request successfully processed
+ *
+ * Note: -
+ */
+static int vesa_get (int pname, int *params)
+{
+ switch (pname) {
+ case VL_GET_CI_PREC:
+ params[0] = vesa_color_precision;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+
+
+/*
+ * the driver
+ */
+vl_driver VESA = {
+ vesa_init,
+ vesa_entermode,
+ NULL,
+ vesa_setCI_f,
+ vesa_setCI_i,
+ vesa_get,
+ vesa_restore,
+ vesa_fini
+};
diff --git a/src/mesa/drivers/dos/vesa.h b/src/mesa/drivers/dos/vesa.h
new file mode 100644
index 0000000..9287697
--- /dev/null
+++ b/src/mesa/drivers/dos/vesa.h
@@ -0,0 +1,47 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.3 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef VESA_H_included
+#define VESA_H_included
+
+#include "internal.h"
+
+extern void *vesa_swbank;
+
+extern void vesa_b_dump_virtual (void);
+extern void vesa_l_dump_virtual (void);
+extern void vesa_l_dump_virtual_mmx (void);
+
+extern vl_driver VESA;
+
+#endif
diff --git a/src/mesa/drivers/dos/vga.c b/src/mesa/drivers/dos/vga.c
new file mode 100644
index 0000000..c8c0151
--- /dev/null
+++ b/src/mesa/drivers/dos/vga.c
@@ -0,0 +1,252 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999 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.6 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include <pc.h>
+#include <stdlib.h>
+
+#include "video.h"
+#include "vga.h"
+
+
+
+static vl_mode modes[] = {
+ {
+ /* .xres = */ 320,
+ /* .yres = */ 200,
+ /* .bpp = */ 8,
+ /* .mode = */ 0x13 | 0x4000,
+ /* .scanlen = */ 320,
+ /* .sel = */ -1,
+ /* .gran = */ 320*200
+ },
+ {
+ /* .xres = */ -1,
+ /* .yres = */ -1,
+ /* .bpp = */ -1,
+ /* .mode = */ 0xffff,
+ /* .scanlen = */ -1,
+ /* .sel = */ -1,
+ /* .gran = */ -1
+ }
+};
+
+static word16 vga_ver;
+static int linear_selector;
+static int oldmode = -1;
+
+#define vga_color_precision 6
+
+
+
+/* Desc: Attempts to detect VGA, check video modes and create selectors.
+ *
+ * In : -
+ * Out : mode array
+ *
+ * Note: -
+ */
+static vl_mode *vga_init (void)
+{
+ int rv = 0;
+
+ if (vga_ver) {
+ return modes;
+ }
+
+ __asm("\n\
+ movw $0x1a00, %%ax \n\
+ int $0x10 \n\
+ cmpb $0x1a, %%al \n\
+ jne 0f \n\
+ cmpb $0x07, %%bl \n\
+ jb 0f \n\
+ andl $0xff, %%ebx \n\
+ movl %%ebx, %0 \n\
+ 0:":"=g"(rv)::"%eax", "%ebx");
+ if (rv == 0) {
+ return NULL;
+ }
+
+ if (_create_selector(&linear_selector, 0xa0000, 0x10000)) {
+ return NULL;
+ }
+
+ modes[0].sel = linear_selector;
+
+ vga_ver = rv;
+ return modes;
+}
+
+
+
+/* Desc: Frees all resources allocated by VGA init code.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void vga_fini (void)
+{
+ if (vga_ver) {
+ _remove_selector(&linear_selector);
+ }
+}
+
+
+
+/* Desc: Attempts to enter specified video mode.
+ *
+ * In : ptr to mode structure, refresh rate
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+static int vga_entermode (vl_mode *p, int refresh)
+{
+ if (!(p->mode & 0x4000)) {
+ return -1;
+ }
+ VGA.blit = _can_mmx() ? vesa_l_dump_virtual_mmx : vesa_l_dump_virtual;
+
+ if (oldmode == -1) {
+ __asm("\n\
+ movb $0x0f, %%ah \n\
+ int $0x10 \n\
+ andl $0xff, %%eax \n\
+ movl %%eax, %0 \n\
+ ":"=g"(oldmode)::"%eax", "%ebx");
+ }
+
+ __asm("int $0x10"::"a"(p->mode&0xff));
+
+ return 0;
+
+ (void)refresh; /* silence compiler warning */
+}
+
+
+
+/* Desc: Restores to the mode prior to first call to vga_entermode.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void vga_restore (void)
+{
+ if (oldmode != -1) {
+ __asm("int $0x10"::"a"(oldmode));
+ oldmode = -1;
+ }
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses integer values
+ */
+static void vga_setCI_i (int index, int red, int green, int blue)
+{
+#if 0
+ __asm("\n\
+ movw $0x1010, %%ax \n\
+ movb %1, %%dh \n\
+ movb %2, %%ch \n\
+ int $0x10 \n\
+ "::"b"(index), "m"(red), "m"(green), "c"(blue):"%eax", "%edx");
+#else
+ outportb(0x03C8, index);
+ outportb(0x03C9, red);
+ outportb(0x03C9, green);
+ outportb(0x03C9, blue);
+#endif
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color index, R, G, B
+ * Out : -
+ *
+ * Note: uses normalized values
+ */
+static void vga_setCI_f (int index, float red, float green, float blue)
+{
+ float max = (1 << vga_color_precision) - 1;
+
+ vga_setCI_i(index, (int)(red * max), (int)(green * max), (int)(blue * max));
+}
+
+
+
+/* Desc: state retrieval
+ *
+ * In : parameter name, ptr to storage
+ * Out : 0 if request successfully processed
+ *
+ * Note: -
+ */
+static int vga_get (int pname, int *params)
+{
+ switch (pname) {
+ case VL_GET_CI_PREC:
+ params[0] = vga_color_precision;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+
+
+/*
+ * the driver
+ */
+vl_driver VGA = {
+ vga_init,
+ vga_entermode,
+ NULL,
+ vga_setCI_f,
+ vga_setCI_i,
+ vga_get,
+ vga_restore,
+ vga_fini
+};
diff --git a/src/mesa/drivers/dos/vga.h b/src/mesa/drivers/dos/vga.h
new file mode 100644
index 0000000..aeb8fad
--- /dev/null
+++ b/src/mesa/drivers/dos/vga.h
@@ -0,0 +1,42 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.3 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef VGA_H_included
+#define VGA_H_included
+
+#include "internal.h"
+#include "vesa.h"
+
+extern vl_driver VGA;
+
+#endif
diff --git a/src/mesa/drivers/dos/video.c b/src/mesa/drivers/dos/video.c
new file mode 100644
index 0000000..d3774e7
--- /dev/null
+++ b/src/mesa/drivers/dos/video.c
@@ -0,0 +1,659 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.5 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ *
+ * Thanks to CrazyPyro (Neil Funk) for FakeColor
+ */
+
+
+#include <stdlib.h>
+
+#include "internal.h"
+#include "vesa.h"
+#include "vga.h"
+#include "null.h"
+#include "video.h"
+
+
+
+static vl_driver *drv;
+/* based upon mode specific data: valid entire session */
+int vl_video_selector;
+static vl_mode *video_mode;
+static int video_scanlen, video_bypp;
+/* valid until next buffer */
+void *vl_current_draw_buffer, *vl_current_read_buffer;
+int vl_current_stride, vl_current_width, vl_current_height, vl_current_bytes;
+int vl_current_offset, vl_current_delta;
+
+
+
+#if HUGE_LOOKUP
+/* These lookup tables are used to extract RGB values in [0,255]
+ * from 15/16-bit pixel values.
+ */
+static unsigned char pix15r[0x8000];
+static unsigned char pix15g[0x8000];
+static unsigned char pix15b[0x8000];
+static unsigned char pix16r[0x10000];
+static unsigned char pix16g[0x10000];
+static unsigned char pix16b[0x10000];
+#else
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static int _rgb_scale_5[32] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+#endif
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static int _rgb_scale_6[64] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 45, 49, 53, 57, 61,
+ 65, 69, 73, 77, 81, 85, 89, 93,
+ 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158,
+ 162, 166, 170, 174, 178, 182, 186, 190,
+ 194, 198, 202, 206, 210, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 255
+};
+
+/* FakeColor data */
+#define R_CNT 6
+#define G_CNT 6
+#define B_CNT 6
+
+#define R_BIAS 7
+#define G_BIAS 7
+#define B_BIAS 7
+
+static word32 VGAPalette[256];
+static word8 array_r[256];
+static word8 array_g[256];
+static word8 array_b[256];
+
+
+
+int (*vl_mixfix) (fixed r, fixed g, fixed b);
+int (*vl_mixrgb) (const unsigned char rgb[]);
+int (*vl_mixrgba) (const unsigned char rgba[]);
+void (*vl_getrgba) (unsigned int offset, unsigned char rgba[4]);
+int (*vl_getpixel) (unsigned int offset);
+void (*vl_clear) (int color);
+void (*vl_rect) (int x, int y, int width, int height, int color);
+void (*vl_flip) (void);
+void (*vl_putpixel) (unsigned int offset, int color);
+
+
+
+/* Desc: color composition (w/o ALPHA)
+ *
+ * In : R, G, B
+ * Out : color
+ *
+ * Note: -
+ */
+static int vl_mixfix8fake (fixed r, fixed g, fixed b)
+{
+ return array_b[b>>FIXED_SHIFT]*G_CNT*R_CNT
+ + array_g[g>>FIXED_SHIFT]*R_CNT
+ + array_r[r>>FIXED_SHIFT];
+}
+#define vl_mixfix8 vl_mixfix8fake
+static int vl_mixfix15 (fixed r, fixed g, fixed b)
+{
+ return ((r>>(3+FIXED_SHIFT))<<10)
+ |((g>>(3+FIXED_SHIFT))<<5)
+ |(b>>(3+FIXED_SHIFT));
+}
+static int vl_mixfix16 (fixed r, fixed g, fixed b)
+{
+ return ((r>>(3+FIXED_SHIFT))<<11)
+ |((g>>(2+FIXED_SHIFT))<<5)
+ |(b>>(3+FIXED_SHIFT));
+}
+#define vl_mixfix24 vl_mixfix32
+static int vl_mixfix32 (fixed r, fixed g, fixed b)
+{
+ return ((r>>FIXED_SHIFT)<<16)
+ |((g>>FIXED_SHIFT)<<8)
+ |(b>>FIXED_SHIFT);
+}
+
+
+
+/* Desc: color composition (w/ ALPHA)
+ *
+ * In : array of integers (R, G, B, A)
+ * Out : color
+ *
+ * Note: -
+ */
+#define vl_mixrgba8 vl_mixrgb8fake
+#define vl_mixrgba15 vl_mixrgb15
+#define vl_mixrgba16 vl_mixrgb16
+#define vl_mixrgba24 vl_mixrgb24
+static int vl_mixrgba32 (const unsigned char rgba[])
+{
+ /* Hack alert:
+ * currently, DMesa uses Mesa's alpha buffer;
+ * so we don't really care about alpha value here...
+ */
+ return /*(rgba[3]<<24)|*/(rgba[0]<<16)|(rgba[1]<<8)|(rgba[2]);
+}
+
+
+
+/* Desc: color composition (w/o ALPHA)
+ *
+ * In : array of integers (R, G, B)
+ * Out : color
+ *
+ * Note: -
+ */
+static int vl_mixrgb8fake (const unsigned char rgb[])
+{
+ return array_b[rgb[2]]*G_CNT*R_CNT
+ + array_g[rgb[1]]*R_CNT
+ + array_r[rgb[0]];
+}
+#define vl_mixrgb8 vl_mixrgb8fake
+static int vl_mixrgb15 (const unsigned char rgb[])
+{
+ return ((rgb[0]>>3)<<10)|((rgb[1]>>3)<<5)|(rgb[2]>>3);
+}
+static int vl_mixrgb16 (const unsigned char rgb[])
+{
+ return ((rgb[0]>>3)<<11)|((rgb[1]>>2)<<5)|(rgb[2]>>3);
+}
+#define vl_mixrgb24 vl_mixrgb32
+static int vl_mixrgb32 (const unsigned char rgb[])
+{
+ return (rgb[0]<<16)|(rgb[1]<<8)|(rgb[2]);
+}
+
+
+
+/* Desc: color decomposition
+ *
+ * In : pixel offset, array of integers to hold color components (R, G, B, A)
+ * Out : -
+ *
+ * Note: uses current read buffer
+ */
+static void v_getrgba8fake6 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
+ rgba[0] = _rgb_scale_6[(c >> 16) & 0x3F];
+ rgba[1] = _rgb_scale_6[(c >> 8) & 0x3F];
+ rgba[2] = _rgb_scale_6[c & 0x3F];
+ /*rgba[3] = c >> 24;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+static void v_getrgba8fake8 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
+ rgba[0] = c >> 16;
+ rgba[1] = c >> 8;
+ rgba[2] = c;
+ /*rgba[3] = c >> 24;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+#define v_getrgba8 v_getrgba8fake6
+static void v_getrgba15 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = ((word16 *)vl_current_read_buffer)[offset];
+#if HUGE_LOOKUP
+ c &= 0x7fff;
+ rgba[0] = pix15r[c];
+ rgba[1] = pix15g[c];
+ rgba[2] = pix15b[c];
+#else
+ rgba[0] = _rgb_scale_5[(c >> 10) & 0x1F];
+ rgba[1] = _rgb_scale_5[(c >> 5) & 0x1F];
+ rgba[2] = _rgb_scale_5[c & 0x1F];
+#endif
+ /*rgba[3] = 255;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+static void v_getrgba16 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = ((word16 *)vl_current_read_buffer)[offset];
+#if HUGE_LOOKUP
+ rgba[0] = pix16r[c];
+ rgba[1] = pix16g[c];
+ rgba[2] = pix16b[c];
+#else
+ rgba[0] = _rgb_scale_5[(c >> 11) & 0x1F];
+ rgba[1] = _rgb_scale_6[(c >> 5) & 0x3F];
+ rgba[2] = _rgb_scale_5[c & 0x1F];
+#endif
+ /*rgba[3] = 255;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+static void v_getrgba24 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = *(word32 *)((long)vl_current_read_buffer+offset*3);
+ rgba[0] = c >> 16;
+ rgba[1] = c >> 8;
+ rgba[2] = c;
+ /*rgba[3] = 255;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+static void v_getrgba32 (unsigned int offset, unsigned char rgba[4])
+{
+ word32 c = ((word32 *)vl_current_read_buffer)[offset];
+ rgba[0] = c >> 16;
+ rgba[1] = c >> 8;
+ rgba[2] = c;
+ /*rgba[3] = c >> 24;*/ /* dummy alpha; we have separate SW alpha, so ignore */
+}
+
+
+
+/* Desc: pixel retrieval
+ *
+ * In : pixel offset
+ * Out : pixel value
+ *
+ * Note: uses current read buffer
+ */
+static int v_getpixel8 (unsigned int offset)
+{
+ return ((word8 *)vl_current_read_buffer)[offset];
+}
+#define v_getpixel15 v_getpixel16
+static int v_getpixel16 (unsigned int offset)
+{
+ return ((word16 *)vl_current_read_buffer)[offset];
+}
+static int v_getpixel24 (unsigned int offset)
+{
+ return *(word32 *)((long)vl_current_read_buffer+offset*3);
+}
+static int v_getpixel32 (unsigned int offset)
+{
+ return ((word32 *)vl_current_read_buffer)[offset];
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : index, R, G, B
+ * Out : -
+ *
+ * Note: color components are in range [0.0 .. 1.0]
+ */
+void vl_setCI (int index, float red, float green, float blue)
+{
+ drv->setCI_f(index, red, green, blue);
+}
+
+
+
+/* Desc: set one palette entry
+ *
+ * In : color, R, G, B
+ * Out : -
+ *
+ * Note: -
+ */
+static void fake_setcolor (int c, int r, int g, int b)
+{
+ VGAPalette[c] = 0xff000000 | (r<<16) | (g<<8) | b;
+
+ drv->setCI_i(c, r, g, b);
+}
+
+
+
+/* Desc: build FakeColor palette
+ *
+ * In : CI precision in bits
+ * Out : -
+ *
+ * Note: -
+ */
+static void fake_buildpalette (int bits)
+{
+ double c_r, c_g, c_b;
+ int r, g, b, color = 0;
+
+ double max = (1 << bits) - 1;
+
+ for (b=0; b<B_CNT; ++b) {
+ for (g=0; g<G_CNT; ++g) {
+ for (r=0; r<R_CNT; ++r) {
+ c_r = 0.5 + (double)r*(max-R_BIAS)/(R_CNT-1.) + R_BIAS;
+ c_g = 0.5 + (double)g*(max-G_BIAS)/(G_CNT-1.) + G_BIAS;
+ c_b = 0.5 + (double)b*(max-B_BIAS)/(B_CNT-1.) + B_BIAS;
+ fake_setcolor(color++, (int)c_r, (int)c_g, (int)c_b);
+ }
+ }
+ }
+
+ for (color=0; color<256; color++) {
+ c_r = (double)color*R_CNT/256.;
+ c_g = (double)color*G_CNT/256.;
+ c_b = (double)color*B_CNT/256.;
+ array_r[color] = (int)c_r;
+ array_g[color] = (int)c_g;
+ array_b[color] = (int)c_b;
+ }
+}
+
+
+
+#if HUGE_LOOKUP
+/* Desc: initialize lookup arrays
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+void v_init_pixeltables (void)
+{
+ unsigned int pixel;
+
+ for (pixel = 0; pixel <= 0xffff; pixel++) {
+ unsigned int r, g, b;
+
+ if (pixel <= 0x7fff) {
+ /* 15bit */
+ r = (pixel & 0x7c00) >> 8;
+ g = (pixel & 0x03E0) >> 3;
+ b = (pixel & 0x001F) << 2;
+
+ r = (unsigned int)(((double)r * 255. / 0x7c) + 0.5);
+ g = (unsigned int)(((double)g * 255. / 0x7c) + 0.5);
+ b = (unsigned int)(((double)b * 255. / 0x7c) + 0.5);
+
+ pix15r[pixel] = r;
+ pix15g[pixel] = g;
+ pix15b[pixel] = b;
+ }
+
+ /* 16bit */
+ r = (pixel & 0xF800) >> 8;
+ g = (pixel & 0x07E0) >> 3;
+ b = (pixel & 0x001F) << 3;
+
+ r = (unsigned int)(((double)r * 255. / 0xF8) + 0.5);
+ g = (unsigned int)(((double)g * 255. / 0xFC) + 0.5);
+ b = (unsigned int)(((double)b * 255. / 0xF8) + 0.5);
+
+ pix16r[pixel] = r;
+ pix16g[pixel] = g;
+ pix16b[pixel] = b;
+ }
+}
+#endif
+
+
+
+/* Desc: initialize hardware
+ *
+ * In : -
+ * Out : list of available modes
+ *
+ * Note: when returning non-NULL, global variable `drv' is guaranteed to be ok
+ */
+static vl_mode *v_init_hw (void)
+{
+ static vl_mode *q = NULL;
+
+ if (q == NULL) {
+ /* are we forced to NUL driver? */
+ if (getenv("DMESA_NULDRV")) {
+ if ((q = NUL.init()) != NULL) {
+ drv = &NUL;
+ }
+ return q;
+ }
+ /* initialize hardware */
+ if ((q = VESA.init()) != NULL) {
+ drv = &VESA;
+ } else if ((q = VGA.init()) != NULL) {
+ drv = &VGA;
+ } else {
+ drv = NULL;
+ }
+ }
+
+ return q;
+}
+
+
+
+/* Desc: sync buffer with video hardware
+ *
+ * In : ptr to old buffer, position, size
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+int vl_sync_buffer (void **buffer, int x, int y, int width, int height)
+{
+ if ((width & 7) || (x < 0) || (y < 0) || (x+width > video_mode->xres) || (y+height > video_mode->yres)) {
+ return -1;
+ } else {
+ void *newbuf = *buffer;
+
+ if ((newbuf == NULL) || (vl_current_width != width) || (vl_current_height != height)) {
+ newbuf = realloc(newbuf, width * height * video_bypp);
+ }
+
+ if (newbuf == NULL) {
+ return -2;
+ }
+
+ vl_current_width = width;
+ vl_current_height = height;
+ vl_current_stride = vl_current_width * video_bypp;
+ vl_current_bytes = vl_current_stride * height;
+
+ vl_current_offset = video_scanlen * y + video_bypp * x;
+ vl_current_delta = video_scanlen - vl_current_stride;
+
+ vl_current_draw_buffer = vl_current_read_buffer = *buffer = newbuf;
+ return 0;
+ }
+}
+
+
+
+/* Desc: state retrieval
+ *
+ * In : name, storage
+ * Out : -1 for an error
+ *
+ * Note: -
+ */
+int vl_get (int pname, int *params)
+{
+ switch (pname) {
+ case VL_GET_SCREEN_SIZE:
+ params[0] = video_mode->xres;
+ params[1] = video_mode->yres;
+ break;
+ case VL_GET_VIDEO_MODES:
+ {
+ int n;
+ vl_mode *q;
+ if ((q = v_init_hw()) == NULL) {
+ return -1;
+ }
+ /* count available visuals */
+ for (n = 0; q->mode != 0xffff; q++) {
+ if ((q + 1)->mode == (q->mode | 0x4000)) {
+ /* same mode, but linear */
+ q++;
+ }
+ if (params) {
+ params[n] = (int)q;
+ }
+ n++;
+ }
+ return n;
+ }
+ default:
+ return (drv != NULL) ? drv->get(pname, params) : -1;
+ }
+ return 0;
+}
+
+
+
+/* Desc: setup mode
+ *
+ * In : ptr to mode definition
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+static int vl_setup_mode (vl_mode *p)
+{
+ if (p == NULL) {
+ return -1;
+ }
+
+#define INITPTR(bpp) \
+ vl_putpixel = v_putpixel##bpp; \
+ vl_getrgba = v_getrgba##bpp; \
+ vl_getpixel = v_getpixel##bpp; \
+ vl_rect = v_rect##bpp; \
+ vl_mixfix = vl_mixfix##bpp; \
+ vl_mixrgb = vl_mixrgb##bpp; \
+ vl_mixrgba = vl_mixrgba##bpp; \
+ vl_clear = _can_mmx() ? v_clear##bpp##_mmx : v_clear##bpp
+
+ switch (p->bpp) {
+ case 8:
+ INITPTR(8);
+ break;
+ case 15:
+ INITPTR(15);
+ break;
+ case 16:
+ INITPTR(16);
+ break;
+ case 24:
+ INITPTR(24);
+ break;
+ case 32:
+ INITPTR(32);
+ break;
+ default:
+ return -1;
+ }
+
+#undef INITPTR
+
+ video_mode = p;
+ video_bypp = (p->bpp+7)/8;
+ video_scanlen = p->scanlen;
+ vl_video_selector = p->sel;
+
+ return 0;
+}
+
+
+
+/* Desc: restore to the mode prior to first call to `vl_video_init'.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+void vl_video_exit (void)
+{
+ drv->restore();
+ drv->fini();
+ video_mode = NULL;
+}
+
+
+
+/* Desc: enter mode
+ *
+ * In : xres, yres, bits/pixel, RGB, refresh rate
+ * Out : pixel width in bits if success
+ *
+ * Note: -
+ */
+int vl_video_init (int width, int height, int bpp, int rgb, int refresh)
+{
+ int fake;
+ vl_mode *p, *q;
+ unsigned int min;
+
+ fake = 0;
+ if (!rgb) {
+ bpp = 8;
+ } else if (bpp == 8) {
+ fake = 1;
+ }
+#if HUGE_LOOKUP
+ else if (bpp < 24) {
+ v_init_pixeltables();
+ }
+#endif
+
+ /* initialize hardware */
+ if ((q = v_init_hw()) == NULL) {
+ return 0;
+ }
+
+ /* search for a mode that fits our request */
+ for (min=-1, p=NULL; q->mode!=0xffff; q++) {
+ if ((q->xres>=width) && (q->yres>=height) && (q->bpp==bpp)) {
+ if (min>=(unsigned)(q->xres*q->yres)) {
+ min = q->xres*q->yres;
+ p = q;
+ }
+ }
+ }
+
+ /* setup and enter mode */
+ if ((vl_setup_mode(p) == 0) && (drv->entermode(p, refresh) == 0)) {
+ vl_flip = drv->blit;
+ if (fake) {
+ drv->get(VL_GET_CI_PREC, (int *)(&min));
+ fake_buildpalette(min);
+ if (min == 8) {
+ vl_getrgba = v_getrgba8fake8;
+ }
+ }
+ return bpp;
+ }
+
+ /* abort */
+ return 0;
+}
diff --git a/src/mesa/drivers/dos/video.h b/src/mesa/drivers/dos/video.h
new file mode 100644
index 0000000..e928f19
--- /dev/null
+++ b/src/mesa/drivers/dos/video.h
@@ -0,0 +1,65 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.5 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef VIDEO_H_included
+#define VIDEO_H_included
+
+typedef int fixed;
+
+#define VL_GET_CARD_NAME 0x0100
+#define VL_GET_VRAM 0x0101
+#define VL_GET_CI_PREC 0x0200
+#define VL_GET_HPIXELS 0x0201
+#define VL_GET_SCREEN_SIZE 0x0202
+#define VL_GET_VIDEO_MODES 0x0300
+
+extern int (*vl_mixfix) (fixed r, fixed g, fixed b);
+extern int (*vl_mixrgb) (const unsigned char rgb[]);
+extern int (*vl_mixrgba) (const unsigned char rgba[]);
+extern void (*vl_getrgba) (unsigned int offset, unsigned char rgba[4]);
+
+extern void (*vl_clear) (int color);
+extern void (*vl_rect) (int x, int y, int width, int height, int color);
+extern void (*vl_flip) (void);
+extern void (*vl_putpixel) (unsigned int offset, int color);
+extern int (*vl_getpixel) (unsigned int offset);
+
+void vl_setCI (int index, float red, float green, float blue);
+
+int vl_sync_buffer (void **buffer, int x, int y, int width, int height);
+int vl_get (int pname, int *params);
+
+void vl_video_exit (void);
+int vl_video_init (int width, int height, int bpp, int rgb, int refresh);
+
+#endif
diff --git a/src/mesa/drivers/dos/virtual.S b/src/mesa/drivers/dos/virtual.S
new file mode 100644
index 0000000..b8b521f
--- /dev/null
+++ b/src/mesa/drivers/dos/virtual.S
@@ -0,0 +1,495 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * Copyright (C) 1999 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.4 for Mesa
+ *
+ * Copyright (C) 2002 - Borca Daniel
+ * Email : dborca@yahoo.com
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#include "x86/assyntax.h"
+
+
+ FILE("virtual.S")
+
+/*
+ * extern void *vl_current_draw_buffer;
+ * extern int vl_current_width, vl_current_bytes;
+ */
+EXTERN _vl_current_draw_buffer
+EXTERN _vl_current_width, _vl_current_bytes
+
+ SEG_TEXT
+ USE32
+
+/* Desc: void v_clear8 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear8
+_v_clear8:
+ MOV_L (REGOFF(4, ESP), EAX)
+ MOV_B (AL, AH)
+ PUSH_W (AX)
+ PUSH_W (AX)
+ POP_L (EAX)
+ jmp _v_clear_common
+
+/* Desc: void v_clear16 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear16
+_v_clear16:
+ MOV_L (REGOFF(4, ESP), EAX)
+ PUSH_W (AX)
+ PUSH_W (AX)
+ POP_L (EAX)
+ jmp _v_clear_common
+
+/* Desc: void v_clear32 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear32
+_v_clear32:
+ MOV_L (REGOFF(4, ESP), EAX)
+ ALIGNTEXT4
+_v_clear_common:
+ MOV_L (CONTENT(_vl_current_bytes), ECX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EDX)
+ SHR_L (CONST(2), ECX)
+ ALIGNTEXT4
+ 0:
+ MOV_L (EAX, REGIND(EDX))
+ ADD_L (CONST(4), EDX)
+ DEC_L (ECX)
+ jnz 0b
+ RET
+
+/* Desc: void v_clear8_mmx (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear8_mmx
+_v_clear8_mmx:
+#ifdef USE_MMX_ASM
+ MOVD (REGOFF(4, ESP), MM0)
+ PUNPCKLBW (MM0, MM0)
+ PUNPCKLWD (MM0, MM0)
+ jmp _v_clear_common_mmx
+#endif
+
+/* Desc: void v_clear16_mmx (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear16_mmx
+_v_clear16_mmx:
+#ifdef USE_MMX_ASM
+ MOVD (REGOFF(4, ESP), MM0)
+ PUNPCKLWD (MM0, MM0)
+ jmp _v_clear_common_mmx
+#endif
+
+/* Desc: void v_clear32_mmx (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear32_mmx
+_v_clear32_mmx:
+#ifdef USE_MMX_ASM
+ MOVD (REGOFF(4, ESP), MM0)
+ ALIGNTEXT4
+_v_clear_common_mmx:
+ PUNPCKLDQ (MM0, MM0)
+ MOV_L (CONTENT(_vl_current_bytes), ECX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EDX)
+ SHR_L (CONST(3), ECX)
+ ALIGNTEXT4
+ 0:
+ MOVQ (MM0, REGIND(EDX))
+ ADD_L (CONST(8), EDX)
+ DEC_L (ECX)
+ jnz 0b
+ EMMS
+#endif
+ RET
+
+/* Desc: void v_clear24 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear24
+_v_clear24:
+ MOV_L (CONST(0xaaaaaaab), EAX)
+ MUL_L (CONTENT(_vl_current_bytes))
+ MOV_L (REGOFF(4, ESP), EAX)
+ MOV_L (EDX, ECX)
+ PUSH_L (EBX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EDX)
+ SHR_L (CONST(1), ECX)
+ MOV_B (REGOFF(10,ESP), BL)
+ ALIGNTEXT4
+ 0:
+ MOV_W (AX, REGIND(EDX))
+ MOV_B (BL, REGOFF(2,EDX))
+ ADD_L (CONST(3), EDX)
+ DEC_L (ECX)
+ jnz 0b
+ POP_L (EBX)
+ RET
+
+/* Desc: void v_clear24_mmx (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_clear24_mmx
+_v_clear24_mmx:
+#ifdef USE_MMX_ASM
+ MOV_L (REGOFF(4, ESP), EAX)
+ MOV_L (EAX, EDX)
+ MOV_L (EAX, ECX)
+ SHL_L (CONST(16), EDX)
+ ROR_L (CONST(8), ECX)
+ MOV_W (CX, DX)
+ ROR_L (CONST(16), ECX)
+ MOV_B (DH, CL)
+ SHL_L (CONST(8), EAX)
+ MOV_B (CH, AL)
+ ROR_L (CONST(8), EAX)
+
+ PUSH_L (EDX)
+ PUSH_L (EAX)
+ MOVQ (REGIND(ESP), MM0)
+ PUSH_L (ECX)
+ MOVQ (REGIND(ESP), MM1)
+ PUSH_L (EDX)
+ MOVQ (REGIND(ESP), MM2)
+
+ MOV_L (CONST(0xaaaaaaab), EAX)
+ MUL_L (CONTENT(_vl_current_bytes))
+ MOV_L (EDX, ECX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EDX)
+ SHR_L (CONST(4), ECX)
+ ALIGNTEXT4
+ 0:
+ MOVQ (MM0, REGIND(EDX))
+ MOVQ (MM1, REGOFF(8,EDX))
+ MOVQ (MM2, REGOFF(16,EDX))
+ ADD_L (CONST(24), EDX)
+ DEC_L (ECX)
+ jnz 0b
+ EMMS
+ ADD_L (CONST(16), ESP)
+#endif
+ RET
+
+/* Desc: void v_rect8 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_rect8
+_v_rect8:
+ CLD
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_L (REGOFF(28, ESP), EAX)
+ MOV_L (CONTENT(_vl_current_width), ESI)
+ MOV_L (REGOFF(16, ESP), EDI)
+ MOV_B (AL, AH)
+ MOV_L (REGOFF(20, ESP), ECX)
+ IMUL_L (ESI, EDI)
+ MOV_L (REGOFF(24, ESP), EDX)
+ SUB_L (ECX, ESI)
+ ADD_L (REGOFF(12, ESP), EDI)
+ PUSH_W (AX)
+ PUSH_W (AX)
+ PUSH_SR (DS)
+ POP_SR (ES)
+ ADD_L (CONTENT(_vl_current_draw_buffer), EDI)
+ POP_L (EAX)
+ PUSH_L (EBX)
+ MOV_L (ECX, EBX)
+ AND_L (CONST(3), EBX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ SHR_L (CONST(2), ECX)
+ REP STOS_L
+ TEST_L (EBX, EBX)
+ jz 2f
+ MOV_L (EBX, ECX)
+ REP STOS_B
+ ALIGNTEXT4
+ 2:
+ POP_L (ECX)
+ ADD_L (ESI, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EBX)
+ POP_L (EDI)
+ POP_L (ESI)
+ RET
+
+/* Desc: void v_rect16 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_rect16
+_v_rect16:
+ CLD
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_L (REGOFF(28, ESP), EAX)
+ MOV_L (CONTENT(_vl_current_width), ESI)
+ MOV_L (REGOFF(16, ESP), EDI)
+ MOV_L (REGOFF(20, ESP), ECX)
+ IMUL_L (ESI, EDI)
+ MOV_L (REGOFF(24, ESP), EDX)
+ SUB_L (ECX, ESI)
+ ADD_L (REGOFF(12, ESP), EDI)
+ PUSH_W (AX)
+ SHL_L (CONST(1), ESI)
+ PUSH_W (AX)
+ SHL_L (CONST(1), EDI)
+ PUSH_SR (DS)
+ POP_SR (ES)
+ ADD_L (CONTENT(_vl_current_draw_buffer), EDI)
+ POP_L (EAX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ SHR_L (CONST(1), ECX)
+ REP STOS_L
+ jnc 2f
+ STOS_W
+ ALIGNTEXT4
+ 2:
+ POP_L (ECX)
+ ADD_L (ESI, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EDI)
+ POP_L (ESI)
+ RET
+
+/* Desc: void v_rect24 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_rect24
+_v_rect24:
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_L (REGOFF(28, ESP), EAX)
+ MOV_L (CONTENT(_vl_current_width), ESI)
+ MOV_L (REGOFF(16, ESP), EDI)
+ MOV_L (REGOFF(20, ESP), ECX)
+ IMUL_L (ESI, EDI)
+ MOV_L (REGOFF(24, ESP), EDX)
+ SUB_L (ECX, ESI)
+ ADD_L (REGOFF(12, ESP), EDI)
+ LEA_L (REGBIS(ESI, ESI, 2), ESI)
+ PUSH_L (EBX)
+ LEA_L (REGBIS(EDI, EDI, 2), EDI)
+ MOV_L (EAX, EBX)
+ ADD_L (CONTENT(_vl_current_draw_buffer), EDI)
+ SHR_L (CONST(16), EBX)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ MOV_W (AX, REGIND(EDI))
+ MOV_B (BL, REGOFF(2,EDI))
+ ADD_L (CONST(3), EDI)
+ DEC_L (ECX)
+ jnz 1b
+ POP_L (ECX)
+ ADD_L (ESI, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EBX)
+ POP_L (EDI)
+ POP_L (ESI)
+ RET
+
+/* Desc: void v_rect32 (int color);
+ *
+ * In : color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_rect32
+_v_rect32:
+ PUSH_L (ESI)
+ PUSH_L (EDI)
+ MOV_L (CONTENT(_vl_current_width), ESI)
+ MOV_L (REGOFF(16, ESP), EDI)
+ MOV_L (REGOFF(20, ESP), ECX)
+ IMUL_L (ESI, EDI)
+ MOV_L (REGOFF(24, ESP), EDX)
+ SUB_L (ECX, ESI)
+ ADD_L (REGOFF(12, ESP), EDI)
+ SHL_L (CONST(2), ESI)
+ SHL_L (CONST(2), EDI)
+ MOV_L (REGOFF(28, ESP), EAX)
+ ADD_L (CONTENT(_vl_current_draw_buffer), EDI)
+ ALIGNTEXT4
+ 0:
+ PUSH_L (ECX)
+ ALIGNTEXT4
+ 1:
+ MOV_L (EAX, REGIND(EDI))
+ ADD_L (CONST(4), EDI)
+ DEC_L (ECX)
+ jnz 1b
+ POP_L (ECX)
+ ADD_L (ESI, EDI)
+ DEC_L (EDX)
+ jnz 0b
+ POP_L (EDI)
+ POP_L (ESI)
+ RET
+
+/* Desc: void v_putpixel8 (unsigned int offset, int color);
+ *
+ * In : offset within buffer, color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_putpixel8
+_v_putpixel8:
+ MOV_L (REGOFF(8, ESP), ECX)
+ MOV_L (REGOFF(4, ESP), EDX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EAX)
+ MOV_B (CL, REGBI(EAX,EDX))
+ RET
+
+/* Desc: void v_putpixel16 (unsigned int offset, int color);
+ *
+ * In : offset within buffer, color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_putpixel16
+_v_putpixel16:
+ MOV_L (REGOFF(8, ESP), ECX)
+ MOV_L (REGOFF(4, ESP), EDX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EAX)
+ MOV_W (CX, REGBIS(EAX,EDX,2))
+ RET
+
+/* Desc: void v_putpixel24 (unsigned int offset, int color);
+ *
+ * In : offset within buffer, color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_putpixel24
+_v_putpixel24:
+ MOV_L (REGOFF(4, ESP), EAX)
+ MOV_L (REGOFF(8, ESP), EDX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), ECX)
+ LEA_L (REGBIS(EAX,EAX,2), EAX)
+ MOV_W (DX, REGBI(ECX,EAX))
+ SHR_L (CONST(16), EDX)
+ MOV_B (DL, REGBID(ECX,EAX,2))
+ RET
+
+/* Desc: void v_putpixel32 (unsigned int offset, int color);
+ *
+ * In : offset within buffer, color
+ * Out : -
+ *
+ * Note: uses current draw buffer
+ */
+ ALIGNTEXT32
+ GLOBL _v_putpixel32
+_v_putpixel32:
+ MOV_L (REGOFF(8, ESP), ECX)
+ MOV_L (REGOFF(4, ESP), EDX)
+ MOV_L (CONTENT(_vl_current_draw_buffer), EAX)
+ MOV_L (ECX, REGBIS(EAX,EDX,4))
+ RET
diff --git a/src/mesa/drivers/dri/common/depthtmp.h b/src/mesa/drivers/dri/common/depthtmp.h
new file mode 100644
index 0000000..a64a62c
--- /dev/null
+++ b/src/mesa/drivers/dri/common/depthtmp.h
@@ -0,0 +1,220 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/common/depthtmp.h,v 1.5 2001/03/21 16:14:20 dawes Exp $ */
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+
+#ifndef HAVE_HW_DEPTH_SPANS
+#define HAVE_HW_DEPTH_SPANS 0
+#endif
+#ifndef HAVE_HW_DEPTH_PIXELS
+#define HAVE_HW_DEPTH_PIXELS 0
+#endif
+
+#ifndef HW_READ_LOCK
+#define HW_READ_LOCK() HW_LOCK()
+#endif
+#ifndef HW_READ_UNLOCK
+#define HW_READ_UNLOCK() HW_UNLOCK()
+#endif
+
+static void TAG(WriteDepthSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth *depth,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan 0..%d (x1 %d)\n",
+ (int)n, (int)x );
+
+ WRITE_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "WriteDepthSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1 );
+
+ if ( mask ) {
+ for ( ; i < n1 ; i++, x1++ ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth[i] );
+ }
+ } else {
+ for ( ; i < n1 ; i++, x1++ ) {
+ WRITE_DEPTH( x1, y, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+#if 0 /**/
+#ifndef NO_MONO
+
+static void TAG(WriteMonoDepthSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth depth,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+
+ if ( DBG ) fprintf( stderr, "%s %d..%d (x1 %d) = %u\n",
+ __FUNCTION__, (int)i, (int)n1, (int)x1, (GLuint)depth );
+
+ if ( mask ) {
+ for ( ; i < n1 ; i++, x1++ ) {
+ if ( mask[i] ) WRITE_DEPTH( x1, y, depth );
+ }
+ } else {
+ for ( ; i < n1 ; i++, x1++ ) {
+ WRITE_DEPTH( x1, y, depth );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+#endif
+#endif /**/
+
+static void TAG(WriteDepthPixels)( GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLdepth depth[],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "WriteDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ WRITE_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ for ( i = 0 ; i < n ; i++ ) {
+ if ( mask[i] ) {
+ const int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ WRITE_DEPTH( x[i], fy, depth[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+#if 0
+/* Read depth spans and pixels
+ */
+static void TAG(ReadDepthSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLdepth depth[] )
+{
+ HW_READ_LOCK()
+ {
+ GLint x1, n1;
+ LOCAL_DEPTH_VARS;
+
+ y = Y_FLIP( y );
+
+ if ( DBG ) fprintf( stderr, "ReadDepthSpan\n" );
+
+#if HAVE_HW_DEPTH_SPANS
+ (void) x1; (void) n1;
+
+ READ_DEPTH_SPAN();
+#else
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN( x, y, n, x1, n1, i );
+ for ( ; i < n1 ; i++ )
+ READ_DEPTH( depth[i], (x1+i), y );
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+#endif
+
+static void TAG(ReadDepthPixels)( GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLdepth depth[] )
+{
+ HW_READ_LOCK()
+ {
+ GLint i;
+ LOCAL_DEPTH_VARS;
+
+ if ( DBG ) fprintf( stderr, "ReadDepthPixels\n" );
+
+#if HAVE_HW_DEPTH_PIXELS
+ (void) i;
+
+ READ_DEPTH_PIXELS();
+#else
+ HW_CLIPLOOP()
+ {
+ for ( i = 0 ; i < n ;i++ ) {
+ int fy = Y_FLIP( y[i] );
+ if ( CLIPPIXEL( x[i], fy ) )
+ READ_DEPTH( depth[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+#endif
+ }
+ HW_READ_UNLOCK();
+}
+
+
+#if HAVE_HW_DEPTH_SPANS
+#undef WRITE_DEPTH_SPAN
+#undef WRITE_DEPTH_PIXELS
+#undef READ_DEPTH_SPAN
+#undef READ_DEPTH_PIXELS
+#else
+#undef WRITE_DEPTH
+#undef READ_DEPTH
+#endif
+#undef TAG
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
new file mode 100644
index 0000000..eff21af
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -0,0 +1,1693 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \note
+ * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
+ * that only the "new" libGL-to-driver interfaces are supported. This breaks
+ * backwards compatability. However, this may be necessary when DRI drivers
+ * are built to be used in non-XFree86 environments.
+ *
+ * \todo There are still some places in the code that need to be wrapped with
+ * \c DRI_NEW_INTERFACE_ONLY.
+ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+# include <X11/Xlibint.h>
+# include <Xext.h>
+# include <extutil.h>
+# include "xf86dri.h"
+# define _mesa_malloc(b) Xmalloc(b)
+# define _mesa_free(m) Xfree(m)
+#else
+# include "imports.h"
+# define None 0
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+#include "dri_util.h"
+#include "drm_sarea.h"
+#include "glcontextmodes.h"
+
+#ifndef PFNGLXGETMSCRATEOMLPROC
+typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRInativeDisplay *dpy, __DRIid drawable, int32_t *numerator, int32_t *denominator);
+#endif
+
+/**
+ * Weak thread-safety dispatch pointer. Older versions of libGL will not have
+ * this symbol, so a "weak" version is included here so that the driver will
+ * dynamically link properly. The value is set to \c NULL. This forces the
+ * driver to fall back to the old dispatch interface.
+ */
+struct _glapi_table *_glapi_DispatchTSD __attribute__((weak)) = NULL;
+
+/**
+ * This is used in a couple of places that call \c driCreateNewDrawable.
+ */
+static const int empty_attribute_list[1] = { None };
+
+/**
+ * Function used to determine if a drawable (window) still exists. Ideally
+ * this function comes from libGL. With older versions of libGL from XFree86
+ * we can fall-back to an internal version.
+ *
+ * \sa __driWindowExists __glXWindowExists
+ */
+static PFNGLXWINDOWEXISTSPROC window_exists;
+
+typedef GLboolean (*PFNGLXCREATECONTEXTWITHCONFIGPROC)( __DRInativeDisplay*, int, int, void *,
+ drm_context_t * );
+
+static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config;
+
+/**
+ * Cached copy of the internal API version used by libGL and the client-side
+ * DRI driver.
+ */
+static int api_ver = 0;
+
+/* forward declarations */
+static int driQueryFrameTracking( __DRInativeDisplay * dpy, void * priv,
+ int64_t * sbc, int64_t * missedFrames, float * lastMissedUsage,
+ float * usage );
+
+static void *driCreateNewDrawable(__DRInativeDisplay *dpy, const __GLcontextModes *modes,
+ __DRIid draw, __DRIdrawable *pdraw, int renderType, const int *attrs);
+
+static void driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate);
+
+
+
+
+#ifdef not_defined
+static GLboolean driFeatureOn(const char *name)
+{
+ char *env = getenv(name);
+
+ if (!env) return GL_FALSE;
+ if (!strcasecmp(env, "enable")) return GL_TRUE;
+ if (!strcasecmp(env, "1")) return GL_TRUE;
+ if (!strcasecmp(env, "on")) return GL_TRUE;
+ if (!strcasecmp(env, "true")) return GL_TRUE;
+ if (!strcasecmp(env, "t")) return GL_TRUE;
+ if (!strcasecmp(env, "yes")) return GL_TRUE;
+ if (!strcasecmp(env, "y")) return GL_TRUE;
+
+ return GL_FALSE;
+}
+#endif /* not_defined */
+
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ *
+ * Is called from the drivers.
+ *
+ * \param f \c printf like format string.
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+ va_list args;
+
+ if (getenv("LIBGL_DEBUG")) {
+ fprintf(stderr, "libGL error: \n");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * fd.o bug #1713: Some rare libGL's have __glXFindDRIScreen defined but do not
+ * export it via glXGetProcAddress. These are not supported anymore, so print
+ * an error message to that effect. - ajax 2004-10-26
+ */
+typedef __DRIscreen *(*PFNGLXFINDDRISCREEN)(__DRInativeDisplay *, int);
+
+static __DRIscreen *glx_find_dri_screen(__DRInativeDisplay *d, int i)
+{
+ PFNGLXFINDDRISCREEN findscreen =
+ (PFNGLXFINDDRISCREEN)glXGetProcAddress("__glXFindDRIScreen");
+
+ if (!findscreen)
+ {
+ __driUtilMessage("glXGetProcAddress(\"__glXFindDRIScreen\") failed!");
+ __driUtilMessage("Your libGL is too old, please upgrade.");
+ return NULL;
+ }
+ else return findscreen(d, i);
+}
+
+/*****************************************************************/
+/** \name Visual utility functions */
+/*****************************************************************/
+/*@{*/
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Find a \c __GLcontextModes structure matching the given visual ID.
+ *
+ * \param dpy Display to search for a matching configuration.
+ * \param scrn Screen number on \c dpy to be searched.
+ * \param vid Desired \c VisualID to find.
+ *
+ * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
+ * if found, or \c NULL if no match is found.
+ */
+static const __GLcontextModes *
+findConfigMode(__DRInativeDisplay *dpy, int scrn, VisualID vid,
+ const __DRIscreen * pDRIScreen)
+{
+ if ( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) ) {
+ const __DRIscreenPrivate * const psp =
+ (const __DRIscreenPrivate *) pDRIScreen->private;
+
+ return _gl_context_modes_find_visual( psp->modes, vid );
+ }
+
+ return NULL;
+}
+
+
+/**
+ * This function is a hack to work-around old versions of libGL.so that
+ * do not export \c XF86DRICreateContextWithConfig. I would modify the
+ * code to just use this function, but the stand-alone driver (i.e., DRI
+ * drivers that are built to work without XFree86) shouldn't have to know
+ * about X structures like a \c Visual.
+ */
+static GLboolean
+fake_XF86DRICreateContextWithConfig( __DRInativeDisplay* dpy, int screen, int configID,
+ XID* context, drm_context_t * hHWContext )
+{
+ Visual vis;
+
+ vis.visualid = configID;
+ return XF86DRICreateContext( dpy, screen, & vis, context, hHWContext );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable list management */
+/*****************************************************************/
+/*@{*/
+
+static GLboolean __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
+{
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ if (drmHashInsert(drawHash, pdp->draw, pdraw))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static __DRIdrawable *__driFindDrawable(void *drawHash, __DRIid draw)
+{
+ int retcode;
+ __DRIdrawable *pdraw;
+
+ retcode = drmHashLookup(drawHash, draw, (void *)&pdraw);
+ if (retcode)
+ return NULL;
+
+ return pdraw;
+}
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+static GLboolean __driWindowExistsFlag;
+
+static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
+{
+ if (xerr->error_code == BadWindow) {
+ __driWindowExistsFlag = GL_FALSE;
+ }
+ return 0;
+}
+
+/**
+ * Determine if a window associated with a \c GLXDrawable exists on the
+ * X-server.
+ *
+ * \param dpy Display associated with the drawable to be queried.
+ * \param draw \c GLXDrawable to test.
+ *
+ * \returns \c GL_TRUE if a window exists that is associated with \c draw,
+ * otherwise \c GL_FALSE is returned.
+ *
+ * \warning This function is not currently thread-safe.
+ *
+ * \deprecated
+ * \c __glXWindowExists (from libGL) is prefered over this function. Starting
+ * with the next major release of XFree86, this function will be removed.
+ * Even now this function is no longer directly called. Instead it is called
+ * via a function pointer if and only if \c __glXWindowExists does not exist.
+ *
+ * \sa __glXWindowExists glXGetProcAddress window_exists
+ */
+static GLboolean __driWindowExists(Display *dpy, GLXDrawable draw)
+{
+ XWindowAttributes xwa;
+ int (*oldXErrorHandler)(Display *, XErrorEvent *);
+
+ XSync(dpy, GL_FALSE);
+ __driWindowExistsFlag = GL_TRUE;
+ oldXErrorHandler = XSetErrorHandler(__driWindowExistsErrorHandler);
+ XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
+ XSetErrorHandler(oldXErrorHandler);
+ return __driWindowExistsFlag;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/**
+ * Find drawables in the local hash that have been destroyed on the
+ * server.
+ *
+ * \param drawHash Hash-table containing all know drawables.
+ */
+static void __driGarbageCollectDrawables(void *drawHash)
+{
+ __DRIid draw;
+ __DRInativeDisplay *dpy;
+ __DRIdrawable *pdraw;
+
+ if (drmHashFirst(drawHash, &draw, (void *)&pdraw) == 1) {
+ do {
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+ dpy = pdp->driScreenPriv->display;
+ if (! (*window_exists)(dpy, draw)) {
+ /* Destroy the local drawable data in the hash table, if the
+ drawable no longer exists in the Xserver */
+ drmHashDelete(drawHash, draw);
+ (*pdraw->destroyDrawable)(dpy, pdraw->private);
+ _mesa_free(pdraw);
+ }
+ } while (drmHashNext(drawHash, &draw, (void *)&pdraw) == 1);
+ }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context (un)binding functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param draw drawable.
+ * \param read Current reading drawable.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
+ * return.
+ *
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL.
+ */
+static GLboolean driUnbindContext3(__DRInativeDisplay *dpy, int scrn,
+ __DRIid draw, __DRIid read,
+ __DRIcontext *ctx)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIdrawable *pdraw;
+ __DRIdrawable *pread;
+ __DRIcontextPrivate *pcp;
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+ __DRIdrawablePrivate *prp;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext3.
+ */
+
+ if (ctx == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = glx_find_dri_screen(dpy, scrn);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+ pcp = (__DRIcontextPrivate *)ctx->private;
+
+ pdraw = __driFindDrawable(psp->drawHash, draw);
+ if (!pdraw) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+ pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ pread = __driFindDrawable(psp->drawHash, read);
+ if (!pread) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+ prp = (__DRIdrawablePrivate *)pread->private;
+
+
+ /* Let driver unbind drawable from context */
+ (*psp->DriverAPI.UnbindContext)(pcp);
+
+
+ if (pdp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pdp->refcount--;
+
+ if (prp != pdp) {
+ if (prp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ prp->refcount--;
+ }
+
+
+ /* XXX this is disabled so that if we call SwapBuffers on an unbound
+ * window we can determine the last context bound to the window and
+ * use that context's lock. (BrianP, 2-Dec-2000)
+ */
+#if 0
+ /* Unbind the drawable */
+ pcp->driDrawablePriv = NULL;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+#endif
+
+ return GL_TRUE;
+}
+
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ *
+ * \bug This function calls \c driCreateNewDrawable in two places with the
+ * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might
+ * be needed in those places when support for pbuffers and / or pixmaps
+ * is added. Is it safe to assume that the drawable is a window?
+ */
+static GLboolean DoBindContext(__DRInativeDisplay *dpy,
+ __DRIid draw, __DRIid read,
+ __DRIcontext *ctx, const __GLcontextModes * modes,
+ __DRIscreenPrivate *psp)
+{
+ __DRIdrawable *pdraw;
+ __DRIdrawablePrivate *pdp;
+ __DRIdrawable *pread;
+ __DRIdrawablePrivate *prp;
+ __DRIcontextPrivate * const pcp = ctx->private;
+
+
+ /* Find the _DRIdrawable which corresponds to the writing drawable. */
+ pdraw = __driFindDrawable(psp->drawHash, draw);
+ if (!pdraw) {
+ /* Allocate a new drawable */
+ pdraw = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable));
+ if (!pdraw) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* Create a new drawable */
+ driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
+ empty_attribute_list);
+ if (!pdraw->private) {
+ /* ERROR!!! */
+ _mesa_free(pdraw);
+ return GL_FALSE;
+ }
+
+ }
+ pdp = (__DRIdrawablePrivate *) pdraw->private;
+
+ /* Find the _DRIdrawable which corresponds to the reading drawable. */
+ if (read == draw) {
+ /* read buffer == draw buffer */
+ prp = pdp;
+ }
+ else {
+ pread = __driFindDrawable(psp->drawHash, read);
+ if (!pread) {
+ /* Allocate a new drawable */
+ pread = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable));
+ if (!pread) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* Create a new drawable */
+ driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
+ empty_attribute_list);
+ if (!pread->private) {
+ /* ERROR!!! */
+ _mesa_free(pread);
+ return GL_FALSE;
+ }
+ }
+ prp = (__DRIdrawablePrivate *) pread->private;
+ }
+
+ /* Bind the drawable to the context */
+ pcp->driDrawablePriv = pdp;
+ pdp->driContextPriv = pcp;
+ pdp->refcount++;
+ if ( pdp != prp ) {
+ prp->refcount++;
+ }
+
+ /*
+ ** Now that we have a context associated with this drawable, we can
+ ** initialize the drawable information if has not been done before.
+ */
+ if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(pdp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+
+ /* Call device-specific MakeCurrent */
+ (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static GLboolean driBindContext3(__DRInativeDisplay *dpy, int scrn,
+ __DRIid draw, __DRIid read,
+ __DRIcontext * ctx)
+{
+ __DRIscreen *pDRIScreen;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driBindContext.
+ */
+
+ if (ctx == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = glx_find_dri_screen(dpy, scrn);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ return DoBindContext( dpy, draw, read, ctx, ctx->mode,
+ (__DRIscreenPrivate *)pDRIScreen->private );
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static GLboolean driBindContext2(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ GLXContext gc)
+{
+ __DRIscreen *pDRIScreen;
+ const __GLcontextModes *modes;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driBindContext.
+ */
+
+ if (gc == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = glx_find_dri_screen(dpy, scrn);
+ modes = (driCompareGLXAPIVersion( 20040317 ) >= 0)
+ ? gc->driContext.mode
+ : findConfigMode( dpy, scrn, gc->vid, pDRIScreen );
+
+ if ( modes == NULL ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* findConfigMode will return NULL if the DRI screen or screen private
+ * are NULL.
+ */
+ assert( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) );
+
+ return DoBindContext( dpy, draw, read, & gc->driContext, modes,
+ (__DRIscreenPrivate *)pDRIScreen->private );
+}
+
+static GLboolean driUnbindContext2(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ GLXContext gc)
+{
+ return driUnbindContext3(dpy, scrn, draw, read, & gc->driContext);
+}
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static GLboolean driBindContext(Display *dpy, int scrn,
+ GLXDrawable draw, GLXContext gc)
+{
+ return driBindContext2(dpy, scrn, draw, draw, gc);
+}
+
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static GLboolean driUnbindContext(Display *dpy, int scrn,
+ GLXDrawable draw, GLXContext gc,
+ int will_rebind)
+{
+ (void) will_rebind;
+ return driUnbindContext2( dpy, scrn, draw, draw, gc );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ *
+ * This function basically updates the __DRIdrawablePrivate struct's
+ * cliprect information by calling \c __DRIDrawablePrivate::getInfo. This is
+ * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
+{
+ __DRIscreenPrivate *psp;
+ __DRIcontextPrivate *pcp = pdp->driContextPriv;
+
+ if (!pcp || (pdp != pcp->driDrawablePriv)) {
+ /* ERROR!!! */
+ return;
+ }
+
+ psp = pdp->driScreenPriv;
+ if (!psp) {
+ /* ERROR!!! */
+ return;
+ }
+
+ if (pdp->pClipRects) {
+ _mesa_free(pdp->pClipRects);
+ }
+
+ if (pdp->pBackClipRects) {
+ _mesa_free(pdp->pBackClipRects);
+ }
+
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+ if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
+ ! (*pdp->getInfo)(pdp->display, pdp->screen, pdp->draw,
+ &pdp->index, &pdp->lastStamp,
+ &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+ &pdp->numClipRects, &pdp->pClipRects,
+ &pdp->backX,
+ &pdp->backY,
+ &pdp->numBackClipRects,
+ &pdp->pBackClipRects )) {
+ /* Error -- eg the window may have been destroyed. Keep going
+ * with no cliprects.
+ */
+ pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+ pdp->numClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->numBackClipRects = 0;
+ pdp->pBackClipRects = NULL;
+ }
+ else
+ pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Swap buffers.
+ *
+ * \param dpy the display handle.
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DRIdrawablePrivate::swapBuffers.
+ *
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers( __DRInativeDisplay *dpy, void *drawablePrivate )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ dPriv->swapBuffers(dPriv);
+ (void) dpy;
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetMSC( void *screenPrivate, int64_t *msc )
+{
+ __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
+
+ return sPriv->DriverAPI.GetMSC( sPriv, msc );
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetSBC( __DRInativeDisplay *dpy, void *drawablePrivate, int64_t *sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ __DRIswapInfo sInfo;
+ int status;
+
+
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+
+ return status;
+}
+
+static int driWaitForSBC( __DRInativeDisplay * dpy, void *drawablePriv,
+ int64_t target_sbc,
+ int64_t * msc, int64_t * sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+ return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
+ msc, sbc );
+}
+
+static int driWaitForMSC( __DRInativeDisplay * dpy, void *drawablePriv,
+ int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc, int64_t * sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+ __DRIswapInfo sInfo;
+ int status;
+
+
+ status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+ divisor, remainder,
+ msc );
+
+ /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+ * is supported but GLX_OML_sync_control is not. Therefore, don't return
+ * an error value if GetSwapInfo() is not implemented.
+ */
+ if ( status == 0
+ && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+ }
+
+ return status;
+}
+
+static int64_t driSwapBuffersMSC( __DRInativeDisplay * dpy, void *drawablePriv,
+ int64_t target_msc,
+ int64_t divisor, int64_t remainder )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+ return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
+ divisor,
+ remainder );
+}
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static void *driCreateNewDrawable(__DRInativeDisplay *dpy,
+ const __GLcontextModes *modes,
+ __DRIid draw,
+ __DRIdrawable *pdraw,
+ int renderType,
+ const int *attrs)
+{
+ __DRIscreen * const pDRIScreen = glx_find_dri_screen(dpy, modes->screen);
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+
+
+ pdraw->private = NULL;
+
+ /* Since pbuffers are not yet supported, no drawable attributes are
+ * supported either.
+ */
+ (void) attrs;
+
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ return NULL;
+ }
+
+ pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
+ if (!pdp) {
+ return NULL;
+ }
+
+ if (!XF86DRICreateDrawable(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
+ _mesa_free(pdp);
+ return NULL;
+ }
+
+ pdp->draw = draw;
+ pdp->pdraw = pdraw;
+ pdp->refcount = 0;
+ pdp->pStamp = NULL;
+ pdp->lastStamp = 0;
+ pdp->index = 0;
+ pdp->x = 0;
+ pdp->y = 0;
+ pdp->w = 0;
+ pdp->h = 0;
+ pdp->numClipRects = 0;
+ pdp->numBackClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->pBackClipRects = NULL;
+ pdp->display = dpy;
+ pdp->screen = modes->screen;
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+ pdp->driScreenPriv = psp;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+
+ pdp->getInfo = (PFNGLXGETDRAWABLEINFOPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXGetDrawableInfo" );
+ if ( pdp->getInfo == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+ (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
+ _mesa_free(pdp);
+ return NULL;
+#else
+ pdp->getInfo = (PFNGLXGETDRAWABLEINFOPROC) XF86DRIGetDrawableInfo;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+ }
+
+ if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
+ renderType == GLX_PIXMAP_BIT)) {
+ (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
+ _mesa_free(pdp);
+ return NULL;
+ }
+
+ pdraw->private = pdp;
+ pdraw->destroyDrawable = driDestroyDrawable;
+ pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
+
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ pdraw->getSBC = driGetSBC;
+ pdraw->waitForSBC = driWaitForSBC;
+ pdraw->waitForMSC = driWaitForMSC;
+ pdraw->swapBuffersMSC = driSwapBuffersMSC;
+ pdraw->frameTracking = NULL;
+ pdraw->queryFrameTracking = driQueryFrameTracking;
+
+ /* This special default value is replaced with the configured
+ * default value when the drawable is first bound to a direct
+ * rendering context. */
+ pdraw->swap_interval = (unsigned)-1;
+ }
+
+ pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
+
+ /* Add pdraw to drawable list */
+ if (!__driAddDrawable(psp->drawHash, pdraw)) {
+ /* ERROR!!! */
+ (*pdraw->destroyDrawable)(dpy, pdp);
+ _mesa_free(pdp);
+ pdp = NULL;
+ pdraw->private = NULL;
+ }
+
+ return (void *) pdp;
+}
+
+static __DRIdrawable *driGetDrawable(__DRInativeDisplay *dpy, __DRIid draw,
+ void *screenPrivate)
+{
+ __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+ /*
+ ** Make sure this routine returns NULL if the drawable is not bound
+ ** to a direct rendering context!
+ */
+ return __driFindDrawable(psp->drawHash, draw);
+}
+
+static void driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate)
+{
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
+ __DRIscreenPrivate *psp = pdp->driScreenPriv;
+ int scrn = psp->myNum;
+
+ if (pdp) {
+ (*psp->DriverAPI.DestroyBuffer)(pdp);
+ if ((*window_exists)(dpy, pdp->draw))
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ if (pdp->pClipRects) {
+ _mesa_free(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+ if (pdp->pBackClipRects) {
+ _mesa_free(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+ _mesa_free(pdp);
+ }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param contextPrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void driDestroyContext(__DRInativeDisplay *dpy, int scrn, void *contextPrivate)
+{
+ __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate;
+
+ if (pcp) {
+ (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+ (void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
+ _mesa_free(pcp);
+ }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param dpy The display handle.
+ * \param modes Mode used to create the new context.
+ * \param render_type Type of rendering target. \c GLX_RGBA is the only
+ * type likely to ever be supported for direct-rendering.
+ * \param sharedPrivate The shared context dependent methods or \c NULL if
+ * non-existent.
+ * \param pctx DRI context to receive the context dependent methods.
+ *
+ * \returns An opaque pointer to the per-context private information on
+ * success, or \c NULL on failure.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure. It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static void *
+driCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes,
+ int render_type, void *sharedPrivate, __DRIcontext *pctx)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIcontextPrivate *pcp;
+ __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
+ __DRIscreenPrivate *psp;
+ void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
+
+ pDRIScreen = glx_find_dri_screen(dpy, modes->screen);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return NULL;
+ }
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+
+ pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
+ if (!pcp) {
+ return NULL;
+ }
+
+ if (! (*create_context_with_config)(dpy, modes->screen, modes->fbconfigID,
+ &pcp->contextID, &pcp->hHWContext)) {
+ _mesa_free(pcp);
+ return NULL;
+ }
+
+ pcp->display = dpy;
+ pcp->driScreenPriv = psp;
+ pcp->driDrawablePriv = NULL;
+
+ /* When the first context is created for a screen, initialize a "dummy"
+ * context.
+ */
+
+ if (!psp->dummyContextPriv.driScreenPriv) {
+ psp->dummyContextPriv.contextID = 0;
+ psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
+ psp->dummyContextPriv.driScreenPriv = psp;
+ psp->dummyContextPriv.driDrawablePriv = NULL;
+ psp->dummyContextPriv.driverPrivate = NULL;
+ /* No other fields should be used! */
+ }
+
+ pctx->destroyContext = driDestroyContext;
+#ifdef DRI_NEW_INTERFACE_ONLY
+ pctx->bindContext = NULL;
+ pctx->unbindContext = NULL;
+ pctx->bindContext2 = NULL;
+ pctx->unbindContext2 = NULL;
+ pctx->bindContext3 = driBindContext3;
+ pctx->unbindContext3 = driUnbindContext3;
+#else
+ pctx->bindContext = (void *)driBindContext;
+ pctx->unbindContext = (void *)driUnbindContext;
+ if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
+ pctx->bindContext2 = (void *)driBindContext2;
+ pctx->unbindContext2 = (void *)driUnbindContext2;
+ }
+
+ if ( driCompareGLXAPIVersion( 20040415 ) >= 0 ) {
+ pctx->bindContext3 = (void *)driBindContext3;
+ pctx->unbindContext3 = (void *)driUnbindContext3;
+ }
+#endif
+
+ if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
+ (void)XF86DRIDestroyContext(dpy, modes->screen, pcp->contextID);
+ _mesa_free(pcp);
+ return NULL;
+ }
+
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+
+ return pcp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param dpy the display handle.
+ * \param vis the visual information.
+ * \param sharedPrivate the shared context dependent methods or \c NULL if
+ * non-existent.
+ * \param pctx will receive the context dependent methods.
+ *
+ * \returns a opaque pointer to the per-context private information on success, or \c NULL
+ * on failure.
+ *
+ * \deprecated
+ * This function has been replaced by \c driCreateNewContext. In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL. Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure. It
+ * gets the visual, converts it into a __GLcontextModesRec and passes it
+ * to __DriverAPIRec::CreateContext to create the context.
+ */
+static void *driCreateContext(Display *dpy, XVisualInfo *vis,
+ void *sharedPrivate, __DRIcontext *pctx)
+{
+ __DRIscreen *pDRIScreen;
+ const __GLcontextModes *modes;
+
+ pDRIScreen = glx_find_dri_screen(dpy, vis->screen);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return NULL;
+ }
+
+
+ /* Setup a __GLcontextModes struct corresponding to vis->visualid
+ * and create the rendering context.
+ */
+
+ modes = findConfigMode(dpy, vis->screen, vis->visualid, pDRIScreen);
+ return (modes == NULL)
+ ? NULL
+ : driCreateNewContext( dpy, modes, GLX_RGBA_TYPE,
+ sharedPrivate, pctx );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param screenPrivate opaque pointer to the per-screen private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPrivate)
+{
+ __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+ if (psp) {
+ /* No interaction with the X-server is possible at this point. This
+ * routine is called after XCloseDisplay, so there is no protocol
+ * stream open to the X-server anymore.
+ */
+
+ if (psp->DriverAPI.DestroyScreen)
+ (*psp->DriverAPI.DestroyScreen)(psp);
+
+ (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ _mesa_free(psp->pDevPriv);
+ (void)drmClose(psp->fd);
+ if ( psp->modes != NULL ) {
+ _gl_context_modes_destroy( psp->modes );
+ }
+ _mesa_free(psp);
+ }
+}
+
+
+/**
+ * Utility function used to create a new driver-private screen structure.
+ *
+ * \param dpy Display pointer
+ * \param scrn Index of the screen
+ * \param psc DRI screen data (not driver private)
+ * \param modes Linked list of known display modes. This list is, at a
+ * minimum, a list of modes based on the current display mode.
+ * These roughly match the set of available X11 visuals, but it
+ * need not be limited to X11! The calling libGL should create
+ * a list that will inform the driver of the current display
+ * mode (i.e., color buffer depth, depth buffer depth, etc.).
+ * \param ddx_version Version of the 2D DDX. This may not be meaningful for
+ * all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ * framebuffer.
+ * \param pSAREA Pointer the the SAREA.
+ * \param fd Device handle for the DRM.
+ * \param internal_api_version Version of the internal interface between the
+ * driver and libGL.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ */
+__DRIscreenPrivate *
+__driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
+ __GLcontextModes * modes,
+ const __DRIversion * ddx_version,
+ const __DRIversion * dri_version,
+ const __DRIversion * drm_version,
+ const __DRIframebuffer * frame_buffer,
+ drm_sarea_t *pSAREA,
+ int fd,
+ int internal_api_version,
+ const struct __DriverAPIRec *driverAPI)
+{
+ __DRIscreenPrivate *psp;
+
+
+#ifdef DRI_NEW_INTERFACE_ONLY
+ if ( internal_api_version < 20040602 ) {
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20040602 or later is required.\n", internal_api_version );
+ return NULL;
+ }
+#else
+ if ( internal_api_version == 20031201 ) {
+ fprintf( stderr, "libGL error: libGL version 20031201 has critical "
+ "binary compatilibity bugs.\nlibGL error: You must upgrade "
+ "to use direct-rendering!\n" );
+ return NULL;
+ }
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+ window_exists = (PFNGLXWINDOWEXISTSPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
+
+ if ( window_exists == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20021128 or later is required.\n", internal_api_version );
+ return NULL;
+#else
+ window_exists = (PFNGLXWINDOWEXISTSPROC) __driWindowExists;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+ }
+
+ create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXCreateContextWithConfig" );
+ if ( create_context_with_config == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20031201 or later is required.\n", internal_api_version );
+ return NULL;
+#else
+ create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+ fake_XF86DRICreateContextWithConfig;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+ }
+
+ api_ver = internal_api_version;
+
+ psp = (__DRIscreenPrivate *)_mesa_malloc(sizeof(__DRIscreenPrivate));
+ if (!psp) {
+ return NULL;
+ }
+
+ /* Create the hash table */
+ psp->drawHash = drmHashCreate();
+ if ( psp->drawHash == NULL ) {
+ _mesa_free( psp );
+ return NULL;
+ }
+
+ psp->display = dpy;
+ psp->myNum = scrn;
+ psp->psc = psc;
+ psp->modes = modes;
+
+ /*
+ ** NOT_DONE: This is used by the X server to detect when the client
+ ** has died while holding the drawable lock. The client sets the
+ ** drawable lock to this value.
+ */
+ psp->drawLockID = 1;
+
+ psp->drmMajor = drm_version->major;
+ psp->drmMinor = drm_version->minor;
+ psp->drmPatch = drm_version->patch;
+ psp->ddxMajor = ddx_version->major;
+ psp->ddxMinor = ddx_version->minor;
+ psp->ddxPatch = ddx_version->patch;
+ psp->driMajor = dri_version->major;
+ psp->driMinor = dri_version->minor;
+ psp->driPatch = dri_version->patch;
+
+ /* install driver's callback functions */
+ memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
+
+ psp->pSAREA = pSAREA;
+
+ psp->pFB = frame_buffer->base;
+ psp->fbSize = frame_buffer->size;
+ psp->fbStride = frame_buffer->stride;
+ psp->fbWidth = frame_buffer->width;
+ psp->fbHeight = frame_buffer->height;
+ psp->devPrivSize = frame_buffer->dev_priv_size;
+ psp->pDevPriv = frame_buffer->dev_priv;
+
+ psp->fd = fd;
+
+ /*
+ ** Do not init dummy context here; actual initialization will be
+ ** done when the first DRI context is created. Init screen priv ptr
+ ** to NULL to let CreateContext routine that it needs to be inited.
+ */
+ psp->dummyContextPriv.driScreenPriv = NULL;
+
+ psc->destroyScreen = driDestroyScreen;
+#ifndef DRI_NEW_INTERFACE_ONLY
+ psc->createContext = driCreateContext;
+#else
+ psc->createContext = NULL;
+#endif
+ psc->createNewDrawable = driCreateNewDrawable;
+ psc->getDrawable = driGetDrawable;
+#ifdef DRI_NEW_INTERFACE_ONLY
+ psc->getMSC = driGetMSC;
+ psc->createNewContext = driCreateNewContext;
+#else
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ psc->getMSC = driGetMSC;
+
+ if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
+ psc->createNewContext = driCreateNewContext;
+ }
+ }
+#endif
+
+ if ( (psp->DriverAPI.InitDriver != NULL)
+ && !(*psp->DriverAPI.InitDriver)(psp) ) {
+ _mesa_free( psp );
+ return NULL;
+ }
+
+
+ return psp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Utility function used to create a new driver-private screen structure.
+ *
+ * \param dpy Display pointer.
+ * \param scrn Index of the screen.
+ * \param psc DRI screen data (not driver private)
+ * \param numConfigs Number of visual configs pointed to by \c configs.
+ * \param configs Array of GLXvisualConfigs exported by the 2D driver.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ *
+ * \deprecated
+ * This function has been replaced by \c __driUtilCreateNewScreen. In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL. Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ */
+__DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *configs,
+ const struct __DriverAPIRec *driverAPI)
+{
+ int directCapable;
+ __DRIscreenPrivate *psp = NULL;
+ drm_handle_t hSAREA;
+ drmAddress pSAREA;
+ char *BusID;
+ __GLcontextModes *modes;
+ __GLcontextModes *temp;
+ int i;
+ __DRIversion ddx_version;
+ __DRIversion dri_version;
+ __DRIversion drm_version;
+ __DRIframebuffer framebuffer;
+ int fd = -1;
+ int status;
+ const char * err_msg;
+ const char * err_extra;
+
+
+ if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)
+ || !directCapable) {
+ return NULL;
+ }
+
+
+ /* Create the linked list of context modes, and populate it with the
+ * GLX visual information passed in by libGL.
+ */
+
+ modes = _gl_context_modes_create( numConfigs, sizeof(__GLcontextModes) );
+ if ( modes == NULL ) {
+ return NULL;
+ }
+
+ temp = modes;
+ for ( i = 0 ; i < numConfigs ; i++ ) {
+ assert( temp != NULL );
+ _gl_copy_visual_to_context_mode( temp, & configs[i] );
+ temp->screen = scrn;
+
+ temp = temp->next;
+ }
+
+ err_msg = "XF86DRIOpenConnection";
+ err_extra = NULL;
+
+ if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+ fd = drmOpen(NULL,BusID);
+ _mesa_free(BusID); /* No longer needed */
+
+ err_msg = "open DRM";
+ err_extra = strerror( -fd );
+
+ if (fd >= 0) {
+ drm_magic_t magic;
+
+ err_msg = "drmGetMagic";
+ err_extra = NULL;
+
+ if (!drmGetMagic(fd, &magic)) {
+ drmVersionPtr version = drmGetVersion(fd);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ }
+
+ err_msg = "XF86DRIAuthConnection";
+ if (XF86DRIAuthConnection(dpy, scrn, magic)) {
+ char *driverName;
+
+ /*
+ * Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createScreen"
+ * function.
+ */
+ err_msg = "XF86DRIGetClientDriverName";
+ if (XF86DRIGetClientDriverName(dpy, scrn,
+ &ddx_version.major,
+ &ddx_version.minor,
+ &ddx_version.patch,
+ &driverName)) {
+
+ /* No longer needed. */
+ _mesa_free( driverName );
+
+ /*
+ * Get the DRI X extension version.
+ */
+ err_msg = "XF86DRIQueryVersion";
+ if (XF86DRIQueryVersion(dpy,
+ &dri_version.major,
+ &dri_version.minor,
+ &dri_version.patch)) {
+ drm_handle_t hFB;
+ int junk;
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
+ * that has information about the screen size, depth, pitch,
+ * ancilliary buffers, DRM mmap handles, etc.
+ */
+ err_msg = "XF86DRIGetDeviceInfo";
+ if (XF86DRIGetDeviceInfo(dpy, scrn,
+ &hFB,
+ &junk,
+ &framebuffer.size,
+ &framebuffer.stride,
+ &framebuffer.dev_priv_size,
+ &framebuffer.dev_priv)) {
+ framebuffer.width = DisplayWidth(dpy, scrn);
+ framebuffer.height = DisplayHeight(dpy, scrn);
+
+ /*
+ * Map the framebuffer region.
+ */
+ status = drmMap(fd, hFB, framebuffer.size,
+ (drmAddressPtr)&framebuffer.base);
+
+ err_msg = "drmMap of framebuffer";
+ err_extra = strerror( -status );
+
+ if ( status == 0 ) {
+ /*
+ * Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createScreen" function.
+ */
+ status = drmMap(fd, hSAREA, SAREA_MAX,
+ &pSAREA);
+
+ err_msg = "drmMap of sarea";
+ err_extra = strerror( -status );
+
+ if ( status == 0 ) {
+ PFNGLXGETINTERNALVERSIONPROC get_ver;
+
+ get_ver = (PFNGLXGETINTERNALVERSIONPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
+
+ err_msg = "InitDriver";
+ err_extra = NULL;
+ psp = __driUtilCreateNewScreen( dpy, scrn, psc, modes,
+ & ddx_version,
+ & dri_version,
+ & drm_version,
+ & framebuffer,
+ pSAREA,
+ fd,
+ (get_ver != NULL) ? (*get_ver)() : 1,
+ driverAPI );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( psp == NULL ) {
+ if ( pSAREA != MAP_FAILED ) {
+ (void)drmUnmap(pSAREA, SAREA_MAX);
+ }
+
+ if ( framebuffer.base != MAP_FAILED ) {
+ (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
+ }
+
+ if ( framebuffer.dev_priv != NULL ) {
+ _mesa_free(framebuffer.dev_priv);
+ }
+
+ if ( fd >= 0 ) {
+ (void)drmClose(fd);
+ }
+
+ if ( modes != NULL ) {
+ _gl_context_modes_destroy( modes );
+ }
+
+ (void)XF86DRICloseConnection(dpy, scrn);
+
+ if ( err_extra != NULL ) {
+ fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
+ err_extra);
+ }
+ else {
+ fprintf(stderr, "libGL error: %s failed\n", err_msg );
+ }
+
+ fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+ }
+
+ return psp;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+/**
+ * Compare the current GLX API version with a driver supplied required version.
+ *
+ * The minimum required version is compared with the API version exported by
+ * the \c __glXGetInternalVersion function (in libGL.so).
+ *
+ * \param required_version Minimum required internal GLX API version.
+ * \return A tri-value return, as from strcmp is returned. A value less
+ * than, equal to, or greater than zero will be returned if the
+ * internal GLX API version is less than, equal to, or greater
+ * than \c required_version.
+ *
+ * \sa __glXGetInternalVersion().
+ */
+int driCompareGLXAPIVersion( GLuint required_version )
+{
+ if ( api_ver > required_version ) {
+ return 1;
+ }
+ else if ( api_ver == required_version ) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int
+driQueryFrameTracking( __DRInativeDisplay * dpy, void * priv,
+ int64_t * sbc, int64_t * missedFrames,
+ float * lastMissedUsage, float * usage )
+{
+ static PFNGLXGETUSTPROC get_ust;
+ __DRIswapInfo sInfo;
+ int status;
+ int64_t ust;
+ __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
+
+ if ( get_ust == NULL ) {
+ get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
+ }
+
+ status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
+ if ( status == 0 ) {
+ *sbc = sInfo.swap_count;
+ *missedFrames = sInfo.swap_missed_count;
+ *lastMissedUsage = sInfo.swap_missed_usage;
+
+ (*get_ust)( & ust );
+ *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
+ }
+
+ return status;
+}
+
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ *
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ * \f$p = t_d / (i * t_r)\f$
+ *
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ *
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param dPriv Pointer to the private drawable structure.
+ * \return If less than a single swap interval time period was required
+ * between GLX buffer swaps, a number greater than 0 and less than
+ * 1.0 is returned. If exactly one swap interval time period is
+ * required, 1.0 is returned, and if more than one is required then
+ * a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ *
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ * be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
+ int64_t current_ust )
+{
+ static PFNGLXGETMSCRATEOMLPROC get_msc_rate = NULL;
+ int32_t n;
+ int32_t d;
+ int interval;
+ float usage = 1.0;
+
+
+ if ( get_msc_rate == NULL ) {
+ get_msc_rate = (PFNGLXGETMSCRATEOMLPROC)
+ glXGetProcAddress( (const GLubyte *) "glXGetMscRateOML" );
+ }
+
+ if ( (get_msc_rate != NULL)
+ && get_msc_rate( dPriv->display, dPriv->draw, &n, &d ) ) {
+ interval = (dPriv->pdraw->swap_interval != 0)
+ ? dPriv->pdraw->swap_interval : 1;
+
+
+ /* We want to calculate
+ * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
+ * current_UST by calling __glXGetUST. last_swap_UST is stored in
+ * dPriv->swap_ust. interval has already been calculated.
+ *
+ * The only tricky part is us_per_refresh. us_per_refresh is
+ * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
+ * around and say us_per_refresh = 1000000 * d / n. Since this goes in
+ * the denominator of the final calculation, we calculate
+ * (interval * 1000000 * d) and move n into the numerator.
+ */
+
+ usage = (current_ust - last_swap_ust);
+ usage *= n;
+ usage /= (interval * d);
+ usage /= 1000000.0;
+ }
+
+ return usage;
+}
+
+/*@}*/
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
new file mode 100644
index 0000000..534a267
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -0,0 +1,568 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * Copyright 1998-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, sub license, 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 NON-INFRINGEMENT.
+ * 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.
+ */
+
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define CAPI /* XXX this should be globally defined somewhere */
+
+#ifdef DRI_NEW_INTERFACE_ONLY
+# include <GL/gl.h>
+#else
+# include "glxclient.h"
+#endif /* DRI_NEW_INTERFACE_ONLY */
+#include "drm.h"
+#include "drm_sarea.h"
+#include "GL/internal/glcore.h"
+#include "GL/internal/dri_interface.h"
+
+#define GLX_BAD_CONTEXT 5
+
+/* This is a temporary relic. Once all drivers are converted to support
+ * the new interface, it can go away.
+ */
+#ifdef DRI_NEW_INTERFACE_ONLY
+#define USE_NEW_INTERFACE
+#endif
+
+typedef struct __DRIdisplayPrivateRec __DRIdisplayPrivate;
+typedef struct __DRIscreenPrivateRec __DRIscreenPrivate;
+typedef struct __DRIcontextPrivateRec __DRIcontextPrivate;
+typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate;
+typedef struct __DRIswapInfoRec __DRIswapInfo;
+
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
+ do { \
+ if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
+ __driUtilUpdateDrawableInfo(pDrawPriv); \
+ } \
+ } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawablePrivate::pStamp and __DRIdrawablePrivate::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
+do { \
+ while (*(pdp->pStamp) != pdp->lastStamp) { \
+ DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, \
+ pdp->driContextPriv->hHWContext); \
+ \
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ \
+ DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, \
+ pdp->driContextPriv->hHWContext); \
+ } \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ *
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+ /**
+ * Driver initialization callback
+ */
+ GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
+
+ /**
+ * Screen destruction callback
+ */
+ void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
+
+ /**
+ * Context creation callback
+ */
+ GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+
+ /**
+ * Context destruction callback
+ */
+ void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Buffer (drawable) creation callback
+ */
+ GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *glVis,
+ GLboolean pixmapBuffer);
+
+ /**
+ * Buffer (drawable) destruction callback
+ */
+ void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
+
+ /**
+ * Buffer swapping callback
+ */
+ void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
+
+ /**
+ * Context activation callback
+ */
+ GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv);
+
+ /**
+ * Context unbinding callback
+ */
+ GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Retrieves statistics about buffer swap operations. Required if
+ * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+ */
+ int (*GetSwapInfo)( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+
+ /**
+ * Required if GLX_SGI_video_sync or GLX_OML_sync_control is
+ * supported.
+ */
+ int (*GetMSC)( __DRIscreenPrivate * priv, int64_t * count );
+
+ /**
+ * These are required if GLX_OML_sync_control is supported.
+ */
+ /*@{*/
+ int (*WaitForMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc );
+ int (*WaitForSBC)( __DRIdrawablePrivate *priv, int64_t target_sbc,
+ int64_t * msc, int64_t * sbc );
+
+ int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder );
+ /*@}*/
+};
+
+
+struct __DRIswapInfoRec {
+ /**
+ * Number of swapBuffers operations that have been *completed*.
+ */
+ u_int64_t swap_count;
+
+ /**
+ * Unadjusted system time of the last buffer swap. This is the time
+ * when the swap completed, not the time when swapBuffers was called.
+ */
+ int64_t swap_ust;
+
+ /**
+ * Number of swap operations that occurred after the swap deadline. That
+ * is if a swap happens more than swap_interval frames after the previous
+ * swap, it has missed its deadline. If swap_interval is 0, then the
+ * swap deadline is 1 frame after the previous swap.
+ */
+ u_int64_t swap_missed_count;
+
+ /**
+ * Amount of time used by the last swap that missed its deadline. This
+ * is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
+ * time_for_single_vrefresh)). If the actual value of swap_interval is
+ * 0, then 1 is used instead. If swap_missed_count is non-zero, this
+ * should be greater-than 1.0.
+ */
+ float swap_missed_usage;
+};
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawablePrivateRec {
+ /**
+ * Kernel drawable handle
+ */
+ drm_drawable_t hHWDrawable;
+
+ /**
+ * Driver's private drawable information.
+ *
+ * This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * X's drawable ID associated with this private drawable.
+ */
+ __DRIid draw;
+ __DRIdrawable *pdraw;
+
+ /**
+ * Reference count for number of context's currently bound to this
+ * drawable.
+ *
+ * Once it reaches zero, the drawable can be destroyed.
+ *
+ * \note This behavior will change with GLX 1.3.
+ */
+ int refcount;
+
+ /**
+ * Index of this drawable information in the SAREA.
+ */
+ unsigned int index;
+
+ /**
+ * Pointer to the "drawable has changed ID" stamp in the SAREA.
+ */
+ unsigned int *pStamp;
+
+ /**
+ * Last value of the stamp.
+ *
+ * If this differs from the value stored at __DRIdrawablePrivate::pStamp,
+ * then the drawable information has been modified by the X server, and the
+ * drawable information (below) should be retrieved from the X server.
+ */
+ unsigned int lastStamp;
+
+ /**
+ * \name Drawable
+ *
+ * Drawable information used in software fallbacks.
+ */
+ /*@{*/
+ int x;
+ int y;
+ int w;
+ int h;
+ int numClipRects;
+ drm_clip_rect_t *pClipRects;
+ /*@}*/
+
+ /**
+ * \name Back and depthbuffer
+ *
+ * Information about the back and depthbuffer where different from above.
+ */
+ /*@{*/
+ int backX;
+ int backY;
+ int backClipRectType;
+ int numBackClipRects;
+ drm_clip_rect_t *pBackClipRects;
+ /*@}*/
+
+ /**
+ * Pointer to context to which this drawable is currently bound.
+ */
+ __DRIcontextPrivate *driContextPriv;
+
+ /**
+ * Pointer to screen on which this drawable was created.
+ */
+ __DRIscreenPrivate *driScreenPriv;
+
+ /**
+ * \name Display and screen information.
+ *
+ * Basically just need these for when the locking code needs to call
+ * __driUtilUpdateDrawableInfo() which calls XF86DRIGetDrawableInfo().
+ */
+ /*@{*/
+ __DRInativeDisplay *display;
+ int screen;
+ /*@}*/
+
+ /**
+ * Called via glXSwapBuffers().
+ */
+ void (*swapBuffers)( __DRIdrawablePrivate *dPriv );
+
+ /**
+ * Get information about the location, size, and clip rects of the
+ * drawable within the display.
+ */
+ PFNGLXGETDRAWABLEINFOPROC getInfo;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextPrivateRec {
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ __DRIid contextID;
+
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ drm_context_t hHWContext;
+
+ /**
+ * Device driver's private context data. This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * This context's display pointer.
+ */
+ __DRInativeDisplay *display;
+
+ /**
+ * Pointer to drawable currently bound to this context.
+ */
+ __DRIdrawablePrivate *driDrawablePriv;
+
+ /**
+ * Pointer to screen on which this context was created.
+ */
+ __DRIscreenPrivate *driScreenPriv;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenPrivateRec {
+ /**
+ * Display for this screen
+ */
+ __DRInativeDisplay *display;
+
+ /**
+ * Current screen's number
+ */
+ int myNum;
+
+ /**
+ * Callback functions into the hardware-specific DRI driver code.
+ */
+ struct __DriverAPIRec DriverAPI;
+
+ /**
+ * \name DDX version
+ * DDX / 2D driver version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int ddxMajor;
+ int ddxMinor;
+ int ddxPatch;
+ /*@}*/
+
+ /**
+ * \name DRI version
+ * DRI X extension version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int driMajor;
+ int driMinor;
+ int driPatch;
+ /*@}*/
+
+ /**
+ * \name DRM version
+ * DRM (kernel module) version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int drmMajor;
+ int drmMinor;
+ int drmPatch;
+ /*@}*/
+
+ /**
+ * ID used when the client sets the drawable lock.
+ *
+ * The X server uses this value to detect if the client has died while
+ * holding the drawable lock.
+ */
+ int drawLockID;
+
+ /**
+ * File descriptor returned when the kernel device driver is opened.
+ *
+ * Used to:
+ * - authenticate client to kernel
+ * - map the frame buffer, SAREA, etc.
+ * - close the kernel device driver
+ */
+ int fd;
+
+ /**
+ * SAREA pointer
+ *
+ * Used to access:
+ * - the device lock
+ * - the device-independent per-drawable and per-context(?) information
+ */
+ drm_sarea_t *pSAREA;
+
+ /**
+ * \name Direct frame buffer access information
+ * Used for software fallbacks.
+ */
+ /*@{*/
+ unsigned char *pFB;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ int fbWidth;
+ int fbHeight;
+ int fbBPP;
+ /*@}*/
+
+ /**
+ * \name Device-dependent private information (stored in the SAREA).
+ *
+ * This data is accessed by the client driver only.
+ */
+ /*@{*/
+ void *pDevPriv;
+ int devPrivSize;
+ /*@}*/
+
+ /**
+ * Dummy context to which drawables are bound when not bound to any
+ * other context.
+ *
+ * A dummy hHWContext is created for this context, and is used by the GL
+ * core when a hardware lock is required but the drawable is not currently
+ * bound (e.g., potentially during a SwapBuffers request). The dummy
+ * context is created when the first "real" context is created on this
+ * screen.
+ */
+ __DRIcontextPrivate dummyContextPriv;
+
+ /**
+ * Hash table to hold the drawable information for this screen.
+ */
+ void *drawHash;
+
+ /**
+ * Device-dependent private information (not stored in the SAREA).
+ *
+ * This pointer is never touched by the DRI layer.
+ */
+ void *private;
+
+ /**
+ * GLX visuals / FBConfigs for this screen. These are stored as a
+ * linked list.
+ *
+ * \note
+ * This field is \b only used in conjunction with the old interfaces. If
+ * the new interfaces are used, this field will be set to \c NULL and will
+ * not be dereferenced.
+ */
+ __GLcontextModes *modes;
+
+ /**
+ * Pointer back to the \c __DRIscreen that contains this structure.
+ */
+
+ __DRIscreen *psc;
+};
+
+
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
+
+
+extern __DRIscreenPrivate * __driUtilCreateNewScreen( __DRInativeDisplay *dpy,
+ int scrn, __DRIscreen *psc, __GLcontextModes * modes,
+ const __DRIversion * ddx_version, const __DRIversion * dri_version,
+ const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer,
+ drm_sarea_t *pSAREA, int fd, int internal_api_version,
+ const struct __DriverAPIRec *driverAPI );
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+extern __DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config,
+ const struct __DriverAPIRec *driverAPI);
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/* Test the version of the internal GLX API. Returns a value like strcmp. */
+extern int
+driCompareGLXAPIVersion( GLuint required_version );
+
+extern float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv,
+ int64_t last_swap_ust, int64_t current_ust );
+
+/* Test for the GLX header glx.h */
+#ifndef GLX
+extern void
+(*glXGetProcAddress(const GLubyte *procname))( void );
+#endif
+
+#endif /* GLX_DIRECT_RENDERING */
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/common/glcontextmodes.c b/src/mesa/drivers/dri/common/glcontextmodes.c
new file mode 100644
index 0000000..c540e5b
--- /dev/null
+++ b/src/mesa/drivers/dri/common/glcontextmodes.c
@@ -0,0 +1,496 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glcontextmodes.c
+ * Utility routines for working with \c __GLcontextModes structures. At
+ * some point most or all of these functions will be moved to the Mesa
+ * code base.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifdef DRI_NEW_INTERFACE_ONLY
+# include <stdlib.h>
+# include <string.h>
+# include <GL/gl.h>
+# include "dri_interface.h"
+# include "imports.h"
+# define __glXMemset memset
+#else
+# include <X11/X.h>
+# include <GL/glx.h>
+# include "GL/glxint.h"
+
+# ifdef XFree86Server
+# include "GL/glx_ansic.h"
+extern void * __glXMalloc( size_t size );
+extern void __glXFree( void * ptr );
+# define _mesa_malloc(b) __glXMalloc(b)
+# define _mesa_free(m) __glXFree(m)
+# else
+# include <X11/Xlibint.h>
+# define __glXMemset memset
+# define _mesa_malloc(b) Xmalloc(b)
+# define _mesa_free(m) Xfree(m)
+# endif /* XFree86Server */
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+#include "glcontextmodes.h"
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+#define NUM_VISUAL_TYPES 6
+
+/**
+ * Convert an X visual type to a GLX visual type.
+ *
+ * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
+ * to be converted.
+ * \return If \c visualType is a valid X visual type, a GLX visual type will
+ * be returned. Otherwise \c GLX_NONE will be returned.
+ */
+GLint
+_gl_convert_from_x_visual_type( int visualType )
+{
+ static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ( (unsigned) visualType < NUM_VISUAL_TYPES )
+ ? glx_visual_types[ visualType ] : GLX_NONE;
+}
+
+
+/**
+ * Convert a GLX visual type to an X visual type.
+ *
+ * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR,
+ * \c GLX_STATIC_GRAY, etc.) to be converted.
+ * \return If \c visualType is a valid GLX visual type, an X visual type will
+ * be returned. Otherwise -1 will be returned.
+ */
+GLint
+_gl_convert_to_x_visual_type( int visualType )
+{
+ static const int x_visual_types[ NUM_VISUAL_TYPES ] = {
+ TrueColor, DirectColor,
+ PseudoColor, StaticColor,
+ GrayScale, StaticGray
+ };
+
+ return ( (unsigned) (visualType - GLX_TRUE_COLOR) <= NUM_VISUAL_TYPES )
+ ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
+}
+
+
+/**
+ * Copy a GLX visual config structure to a GL context mode structure. All
+ * of the fields in \c config are copied to \c mode. Additional fields in
+ * \c mode that can be derrived from the fields of \c config (i.e.,
+ * \c haveDepthBuffer) are also filled in. The remaining fields in \c mode
+ * that cannot be derrived are set to default values.
+ *
+ * \param mode Destination GL context mode.
+ * \param config Source GLX visual config.
+ *
+ * \note
+ * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes
+ * structure will be set to the \c vid of the \c __GLXvisualConfig structure.
+ */
+void
+_gl_copy_visual_to_context_mode( __GLcontextModes * mode,
+ const __GLXvisualConfig * config )
+{
+ __GLcontextModes * const next = mode->next;
+
+ (void) __glXMemset( mode, 0, sizeof( __GLcontextModes ) );
+ mode->next = next;
+
+ mode->visualID = config->vid;
+ mode->visualType = _gl_convert_from_x_visual_type( config->class );
+ mode->xRenderable = GL_TRUE;
+ mode->fbconfigID = config->vid;
+ mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
+
+ mode->rgbMode = (config->rgba != 0);
+ mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+
+ mode->colorIndexMode = !(mode->rgbMode);
+ mode->doubleBufferMode = (config->doubleBuffer != 0);
+ mode->stereoMode = (config->stereo != 0);
+
+ mode->haveAccumBuffer = ((config->accumRedSize +
+ config->accumGreenSize +
+ config->accumBlueSize +
+ config->accumAlphaSize) > 0);
+ mode->haveDepthBuffer = (config->depthSize > 0);
+ mode->haveStencilBuffer = (config->stencilSize > 0);
+
+ mode->redBits = config->redSize;
+ mode->greenBits = config->greenSize;
+ mode->blueBits = config->blueSize;
+ mode->alphaBits = config->alphaSize;
+ mode->redMask = config->redMask;
+ mode->greenMask = config->greenMask;
+ mode->blueMask = config->blueMask;
+ mode->alphaMask = config->alphaMask;
+ mode->rgbBits = config->bufferSize;
+ mode->indexBits = config->bufferSize;
+
+ mode->accumRedBits = config->accumRedSize;
+ mode->accumGreenBits = config->accumGreenSize;
+ mode->accumBlueBits = config->accumBlueSize;
+ mode->accumAlphaBits = config->accumAlphaSize;
+ mode->depthBits = config->depthSize;
+ mode->stencilBits = config->stencilSize;
+
+ mode->numAuxBuffers = config->auxBuffers;
+ mode->level = config->level;
+
+ mode->visualRating = config->visualRating;
+ mode->transparentPixel = config->transparentPixel;
+ mode->transparentRed = config->transparentRed;
+ mode->transparentGreen = config->transparentGreen;
+ mode->transparentBlue = config->transparentBlue;
+ mode->transparentAlpha = config->transparentAlpha;
+ mode->transparentIndex = config->transparentIndex;
+
+ mode->swapMethod = GLX_SWAP_UNDEFINED_OML;
+}
+
+
+/**
+ * Get data from a GL context mode.
+ *
+ * \param mode GL context mode whose data is to be returned.
+ * \param attribute Attribute of \c mode that is to be returned.
+ * \param value_return Location to store the data member of \c mode.
+ * \return If \c attribute is a valid attribute of \c mode, zero is
+ * returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned.
+ */
+int
+_gl_get_context_mode_data(const __GLcontextModes *mode, int attribute,
+ int *value_return)
+{
+ switch (attribute) {
+ case GLX_USE_GL:
+ *value_return = GL_TRUE;
+ return 0;
+ case GLX_BUFFER_SIZE:
+ *value_return = mode->rgbBits;
+ return 0;
+ case GLX_RGBA:
+ *value_return = mode->rgbMode;
+ return 0;
+ case GLX_RED_SIZE:
+ *value_return = mode->redBits;
+ return 0;
+ case GLX_GREEN_SIZE:
+ *value_return = mode->greenBits;
+ return 0;
+ case GLX_BLUE_SIZE:
+ *value_return = mode->blueBits;
+ return 0;
+ case GLX_ALPHA_SIZE:
+ *value_return = mode->alphaBits;
+ return 0;
+ case GLX_DOUBLEBUFFER:
+ *value_return = mode->doubleBufferMode;
+ return 0;
+ case GLX_STEREO:
+ *value_return = mode->stereoMode;
+ return 0;
+ case GLX_AUX_BUFFERS:
+ *value_return = mode->numAuxBuffers;
+ return 0;
+ case GLX_DEPTH_SIZE:
+ *value_return = mode->depthBits;
+ return 0;
+ case GLX_STENCIL_SIZE:
+ *value_return = mode->stencilBits;
+ return 0;
+ case GLX_ACCUM_RED_SIZE:
+ *value_return = mode->accumRedBits;
+ return 0;
+ case GLX_ACCUM_GREEN_SIZE:
+ *value_return = mode->accumGreenBits;
+ return 0;
+ case GLX_ACCUM_BLUE_SIZE:
+ *value_return = mode->accumBlueBits;
+ return 0;
+ case GLX_ACCUM_ALPHA_SIZE:
+ *value_return = mode->accumAlphaBits;
+ return 0;
+ case GLX_LEVEL:
+ *value_return = mode->level;
+ return 0;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ *value_return = mode->transparentPixel;
+ return 0;
+ case GLX_TRANSPARENT_RED_VALUE:
+ *value_return = mode->transparentRed;
+ return 0;
+ case GLX_TRANSPARENT_GREEN_VALUE:
+ *value_return = mode->transparentGreen;
+ return 0;
+ case GLX_TRANSPARENT_BLUE_VALUE:
+ *value_return = mode->transparentBlue;
+ return 0;
+ case GLX_TRANSPARENT_ALPHA_VALUE:
+ *value_return = mode->transparentAlpha;
+ return 0;
+ case GLX_TRANSPARENT_INDEX_VALUE:
+ *value_return = mode->transparentIndex;
+ return 0;
+ case GLX_X_VISUAL_TYPE:
+ *value_return = mode->visualType;
+ return 0;
+ case GLX_CONFIG_CAVEAT:
+ *value_return = mode->visualRating;
+ return 0;
+ case GLX_VISUAL_ID:
+ *value_return = mode->visualID;
+ return 0;
+ case GLX_DRAWABLE_TYPE:
+ *value_return = mode->drawableType;
+ return 0;
+ case GLX_RENDER_TYPE:
+ *value_return = mode->renderType;
+ return 0;
+ case GLX_X_RENDERABLE:
+ *value_return = mode->xRenderable;
+ return 0;
+ case GLX_FBCONFIG_ID:
+ *value_return = mode->fbconfigID;
+ return 0;
+ case GLX_MAX_PBUFFER_WIDTH:
+ *value_return = mode->maxPbufferWidth;
+ return 0;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ *value_return = mode->maxPbufferHeight;
+ return 0;
+ case GLX_MAX_PBUFFER_PIXELS:
+ *value_return = mode->maxPbufferPixels;
+ return 0;
+ case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+ *value_return = mode->optimalPbufferWidth;
+ return 0;
+ case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+ *value_return = mode->optimalPbufferHeight;
+ return 0;
+ case GLX_SWAP_METHOD_OML:
+ *value_return = mode->swapMethod;
+ return 0;
+ case GLX_SAMPLE_BUFFERS_SGIS:
+ *value_return = mode->sampleBuffers;
+ return 0;
+ case GLX_SAMPLES_SGIS:
+ *value_return = mode->samples;
+ 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
+ * server.
+ */
+ case GLX_VISUAL_SELECT_GROUP_SGIX:
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+/**
+ * Allocate a linked list of \c __GLcontextModes structures. The fields of
+ * each structure will be initialized to "reasonable" default values. In
+ * most cases this is the default value defined by table 3.4 of the GLX
+ * 1.3 specification. This means that most values are either initialized to
+ * zero or \c GLX_DONT_CARE (which is -1). As support for additional
+ * extensions is added, the new values will be initialized to appropriate
+ * values from the extension specification.
+ *
+ * \param count Number of structures to allocate.
+ * \param minimum_size Minimum size of a structure to allocate. This allows
+ * for differences in the version of the
+ * \c __GLcontextModes stucture used in libGL and in a
+ * DRI-based driver.
+ * \returns A pointer to the first element in a linked list of \c count
+ * stuctures on success, or \c NULL on failure.
+ *
+ * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
+ * The fundamental assumption is that if the \c minimum_size
+ * specified by the driver and the size of the \c __GLcontextModes
+ * structure in libGL is the same, then the meaning of each byte in
+ * the structure is the same in both places. \b Be \b careful!
+ * Basically this means that fields have to be added in libGL and
+ * then propagated to drivers. Drivers should \b never arbitrarilly
+ * extend the \c __GLcontextModes data-structure.
+ */
+__GLcontextModes *
+_gl_context_modes_create( unsigned count, size_t minimum_size )
+{
+ const size_t size = (minimum_size > sizeof( __GLcontextModes ))
+ ? minimum_size : sizeof( __GLcontextModes );
+ __GLcontextModes * base = NULL;
+ __GLcontextModes ** next;
+ unsigned i;
+
+ next = & base;
+ for ( i = 0 ; i < count ; i++ ) {
+ *next = (__GLcontextModes *) _mesa_malloc( size );
+ if ( *next == NULL ) {
+ _gl_context_modes_destroy( base );
+ base = NULL;
+ break;
+ }
+
+ (void) __glXMemset( *next, 0, size );
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+
+ next = & ((*next)->next);
+ }
+
+ return base;
+}
+
+
+/**
+ * Destroy a linked list of \c __GLcontextModes structures created by
+ * \c _gl_context_modes_create.
+ *
+ * \param modes Linked list of structures to be destroyed. All structres
+ * in the list will be freed.
+ */
+void
+_gl_context_modes_destroy( __GLcontextModes * modes )
+{
+ while ( modes != NULL ) {
+ __GLcontextModes * const next = modes->next;
+
+ _mesa_free( modes );
+ modes = next;
+ }
+}
+
+
+/**
+ * Find a context mode matching a Visual ID.
+ *
+ * \param modes List list of context-mode structures to be searched.
+ * \param vid Visual ID to be found.
+ * \returns A pointer to a context-mode in \c modes if \c vid was found in
+ * the list, or \c NULL if it was not.
+ */
+
+__GLcontextModes *
+_gl_context_modes_find_visual( __GLcontextModes * modes, int vid )
+{
+ while ( modes != NULL ) {
+ if ( modes->visualID == vid ) {
+ break;
+ }
+
+ modes = modes->next;
+ }
+
+ return modes;
+}
+
+
+/**
+ * Determine if two context-modes are the same. This is intended to be used
+ * by libGL implementations to compare to sets of driver generated FBconfigs.
+ *
+ * \param a Context-mode to be compared.
+ * \param b Context-mode to be compared.
+ * \returns \c GL_TRUE if the two context-modes are the same. \c GL_FALSE is
+ * returned otherwise.
+ */
+GLboolean
+_gl_context_modes_are_same( const __GLcontextModes * a,
+ const __GLcontextModes * b )
+{
+ return( (a->rgbMode == b->rgbMode) &&
+ (a->floatMode == b->floatMode) &&
+ (a->colorIndexMode == b->colorIndexMode) &&
+ (a->doubleBufferMode == b->doubleBufferMode) &&
+ (a->stereoMode == b->stereoMode) &&
+ (a->redBits == b->redBits) &&
+ (a->greenBits == b->greenBits) &&
+ (a->blueBits == b->blueBits) &&
+ (a->alphaBits == b->alphaBits) &&
+#if 0 /* For some reason these don't get set on the client-side in libGL. */
+ (a->redMask == b->redMask) &&
+ (a->greenMask == b->greenMask) &&
+ (a->blueMask == b->blueMask) &&
+ (a->alphaMask == b->alphaMask) &&
+#endif
+ (a->rgbBits == b->rgbBits) &&
+ (a->indexBits == b->indexBits) &&
+ (a->accumRedBits == b->accumRedBits) &&
+ (a->accumGreenBits == b->accumGreenBits) &&
+ (a->accumBlueBits == b->accumBlueBits) &&
+ (a->accumAlphaBits == b->accumAlphaBits) &&
+ (a->depthBits == b->depthBits) &&
+ (a->stencilBits == b->stencilBits) &&
+ (a->numAuxBuffers == b->numAuxBuffers) &&
+ (a->level == b->level) &&
+ (a->pixmapMode == b->pixmapMode) &&
+ (a->visualRating == b->visualRating) &&
+
+ (a->transparentPixel == b->transparentPixel) &&
+
+ ((a->transparentPixel != GLX_TRANSPARENT_RGB) ||
+ ((a->transparentRed == b->transparentRed) &&
+ (a->transparentGreen == b->transparentGreen) &&
+ (a->transparentBlue == b->transparentBlue) &&
+ (a->transparentAlpha == b->transparentAlpha))) &&
+
+ ((a->transparentPixel != GLX_TRANSPARENT_INDEX) ||
+ (a->transparentIndex == b->transparentIndex)) &&
+
+ (a->sampleBuffers == b->sampleBuffers) &&
+ (a->samples == b->samples) &&
+ ((a->drawableType & b->drawableType) != 0) &&
+ (a->renderType == b->renderType) &&
+ (a->maxPbufferWidth == b->maxPbufferWidth) &&
+ (a->maxPbufferHeight == b->maxPbufferHeight) &&
+ (a->maxPbufferPixels == b->maxPbufferPixels) &&
+ (a->optimalPbufferWidth == b->optimalPbufferWidth) &&
+ (a->optimalPbufferHeight == b->optimalPbufferHeight) &&
+ (a->swapMethod == b->swapMethod) );
+}
diff --git a/src/mesa/drivers/dri/common/glcontextmodes.h b/src/mesa/drivers/dri/common/glcontextmodes.h
new file mode 100644
index 0000000..46b4c68
--- /dev/null
+++ b/src/mesa/drivers/dri/common/glcontextmodes.h
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file glcontextmodes.h
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef GLCONTEXTMODES_H
+#define GLCONTEXTMODES_H
+
+#include "GL/internal/glcore.h"
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+extern GLint _gl_convert_from_x_visual_type( int visualType );
+extern GLint _gl_convert_to_x_visual_type( int visualType );
+extern void _gl_copy_visual_to_context_mode( __GLcontextModes * mode,
+ const __GLXvisualConfig * config );
+extern int _gl_get_context_mode_data( const __GLcontextModes *mode,
+ int attribute, int *value_return );
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+extern __GLcontextModes * _gl_context_modes_create( unsigned count,
+ size_t minimum_size );
+extern void _gl_context_modes_destroy( __GLcontextModes * modes );
+extern __GLcontextModes * _gl_context_modes_find_visual(
+ __GLcontextModes * modes, int vid );
+extern GLboolean _gl_context_modes_are_same( const __GLcontextModes * a,
+ const __GLcontextModes * b );
+
+#endif /* GLCONTEXTMODES_H */
diff --git a/src/mesa/drivers/dri/common/mm.c b/src/mesa/drivers/dri/common/mm.c
new file mode 100644
index 0000000..6572ccd
--- /dev/null
+++ b/src/mesa/drivers/dri/common/mm.c
@@ -0,0 +1,196 @@
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Wittawat Yamwong
+ *
+ * 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
+ * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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/lib/GL/mesa/src/drv/common/mm.c,v 1.4 2002/10/30 12:51:27 alanh Exp $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mm.h"
+
+
+void mmDumpMemInfo( memHeap_t *heap )
+{
+ TMemBlock *p;
+
+ fprintf(stderr, "Memory heap %p:\n", (void *)heap);
+ if (heap == 0) {
+ fprintf(stderr, " heap == 0\n");
+ } else {
+ p = (TMemBlock *)heap;
+ while (p) {
+ fprintf(stderr, " Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
+ p->free ? '.':'U',
+ p->reserved ? 'R':'.');
+ p = p->next;
+ }
+ }
+ fprintf(stderr, "End of memory blocks\n");
+}
+
+memHeap_t *mmInit(int ofs,
+ int size)
+{
+ PMemBlock blocks;
+
+ if (size <= 0) {
+ return 0;
+ }
+ blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock));
+ if (blocks) {
+ blocks->ofs = ofs;
+ blocks->size = size;
+ blocks->free = 1;
+ return (memHeap_t *)blocks;
+ } else
+ return 0;
+}
+
+
+static TMemBlock* SliceBlock(TMemBlock *p,
+ int startofs, int size,
+ int reserved, int alignment)
+{
+ TMemBlock *newblock;
+
+ /* break left */
+ if (startofs > p->ofs) {
+ newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs;
+ newblock->size = p->size - (startofs - p->ofs);
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size -= newblock->size;
+ p->next = newblock;
+ p = newblock;
+ }
+
+ /* break right */
+ if (size < p->size) {
+ newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock));
+ if (!newblock)
+ return NULL;
+ newblock->ofs = startofs + size;
+ newblock->size = p->size - size;
+ newblock->free = 1;
+ newblock->next = p->next;
+ p->size = size;
+ p->next = newblock;
+ }
+
+ /* p = middle block */
+ p->align = alignment;
+ p->free = 0;
+ p->reserved = reserved;
+ return p;
+}
+
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch)
+{
+ int mask,startofs,endofs;
+ TMemBlock *p;
+
+ if (!heap || align2 < 0 || size <= 0)
+ return NULL;
+ mask = (1 << align2)-1;
+ startofs = 0;
+ p = (TMemBlock *)heap;
+ while (p) {
+ if ((p)->free) {
+ startofs = (p->ofs + mask) & ~mask;
+ if ( startofs < startSearch ) {
+ startofs = startSearch;
+ }
+ endofs = startofs+size;
+ if (endofs <= (p->ofs+p->size))
+ break;
+ }
+ p = p->next;
+ }
+ if (!p)
+ return NULL;
+ p = SliceBlock(p,startofs,size,0,mask+1);
+ p->heap = heap;
+ return p;
+}
+
+static __inline__ int Join2Blocks(TMemBlock *p)
+{
+ if (p->free && p->next && p->next->free) {
+ TMemBlock *q = p->next;
+ p->size += q->size;
+ p->next = q->next;
+ free(q);
+ return 1;
+ }
+ return 0;
+}
+
+int mmFreeMem(PMemBlock b)
+{
+ TMemBlock *p,*prev;
+
+ if (!b)
+ return 0;
+ if (!b->heap) {
+ fprintf(stderr, "no heap\n");
+ return -1;
+ }
+ p = b->heap;
+ prev = NULL;
+ while (p && p != b) {
+ prev = p;
+ p = p->next;
+ }
+ if (!p || p->free || p->reserved) {
+ if (!p)
+ fprintf(stderr, "block not found in heap\n");
+ else if (p->free)
+ fprintf(stderr, "block already free\n");
+ else
+ fprintf(stderr, "block is reserved\n");
+ return -1;
+ }
+ p->free = 1;
+ Join2Blocks(p);
+ if (prev)
+ Join2Blocks(prev);
+ return 0;
+}
+
+
+void mmDestroy(memHeap_t *heap)
+{
+ TMemBlock *p,*q;
+
+ if (!heap)
+ return;
+ p = (TMemBlock *)heap;
+ while (p) {
+ q = p->next;
+ free(p);
+ p = q;
+ }
+}
diff --git a/src/mesa/drivers/dri/common/mm.h b/src/mesa/drivers/dri/common/mm.h
new file mode 100644
index 0000000..d52871d
--- /dev/null
+++ b/src/mesa/drivers/dri/common/mm.h
@@ -0,0 +1,82 @@
+/*
+ * GLX Hardware Device Driver common code
+ * Copyright (C) 1999 Keith Whitwell
+ *
+ * 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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 MM_INC
+#define MM_INC
+
+struct mem_block_t {
+ struct mem_block_t *next;
+ struct mem_block_t *heap;
+ int ofs,size;
+ int align;
+ int free:1;
+ int reserved:1;
+};
+typedef struct mem_block_t TMemBlock;
+typedef struct mem_block_t *PMemBlock;
+
+/* a heap is just the first block in a chain */
+typedef struct mem_block_t memHeap_t;
+
+static __inline__ int mmBlockSize(PMemBlock b)
+{ return b->size; }
+
+static __inline__ int mmOffset(PMemBlock b)
+{ return b->ofs; }
+
+/*
+ * input: total size in bytes
+ * return: a heap pointer if OK, NULL if error
+ */
+memHeap_t *mmInit( int ofs, int size );
+
+/*
+ * Allocate 'size' bytes with 2^align2 bytes alignment,
+ * restrict the search to free memory after 'startSearch'
+ * depth and back buffers should be in different 4mb banks
+ * to get better page hits if possible
+ * input: size = size of block
+ * align2 = 2^align2 bytes alignment
+ * startSearch = linear offset from start of heap to begin search
+ * return: pointer to the allocated block, 0 if error
+ */
+PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2,
+ int startSearch );
+
+/*
+ * Free block starts at offset
+ * input: pointer to a block
+ * return: 0 if OK, -1 if error
+ */
+int mmFreeMem( PMemBlock b );
+
+/*
+ * destroy MM
+ */
+void mmDestroy( memHeap_t *mmInit );
+
+/* For debuging purpose. */
+void mmDumpMemInfo( memHeap_t *mmInit );
+
+#endif
diff --git a/src/mesa/drivers/dri/common/mmio.h b/src/mesa/drivers/dri/common/mmio.h
new file mode 100644
index 0000000..a9bdce4
--- /dev/null
+++ b/src/mesa/drivers/dri/common/mmio.h
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright IBM Corporation 2004
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM AND/OR THEIR 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.
+ */
+
+/**
+ * \file mmio.h
+ * Functions for properly handling memory mapped IO on various platforms.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+
+#ifndef MMIO_H
+#define MMIO_H
+
+#if defined( __powerpc__ )
+
+static __inline__ u_int32_t
+read_MMIO_LE32( volatile void * base, unsigned long offset )
+{
+ volatile void * p = ((volatile char *) base) + offset;
+ u_int32_t val;
+
+ __asm__ __volatile__( "lwbrx %0, %1, %2 ; eieio"
+ : "=r" (val)
+ : "b" (base), "r" (offset), "m" (p) );
+ return val;
+}
+
+#else
+
+static __inline__ u_int32_t
+read_MMIO_LE32( volatile void * base, unsigned long offset )
+{
+ volatile u_int32_t * p = (volatile u_int32_t *) (((volatile char *) base) + offset);
+ return LE32_TO_CPU( p[0] );
+}
+
+#endif
+
+#endif /* MMIO_H */
diff --git a/src/mesa/drivers/dri/common/mmx.h b/src/mesa/drivers/dri/common/mmx.h
new file mode 100644
index 0000000..49ce7e3
--- /dev/null
+++ b/src/mesa/drivers/dri/common/mmx.h
@@ -0,0 +1,560 @@
+/* mmx.h
+
+ MultiMedia eXtensions GCC interface library for IA32.
+
+ To use this library, simply include this header file
+ and compile with GCC. You MUST have inlining enabled
+ in order for mmx_ok() to work; this can be done by
+ simply using -O on the GCC command line.
+
+ Compiling with -DMMX_TRACE will cause detailed trace
+ output to be sent to stderr for each mmx operation.
+ This adds lots of code, and obviously slows execution to
+ a crawl, but can be very useful for debugging.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR ANY PARTICULAR PURPOSE.
+
+ 1997-98 by H. Dietz and R. Fisher
+
+ History:
+ 97-98* R.Fisher Early versions
+ 980501 R.Fisher Original Release
+ 980611* H.Dietz Rewrite, correctly implementing inlines, and
+ R.Fisher including direct register accesses.
+ 980616 R.Fisher Release of 980611 as 980616.
+ 980714 R.Fisher Minor corrections to Makefile, etc.
+ 980715 R.Fisher mmx_ok() now prevents optimizer from using
+ clobbered values.
+ mmx_ok() now checks if cpuid instruction is
+ available before trying to use it.
+ 980726* R.Fisher mm_support() searches for AMD 3DNow, Cyrix
+ Extended MMX, and standard MMX. It returns a
+ value which is positive if any of these are
+ supported, and can be masked with constants to
+ see which. mmx_ok() is now a call to this
+ 980726* R.Fisher Added i2r support for shift functions
+ 980919 R.Fisher Fixed AMD extended feature recognition bug.
+ 980921 R.Fisher Added definition/check for _MMX_H.
+ Added "float s[2]" to mmx_t for use with
+ 3DNow and EMMX. So same mmx_t can be used.
+ 981013 R.Fisher Fixed cpuid function 1 bug (looked at wrong reg)
+ Fixed psllq_i2r error in mmxtest.c
+
+ * Unreleased (internal or interim) versions
+
+ Notes:
+ It appears that the latest gas has the pand problem fixed, therefore
+ I'll undefine BROKEN_PAND by default.
+ String compares may be quicker than the multiple test/jumps in vendor
+ test sequence in mmx_ok(), but I'm not concerned with that right now.
+
+ Acknowledgments:
+ Jussi Laako for pointing out the errors ultimately found to be
+ connected to the failure to notify the optimizer of clobbered values.
+ Roger Hardiman for reminding us that CPUID isn't everywhere, and that
+ someone may actually try to use this on a machine without CPUID.
+ Also for suggesting code for checking this.
+ Robert Dale for pointing out the AMD recognition bug.
+ Jimmy Mayfield and Carl Witty for pointing out the Intel recognition
+ bug.
+ Carl Witty for pointing out the psllq_i2r test bug.
+*/
+
+#ifndef _MMX_H
+#define _MMX_H
+
+//#define MMX_TRACE
+
+/* Warning: at this writing, the version of GAS packaged
+ with most Linux distributions does not handle the
+ parallel AND operation mnemonic correctly. If the
+ symbol BROKEN_PAND is defined, a slower alternative
+ coding will be used. If execution of mmxtest results
+ in an illegal instruction fault, define this symbol.
+*/
+#undef BROKEN_PAND
+
+
+/* The type of an value that fits in an MMX register
+ (note that long long constant values MUST be suffixed
+ by LL and unsigned long long values by ULL, lest
+ they be truncated by the compiler)
+*/
+typedef union {
+ long long q; /* Quadword (64-bit) value */
+ unsigned long long uq; /* Unsigned Quadword */
+ int d[2]; /* 2 Doubleword (32-bit) values */
+ unsigned int ud[2]; /* 2 Unsigned Doubleword */
+ short w[4]; /* 4 Word (16-bit) values */
+ unsigned short uw[4]; /* 4 Unsigned Word */
+ char b[8]; /* 8 Byte (8-bit) values */
+ unsigned char ub[8]; /* 8 Unsigned Byte */
+ float s[2]; /* Single-precision (32-bit) value */
+} mmx_t;
+
+/* Helper functions for the instruction macros that follow...
+ (note that memory-to-register, m2r, instructions are nearly
+ as efficient as register-to-register, r2r, instructions;
+ however, memory-to-memory instructions are really simulated
+ as a convenience, and are only 1/3 as efficient)
+*/
+#ifdef MMX_TRACE
+
+/* Include the stuff for printing a trace to stderr...
+*/
+
+#include <stdio.h>
+
+#define mmx_i2r(op, imm, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (imm); \
+ fprintf(stderr, #op "_i2r(" #imm "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (imm)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_m2r(op, mem, reg) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mem); \
+ fprintf(stderr, #op "_m2r(" #mem "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem)); \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #reg "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_r2m(op, reg, mem) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #reg ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2m(" #reg "=0x%016llx, ", mmx_trace.q); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ ); \
+ mmx_trace = (mem); \
+ fprintf(stderr, #mem "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_r2r(op, regs, regd) \
+ { \
+ mmx_t mmx_trace; \
+ __asm__ __volatile__ ("movq %%" #regs ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #op "_r2r(" #regs "=0x%016llx, ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd); \
+ __asm__ __volatile__ ("movq %%" #regd ", %0" \
+ : "=X" (mmx_trace) \
+ : /* nothing */ ); \
+ fprintf(stderr, #regd "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#define mmx_m2m(op, mems, memd) \
+ { \
+ mmx_t mmx_trace; \
+ mmx_trace = (mems); \
+ fprintf(stderr, #op "_m2m(" #mems "=0x%016llx, ", mmx_trace.q); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%016llx) => ", mmx_trace.q); \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (memd) \
+ : "X" (mems)); \
+ mmx_trace = (memd); \
+ fprintf(stderr, #memd "=0x%016llx\n", mmx_trace.q); \
+ }
+
+#else
+
+/* These macros are a lot simpler without the tracing...
+*/
+
+#define mmx_i2r(op, imm, reg) \
+ __asm__ __volatile__ (#op " $" #imm ", %%" #reg \
+ : /* nothing */ \
+ : /* nothing */);
+
+#define mmx_m2r(op, mem, reg) \
+ __asm__ __volatile__ (#op " %0, %%" #reg \
+ : /* nothing */ \
+ : "X" (mem))
+
+#define mmx_r2m(op, reg, mem) \
+ __asm__ __volatile__ (#op " %%" #reg ", %0" \
+ : "=X" (mem) \
+ : /* nothing */ )
+
+#define mmx_r2r(op, regs, regd) \
+ __asm__ __volatile__ (#op " %" #regs ", %" #regd)
+
+#define mmx_m2m(op, mems, memd) \
+ __asm__ __volatile__ ("movq %0, %%mm0\n\t" \
+ #op " %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (memd) \
+ : "X" (mems))
+
+#endif
+
+
+/* 1x64 MOVe Quadword
+ (this is both a load and a store...
+ in fact, it is the only way to store)
+*/
+#define movq_m2r(var, reg) mmx_m2r(movq, var, reg)
+#define movq_r2m(reg, var) mmx_r2m(movq, reg, var)
+#define movq_r2r(regs, regd) mmx_r2r(movq, regs, regd)
+#define movq(vars, vard) \
+ __asm__ __volatile__ ("movq %1, %%mm0\n\t" \
+ "movq %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 1x32 MOVe Doubleword
+ (like movq, this is both load and store...
+ but is most useful for moving things between
+ mmx registers and ordinary registers)
+*/
+#define movd_m2r(var, reg) mmx_m2r(movd, var, reg)
+#define movd_r2m(reg, var) mmx_r2m(movd, reg, var)
+#define movd_r2r(regs, regd) mmx_r2r(movd, regs, regd)
+#define movd(vars, vard) \
+ __asm__ __volatile__ ("movd %1, %%mm0\n\t" \
+ "movd %%mm0, %0" \
+ : "=X" (vard) \
+ : "X" (vars))
+
+
+/* 2x32, 4x16, and 8x8 Parallel ADDs
+*/
+#define paddd_m2r(var, reg) mmx_m2r(paddd, var, reg)
+#define paddd_r2r(regs, regd) mmx_r2r(paddd, regs, regd)
+#define paddd(vars, vard) mmx_m2m(paddd, vars, vard)
+
+#define paddw_m2r(var, reg) mmx_m2r(paddw, var, reg)
+#define paddw_r2r(regs, regd) mmx_r2r(paddw, regs, regd)
+#define paddw(vars, vard) mmx_m2m(paddw, vars, vard)
+
+#define paddb_m2r(var, reg) mmx_m2r(paddb, var, reg)
+#define paddb_r2r(regs, regd) mmx_r2r(paddb, regs, regd)
+#define paddb(vars, vard) mmx_m2m(paddb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Saturation arithmetic
+*/
+#define paddsw_m2r(var, reg) mmx_m2r(paddsw, var, reg)
+#define paddsw_r2r(regs, regd) mmx_r2r(paddsw, regs, regd)
+#define paddsw(vars, vard) mmx_m2m(paddsw, vars, vard)
+
+#define paddsb_m2r(var, reg) mmx_m2r(paddsb, var, reg)
+#define paddsb_r2r(regs, regd) mmx_r2r(paddsb, regs, regd)
+#define paddsb(vars, vard) mmx_m2m(paddsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel ADDs using Unsigned Saturation arithmetic
+*/
+#define paddusw_m2r(var, reg) mmx_m2r(paddusw, var, reg)
+#define paddusw_r2r(regs, regd) mmx_r2r(paddusw, regs, regd)
+#define paddusw(vars, vard) mmx_m2m(paddusw, vars, vard)
+
+#define paddusb_m2r(var, reg) mmx_m2r(paddusb, var, reg)
+#define paddusb_r2r(regs, regd) mmx_r2r(paddusb, regs, regd)
+#define paddusb(vars, vard) mmx_m2m(paddusb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel SUBs
+*/
+#define psubd_m2r(var, reg) mmx_m2r(psubd, var, reg)
+#define psubd_r2r(regs, regd) mmx_r2r(psubd, regs, regd)
+#define psubd(vars, vard) mmx_m2m(psubd, vars, vard)
+
+#define psubw_m2r(var, reg) mmx_m2r(psubw, var, reg)
+#define psubw_r2r(regs, regd) mmx_r2r(psubw, regs, regd)
+#define psubw(vars, vard) mmx_m2m(psubw, vars, vard)
+
+#define psubb_m2r(var, reg) mmx_m2r(psubb, var, reg)
+#define psubb_r2r(regs, regd) mmx_r2r(psubb, regs, regd)
+#define psubb(vars, vard) mmx_m2m(psubb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Saturation arithmetic
+*/
+#define psubsw_m2r(var, reg) mmx_m2r(psubsw, var, reg)
+#define psubsw_r2r(regs, regd) mmx_r2r(psubsw, regs, regd)
+#define psubsw(vars, vard) mmx_m2m(psubsw, vars, vard)
+
+#define psubsb_m2r(var, reg) mmx_m2r(psubsb, var, reg)
+#define psubsb_r2r(regs, regd) mmx_r2r(psubsb, regs, regd)
+#define psubsb(vars, vard) mmx_m2m(psubsb, vars, vard)
+
+
+/* 4x16 and 8x8 Parallel SUBs using Unsigned Saturation arithmetic
+*/
+#define psubusw_m2r(var, reg) mmx_m2r(psubusw, var, reg)
+#define psubusw_r2r(regs, regd) mmx_r2r(psubusw, regs, regd)
+#define psubusw(vars, vard) mmx_m2m(psubusw, vars, vard)
+
+#define psubusb_m2r(var, reg) mmx_m2r(psubusb, var, reg)
+#define psubusb_r2r(regs, regd) mmx_r2r(psubusb, regs, regd)
+#define psubusb(vars, vard) mmx_m2m(psubusb, vars, vard)
+
+
+/* 4x16 Parallel MULs giving Low 4x16 portions of results
+*/
+#define pmullw_m2r(var, reg) mmx_m2r(pmullw, var, reg)
+#define pmullw_r2r(regs, regd) mmx_r2r(pmullw, regs, regd)
+#define pmullw(vars, vard) mmx_m2m(pmullw, vars, vard)
+
+
+/* 4x16 Parallel MULs giving High 4x16 portions of results
+*/
+#define pmulhw_m2r(var, reg) mmx_m2r(pmulhw, var, reg)
+#define pmulhw_r2r(regs, regd) mmx_r2r(pmulhw, regs, regd)
+#define pmulhw(vars, vard) mmx_m2m(pmulhw, vars, vard)
+
+
+/* 4x16->2x32 Parallel Mul-ADD
+ (muls like pmullw, then adds adjacent 16-bit fields
+ in the multiply result to make the final 2x32 result)
+*/
+#define pmaddwd_m2r(var, reg) mmx_m2r(pmaddwd, var, reg)
+#define pmaddwd_r2r(regs, regd) mmx_r2r(pmaddwd, regs, regd)
+#define pmaddwd(vars, vard) mmx_m2m(pmaddwd, vars, vard)
+
+
+/* 1x64 bitwise AND
+*/
+#ifdef BROKEN_PAND
+#define pand_m2r(var, reg) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, reg); \
+ mmx_m2r(pandn, var, reg); \
+ }
+#define pand_r2r(regs, regd) \
+ { \
+ mmx_m2r(pandn, (mmx_t) -1LL, regd); \
+ mmx_r2r(pandn, regs, regd) \
+ }
+#define pand(vars, vard) \
+ { \
+ movq_m2r(vard, mm0); \
+ mmx_m2r(pandn, (mmx_t) -1LL, mm0); \
+ mmx_m2r(pandn, vars, mm0); \
+ movq_r2m(mm0, vard); \
+ }
+#else
+#define pand_m2r(var, reg) mmx_m2r(pand, var, reg)
+#define pand_r2r(regs, regd) mmx_r2r(pand, regs, regd)
+#define pand(vars, vard) mmx_m2m(pand, vars, vard)
+#endif
+
+
+/* 1x64 bitwise AND with Not the destination
+*/
+#define pandn_m2r(var, reg) mmx_m2r(pandn, var, reg)
+#define pandn_r2r(regs, regd) mmx_r2r(pandn, regs, regd)
+#define pandn(vars, vard) mmx_m2m(pandn, vars, vard)
+
+
+/* 1x64 bitwise OR
+*/
+#define por_m2r(var, reg) mmx_m2r(por, var, reg)
+#define por_r2r(regs, regd) mmx_r2r(por, regs, regd)
+#define por(vars, vard) mmx_m2m(por, vars, vard)
+
+
+/* 1x64 bitwise eXclusive OR
+*/
+#define pxor_m2r(var, reg) mmx_m2r(pxor, var, reg)
+#define pxor_r2r(regs, regd) mmx_r2r(pxor, regs, regd)
+#define pxor(vars, vard) mmx_m2m(pxor, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for EQuality
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpeqd_m2r(var, reg) mmx_m2r(pcmpeqd, var, reg)
+#define pcmpeqd_r2r(regs, regd) mmx_r2r(pcmpeqd, regs, regd)
+#define pcmpeqd(vars, vard) mmx_m2m(pcmpeqd, vars, vard)
+
+#define pcmpeqw_m2r(var, reg) mmx_m2r(pcmpeqw, var, reg)
+#define pcmpeqw_r2r(regs, regd) mmx_r2r(pcmpeqw, regs, regd)
+#define pcmpeqw(vars, vard) mmx_m2m(pcmpeqw, vars, vard)
+
+#define pcmpeqb_m2r(var, reg) mmx_m2r(pcmpeqb, var, reg)
+#define pcmpeqb_r2r(regs, regd) mmx_r2r(pcmpeqb, regs, regd)
+#define pcmpeqb(vars, vard) mmx_m2m(pcmpeqb, vars, vard)
+
+
+/* 2x32, 4x16, and 8x8 Parallel CoMPare for Greater Than
+ (resulting fields are either 0 or -1)
+*/
+#define pcmpgtd_m2r(var, reg) mmx_m2r(pcmpgtd, var, reg)
+#define pcmpgtd_r2r(regs, regd) mmx_r2r(pcmpgtd, regs, regd)
+#define pcmpgtd(vars, vard) mmx_m2m(pcmpgtd, vars, vard)
+
+#define pcmpgtw_m2r(var, reg) mmx_m2r(pcmpgtw, var, reg)
+#define pcmpgtw_r2r(regs, regd) mmx_r2r(pcmpgtw, regs, regd)
+#define pcmpgtw(vars, vard) mmx_m2m(pcmpgtw, vars, vard)
+
+#define pcmpgtb_m2r(var, reg) mmx_m2r(pcmpgtb, var, reg)
+#define pcmpgtb_r2r(regs, regd) mmx_r2r(pcmpgtb, regs, regd)
+#define pcmpgtb(vars, vard) mmx_m2m(pcmpgtb, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Left Logical
+*/
+#define psllq_i2r(imm, reg) mmx_i2r(psllq, imm, reg)
+#define psllq_m2r(var, reg) mmx_m2r(psllq, var, reg)
+#define psllq_r2r(regs, regd) mmx_r2r(psllq, regs, regd)
+#define psllq(vars, vard) mmx_m2m(psllq, vars, vard)
+
+#define pslld_i2r(imm, reg) mmx_i2r(pslld, imm, reg)
+#define pslld_m2r(var, reg) mmx_m2r(pslld, var, reg)
+#define pslld_r2r(regs, regd) mmx_r2r(pslld, regs, regd)
+#define pslld(vars, vard) mmx_m2m(pslld, vars, vard)
+
+#define psllw_i2r(imm, reg) mmx_i2r(psllw, imm, reg)
+#define psllw_m2r(var, reg) mmx_m2r(psllw, var, reg)
+#define psllw_r2r(regs, regd) mmx_r2r(psllw, regs, regd)
+#define psllw(vars, vard) mmx_m2m(psllw, vars, vard)
+
+
+/* 1x64, 2x32, and 4x16 Parallel Shift Right Logical
+*/
+#define psrlq_i2r(imm, reg) mmx_i2r(psrlq, imm, reg)
+#define psrlq_m2r(var, reg) mmx_m2r(psrlq, var, reg)
+#define psrlq_r2r(regs, regd) mmx_r2r(psrlq, regs, regd)
+#define psrlq(vars, vard) mmx_m2m(psrlq, vars, vard)
+
+#define psrld_i2r(imm, reg) mmx_i2r(psrld, imm, reg)
+#define psrld_m2r(var, reg) mmx_m2r(psrld, var, reg)
+#define psrld_r2r(regs, regd) mmx_r2r(psrld, regs, regd)
+#define psrld(vars, vard) mmx_m2m(psrld, vars, vard)
+
+#define psrlw_i2r(imm, reg) mmx_i2r(psrlw, imm, reg)
+#define psrlw_m2r(var, reg) mmx_m2r(psrlw, var, reg)
+#define psrlw_r2r(regs, regd) mmx_r2r(psrlw, regs, regd)
+#define psrlw(vars, vard) mmx_m2m(psrlw, vars, vard)
+
+
+/* 2x32 and 4x16 Parallel Shift Right Arithmetic
+*/
+#define psrad_i2r(imm, reg) mmx_i2r(psrad, imm, reg)
+#define psrad_m2r(var, reg) mmx_m2r(psrad, var, reg)
+#define psrad_r2r(regs, regd) mmx_r2r(psrad, regs, regd)
+#define psrad(vars, vard) mmx_m2m(psrad, vars, vard)
+
+#define psraw_i2r(imm, reg) mmx_i2r(psraw, imm, reg)
+#define psraw_m2r(var, reg) mmx_m2r(psraw, var, reg)
+#define psraw_r2r(regs, regd) mmx_r2r(psraw, regs, regd)
+#define psraw(vars, vard) mmx_m2m(psraw, vars, vard)
+
+
+/* 2x32->4x16 and 4x16->8x8 PACK and Signed Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packssdw_m2r(var, reg) mmx_m2r(packssdw, var, reg)
+#define packssdw_r2r(regs, regd) mmx_r2r(packssdw, regs, regd)
+#define packssdw(vars, vard) mmx_m2m(packssdw, vars, vard)
+
+#define packsswb_m2r(var, reg) mmx_m2r(packsswb, var, reg)
+#define packsswb_r2r(regs, regd) mmx_r2r(packsswb, regs, regd)
+#define packsswb(vars, vard) mmx_m2m(packsswb, vars, vard)
+
+
+/* 4x16->8x8 PACK and Unsigned Saturate
+ (packs source and dest fields into dest in that order)
+*/
+#define packuswb_m2r(var, reg) mmx_m2r(packuswb, var, reg)
+#define packuswb_r2r(regs, regd) mmx_r2r(packuswb, regs, regd)
+#define packuswb(vars, vard) mmx_m2m(packuswb, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK Low
+ (interleaves low half of dest with low half of source
+ as padding in each result field)
+*/
+#define punpckldq_m2r(var, reg) mmx_m2r(punpckldq, var, reg)
+#define punpckldq_r2r(regs, regd) mmx_r2r(punpckldq, regs, regd)
+#define punpckldq(vars, vard) mmx_m2m(punpckldq, vars, vard)
+
+#define punpcklwd_m2r(var, reg) mmx_m2r(punpcklwd, var, reg)
+#define punpcklwd_r2r(regs, regd) mmx_r2r(punpcklwd, regs, regd)
+#define punpcklwd(vars, vard) mmx_m2m(punpcklwd, vars, vard)
+
+#define punpcklbw_m2r(var, reg) mmx_m2r(punpcklbw, var, reg)
+#define punpcklbw_r2r(regs, regd) mmx_r2r(punpcklbw, regs, regd)
+#define punpcklbw(vars, vard) mmx_m2m(punpcklbw, vars, vard)
+
+
+/* 2x32->1x64, 4x16->2x32, and 8x8->4x16 UNPaCK High
+ (interleaves high half of dest with high half of source
+ as padding in each result field)
+*/
+#define punpckhdq_m2r(var, reg) mmx_m2r(punpckhdq, var, reg)
+#define punpckhdq_r2r(regs, regd) mmx_r2r(punpckhdq, regs, regd)
+#define punpckhdq(vars, vard) mmx_m2m(punpckhdq, vars, vard)
+
+#define punpckhwd_m2r(var, reg) mmx_m2r(punpckhwd, var, reg)
+#define punpckhwd_r2r(regs, regd) mmx_r2r(punpckhwd, regs, regd)
+#define punpckhwd(vars, vard) mmx_m2m(punpckhwd, vars, vard)
+
+#define punpckhbw_m2r(var, reg) mmx_m2r(punpckhbw, var, reg)
+#define punpckhbw_r2r(regs, regd) mmx_r2r(punpckhbw, regs, regd)
+#define punpckhbw(vars, vard) mmx_m2m(punpckhbw, vars, vard)
+
+
+/* Empty MMx State
+ (used to clean-up when going from mmx to float use
+ of the registers that are shared by both; note that
+ there is no float-to-mmx operation needed, because
+ only the float tag word info is corruptible)
+*/
+#ifdef MMX_TRACE
+
+#define emms() \
+ { \
+ fprintf(stderr, "emms()\n"); \
+ __asm__ __volatile__ ("emms"); \
+ }
+
+#else
+
+#define emms() __asm__ __volatile__ ("emms")
+
+#endif
+
+#endif
+
diff --git a/src/mesa/drivers/dri/common/spantmp.h b/src/mesa/drivers/dri/common/spantmp.h
new file mode 100644
index 0000000..be54ebb
--- /dev/null
+++ b/src/mesa/drivers/dri/common/spantmp.h
@@ -0,0 +1,305 @@
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_WRITE_LOCK
+#define HW_WRITE_LOCK() HW_LOCK()
+#endif
+
+#ifndef HW_WRITE_UNLOCK
+#define HW_WRITE_UNLOCK() HW_UNLOCK()
+#endif
+
+#ifndef HW_READ_LOCK
+#define HW_READ_LOCK() HW_LOCK()
+#endif
+
+#ifndef HW_READ_UNLOCK
+#define HW_READ_UNLOCK() HW_UNLOCK()
+#endif
+
+#ifndef HW_READ_CLIPLOOP
+#define HW_READ_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+#ifndef HW_WRITE_CLIPLOOP
+#define HW_WRITE_CLIPLOOP() HW_CLIPLOOP()
+#endif
+
+
+static void TAG(WriteRGBASpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBASpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBSpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteRGBSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_RGBA( x1, y, rgb[i][0], rgb[i][1], rgb[i][2], 255 );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+static void TAG(WriteRGBAPixels)( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++)
+ {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_RGBA( x[i], fy,
+ rgba[i][0], rgba[i][1],
+ rgba[i][2], rgba[i][3] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBASpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ y = Y_FLIP( y );
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBASpan\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ if (mask)
+ {
+ for (;n1>0;i++,x1++,n1--)
+ if (mask[i])
+ WRITE_PIXEL( x1, y, p );
+ }
+ else
+ {
+ for (;n1>0;i++,x1++,n1--)
+ WRITE_PIXEL( x1, y, p );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteMonoRGBAPixels)( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint i;
+ LOCAL_VARS;
+ INIT_MONO_PIXEL(p, color);
+
+ if (DBG) fprintf(stderr, "WriteMonoRGBAPixels\n");
+
+ HW_WRITE_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL( x[i], fy ))
+ WRITE_PIXEL( x[i], fy, p );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+#if 0
+static void TAG(ReadRGBASpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ HW_READ_LOCK()
+ {
+ GLint x1,n1;
+ LOCAL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadRGBASpan\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;n1>0;i++,x1++,n1--)
+ READ_RGBA( rgba[i], x1, y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+#endif
+
+
+static void TAG(ReadRGBAPixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ HW_READ_LOCK()
+ {
+ GLint i;
+ LOCAL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadRGBAPixels\n");
+
+ HW_READ_CLIPLOOP()
+ {
+ if (mask)
+ {
+ for (i=0;i<n;i++)
+ if (mask[i]) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ else
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_RGBA( rgba[i], x[i], fy );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+
+
+#undef WRITE_PIXEL
+#undef WRITE_RGBA
+#undef READ_RGBA
+#undef TAG
diff --git a/src/mesa/drivers/dri/common/stenciltmp.h b/src/mesa/drivers/dri/common/stenciltmp.h
new file mode 100644
index 0000000..365e981
--- /dev/null
+++ b/src/mesa/drivers/dri/common/stenciltmp.h
@@ -0,0 +1,147 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/common/stenciltmp.h,v 1.3 2001/03/21 16:14:20 dawes Exp $ */
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+#ifndef HW_WRITE_LOCK
+#define HW_WRITE_LOCK() HW_LOCK()
+#endif
+#ifndef HW_WRITE_UNLOCK
+#define HW_WRITE_UNLOCK() HW_UNLOCK()
+#endif
+
+#ifndef HW_READ_LOCK
+#define HW_READ_LOCK() HW_LOCK()
+#endif
+#ifndef HW_READ_UNLOCK
+#define HW_READ_UNLOCK() HW_UNLOCK()
+#endif
+
+static void TAG(WriteStencilSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLstencil *stencil,
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint x1;
+ GLint n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+
+ if (DBG) fprintf(stderr, "WriteStencilSpan %d..%d (x1 %d)\n",
+ (int)i, (int)n1, (int)x1);
+
+ if (mask)
+ {
+ for (;i<n1;i++,x1++)
+ if (mask[i])
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ else
+ {
+ for (;i<n1;i++,x1++)
+ WRITE_STENCIL( x1, y, stencil[i] );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+static void TAG(WriteStencilPixels)( GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLstencil stencil[],
+ const GLubyte mask[] )
+{
+ HW_WRITE_LOCK()
+ {
+ GLint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "WriteStencilPixels\n");
+
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++)
+ {
+ if (mask[i]) {
+ const int fy = Y_FLIP(y[i]);
+ if (CLIPPIXEL(x[i],fy))
+ WRITE_STENCIL( x[i], fy, stencil[i] );
+ }
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_WRITE_UNLOCK();
+}
+
+
+/* Read stencil spans and pixels
+ */
+static void TAG(ReadStencilSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLstencil stencil[])
+{
+ HW_READ_LOCK()
+ {
+ GLint x1,n1;
+ LOCAL_STENCIL_VARS;
+
+ y = Y_FLIP(y);
+
+ if (DBG) fprintf(stderr, "ReadStencilSpan\n");
+
+ HW_CLIPLOOP()
+ {
+ GLint i = 0;
+ CLIPSPAN(x,y,n,x1,n1,i);
+ for (;i<n1;i++)
+ READ_STENCIL( stencil[i], (x1+i), y );
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+static void TAG(ReadStencilPixels)( GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLstencil stencil[] )
+{
+ HW_READ_LOCK()
+ {
+ GLint i;
+ LOCAL_STENCIL_VARS;
+
+ if (DBG) fprintf(stderr, "ReadStencilPixels\n");
+
+ HW_CLIPLOOP()
+ {
+ for (i=0;i<n;i++) {
+ int fy = Y_FLIP( y[i] );
+ if (CLIPPIXEL( x[i], fy ))
+ READ_STENCIL( stencil[i], x[i], fy );
+ }
+ }
+ HW_ENDCLIPLOOP();
+ }
+ HW_READ_UNLOCK();
+}
+
+
+
+
+#undef WRITE_STENCIL
+#undef READ_STENCIL
+#undef TAG
diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c
new file mode 100644
index 0000000..48a8f5c
--- /dev/null
+++ b/src/mesa/drivers/dri/common/texmem.c
@@ -0,0 +1,1278 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (C) Copyright IBM Corporation 2002, 2003
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+/* $XFree86:$ */
+
+/** \file texmem.c
+ * Implements all of the device-independent texture memory management.
+ *
+ * Currently, only a simple LRU texture memory management policy is
+ * implemented. In the (hopefully very near) future, better policies will be
+ * implemented. The idea is that the DRI should be able to run in one of two
+ * modes. In the default mode the DRI will dynamically attempt to discover
+ * the best texture management policy for the running application. In the
+ * other mode, the user (via some sort of as yet TBD mechanism) will select
+ * a texture management policy that is known to work well with the
+ * application.
+ */
+
+#include "texmem.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "macros.h"
+#include "texformat.h"
+
+#include <assert.h>
+
+
+
+static unsigned dummy_swap_counter;
+
+
+/**
+ * Calculate \f$\log_2\f$ of a value. This is a particularly poor
+ * implementation of this function. However, since system performance is in
+ * no way dependent on this function, the slowness of the implementation is
+ * irrelevent.
+ *
+ * \param n Value whose \f$\log_2\f$ is to be calculated
+ */
+
+static GLuint
+driLog2( GLuint n )
+{
+ GLuint log2;
+
+ for ( log2 = 1 ; n > 1 ; log2++ ) {
+ n >>= 1;
+ }
+
+ return log2;
+}
+
+
+
+
+/**
+ * Determine if a texture is resident in textureable memory. Depending on
+ * the driver, this may or may not be on-card memory. It could be AGP memory
+ * or anyother type of memory from which the hardware can directly read
+ * texels.
+ *
+ * This function is intended to be used as the \c IsTextureResident function
+ * in the device's \c dd_function_table.
+ *
+ * \param ctx GL context pointer (currently unused)
+ * \param texObj Texture object to be tested
+ */
+
+GLboolean
+driIsTextureResident( GLcontext * ctx,
+ struct gl_texture_object * texObj )
+{
+ driTextureObject * t;
+
+
+ t = (driTextureObject *) texObj->DriverData;
+ return( (t != NULL) && (t->memBlock != NULL) );
+}
+
+
+
+
+/**
+ * (Re)initialize the global circular LRU list. The last element
+ * in the array (\a heap->nrRegions) is the sentinal. Keeping it
+ * at the end of the array allows the other elements of the array
+ * to be addressed rationally when looking up objects at a particular
+ * location in texture memory.
+ *
+ * \param heap Texture heap to be reset
+ */
+
+static void resetGlobalLRU( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << heap->logGranularity;
+ unsigned i;
+
+ for (i = 0 ; (i+1) * sz <= heap->size ; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = heap->nrRegions;
+ list[i].prev = i-1;
+ list[i].next = heap->nrRegions;
+ list[heap->nrRegions].prev = i;
+ list[heap->nrRegions].next = 0;
+ heap->global_age[0] = 0;
+}
+
+/**
+ * Print out debugging information about the local texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printLocalLRU( driTexHeap * heap, const char *callername )
+{
+ driTextureObject *t;
+ unsigned sz = 1U << heap->logGranularity;
+
+ fprintf( stderr, "%s in %s:\nLocal LRU, heap %d:\n",
+ __FUNCTION__, callername, heap->heapId );
+
+ foreach ( t, &heap->texture_objects ) {
+ if (!t->memBlock)
+ continue;
+ if (!t->tObj) {
+ fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs / sz,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ } else {
+ fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
+ (void *)t,
+ t->memBlock->ofs,
+ t->memBlock->size );
+ }
+ }
+ foreach ( t, heap->swapped_objects ) {
+ if (!t->tObj) {
+ fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );
+ } else {
+ fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+/**
+ * Print out debugging information about the global texture LRU.
+ *
+ * \param heap Texture heap to be printed
+ * \param callername Name of calling function
+ */
+static void printGlobalLRU( driTexHeap * heap, const char *callername )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ int i, j;
+
+ fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n",
+ __FUNCTION__, callername, heap->heapId, (void *)list );
+
+ for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ j, list[j].age, list[j].next, list[j].prev, list[j].in_use );
+ j = list[j].next;
+ if ( j == heap->nrRegions ) break;
+ }
+
+ if ( j != heap->nrRegions ) {
+ fprintf( stderr, "Loop detected in global LRU\n" );
+ for ( i = 0 ; i < heap->nrRegions ; i++ ) {
+ fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
+ i, list[i].age, list[i].next, list[i].prev, list[i].in_use );
+ }
+ }
+
+ fprintf( stderr, "\n" );
+}
+
+
+/**
+ * Called by the client whenever it touches a local texture.
+ *
+ * \param t Texture object that the client has accessed
+ */
+
+void driUpdateTextureLRU( driTextureObject * t )
+{
+ driTexHeap * heap;
+ drmTextureRegionPtr list;
+ unsigned shift;
+ unsigned start;
+ unsigned end;
+ unsigned i;
+
+
+ heap = t->heap;
+ if ( heap != NULL ) {
+ shift = heap->logGranularity;
+ start = t->memBlock->ofs >> shift;
+ end = (t->memBlock->ofs + t->memBlock->size - 1) >> shift;
+
+
+ heap->local_age = ++heap->global_age[0];
+ list = heap->global_regions;
+
+
+ /* Update the context's local LRU
+ */
+
+ move_to_head( & heap->texture_objects, t );
+
+
+ for (i = start ; i <= end ; i++) {
+ list[i].age = heap->local_age;
+
+ /* remove_from_list(i)
+ */
+ list[(unsigned)list[i].next].prev = list[i].prev;
+ list[(unsigned)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i)
+ */
+ list[i].prev = heap->nrRegions;
+ list[i].next = list[heap->nrRegions].next;
+ list[(unsigned)list[heap->nrRegions].next].prev = i;
+ list[heap->nrRegions].next = i;
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+ }
+}
+
+
+
+
+/**
+ * Keep track of swapped out texture objects.
+ *
+ * \param t Texture object to be "swapped" out of its texture heap
+ */
+
+void driSwapOutTextureObject( driTextureObject * t )
+{
+ unsigned face;
+
+
+ if ( t->memBlock != NULL ) {
+ assert( t->heap != NULL );
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ t->heap->texture_swaps[0]++;
+ move_to_tail( t->heap->swapped_objects, t );
+ t->heap = NULL;
+ }
+ else {
+ assert( t->heap == NULL );
+ }
+
+
+ for ( face = 0 ; face < 6 ; face++ ) {
+ t->dirty_images[face] = ~0;
+ }
+}
+
+
+
+
+/**
+ * Destroy hardware state associated with texture \a t. Calls the
+ * \a destroy_texture_object method associated with the heap from which
+ * \a t was allocated.
+ *
+ * \param t Texture object to be destroyed
+ */
+
+void driDestroyTextureObject( driTextureObject * t )
+{
+ driTexHeap * heap;
+
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",
+ __FILE__, __LINE__,
+ (void *)t,
+ (void *)((t != NULL) ? t->tObj : NULL),
+ (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));
+ }
+
+ if ( t != NULL ) {
+ if ( t->memBlock ) {
+ heap = t->heap;
+ assert( heap != NULL );
+
+ heap->texture_swaps[0]++;
+
+ mmFreeMem( t->memBlock );
+ t->memBlock = NULL;
+
+ if (t->timestamp > t->heap->timestamp)
+ t->heap->timestamp = t->timestamp;
+
+ heap->destroy_texture_object( heap->driverContext, t );
+ t->heap = NULL;
+ }
+
+ if ( t->tObj != NULL ) {
+ assert( t->tObj->DriverData == t );
+ t->tObj->DriverData = NULL;
+ }
+
+ remove_from_list( t );
+ FREE( t );
+ }
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );
+ }
+}
+
+
+
+
+/**
+ * Update the local heap's representation of texture memory based on
+ * data in the SAREA. This is done each time it is detected that some other
+ * direct rendering client has held the lock. This pertains to both our local
+ * textures and the textures belonging to other clients. Keep track of other
+ * client's textures by pushing a placeholder texture onto the LRU list --
+ * these are denoted by \a tObj being \a NULL.
+ *
+ * \param heap Heap whose state is to be updated
+ * \param offset Byte offset in the heap that has been stolen
+ * \param size Size, in bytes, of the stolen block
+ * \param in_use Non-zero if the block is pinned/reserved by the kernel
+ */
+
+static void driTexturesGone( driTexHeap * heap, int offset, int size,
+ int in_use )
+{
+ driTextureObject * t;
+ driTextureObject * tmp;
+
+
+ foreach_s ( t, tmp, & heap->texture_objects ) {
+ if ( (t->memBlock->ofs < (offset + size))
+ && ((t->memBlock->ofs + t->memBlock->size) > offset) ) {
+ /* It overlaps - kick it out. If the texture object is just a
+ * place holder, then destroy it all together. Otherwise, mark
+ * it as being swapped out.
+ */
+
+ if ( t->tObj != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ driDestroyTextureObject( t );
+ }
+ }
+ }
+
+
+ {
+ t = (driTextureObject *) CALLOC( heap->texture_object_size );
+ if ( t == NULL ) return;
+
+ t->memBlock = mmAllocMem( heap->memory_heap, size, 0, offset );
+ if ( t->memBlock == NULL ) {
+ fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,
+ (int)size, (int)offset );
+ mmDumpMemInfo( heap->memory_heap );
+ return;
+ }
+ t->heap = heap;
+ if (in_use)
+ t->bound = 99;
+ insert_at_head( & heap->texture_objects, t );
+ }
+}
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ */
+
+void driAgeTextures( driTexHeap * heap )
+{
+ drmTextureRegionPtr list = heap->global_regions;
+ unsigned sz = 1U << (heap->logGranularity);
+ unsigned i, nr = 0;
+
+
+ /* Have to go right round from the back to ensure stuff ends up
+ * LRU in the local list... Fix with a cursor pointer.
+ */
+
+ for (i = list[heap->nrRegions].prev ;
+ i != heap->nrRegions && nr < heap->nrRegions ;
+ i = list[i].prev, nr++) {
+ /* If switching texturing schemes, then the SAREA might not have been
+ * properly cleared, so we need to reset the global texture LRU.
+ */
+
+ if ( (i * sz) > heap->size ) {
+ nr = heap->nrRegions;
+ break;
+ }
+
+ if (list[i].age > heap->local_age)
+ driTexturesGone( heap, i * sz, sz, list[i].in_use);
+ }
+
+ /* Loop or uninitialized heap detected. Reset.
+ */
+
+ if (nr == heap->nrRegions) {
+ driTexturesGone( heap, 0, heap->size, 0);
+ resetGlobalLRU( heap );
+ }
+
+ if ( 0 ) {
+ printGlobalLRU( heap, __FUNCTION__ );
+ printLocalLRU( heap, __FUNCTION__ );
+ }
+
+ heap->local_age = heap->global_age[0];
+}
+
+
+
+
+/**
+ * Allocate memory from a texture heap to hold a texture object. This
+ * routine will attempt to allocate memory for the texture from the heaps
+ * specified by \c heap_array in order. That is, first it will try to
+ * allocate from \c heap_array[0], then \c heap_array[1], and so on.
+ *
+ * \param heap_array Array of pointers to texture heaps to use
+ * \param nr_heaps Number of heap pointer in \a heap_array
+ * \param t Texture object for which space is needed
+ * \return The ID of the heap from which memory was allocated, or -1 if
+ * memory could not be allocated.
+ *
+ * \bug The replacement policy implemented by this function is horrible.
+ */
+
+
+int
+driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t )
+{
+ driTexHeap * heap;
+ driTextureObject * temp;
+ driTextureObject * cursor;
+ unsigned id;
+
+
+ /* In case it already has texture space, initialize heap. This also
+ * prevents GCC from issuing a warning that heap might be used
+ * uninitialized.
+ */
+
+ heap = t->heap;
+
+
+ /* Run through each of the existing heaps and try to allocate a buffer
+ * to hold the texture.
+ */
+
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
+ heap = heap_array[ id ];
+ if ( heap != NULL ) {
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+ }
+ }
+
+
+ /* Kick textures out until the requested texture fits.
+ */
+
+ if ( t->memBlock == NULL ) {
+ for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) {
+ heap = heap_array[ id ];
+ if ( t->totalSize <= heap->size ) {
+
+ for ( cursor = heap->texture_objects.prev, temp = cursor->prev;
+ cursor != &heap->texture_objects ;
+ cursor = temp, temp = cursor->prev ) {
+
+ /* The the LRU element. If the texture is bound to one of
+ * the texture units, then we cannot kick it out.
+ */
+ if ( cursor->bound /* || cursor->reserved */ ) {
+ continue;
+ }
+
+ /* If this is a placeholder, there's no need to keep it */
+ if (cursor->tObj)
+ driSwapOutTextureObject( cursor );
+ else
+ driDestroyTextureObject( cursor );
+
+ t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize,
+ heap->alignmentShift, 0 );
+
+ if (t->memBlock)
+ break;
+ }
+ } /* if ( t->totalSize <= heap->size ) ... */
+ }
+ }
+
+
+ if ( t->memBlock != NULL ) {
+ /* id and heap->heapId may or may not be the same value here.
+ */
+
+ assert( heap != NULL );
+ assert( (t->heap == NULL) || (t->heap == heap) );
+
+ t->heap = heap;
+ return heap->heapId;
+ }
+ else {
+ assert( t->heap == NULL );
+
+ fprintf( stderr, "[%s:%d] unable to allocate texture\n",
+ __FUNCTION__, __LINE__ );
+ return -1;
+ }
+}
+
+
+
+
+
+
+/**
+ * Set the location where the texture-swap counter is stored.
+ */
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter )
+{
+ heap->texture_swaps = (counter == NULL) ? & dummy_swap_counter : counter;
+}
+
+
+
+
+/**
+ * Create a new heap for texture data.
+ *
+ * \param heap_id Device-dependent heap identifier. This value
+ * will returned by driAllocateTexture when memory
+ * is allocated from this heap.
+ * \param context Device-dependent driver context. This is
+ * supplied as the first parameter to the
+ * \c destroy_tex_obj function.
+ * \param size Size, in bytes, of the texture region
+ * \param alignmentShift Alignment requirement for textures. If textures
+ * must be allocated on a 4096 byte boundry, this
+ * would be 12.
+ * \param nr_regions Number of regions into which this texture space
+ * should be partitioned
+ * \param global_regions Array of \c drmTextureRegion structures in the SAREA
+ * \param global_age Pointer to the global texture age in the SAREA
+ * \param swapped_objects Pointer to the list of texture objects that are
+ * not in texture memory (i.e., have been swapped
+ * out).
+ * \param texture_object_size Size, in bytes, of a device-dependent texture
+ * object
+ * \param destroy_tex_obj Function used to destroy a device-dependent
+ * texture object
+ *
+ * \sa driDestroyTextureHeap
+ */
+
+driTexHeap *
+driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
+ unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects,
+ unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj
+ )
+{
+ driTexHeap * heap;
+ unsigned l;
+
+
+ if ( 0 )
+ fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",
+ __FUNCTION__,
+ heap_id, (void *)context, size, alignmentShift, nr_regions );
+
+ heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );
+ if ( heap != NULL ) {
+ l = driLog2( (size - 1) / nr_regions );
+ if ( l < alignmentShift )
+ {
+ l = alignmentShift;
+ }
+
+ heap->logGranularity = l;
+ heap->size = size & ~((1L << l) - 1);
+
+ heap->memory_heap = mmInit( 0, heap->size );
+ if ( heap->memory_heap != NULL ) {
+ heap->heapId = heap_id;
+ heap->driverContext = context;
+
+ heap->alignmentShift = alignmentShift;
+ heap->nrRegions = nr_regions;
+ heap->global_regions = global_regions;
+ heap->global_age = global_age;
+ heap->swapped_objects = swapped_objects;
+ heap->texture_object_size = texture_object_size;
+ heap->destroy_texture_object = destroy_tex_obj;
+
+ /* Force global heap init */
+ if (heap->global_age[0] == 0)
+ heap->local_age = ~0;
+ else
+ heap->local_age = 0;
+
+ make_empty_list( & heap->texture_objects );
+ driSetTextureSwapCounterLocation( heap, NULL );
+ }
+ else {
+ FREE( heap );
+ heap = NULL;
+ }
+ }
+
+
+ if ( 0 )
+ fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );
+
+ return heap;
+}
+
+
+
+
+/** Destroys a texture heap
+ *
+ * \param heap Texture heap to be destroyed
+ */
+
+void
+driDestroyTextureHeap( driTexHeap * heap )
+{
+ driTextureObject * t;
+ driTextureObject * temp;
+
+
+ if ( heap != NULL ) {
+ foreach_s( t, temp, & heap->texture_objects ) {
+ driDestroyTextureObject( t );
+ }
+ foreach_s( t, temp, heap->swapped_objects ) {
+ driDestroyTextureObject( t );
+ }
+
+ mmDestroy( heap->memory_heap );
+ FREE( heap );
+ }
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Determine how many texels (including all mipmap levels) would be required
+ * for a texture map of size \f$2^^\c base_size_log2\f$ would require.
+ *
+ * \param base_size_log2 \f$log_2\f$ of the size of a side of the texture
+ * \param dimensions Number of dimensions of the texture. Either 2 or 3.
+ * \param faces Number of faces of the texture. Either 1 or 6 (for cube maps).
+ * \return Number of texels
+ */
+
+static unsigned
+texels_this_map_size( int base_size_log2, unsigned dimensions, unsigned faces )
+{
+ unsigned texels;
+
+
+ assert( (faces == 1) || (faces == 6) );
+ assert( (dimensions == 2) || (dimensions == 3) );
+
+ texels = 0;
+ if ( base_size_log2 >= 0 ) {
+ texels = (1U << (dimensions * base_size_log2));
+
+ /* See http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg03636.html
+ * for the complete explaination of why this formulation is used.
+ * Basically, the smaller mipmap levels sum to 0.333 the size of the
+ * level 0 map. The total size is therefore the size of the map
+ * multipled by 1.333. The +2 is there to round up.
+ */
+
+ texels = (texels * 4 * faces + 2) / 3;
+ }
+
+ return texels;
+}
+
+
+
+
+struct maps_per_heap {
+ unsigned c[32];
+};
+
+static void
+fill_in_maximums( driTexHeap * const * heaps, unsigned nr_heaps,
+ unsigned max_bytes_per_texel, unsigned max_size,
+ unsigned mipmaps_at_once, unsigned dimensions,
+ unsigned faces, struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+ unsigned mask;
+
+
+ /* Determine how many textures of each size can be stored in each
+ * texture heap.
+ */
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ ) {
+ if ( heaps[ heap ] == NULL ) {
+ (void) memset( max_textures[ heap ].c, 0,
+ sizeof( max_textures[ heap ].c ) );
+ continue;
+ }
+
+ mask = (1U << heaps[ heap ]->logGranularity) - 1;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] heap[%u] = %u bytes, mask = 0x%08x\n",
+ __FILE__, __LINE__,
+ heap, heaps[ heap ]->size, mask );
+ }
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total;
+
+
+ /* Determine the total number of bytes required by a texture of
+ * size log2_size.
+ */
+
+ total = texels_this_map_size( log2_size, dimensions, faces )
+ - texels_this_map_size( log2_size - mipmaps_at_once,
+ dimensions, faces );
+ total *= max_bytes_per_texel;
+ total = (total + mask) & ~mask;
+
+ /* The number of textures of a given size that will fit in a heap
+ * is equal to the size of the heap divided by the size of the
+ * texture.
+ */
+
+ max_textures[ heap ].c[ log2_size ] = heaps[ heap ]->size / total;
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] "
+ "= 0x%08x / 0x%08x "
+ "= %u (%u)\n",
+ __FILE__, __LINE__,
+ heap, log2_size,
+ heaps[ heap ]->size, total,
+ heaps[ heap ]->size / total,
+ max_textures[ heap ].c[ log2_size ] );
+ }
+ }
+ }
+}
+
+
+static unsigned
+get_max_size( unsigned nr_heaps,
+ unsigned texture_units,
+ unsigned max_size,
+ int all_textures_one_heap,
+ struct maps_per_heap * max_textures )
+{
+ unsigned heap;
+ unsigned log2_size;
+
+
+ /* Determine the largest texture size such that a texture of that size
+ * can be bound to each texture unit at the same time. Some hardware
+ * may require that all textures be in the same texture heap for
+ * multitexturing.
+ */
+
+ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) {
+ unsigned total = 0;
+
+ for ( heap = 0 ; heap < nr_heaps ; heap++ )
+ {
+ total += max_textures[ heap ].c[ log2_size ];
+
+ if ( 0 ) {
+ fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] = %u, "
+ "total = %u\n", __FILE__, __LINE__, heap, log2_size,
+ max_textures[ heap ].c[ log2_size ], total );
+ }
+
+ if ( (max_textures[ heap ].c[ log2_size ] >= texture_units)
+ || (!all_textures_one_heap && (total >= texture_units)) ) {
+ /* The number of mipmap levels is the log-base-2 of the
+ * maximum texture size plus 1. If the maximum texture size
+ * is 1x1, the log-base-2 is 0 and 1 mipmap level (the base
+ * level) is available.
+ */
+
+ return log2_size + 1;
+ }
+ }
+ }
+
+ /* This should NEVER happen. It should always be possible to have at
+ * *least* a 1x1 texture in memory!
+ */
+ assert( log2_size != 0 );
+ return 0;
+}
+
+#define SET_MAX(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 )
+
+#define SET_MAX_RECT(f,v) \
+ do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << max_sizes[v]; } } while( 0 )
+
+
+/**
+ * Given the amount of texture memory, the number of texture units, and the
+ * maximum size of a texel, calculate the maximum texture size the driver can
+ * advertise.
+ *
+ * \param heaps Texture heaps for this card
+ * \param nr_heap Number of texture heaps
+ * \param limits OpenGL contants. MaxTextureUnits must be set.
+ * \param max_bytes_per_texel Maximum size of a single texel, in bytes
+ * \param max_2D_size \f$\log_2\f$ of the maximum 2D texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_3D_size \f$\log_2\f$ of the maximum 3D texture size (i.e.,
+ * 1024x1024x1024 textures, this would be 10)
+ * \param max_cube_size \f$\log_2\f$ of the maximum cube texture size (i.e.,
+ * 1024x1024 textures, this would be 10)
+ * \param max_rect_size \f$\log_2\f$ of the maximum texture rectangle size
+ * (i.e., 1024x1024 textures, this would be 10). This is a power-of-2
+ * even though texture rectangles need not be a power-of-2.
+ * \param mipmaps_at_once Total number of mipmaps that can be used
+ * at one time. For most hardware this will be \f$\c max_size + 1\f$.
+ * For hardware that does not support mipmapping, this will be 1.
+ * \param all_textures_one_heap True if the hardware requires that all
+ * textures be in a single texture heap for multitexturing.
+ */
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap )
+{
+ struct maps_per_heap max_textures[8];
+ unsigned i;
+ const unsigned dimensions[4] = { 2, 3, 2, 2 };
+ const unsigned faces[4] = { 1, 1, 6, 1 };
+ unsigned max_sizes[4];
+ unsigned mipmaps[4];
+
+
+ max_sizes[0] = max_2D_size;
+ max_sizes[1] = max_3D_size;
+ max_sizes[2] = max_cube_size;
+ max_sizes[3] = max_rect_size;
+
+ mipmaps[0] = mipmaps_at_once;
+ mipmaps[1] = mipmaps_at_once;
+ mipmaps[2] = 1;
+ mipmaps[3] = mipmaps_at_once;
+
+
+ /* Calculate the maximum number of texture levels in two passes. The
+ * first pass determines how many textures of each power-of-two size
+ * (including all mipmap levels for that size) can fit in each texture
+ * heap. The second pass finds the largest texture size that allows
+ * a texture of that size to be bound to every texture unit.
+ */
+
+ for ( i = 0 ; i < 4 ; i++ ) {
+ if ( max_sizes[ i ] != 0 ) {
+ fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel,
+ max_sizes[ i ], mipmaps[ i ],
+ dimensions[ i ], faces[ i ],
+ max_textures );
+
+ max_sizes[ i ] = get_max_size( nr_heaps,
+ limits->MaxTextureUnits,
+ max_sizes[ i ],
+ all_textures_one_heap,
+ max_textures );
+ }
+ }
+
+ SET_MAX( MaxTextureLevels, 0 );
+ SET_MAX( Max3DTextureLevels, 1 );
+ SET_MAX( MaxCubeTextureLevels, 2 );
+ SET_MAX_RECT( MaxTextureRectSize, 3 );
+}
+
+
+
+
+/**
+ * Perform initial binding of default textures objects on a per unit, per
+ * texture target basis.
+ *
+ * \param ctx Current OpenGL context
+ * \param swapped List of swapped-out textures
+ * \param targets Bit-mask of value texture targets
+ */
+
+void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
+ GLuint targets )
+{
+ struct gl_texture_object *texObj;
+ GLuint tmp = ctx->Texture.CurrentUnit;
+ unsigned i;
+
+
+ for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
+ ctx->Texture.CurrentUnit = i;
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].Current1D;
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].Current2D;
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) {
+ texObj = ctx->Texture.Unit[i].Current3D;
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentCubeMap;
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+
+ if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) {
+ texObj = ctx->Texture.Unit[i].CurrentRect;
+ ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj );
+ move_to_tail( swapped, (driTextureObject *) texObj->DriverData );
+ }
+ }
+
+ ctx->Texture.CurrentUnit = tmp;
+}
+
+
+
+
+/**
+ * Verify that the specified texture is in the specificed heap.
+ *
+ * \param tex Texture to be tested.
+ * \param heap Texture memory heap to be tested.
+ * \return True if the texture is in the heap, false otherwise.
+ */
+
+static GLboolean
+check_in_heap( const driTextureObject * tex, const driTexHeap * heap )
+{
+#if 1
+ return tex->heap == heap;
+#else
+ driTextureObject * curr;
+
+ foreach( curr, & heap->texture_objects ) {
+ if ( curr == tex ) {
+ break;
+ }
+ }
+
+ return curr == tex;
+#endif
+}
+
+
+
+/****************************************************************************/
+/**
+ * Validate the consistency of a set of texture heaps.
+ * Original version by Keith Whitwell in r200/r200_sanity.c.
+ */
+
+GLboolean
+driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped )
+{
+ driTextureObject *t;
+ unsigned i;
+
+ for ( i = 0 ; i < nr_heaps ; i++ ) {
+ int last_end = 0;
+ unsigned textures_in_heap = 0;
+ unsigned blocks_in_mempool = 0;
+ const driTexHeap * heap = texture_heaps[i];
+ const memHeap_t * p = heap->memory_heap;
+
+ /* Check each texture object has a MemBlock, and is linked into
+ * the correct heap.
+ *
+ * Check the texobj base address corresponds to the MemBlock
+ * range. Check the texobj size (recalculate?) fits within
+ * the MemBlock.
+ *
+ * Count the number of texobj's using this heap.
+ */
+
+ foreach ( t, &heap->texture_objects ) {
+ if ( !check_in_heap( t, heap ) ) {
+ fprintf( stderr, "%s memory block for texture object @ %p not "
+ "found in heap #%d\n",
+ __FUNCTION__, (void *)t, i );
+ return GL_FALSE;
+ }
+
+
+ if ( t->totalSize > t->memBlock->size ) {
+ fprintf( stderr, "%s: Memory block for texture object @ %p is "
+ "only %u bytes, but %u are required\n",
+ __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size );
+ return GL_FALSE;
+ }
+
+ textures_in_heap++;
+ }
+
+ /* Validate the contents of the heap:
+ * - Ordering
+ * - Overlaps
+ * - Bounds
+ */
+
+ while ( p != NULL ) {
+ if (p->reserved) {
+ fprintf( stderr, "%s: Block (%08x,%x), is reserved?!\n",
+ __FUNCTION__, p->ofs, p->size );
+ return GL_FALSE;
+ }
+
+ if (p->ofs != last_end) {
+ fprintf( stderr, "%s: blocks_in_mempool = %d, last_end = %d, p->ofs = %d\n",
+ __FUNCTION__, blocks_in_mempool, last_end, p->ofs );
+ return GL_FALSE;
+ }
+
+ if (!p->reserved && !p->free) {
+ blocks_in_mempool++;
+ }
+
+ last_end = p->ofs + p->size;
+ p = p->next;
+ }
+
+ if (textures_in_heap != blocks_in_mempool) {
+ fprintf( stderr, "%s: Different number of textures objects (%u) and "
+ "inuse memory blocks (%u)\n",
+ __FUNCTION__, textures_in_heap, blocks_in_mempool );
+ return GL_FALSE;
+ }
+
+#if 0
+ fprintf( stderr, "%s: textures_in_heap = %u\n",
+ __FUNCTION__, textures_in_heap );
+#endif
+ }
+
+
+ /* Check swapped texobj's have zero memblocks
+ */
+ i = 0;
+ foreach ( t, swapped ) {
+ if ( t->memBlock != NULL ) {
+ fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n",
+ __FUNCTION__, (void *)t, (void *)t->memBlock );
+ return GL_FALSE;
+ }
+ i++;
+ }
+
+#if 0
+ fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );
+#endif
+
+ return GL_TRUE;
+}
+
+
+
+
+/****************************************************************************/
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+
+void
+driCalculateTextureFirstLastLevel( driTextureObject * t )
+{
+ struct gl_texture_object * const tObj = t->tObj;
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[0][tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, t->tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, t->tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+}
+
+
+
+
+/**
+ * \name DRI texture formats. Pointers initialized to either the big- or
+ * little-endian Mesa formats.
+ */
+/*@{*/
+const struct gl_texture_format *_dri_texformat_rgba8888 = NULL;
+const struct gl_texture_format *_dri_texformat_argb8888 = NULL;
+const struct gl_texture_format *_dri_texformat_rgb565 = NULL;
+const struct gl_texture_format *_dri_texformat_argb4444 = NULL;
+const struct gl_texture_format *_dri_texformat_argb1555 = NULL;
+const struct gl_texture_format *_dri_texformat_al88 = NULL;
+const struct gl_texture_format *_dri_texformat_a8 = &_mesa_texformat_a8;
+const struct gl_texture_format *_dri_texformat_ci8 = &_mesa_texformat_ci8;
+const struct gl_texture_format *_dri_texformat_i8 = &_mesa_texformat_i8;
+const struct gl_texture_format *_dri_texformat_l8 = &_mesa_texformat_l8;
+/*@}*/
+
+
+/**
+ * Initialize little endian target, host byte order independent texture formats
+ */
+void
+driInitTextureFormats(void)
+{
+ const GLuint ui = 1;
+ const GLubyte littleEndian = *((const GLubyte *) &ui);
+
+ if (littleEndian) {
+ _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888;
+ _dri_texformat_argb8888 = &_mesa_texformat_argb8888;
+ _dri_texformat_rgb565 = &_mesa_texformat_rgb565;
+ _dri_texformat_argb4444 = &_mesa_texformat_argb4444;
+ _dri_texformat_argb1555 = &_mesa_texformat_argb1555;
+ _dri_texformat_al88 = &_mesa_texformat_al88;
+ }
+ else {
+ _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888_rev;
+ _dri_texformat_argb8888 = &_mesa_texformat_argb8888_rev;
+ _dri_texformat_rgb565 = &_mesa_texformat_rgb565_rev;
+ _dri_texformat_argb4444 = &_mesa_texformat_argb4444_rev;
+ _dri_texformat_argb1555 = &_mesa_texformat_argb1555_rev;
+ _dri_texformat_al88 = &_mesa_texformat_al88_rev;
+ }
+}
diff --git a/src/mesa/drivers/dri/common/texmem.h b/src/mesa/drivers/dri/common/texmem.h
new file mode 100644
index 0000000..266afd8
--- /dev/null
+++ b/src/mesa/drivers/dri/common/texmem.h
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (c) Copyright IBM Corporation 2002
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ * Keith Whitwell <keithw@tungstengraphics.com>
+ * Kevin E. Martin <kem@users.sourceforge.net>
+ * Gareth Hughes <gareth@nvidia.com>
+ */
+/* $XFree86:$ */
+
+/** \file texmem.h
+ * Public interface to the DRI texture memory management routines.
+ *
+ * \sa texmem.c
+ */
+
+#ifndef DRI_TEXMEM_H
+#define DRI_TEXMEM_H
+
+#include "mtypes.h"
+#include "mm.h"
+#include "xf86drm.h"
+
+struct dri_tex_heap;
+typedef struct dri_tex_heap driTexHeap;
+
+struct dri_texture_object;
+typedef struct dri_texture_object driTextureObject;
+
+
+/**
+ * Base texture object type. Each driver will extend this type with its own
+ * private data members.
+ */
+
+struct dri_texture_object {
+ struct dri_texture_object * next;
+ struct dri_texture_object * prev;
+
+ driTexHeap * heap; /**< Texture heap currently stored in */
+ struct gl_texture_object * tObj;/**< Pointer to Mesa texture object
+ * If NULL, this texture object is a
+ * "placeholder" object representing
+ * texture memory in use by another context.
+ * A placeholder should have a heap and a memBlock.
+ */
+ PMemBlock memBlock; /**< Memory block containing texture */
+ unsigned bound; /**< Texture unit currently bound to */
+
+ unsigned totalSize; /**< Total size of the texture,
+ * including all mipmap levels
+ */
+
+ unsigned dirty_images[6]; /**< Flags for whether or not images
+ * need to be uploaded to local or
+ * AGP texture space. One flag set
+ * for each cube face for cubic
+ * textures. Bit zero corresponds to
+ * the base-level, which may or may
+ * not be the level zero mipmap.
+ */
+
+ unsigned timestamp; /**< Timestamp used to
+ * synchronize with 3d engine
+ * in hardware where textures
+ * are uploaded directly to
+ * the framebuffer.
+ */
+
+ unsigned firstLevel; /**< Image in \c tObj->Image[0] that
+ * corresponds to the base-level of
+ * this texture object.
+ */
+
+ unsigned lastLevel; /**< Last image in \c tObj->Image[0]
+ * used by the
+ * current LOD settings of
+ * this texture object. This
+ * value must be greater than
+ * or equal to \c firstLevel.
+ */
+};
+
+
+typedef void (destroy_texture_object_t)( void * driverContext,
+ driTextureObject * t );
+
+/**
+ * Client-private representation of texture memory state.
+ *
+ * Clients will place one or more of these structs in their driver
+ * context struct to manage one or more global texture heaps.
+ */
+
+struct dri_tex_heap {
+
+ /** Client-supplied heap identifier
+ */
+ unsigned heapId;
+
+ /** Pointer to the client's private context
+ */
+ void *driverContext;
+
+ /** Total size of the heap, in bytes
+ */
+ unsigned size;
+
+ /** \brief \f$log_2\f$ of size of single heap region
+ *
+ * Each context takes memory from the global texture heap in
+ * \f$2^{logGranularity}\f$ byte blocks. The value of
+ * \a logGranularity is based on the amount of memory represented
+ * by the heap and the maximum number of regions in the SAREA. Given
+ * \a b bytes of texture memory an \a n regions in the SAREA,
+ * \a logGranularity will be \f$\lfloor\log_2( b / n )\rfloor\f$.
+ */
+ unsigned logGranularity;
+
+ /** \brief Required alignment of allocations in this heap
+ *
+ * The alignment shift is supplied to \a mmAllocMem when memory is
+ * allocated from this heap. The value of \a alignmentShift will
+ * typically reflect some require of the hardware. This value has
+ * \b no \b relation to \a logGranularity. \a alignmentShift is a
+ * per-context value.
+ *
+ * \sa mmAllocMem
+ */
+ unsigned alignmentShift;
+
+ /** Number of elements in global list (the SAREA).
+ */
+ unsigned nrRegions;
+
+ /** Pointer to SAREA \a driTexRegion array
+ */
+ drmTextureRegionPtr global_regions;
+
+ /** Pointer to the texture state age (generation number) in the SAREA
+ */
+ unsigned * global_age;
+
+ /** Local age (generation number) of texture state
+ */
+ unsigned local_age;
+
+ /** Memory heap used to manage texture memory represented by
+ * this texture heap.
+ */
+ memHeap_t * memory_heap;
+
+ /** List of objects that we currently believe to be in texture
+ * memory.
+ */
+ driTextureObject texture_objects;
+
+ /** Pointer to the list of texture objects that are not in
+ * texture memory.
+ */
+ driTextureObject * swapped_objects;
+
+ /** Size of the driver-speicific texture object.
+ */
+ unsigned texture_object_size;
+
+
+ /**
+ * \brief Function to destroy driver-specific texture object data.
+ *
+ * This function is supplied by the driver so that the texture manager
+ * can release all resources associated with a texture object. This
+ * function should only release driver-specific data. That is,
+ * \a driDestroyTextureObject will release the texture memory
+ * associated with the texture object, it will release the memory
+ * for the texture object itself, and it will unlink the texture
+ * object from the texture object lists.
+ *
+ * \param driverContext Pointer to the driver supplied context
+ * \param t Texture object that is to be destroyed
+ * \sa driDestroyTextureObject
+ */
+
+ destroy_texture_object_t * destroy_texture_object;
+
+
+ /**
+ */
+ unsigned * texture_swaps;
+
+ /**
+ * Timestamp used to synchronize with 3d engine in hardware
+ * where textures are uploaded directly to the
+ * framebuffer.
+ */
+ unsigned timestamp;
+};
+
+
+
+
+/**
+ * Called by the client on lock contention to determine whether textures have
+ * been stolen. If another client has modified a region in which we have
+ * textures, then we need to figure out which of our textures have been
+ * removed and update our global LRU.
+ *
+ * \param heap Texture heap to be updated
+ * \hideinitializer
+ */
+
+#define DRI_AGE_TEXTURES( heap ) \
+ do { \
+ if ( ((heap) != NULL) \
+ && ((heap)->local_age != (heap)->global_age[0]) ) \
+ driAgeTextures( heap ); \
+ } while( 0 )
+
+
+
+
+/* This should be called whenever there has been contention on the hardware
+ * lock. driAgeTextures should not be called directly. Instead, clients
+ * should use DRI_AGE_TEXTURES, above.
+ */
+
+void driAgeTextures( driTexHeap * heap );
+
+void driUpdateTextureLRU( driTextureObject * t );
+void driSwapOutTextureObject( driTextureObject * t );
+void driDestroyTextureObject( driTextureObject * t );
+int driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps,
+ driTextureObject * t );
+
+GLboolean driIsTextureResident( GLcontext * ctx,
+ struct gl_texture_object * texObj );
+
+driTexHeap * driCreateTextureHeap( unsigned heap_id, void * context,
+ unsigned size, unsigned alignmentShift, unsigned nr_regions,
+ drmTextureRegionPtr global_regions, unsigned * global_age,
+ driTextureObject * swapped_objects, unsigned texture_object_size,
+ destroy_texture_object_t * destroy_tex_obj );
+void driDestroyTextureHeap( driTexHeap * heap );
+
+void
+driCalculateMaxTextureLevels( driTexHeap * const * heaps,
+ unsigned nr_heaps,
+ struct gl_constants * limits,
+ unsigned max_bytes_per_texel,
+ unsigned max_2D_size,
+ unsigned max_3D_size,
+ unsigned max_cube_size,
+ unsigned max_rect_size,
+ unsigned mipmaps_at_once,
+ int all_textures_one_heap );
+
+void
+driSetTextureSwapCounterLocation( driTexHeap * heap, unsigned * counter );
+
+#define DRI_TEXMGR_DO_TEXTURE_1D 0x0001
+#define DRI_TEXMGR_DO_TEXTURE_2D 0x0002
+#define DRI_TEXMGR_DO_TEXTURE_3D 0x0004
+#define DRI_TEXMGR_DO_TEXTURE_CUBE 0x0008
+#define DRI_TEXMGR_DO_TEXTURE_RECT 0x0010
+
+void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
+ GLuint targets );
+
+GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
+ unsigned nr_heaps, const driTextureObject * swapped );
+
+extern void driCalculateTextureFirstLastLevel( driTextureObject * t );
+
+
+extern const struct gl_texture_format *_dri_texformat_rgba8888;
+extern const struct gl_texture_format *_dri_texformat_argb8888;
+extern const struct gl_texture_format *_dri_texformat_rgb565;
+extern const struct gl_texture_format *_dri_texformat_argb4444;
+extern const struct gl_texture_format *_dri_texformat_argb1555;
+extern const struct gl_texture_format *_dri_texformat_al88;
+extern const struct gl_texture_format *_dri_texformat_a8;
+extern const struct gl_texture_format *_dri_texformat_ci8;
+extern const struct gl_texture_format *_dri_texformat_i8;
+extern const struct gl_texture_format *_dri_texformat_l8;
+
+extern void driInitTextureFormats( void );
+
+#endif /* DRI_TEXMEM_H */
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
new file mode 100644
index 0000000..00686bc
--- /dev/null
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -0,0 +1,531 @@
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+/* $XFree86:$ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "mtypes.h"
+#include "extensions.h"
+#include "utils.h"
+
+#if !defined( DRI_NEW_INTERFACE_ONLY )
+#include "xf86dri.h" /* For XF86DRIQueryVersion prototype. */
+#endif
+
+#if defined(USE_X86_ASM)
+#include "x86/common_x86_asm.h"
+#endif
+
+unsigned
+driParseDebugString( const char * debug,
+ const struct dri_debug_control * control )
+{
+ unsigned flag;
+
+
+ flag = 0;
+ if ( debug != NULL ) {
+ while( control->string != NULL ) {
+ if ( !strcmp( debug, "all" ) ||
+ strstr( debug, control->string ) != NULL ) {
+ flag |= control->flag;
+ }
+
+ control++;
+ }
+ }
+
+ return flag;
+}
+
+
+
+
+unsigned
+driGetRendererString( char * buffer, const char * hardware_name,
+ const char * driver_date, GLuint agp_mode )
+{
+#ifdef USE_X86_ASM
+ char * x86_str = "";
+ char * mmx_str = "";
+ char * tdnow_str = "";
+ char * sse_str = "";
+#endif
+ unsigned offset;
+
+
+ offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date );
+
+ /* Append any AGP-specific information.
+ */
+ switch ( agp_mode ) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
+ break;
+
+ default:
+ break;
+ }
+
+ /* Append any CPU-specific information.
+ */
+#ifdef USE_X86_ASM
+ if ( _mesa_x86_cpu_features ) {
+ x86_str = " x86";
+ }
+# ifdef USE_MMX_ASM
+ if ( cpu_has_mmx ) {
+ mmx_str = (cpu_has_mmxext) ? "/MMX+" : "/MMX";
+ }
+# endif
+# ifdef USE_3DNOW_ASM
+ if ( cpu_has_3dnow ) {
+ tdnow_str = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!";
+ }
+# endif
+# ifdef USE_SSE_ASM
+ if ( cpu_has_xmm ) {
+ sse_str = (cpu_has_xmm2) ? "/SSE2" : "/SSE";
+ }
+# endif
+
+ offset += sprintf( & buffer[ offset ], "%s%s%s%s",
+ x86_str, mmx_str, tdnow_str, sse_str );
+
+#elif defined(USE_SPARC_ASM)
+
+ offset += sprintf( & buffer[ offset ], " Sparc" );
+
+#endif
+
+ return offset;
+}
+
+
+
+
+void driInitExtensions( GLcontext * ctx,
+ const char * const extensions_to_enable[],
+ GLboolean enable_imaging )
+{
+ unsigned i;
+
+ if ( enable_imaging ) {
+ _mesa_enable_imaging_extensions( ctx );
+ }
+
+ for ( i = 0 ; extensions_to_enable[i] != NULL ; i++ ) {
+ _mesa_enable_extension( ctx, extensions_to_enable[i] );
+ }
+}
+
+
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Utility function used by drivers to test the verions of other components.
+ *
+ * \deprecated
+ * All drivers using the new interface should use \c driCheckDriDdxVersions2
+ * instead. This function is implemented using a call that is not available
+ * to drivers using the new interface. Furthermore, the information gained
+ * by this call (the DRI and DDX version information) is already provided to
+ * the driver via the new interface.
+ */
+GLboolean
+driCheckDriDdxDrmVersions(__DRIscreenPrivate *sPriv,
+ const char * driver_name,
+ int dri_major, int dri_minor,
+ int ddx_major, int ddx_minor,
+ int drm_major, int drm_minor)
+{
+ static const char format[] = "%s DRI driver expected %s version %d.%d.x "
+ "but got version %d.%d.%d";
+ int major, minor, patch;
+
+ /* Check the DRI version */
+ if (XF86DRIQueryVersion(sPriv->display, &major, &minor, &patch)) {
+ if (major != dri_major || minor < dri_minor) {
+ __driUtilMessage(format, driver_name, "DRI", dri_major, dri_minor,
+ major, minor, patch);
+ return GL_FALSE;
+ }
+ }
+
+ /* Check that the DDX driver version is compatible */
+ if (sPriv->ddxMajor != ddx_major || sPriv->ddxMinor < ddx_minor) {
+ __driUtilMessage(format, driver_name, "DDX", ddx_major, ddx_minor,
+ sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DRM driver version is compatible */
+ if (sPriv->drmMajor != drm_major || sPriv->drmMinor < drm_minor) {
+ __driUtilMessage(format, driver_name, "DRM", drm_major, drm_minor,
+ sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/**
+ * Utility function used by drivers to test the verions of other components.
+ *
+ * If one of the version requirements is not met, a message is logged using
+ * \c __driUtilMessage.
+ *
+ * \param driver_name Name of the driver. Used in error messages.
+ * \param driActual Actual DRI version supplied __driCreateNewScreen.
+ * \param driExpected Minimum DRI version required by the driver.
+ * \param ddxActual Actual DDX version supplied __driCreateNewScreen.
+ * \param ddxExpected Minimum DDX version required by the driver.
+ * \param drmActual Actual DRM version supplied __driCreateNewScreen.
+ * \param drmExpected Minimum DRM version required by the driver.
+ *
+ * \returns \c GL_TRUE if all version requirements are met. Otherwise,
+ * \c GL_FALSE is returned.
+ *
+ * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions, __driUtilMessage
+ */
+GLboolean
+driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual,
+ const __DRIversion * driExpected,
+ const __DRIversion * ddxActual,
+ const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual,
+ const __DRIversion * drmExpected)
+{
+ static const char format[] = "%s DRI driver expected %s version %d.%d.x "
+ "but got version %d.%d.%d";
+
+
+ /* Check the DRI version */
+ if ( (driActual->major != driExpected->major)
+ || (driActual->minor < driExpected->minor) ) {
+ __driUtilMessage(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)
+ || (ddxActual->minor < ddxExpected->minor) ) {
+ __driUtilMessage(format, driver_name, "DDX",
+ ddxExpected->major, ddxExpected->minor,
+ ddxActual->major, ddxActual->minor, ddxActual->patch);
+ return GL_FALSE;
+ }
+
+ /* Check that the DRM driver version is compatible */
+ if ( (drmActual->major != drmExpected->major)
+ || (drmActual->minor < drmExpected->minor) ) {
+ __driUtilMessage(format, driver_name, "DRM",
+ drmExpected->major, drmExpected->minor,
+ drmActual->major, drmActual->minor, drmActual->patch);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height )
+{
+ /* left clipping */
+ if (*x < buffer->_Xmin) {
+ *width -= (buffer->_Xmin - *x);
+ *x = buffer->_Xmin;
+ }
+
+ /* right clipping */
+ if (*x + *width > buffer->_Xmax)
+ *width -= (*x + *width - buffer->_Xmax - 1);
+
+ if (*width <= 0)
+ return GL_FALSE;
+
+ /* bottom clipping */
+ if (*y < buffer->_Ymin) {
+ *height -= (buffer->_Ymin - *y);
+ *y = buffer->_Ymin;
+ }
+
+ /* top clipping */
+ if (*y + *height > buffer->_Ymax)
+ *height -= (*y + *height - buffer->_Ymax - 1);
+
+ if (*height <= 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+
+/**
+ * Creates a set of \c __GLcontextModes that a driver will expose.
+ *
+ * A set of \c __GLcontextModes will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c __GLcontextModes element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param ptr_to_modes Pointer to a pointer to a linked list of
+ * \c __GLcontextModes. Upon completion, a pointer to
+ * the next element to be process will be stored here.
+ * If the function fails and returns \c GL_FALSE, this
+ * value will be unmodified, but some elements in the
+ * linked list may be modified.
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+GLboolean
+driFillInModes( __GLcontextModes ** ptr_to_modes,
+ GLenum fb_format, GLenum fb_type,
+ const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ int visType )
+{
+ static const u_int8_t bits_table[3][4] = {
+ /* R G B A */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ /* The following arrays are all indexed by the fb_type masked with 0x07.
+ * Given the four supported fb_type values, this results in valid array
+ * indices of 3, 4, 5, and 7.
+ */
+ static const u_int32_t masks_table_rgb[8][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_rgba[8][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */
+ { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_bgr[8][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const u_int32_t masks_table_bgra[8][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */
+ { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */
+ { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
+ };
+
+ static const u_int8_t bytes_per_pixel[8] = {
+ 0, 0, 0, 2, 2, 4, 0, 4
+ };
+
+ const u_int8_t * bits;
+ const u_int32_t * masks;
+ const int index = fb_type & 0x07;
+ __GLcontextModes * modes = *ptr_to_modes;
+ unsigned i;
+ unsigned j;
+ unsigned k;
+
+
+ if ( bytes_per_pixel[ index ] == 0 ) {
+ fprintf( stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n",
+ __FUNCTION__, __LINE__, fb_type );
+ return GL_FALSE;
+ }
+
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+
+ switch ( fb_format ) {
+ case GL_RGB:
+ bits = (bytes_per_pixel[ index ] == 2)
+ ? bits_table[0] : bits_table[1];
+ masks = masks_table_rgb[ index ];
+ break;
+
+ case GL_RGBA:
+ bits = (bytes_per_pixel[ index ] == 2)
+ ? bits_table[0] : bits_table[2];
+ masks = masks_table_rgba[ index ];
+ break;
+
+ case GL_BGR:
+ bits = (bytes_per_pixel[ index ] == 2)
+ ? bits_table[0] : bits_table[1];
+ masks = masks_table_bgr[ index ];
+ break;
+
+ case GL_BGRA:
+ bits = (bytes_per_pixel[ index ] == 2)
+ ? bits_table[0] : bits_table[2];
+ masks = masks_table_bgra[ index ];
+ break;
+
+ default:
+ fprintf( stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n",
+ __FUNCTION__, __LINE__, fb_format );
+ return GL_FALSE;
+ }
+
+
+ for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
+ for ( i = 0 ; i < num_db_modes ; i++ ) {
+ for ( j = 0 ; j < 2 ; j++ ) {
+
+ modes->redBits = bits[0];
+ modes->greenBits = bits[1];
+ modes->blueBits = bits[2];
+ modes->alphaBits = bits[3];
+ modes->redMask = masks[0];
+ modes->greenMask = masks[1];
+ modes->blueMask = masks[2];
+ modes->alphaMask = masks[3];
+ modes->rgbBits = modes->redBits + modes->greenBits
+ + modes->blueBits + modes->alphaBits;
+
+ modes->accumRedBits = 16 * j;
+ modes->accumGreenBits = 16 * j;
+ modes->accumBlueBits = 16 * j;
+ modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
+ modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
+
+ modes->stencilBits = stencil_bits[k];
+ modes->depthBits = depth_bits[k];
+
+ modes->visualType = visType;
+ modes->renderType = GLX_RGBA_BIT;
+ modes->drawableType = GLX_WINDOW_BIT;
+ modes->rgbMode = GL_TRUE;
+
+ if ( db_modes[i] == GLX_NONE ) {
+ modes->doubleBufferMode = GL_FALSE;
+ }
+ else {
+ modes->doubleBufferMode = GL_TRUE;
+ modes->swapMethod = db_modes[i];
+ }
+
+ modes = modes->next;
+ }
+ }
+ }
+
+ *ptr_to_modes = modes;
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h
new file mode 100644
index 0000000..21d7ad2
--- /dev/null
+++ b/src/mesa/drivers/dri/common/utils.h
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright IBM Corporation 2002, 2004
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+/* $XFree86:$ */
+
+#ifndef DRI_DEBUG_H
+#define DRI_DEBUG_H
+
+#include "context.h"
+#include "dri_util.h"
+
+struct dri_debug_control
+{
+ const char * string;
+ unsigned flag;
+};
+
+extern unsigned driParseDebugString( const char * debug,
+ const struct dri_debug_control * control );
+
+extern unsigned driGetRendererString( char * buffer,
+ const char * hardware_name, const char * driver_date, GLuint agp_mode );
+
+extern void driInitExtensions( GLcontext * ctx,
+ const char * const card_extensions[], GLboolean enable_imaging );
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+extern GLboolean driCheckDriDdxDrmVersions( __DRIscreenPrivate *sPriv,
+ const char * driver_name, int dri_major, int dri_minor,
+ int ddx_major, int ddx_minor, int drm_major, int drm_minor );
+#endif
+
+extern GLboolean driCheckDriDdxDrmVersions2(const char * driver_name,
+ const __DRIversion * driActual, const __DRIversion * driExpected,
+ const __DRIversion * ddxActual, const __DRIversion * ddxExpected,
+ const __DRIversion * drmActual, const __DRIversion * drmExpected);
+
+extern GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height );
+
+extern GLboolean driFillInModes( __GLcontextModes ** modes,
+ GLenum fb_format, GLenum fb_type,
+ const u_int8_t * depth_bits, const u_int8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes, int visType );
+
+#endif /* DRI_DEBUG_H */
diff --git a/src/mesa/drivers/dri/common/vblank.c b/src/mesa/drivers/dri/common/vblank.c
new file mode 100644
index 0000000..aaeaebb
--- /dev/null
+++ b/src/mesa/drivers/dri/common/vblank.c
@@ -0,0 +1,349 @@
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+/* $XFree86:$ */
+
+#include "glheader.h"
+#include "xf86drm.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "dd.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+
+/****************************************************************************/
+/**
+ * Get the current MSC refresh counter.
+ *
+ * Stores the 64-bit count of vertical refreshes since some (arbitrary)
+ * point in time in \c count. Unless the value wraps around, which it
+ * may, it will never decrease.
+ *
+ * \warning This function is called from \c glXGetVideoSyncSGI, which expects
+ * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which
+ * expects a \c count of type \c int64_t (signed 64-bit). The kernel ioctl
+ * currently always returns a \c sequence of type \c unsigned.
+ *
+ * \param priv Pointer to the DRI screen private struct.
+ * \param count Storage to hold MSC counter.
+ * \return Zero is returned on success. A negative errno value
+ * is returned on failure.
+ */
+int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
+{
+ drmVBlank vbl;
+ int ret;
+
+ /* Don't wait for anything. Just get the current refresh count. */
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.sequence = 0;
+
+ ret = drmWaitVBlank( priv->fd, &vbl );
+ *count = (int64_t)vbl.reply.sequence;
+
+ return ret;
+}
+
+
+/****************************************************************************/
+/**
+ * Wait for a specified refresh count. This implements most of the
+ * functionality of \c glXWaitForMscOML from the GLX_OML_sync_control spec.
+ * Waits for the \c target_msc refresh. If that has already passed, it
+ * waits until \f$(MSC \bmod divisor)\f$ is equal to \c remainder. If
+ * \c target_msc is 0, use the behavior of glXWaitVideoSyncSGI(), which
+ * omits the initial check against a target MSC value.
+ *
+ * This function is actually something of a hack. The problem is that, at
+ * the time of this writing, none of the existing DRM modules support an
+ * ioctl that returns a 64-bit count (at least not on 32-bit platforms).
+ * However, this function exists to support a GLX function that requires
+ * the use of 64-bit counts. As such, there is a little bit of ugly
+ * hackery at the end of this function to make the 32-bit count act like
+ * a 64-bit count. There are still some cases where this will break, but
+ * I believe it catches the most common cases.
+ *
+ * The real solution is to provide an ioctl that uses a 64-bit count.
+ *
+ * \param dpy Pointer to the \c Display.
+ * \param priv Pointer to the DRI drawable private.
+ * \param target_msc Desired refresh count to wait for. A value of 0
+ * means to use the glXWaitVideoSyncSGI() behavior.
+ * \param divisor MSC divisor if \c target_msc is already reached.
+ * \param remainder Desired MSC remainder if \c target_msc is already
+ * reached.
+ * \param msc Buffer to hold MSC when done waiting.
+ *
+ * \return Zero on success or \c GLX_BAD_CONTEXT on failure.
+ */
+
+int driWaitForMSC32( __DRIdrawablePrivate *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder,
+ int64_t * msc )
+{
+ drmVBlank vbl;
+
+
+ if ( divisor != 0 ) {
+ unsigned int target = (unsigned int)target_msc;
+ unsigned int next = target;
+ unsigned int r;
+ int dont_wait = (target_msc == 0);
+
+ do {
+ /* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
+ * The first time around, just get the current count and proceed
+ * to the test for (MSC % divisor) == remainder.
+ */
+ vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
+ DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = next;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+
+ dont_wait = 0;
+ if (target_msc != 0 && vbl.reply.sequence == target)
+ break;
+
+ /* Assuming the wait-done test fails, the next refresh to wait for
+ * will be one that satisfies (MSC % divisor) == remainder. The
+ * value (MSC - (MSC % divisor) + remainder) is the refresh value
+ * closest to the current value that would satisfy the equation.
+ * If this refresh has already happened, we add divisor to obtain
+ * the next refresh after the current one that will satisfy it.
+ */
+ r = (vbl.reply.sequence % (unsigned int)divisor);
+ next = (vbl.reply.sequence - r + (unsigned int)remainder);
+ if (next <= vbl.reply.sequence) next += (unsigned int)divisor;
+
+ } while ( r != (unsigned int)remainder );
+ }
+ else {
+ /* If the \c divisor is zero, just wait until the MSC is greater
+ * than or equal to \c target_msc.
+ */
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+ vbl.request.sequence = target_msc;
+
+ if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
+ /* FIXME: This doesn't seem like the right thing to return here.
+ */
+ return GLX_BAD_CONTEXT;
+ }
+ }
+
+ *msc = (target_msc & 0xffffffff00000000LL);
+ *msc |= vbl.reply.sequence;
+ if ( *msc < target_msc ) {
+ *msc += 0x0000000100000000LL;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Gets a set of default vertical-blank-wait flags based on the internal GLX
+ * API version and several configuration options.
+ */
+
+GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
+{
+ GLuint flags = 0;
+ int vblank_mode;
+
+ flags |= (driCompareGLXAPIVersion( 20030317 ) >= 0)
+ ? VBLANK_FLAG_INTERVAL : 0;
+
+ if ( driCheckOption( optionCache, "vblank_mode", DRI_ENUM ) )
+ vblank_mode = driQueryOptioni( optionCache, "vblank_mode" );
+ else
+ vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+ switch (vblank_mode) {
+ case DRI_CONF_VBLANK_NEVER:
+ flags = 0;
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+ flags |= VBLANK_FLAG_THROTTLE;
+ break;
+ case DRI_CONF_VBLANK_ALWAYS_SYNC:
+ flags |= VBLANK_FLAG_SYNC;
+ break;
+ }
+
+ return flags;
+}
+
+
+/****************************************************************************/
+/**
+ * Sets the default swap interval when the drawable is first bound to a
+ * direct rendering context.
+ */
+
+void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags )
+{
+ if ( priv->pdraw->swap_interval == (unsigned)-1 ) {
+ priv->pdraw->swap_interval = (flags & VBLANK_FLAG_THROTTLE) != 0 ? 1 : 0;
+ }
+}
+
+
+/****************************************************************************/
+/**
+ * Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
+ * wrap the error message logging. The error message should only be logged
+ * the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
+ * successful, \c vbl_seq will be set the sequence value in the reply.
+ *
+ * \param vbl Pointer to drmVBlank packet desribing how to wait.
+ * \param vbl_seq Location to store the current refresh counter.
+ * \param fd File descriptor use to call into the DRM.
+ * \return Zero on success or -1 on failure.
+ */
+
+static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
+{
+ int ret;
+
+
+ ret = drmWaitVBlank( fd, vbl );
+ if ( ret != 0 ) {
+ static GLboolean first_time = GL_TRUE;
+
+ if ( first_time ) {
+ fprintf(stderr,
+ "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
+ " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
+ " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
+ first_time = GL_FALSE;
+ }
+
+ return -1;
+ }
+
+ *vbl_seq = vbl->reply.sequence;
+ return 0;
+}
+
+
+/****************************************************************************/
+/**
+ * Waits for the vertical blank for use with glXSwapBuffers.
+ *
+ * \param vbl_seq Vertical blank sequence number (MSC) after the last buffer
+ * swap. Updated after this wait.
+ * \param flags \c VBLANK_FLAG bits that control how long to wait.
+ * \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
+ * than the "target" based on \c flags. The idea is that if
+ * \c missed_deadline is set, then the application is not
+ * achieving its desired framerate.
+ * \return Zero on success, -1 on error.
+ */
+
+int
+driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq,
+ GLuint flags, GLboolean * missed_deadline )
+{
+ drmVBlank vbl;
+ unsigned original_seq;
+ unsigned deadline;
+ unsigned interval;
+
+
+ *missed_deadline = GL_FALSE;
+ if ( (flags & (VBLANK_FLAG_INTERVAL |
+ VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) == 0 ||
+ (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+ return 0;
+ }
+
+
+ /* VBLANK_FLAG_SYNC means to wait for at least one vertical blank. If
+ * that flag is not set, do a fake wait for zero vertical blanking
+ * periods so that we can get the current MSC.
+ *
+ * VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
+ * least one vertical blank since the last wait. Since do_wait modifies
+ * vbl_seq, we have to save the original value of vbl_seq for the
+ * VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
+ */
+
+ original_seq = *vbl_seq;
+
+ vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+
+ if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE;
+
+ if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) {
+ interval = priv->pdraw->swap_interval;
+ /* this must have been initialized when the drawable was first bound
+ * to a direct rendering context. */
+ assert ( interval != (unsigned)-1 );
+ }
+ else if ( (flags & VBLANK_FLAG_THROTTLE) != 0 ) {
+ interval = 1;
+ }
+ else {
+ interval = 0;
+ }
+
+
+ /* Wait until the next vertical blank. If the interval is zero, then
+ * the deadline is one vertical blank after the previous wait.
+ */
+
+ vbl.request.sequence = original_seq + interval;
+ if ( *vbl_seq < vbl.request.sequence ) {
+ if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
+ return -1;
+ }
+ }
+
+ deadline = original_seq + ((interval == 0) ? 1 : interval);
+ *missed_deadline = ( *vbl_seq > deadline );
+
+ return 0;
+}
diff --git a/src/mesa/drivers/dri/common/vblank.h b/src/mesa/drivers/dri/common/vblank.h
new file mode 100644
index 0000000..3dc965d
--- /dev/null
+++ b/src/mesa/drivers/dri/common/vblank.h
@@ -0,0 +1,69 @@
+/* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * (c) Copyright IBM Corporation 2002
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR 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:
+ * Ian Romanick <idr@us.ibm.com>
+ */
+/* $XFree86:$ */
+
+#ifndef DRI_VBLANK_H
+#define DRI_VBLANK_H
+
+#include "context.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
+ */
+#define VBLANK_FLAG_THROTTLE (1U << 1) /* Wait 1 refresh since last call.
+ */
+#define VBLANK_FLAG_SYNC (1U << 2) /* Sync to the next refresh.
+ */
+#define VBLANK_FLAG_NO_IRQ (1U << 7) /* DRM has no IRQ to wait on.
+ */
+
+extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
+extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
+ int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
+extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
+extern void driDrawableInitVBlank ( __DRIdrawablePrivate *priv, GLuint flags );
+extern int driWaitForVBlank( const __DRIdrawablePrivate *priv,
+ GLuint * vbl_seq, GLuint flags, GLboolean * missed_deadline );
+
+#undef usleep
+#include <unistd.h> /* for usleep() */
+#include <sched.h> /* for sched_yield() */
+
+#ifdef linux
+#include <sched.h> /* for sched_yield() */
+#endif
+
+#define DO_USLEEP(nr) \
+ do { \
+ if (0) fprintf(stderr, "%s: usleep for %u\n", __FUNCTION__, nr ); \
+ if (1) usleep( nr ); \
+ sched_yield(); \
+ } while( 0 )
+
+#endif /* DRI_VBLANK_H */
diff --git a/src/mesa/drivers/dri/common/xmlconfig.c b/src/mesa/drivers/dri/common/xmlconfig.c
new file mode 100644
index 0000000..b635894
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlconfig.c
@@ -0,0 +1,1002 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+/**
+ * \file xmlconfig.c
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#include "glheader.h"
+
+#include <string.h>
+#include <assert.h>
+#include <expat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "imports.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+/*
+ * OS dependent ways of getting the name of the running program
+ */
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
+
+#undef GET_PROGRAM_NAME
+
+#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__)
+# if !defined(__GLIBC__) || (__GLIBC__ < 2)
+/* These aren't declared in any libc5 header */
+extern char *program_invocation_name, *program_invocation_short_name;
+# endif
+# define GET_PROGRAM_NAME() program_invocation_short_name
+#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+# include <osreldate.h>
+# if (__FreeBSD_version >= 440000)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+# endif
+#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+#endif
+
+#if !defined(GET_PROGRAM_NAME)
+# if defined(OpenBSD) || defined(NetBSD) || defined(__UCLIBC__)
+/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU.
+ * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's
+ * used as a last resort, if there is no documented facility available. */
+static const char *__getProgramName () {
+ extern const char *__progname;
+ char * arg = strrchr(__progname, '/');
+ if (arg)
+ return arg+1;
+ else
+ return __progname;
+}
+# define GET_PROGRAM_NAME() __getProgramName()
+# else
+# define GET_PROGRAM_NAME() ""
+# warning "Per application configuration won't work with your OS version."
+# endif
+#endif
+
+/** \brief Find an option in an option cache with the name as key */
+static GLuint findOption (const driOptionCache *cache, const char *name) {
+ GLuint len = strlen (name);
+ GLuint size = 1 << cache->tableSize, mask = size - 1;
+ GLuint hash = 0;
+ GLuint i, shift;
+
+ /* compute a hash from the variable length name */
+ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
+ hash += (GLuint)name[i] << shift;
+ hash *= hash;
+ hash = (hash >> (16-cache->tableSize/2)) & mask;
+
+ /* this is just the starting point of the linear search for the option */
+ for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
+ /* if we hit an empty entry then the option is not defined (yet) */
+ if (cache->info[hash].name == 0)
+ break;
+ else if (!strcmp (name, cache->info[hash].name))
+ break;
+ }
+ /* this assertion fails if the hash table is full */
+ assert (i < size);
+
+ return hash;
+}
+
+/** \brief Count the real number of options in an option cache */
+static GLuint countOptions (const driOptionCache *cache) {
+ GLuint size = 1 << cache->tableSize;
+ GLuint i, count = 0;
+ for (i = 0; i < size; ++i)
+ if (cache->info[i].name)
+ count++;
+ return count;
+}
+
+/** \brief Like strdup but using MALLOC and with error checking. */
+#define XSTRDUP(dest,source) do { \
+ GLuint len = strlen (source); \
+ if (!(dest = MALLOC (len+1))) { \
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ memcpy (dest, source, len+1); \
+} while (0)
+
+static int compare (const void *a, const void *b) {
+ return strcmp (*(char *const*)a, *(char *const*)b);
+}
+/** \brief Binary search in a string array. */
+static GLuint bsearchStr (const XML_Char *name,
+ const XML_Char *elems[], GLuint count) {
+ const XML_Char **found;
+ found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
+ if (found)
+ return found - elems;
+ else
+ return count;
+}
+
+/** \brief Locale-independent integer parser.
+ *
+ * Works similar to strtol. Leading space is NOT skipped. The input
+ * number may have an optional sign. Radix is specified by base. If
+ * base is 0 then decimal is assumed unless the input number is
+ * prefixed by 0x or 0X for hexadecimal or 0 for octal. After
+ * returning tail points to the first character that is not part of
+ * the integer number. If no number was found then tail points to the
+ * start of the input string. */
+static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) {
+ GLint radix = base == 0 ? 10 : base;
+ GLint result = 0;
+ GLint sign = 1;
+ GLboolean numberFound = GL_FALSE;
+ const XML_Char *start = string;
+
+ assert (radix >= 2 && radix <= 36);
+
+ if (*string == '-') {
+ sign = -1;
+ string++;
+ } else if (*string == '+')
+ string++;
+ if (base == 0 && *string == '0') {
+ numberFound = GL_TRUE;
+ if (*(string+1) == 'x' || *(string+1) == 'X') {
+ radix = 16;
+ string += 2;
+ } else {
+ radix = 8;
+ string++;
+ }
+ }
+ do {
+ GLint digit = -1;
+ if (radix <= 10) {
+ if (*string >= '0' && *string < '0' + radix)
+ digit = *string - '0';
+ } else {
+ if (*string >= '0' && *string <= '9')
+ digit = *string - '0';
+ else if (*string >= 'a' && *string < 'a' + radix - 10)
+ digit = *string - 'a' + 10;
+ else if (*string >= 'A' && *string < 'A' + radix - 10)
+ digit = *string - 'A' + 10;
+ }
+ if (digit != -1) {
+ numberFound = GL_TRUE;
+ result = radix*result + digit;
+ string++;
+ } else
+ break;
+ } while (GL_TRUE);
+ *tail = numberFound ? string : start;
+ return sign * result;
+}
+
+/** \brief Locale-independent floating-point parser.
+ *
+ * Works similar to strtod. Leading space is NOT skipped. The input
+ * number may have an optional sign. '.' is interpreted as decimal
+ * point and may occor at most once. Optionally the number may end in
+ * [eE]<exponent>, where <exponent> is an integer as recognized by
+ * strToI. In that case the result is number * 10^exponent. After
+ * returning tail points to the first character that is not part of
+ * the floating point number. If no number was found then tail points
+ * to the start of the input string.
+ *
+ * Uses two passes for maximum accuracy. */
+static GLfloat strToF (const XML_Char *string, const XML_Char **tail) {
+ GLint nDigits = 0, pointPos, exponent;
+ GLfloat sign = 1.0f, result = 0.0f, scale;
+ const XML_Char *start = string, *numStart;
+
+ /* sign */
+ if (*string == '-') {
+ sign = -1.0f;
+ string++;
+ } else if (*string == '+')
+ string++;
+
+ /* first pass: determine position of decimal point, number of
+ * digits, exponent and the end of the number. */
+ numStart = string;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ pointPos = nDigits;
+ if (*string == '.') {
+ string++;
+ while (*string >= '0' && *string <= '9') {
+ string++;
+ nDigits++;
+ }
+ }
+ if (nDigits == 0) {
+ /* no digits, no number */
+ *tail = start;
+ return 0.0f;
+ }
+ *tail = string;
+ if (*string == 'e' || *string == 'E') {
+ const XML_Char *expTail;
+ exponent = strToI (string+1, &expTail, 10);
+ if (expTail == string+1)
+ exponent = 0;
+ else
+ *tail = expTail;
+ } else
+ exponent = 0;
+ string = numStart;
+
+ /* scale of the first digit */
+ scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent));
+
+ /* second pass: parse digits */
+ do {
+ if (*string != '.') {
+ assert (*string >= '0' && *string <= '9');
+ result += scale * (GLfloat)(*string - '0');
+ scale *= 0.1f;
+ nDigits--;
+ }
+ string++;
+ } while (nDigits > 0);
+
+ return result;
+}
+
+/** \brief Parse a value of a given type. */
+static GLboolean parseValue (driOptionValue *v, driOptionType type,
+ const XML_Char *string) {
+ const XML_Char *tail;
+ /* skip leading white-space */
+ string += strspn (string, " \f\n\r\t\v");
+ switch (type) {
+ case DRI_BOOL:
+ if (!strcmp (string, "false")) {
+ v->_bool = GL_FALSE;
+ tail = string + 5;
+ } else if (!strcmp (string, "true")) {
+ v->_bool = GL_TRUE;
+ tail = string + 4;
+ }
+ else
+ return GL_FALSE;
+ break;
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ v->_int = strToI (string, &tail, 0);
+ break;
+ case DRI_FLOAT:
+ v->_float = strToF (string, &tail);
+ break;
+ }
+
+ if (tail == string)
+ return GL_FALSE; /* empty string (or containing only white-space) */
+ /* skip trailing white space */
+ if (*tail)
+ tail += strspn (tail, " \f\n\r\t\v");
+ if (*tail)
+ return GL_FALSE; /* something left over that is not part of value */
+
+ return GL_TRUE;
+}
+
+/** \brief Parse a list of ranges of type info->type. */
+static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
+ XML_Char *cp, *range;
+ GLuint nRanges, i;
+ driOptionRange *ranges;
+
+ XSTRDUP (cp, string);
+ /* pass 1: determine the number of ranges (number of commas + 1) */
+ range = cp;
+ for (nRanges = 1; *range; ++range)
+ if (*range == ',')
+ ++nRanges;
+
+ if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ /* pass 2: parse all ranges into preallocated array */
+ range = cp;
+ for (i = 0; i < nRanges; ++i) {
+ XML_Char *end, *sep;
+ assert (range);
+ end = strchr (range, ',');
+ if (end)
+ *end = '\0';
+ sep = strchr (range, ':');
+ if (sep) { /* non-empty interval */
+ *sep = '\0';
+ if (!parseValue (&ranges[i].start, info->type, range) ||
+ !parseValue (&ranges[i].end, info->type, sep+1))
+ break;
+ if (info->type == DRI_INT &&
+ ranges[i].start._int > ranges[i].end._int)
+ break;
+ if (info->type == DRI_FLOAT &&
+ ranges[i].start._float > ranges[i].end._float)
+ break;
+ } else { /* empty interval */
+ if (!parseValue (&ranges[i].start, info->type, range))
+ break;
+ ranges[i].end = ranges[i].start;
+ }
+ if (end)
+ range = end+1;
+ else
+ range = NULL;
+ }
+ FREE (cp);
+ if (i < nRanges) {
+ FREE (ranges);
+ return GL_FALSE;
+ } else
+ assert (range == NULL);
+
+ info->nRanges = nRanges;
+ info->ranges = ranges;
+ return GL_TRUE;
+}
+
+/** \brief Check if a value is in one of info->ranges. */
+static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
+ GLuint i;
+ assert (info->type != DRI_BOOL); /* should be caught by the parser */
+ if (info->nRanges == 0)
+ return GL_TRUE;
+ switch (info->type) {
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_int >= info->ranges[i].start._int &&
+ v->_int <= info->ranges[i].end._int)
+ return GL_TRUE;
+ break;
+ case DRI_FLOAT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_float >= info->ranges[i].start._float &&
+ v->_float <= info->ranges[i].end._float)
+ return GL_TRUE;
+ break;
+ default:
+ assert (0); /* should never happen */
+ }
+ return GL_FALSE;
+}
+
+/** \brief Output a warning message. */
+#define XML_WARNING1(msg) do {\
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_WARNING(msg,args...) do { \
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output an error message. */
+#define XML_ERROR1(msg) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_ERROR(msg,args...) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output a fatal error message and abort. */
+#define XML_FATAL1(msg) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+ abort();\
+} while (0)
+#define XML_FATAL(msg,args...) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+ abort();\
+} while (0)
+
+/** \brief Parser context for __driConfigOptions. */
+struct OptInfoData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLboolean inDriInfo;
+ GLboolean inSection;
+ GLboolean inDesc;
+ GLboolean inOption;
+ GLboolean inEnum;
+ int curOption;
+};
+
+/** \brief Elements in __driConfigOptions. */
+enum OptInfoElem {
+ OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
+};
+static const XML_Char *OptInfoElems[] = {
+ "description", "driinfo", "enum", "option", "section"
+};
+
+/** \brief Parse attributes of an enum element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *value = NULL, *text = NULL;
+ driOptionValue v;
+ GLuint opt = data->curOption;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal enum attribute: %s.", attr[i]);
+ }
+ if (!value) XML_FATAL1 ("value attribute missing in enum.");
+ if (!text) XML_FATAL1 ("text attribute missing in enum.");
+ if (!parseValue (&v, data->cache->info[opt].type, value))
+ XML_FATAL ("illegal enum value: %s.", value);
+ if (!checkValue (&v, &data->cache->info[opt]))
+ XML_FATAL ("enum value out of valid range: %s.", value);
+}
+
+/** \brief Parse attributes of a description element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *lang = NULL, *text = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "lang")) lang = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal description attribute: %s.", attr[i]);
+ }
+ if (!lang) XML_FATAL1 ("lang attribute missing in description.");
+ if (!text) XML_FATAL1 ("text attribute missing in description.");
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
+ enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
+ static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
+ const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
+ const char *defaultVal;
+ driOptionCache *cache = data->cache;
+ GLuint opt, i;
+ for (i = 0; attr[i]; i += 2) {
+ GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
+ if (attrName >= OA_COUNT)
+ XML_FATAL ("illegal option attribute: %s", attr[i]);
+ attrVal[attrName] = attr[i+1];
+ }
+ if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option.");
+ if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option.");
+ if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option.");
+
+ opt = findOption (cache, attrVal[OA_NAME]);
+ if (cache->info[opt].name)
+ XML_FATAL ("option %s redefined.", attrVal[OA_NAME]);
+ data->curOption = opt;
+
+ XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]);
+
+ if (!strcmp (attrVal[OA_TYPE], "bool"))
+ cache->info[opt].type = DRI_BOOL;
+ else if (!strcmp (attrVal[OA_TYPE], "enum"))
+ cache->info[opt].type = DRI_ENUM;
+ else if (!strcmp (attrVal[OA_TYPE], "int"))
+ cache->info[opt].type = DRI_INT;
+ else if (!strcmp (attrVal[OA_TYPE], "float"))
+ cache->info[opt].type = DRI_FLOAT;
+ else
+ XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
+
+ defaultVal = getenv (cache->info[opt].name);
+ if (defaultVal != NULL) {
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr,
+ "ATTENTION: default value of option %s overridden by environment.\n",
+ cache->info[opt].name);
+ } else
+ defaultVal = attrVal[OA_DEFAULT];
+ if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
+ XML_FATAL ("illegal default value: %s.", defaultVal);
+
+ if (attrVal[OA_VALID]) {
+ if (cache->info[opt].type == DRI_BOOL)
+ XML_FATAL1 ("boolean option with valid attribute.");
+ if (!parseRanges (&cache->info[opt], attrVal[OA_VALID]))
+ XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]);
+ if (!checkValue (&cache->values[opt], &cache->info[opt]))
+ XML_FATAL ("default value out of valid range '%s': %s.",
+ attrVal[OA_VALID], defaultVal);
+ } else if (cache->info[opt].type == DRI_ENUM) {
+ XML_FATAL1 ("valid attribute missing in option (mandatory for enums).");
+ } else {
+ cache->info[opt].nRanges = 0;
+ cache->info[opt].ranges = NULL;
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optInfoStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ if (data->inDriInfo)
+ XML_FATAL1 ("nested <driinfo> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <driinfo> element.");
+ data->inDriInfo = GL_TRUE;
+ break;
+ case OI_SECTION:
+ if (!data->inDriInfo)
+ XML_FATAL1 ("<section> must be inside <driinfo>.");
+ if (data->inSection)
+ XML_FATAL1 ("nested <section> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <section> element.");
+ data->inSection = GL_TRUE;
+ break;
+ case OI_DESCRIPTION:
+ if (!data->inSection && !data->inOption)
+ XML_FATAL1 ("<description> must be inside <description> or <option.");
+ if (data->inDesc)
+ XML_FATAL1 ("nested <description> elements.");
+ data->inDesc = GL_TRUE;
+ parseDescAttr (data, attr);
+ break;
+ case OI_OPTION:
+ if (!data->inSection)
+ XML_FATAL1 ("<option> must be inside <section>.");
+ if (data->inDesc)
+ XML_FATAL1 ("<option> nested in <description> element.");
+ if (data->inOption)
+ XML_FATAL1 ("nested <option> elements.");
+ data->inOption = GL_TRUE;
+ parseOptInfoAttr (data, attr);
+ break;
+ case OI_ENUM:
+ if (!(data->inOption && data->inDesc))
+ XML_FATAL1 ("<enum> must be inside <option> and <description>.");
+ if (data->inEnum)
+ XML_FATAL1 ("nested <enum> elements.");
+ data->inEnum = GL_TRUE;
+ parseEnumAttr (data, attr);
+ break;
+ default:
+ XML_FATAL ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optInfoEndElem (void *userData, const XML_Char *name) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ data->inDriInfo = GL_FALSE;
+ break;
+ case OI_SECTION:
+ data->inSection = GL_FALSE;
+ break;
+ case OI_DESCRIPTION:
+ data->inDesc = GL_FALSE;
+ break;
+ case OI_OPTION:
+ data->inOption = GL_FALSE;
+ break;
+ case OI_ENUM:
+ data->inEnum = GL_FALSE;
+ break;
+ default:
+ assert (0); /* should have been caught by StartElem */
+ }
+}
+
+void driParseOptionInfo (driOptionCache *info,
+ const char *configOptions, GLuint nConfigOptions) {
+ XML_Parser p;
+ int status;
+ struct OptInfoData userData;
+ struct OptInfoData *data = &userData;
+ GLuint realNoptions;
+
+ /* determine hash table size and allocate memory:
+ * 3/2 of the number of options, rounded up, so there remains always
+ * at least one free entry. This is needed for detecting undefined
+ * options in configuration files without getting a hash table overflow.
+ * Round this up to a power of two. */
+ GLuint minSize = (nConfigOptions*3 + 1) / 2;
+ GLuint size, log2size;
+ for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size);
+ info->tableSize = log2size;
+ info->info = CALLOC (size * sizeof (driOptionInfo));
+ info->values = CALLOC (size * sizeof (driOptionValue));
+ if (info->info == NULL || info->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */
+ XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem);
+ XML_SetUserData (p, data);
+
+ userData.name = "__driConfigOptions";
+ userData.parser = p;
+ userData.cache = info;
+ userData.inDriInfo = GL_FALSE;
+ userData.inSection = GL_FALSE;
+ userData.inDesc = GL_FALSE;
+ userData.inOption = GL_FALSE;
+ userData.inEnum = GL_FALSE;
+ userData.curOption = -1;
+
+ status = XML_Parse (p, configOptions, strlen (configOptions), 1);
+ if (!status)
+ XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+
+ XML_ParserFree (p);
+
+ /* Check if the actual number of options matches nConfigOptions.
+ * A mismatch is not fatal (a hash table overflow would be) but we
+ * want the driver developer's attention anyway. */
+ realNoptions = countOptions (info);
+ if (realNoptions != nConfigOptions) {
+ fprintf (stderr,
+ "Error: nConfigOptions (%u) does not match the actual number of options in\n"
+ " __driConfigOptions (%u).\n",
+ nConfigOptions, realNoptions);
+ }
+}
+
+/** \brief Parser context for configuration files. */
+struct OptConfData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLint screenNum;
+ const char *driverName, *execName;
+ GLuint ignoringDevice;
+ GLuint ignoringApp;
+ GLuint inDriConf;
+ GLuint inDevice;
+ GLuint inApp;
+ GLuint inOption;
+};
+
+/** \brief Elements in configuration files. */
+enum OptConfElem {
+ OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT
+};
+static const XML_Char *OptConfElems[] = {
+ "application", "device", "driconf", "option"
+};
+
+/** \brief Parse attributes of a device element. */
+static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *driver = NULL, *screen = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "driver")) driver = attr[i+1];
+ else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
+ else XML_WARNING("unkown device attribute: %s.", attr[i]);
+ }
+ if (driver && strcmp (driver, data->driverName))
+ data->ignoringDevice = data->inDevice;
+ else if (screen) {
+ driOptionValue screenNum;
+ if (!parseValue (&screenNum, DRI_INT, screen))
+ XML_WARNING("illegal screen number: %s.", screen);
+ else if (screenNum._int != data->screenNum)
+ data->ignoringDevice = data->inDevice;
+ }
+}
+
+/** \brief Parse attributes of an application element. */
+static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *exec = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
+ else XML_WARNING("unkown application attribute: %s.", attr[i]);
+ }
+ if (exec && strcmp (exec, data->execName))
+ data->ignoringApp = data->inApp;
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *value = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else XML_WARNING("unkown option attribute: %s.", attr[i]);
+ }
+ if (!name) XML_WARNING1 ("name attribute missing in option.");
+ if (!value) XML_WARNING1 ("value attribute missing in option.");
+ if (name && value) {
+ driOptionCache *cache = data->cache;
+ GLuint opt = findOption (cache, name);
+ if (cache->info[opt].name == NULL)
+ XML_WARNING ("undefined option: %s.", name);
+ else if (getenv (cache->info[opt].name))
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
+ cache->info[opt].name);
+ else if (!parseValue (&cache->values[opt], cache->info[opt].type, value))
+ XML_WARNING ("illegal option value: %s.", value);
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optConfStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ if (data->inDriConf)
+ XML_WARNING1 ("nested <driconf> elements.");
+ if (attr[0])
+ XML_WARNING1 ("attributes specified on <driconf> element.");
+ data->inDriConf++;
+ break;
+ case OC_DEVICE:
+ if (!data->inDriConf)
+ XML_WARNING1 ("<device> should be inside <driconf>.");
+ if (data->inDevice)
+ XML_WARNING1 ("nested <device> elements.");
+ data->inDevice++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseDeviceAttr (data, attr);
+ break;
+ case OC_APPLICATION:
+ if (!data->inDevice)
+ XML_WARNING1 ("<application> should be inside <device>.");
+ if (data->inApp)
+ XML_WARNING1 ("nested <application> elements.");
+ data->inApp++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseAppAttr (data, attr);
+ break;
+ case OC_OPTION:
+ if (!data->inApp)
+ XML_WARNING1 ("<option> should be inside <application>.");
+ if (data->inOption)
+ XML_WARNING1 ("nested <option> elements.");
+ data->inOption++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseOptConfAttr (data, attr);
+ break;
+ default:
+ XML_WARNING ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optConfEndElem (void *userData, const XML_Char *name) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ data->inDriConf--;
+ break;
+ case OC_DEVICE:
+ if (data->inDevice-- == data->ignoringDevice)
+ data->ignoringDevice = 0;
+ break;
+ case OC_APPLICATION:
+ if (data->inApp-- == data->ignoringApp)
+ data->ignoringApp = 0;
+ break;
+ case OC_OPTION:
+ data->inOption--;
+ break;
+ default:
+ /* unknown element, warning was produced on start tag */;
+ }
+}
+
+/** \brief Initialize an option cache based on info */
+static void initOptionCache (driOptionCache *cache, const driOptionCache *info) {
+ cache->info = info->info;
+ cache->tableSize = info->tableSize;
+ cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
+ if (cache->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+ memcpy (cache->values, info->values,
+ (1<<info->tableSize) * sizeof (driOptionValue));
+}
+
+/** \brief Parse the named configuration file */
+static void parseOneConfigFile (XML_Parser p) {
+#define BUF_SIZE 0x1000
+ struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p);
+ int status;
+ int fd;
+
+ if ((fd = open (data->name, O_RDONLY)) == -1) {
+ __driUtilMessage ("Can't open configuration file %s: %s.",
+ data->name, strerror (errno));
+ return;
+ }
+
+ while (1) {
+ int bytesRead;
+ void *buffer = XML_GetBuffer (p, BUF_SIZE);
+ if (!buffer) {
+ __driUtilMessage ("Can't allocate parser buffer.");
+ break;
+ }
+ bytesRead = read (fd, buffer, BUF_SIZE);
+ if (bytesRead == -1) {
+ __driUtilMessage ("Error reading from configuration file %s: %s.",
+ data->name, strerror (errno));
+ break;
+ }
+ status = XML_ParseBuffer (p, bytesRead, bytesRead == 0);
+ if (!status) {
+ XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+ break;
+ }
+ if (bytesRead == 0)
+ break;
+ }
+
+ close (fd);
+#undef BUF_SIZE
+}
+
+void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
+ GLint screenNum, const char *driverName) {
+ char *filenames[2] = {"/etc/drirc", NULL};
+ char *home;
+ GLuint i;
+ struct OptConfData userData;
+
+ initOptionCache (cache, info);
+
+ userData.cache = cache;
+ userData.screenNum = screenNum;
+ userData.driverName = driverName;
+ userData.execName = GET_PROGRAM_NAME();
+
+ if ((home = getenv ("HOME"))) {
+ GLuint len = strlen (home);
+ filenames[1] = MALLOC (len + 7+1);
+ if (filenames[1] == NULL)
+ __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
+ else {
+ memcpy (filenames[1], home, len);
+ memcpy (filenames[1] + len, "/.drirc", 7+1);
+ }
+ }
+
+ for (i = 0; i < 2; ++i) {
+ XML_Parser p;
+ if (filenames[i] == NULL)
+ continue;
+
+ p = XML_ParserCreate (NULL); /* use encoding specified by file */
+ XML_SetElementHandler (p, optConfStartElem, optConfEndElem);
+ XML_SetUserData (p, &userData);
+ userData.parser = p;
+ userData.name = filenames[i];
+ userData.ignoringDevice = 0;
+ userData.ignoringApp = 0;
+ userData.inDriConf = 0;
+ userData.inDevice = 0;
+ userData.inApp = 0;
+ userData.inOption = 0;
+
+ parseOneConfigFile (p);
+ XML_ParserFree (p);
+ }
+
+ if (filenames[1])
+ FREE (filenames[1]);
+}
+
+void driDestroyOptionInfo (driOptionCache *info) {
+ driDestroyOptionCache (info);
+ if (info->info) {
+ GLuint i, size = 1 << info->tableSize;
+ for (i = 0; i < size; ++i) {
+ if (info->info[i].name) {
+ FREE (info->info[i].name);
+ if (info->info[i].ranges)
+ FREE (info->info[i].ranges);
+ }
+ }
+ FREE (info->info);
+ }
+}
+
+void driDestroyOptionCache (driOptionCache *cache) {
+ if (cache->values)
+ FREE (cache->values);
+}
+
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type) {
+ GLuint i = findOption (cache, name);
+ return cache->info[i].name != NULL && cache->info[i].type == type;
+}
+
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_BOOL);
+ return cache->values[i]._bool;
+}
+
+GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
+ return cache->values[i]._int;
+}
+
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_FLOAT);
+ return cache->values[i]._float;
+}
diff --git a/src/mesa/drivers/dri/common/xmlconfig.h b/src/mesa/drivers/dri/common/xmlconfig.h
new file mode 100644
index 0000000..c363af7
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlconfig.h
@@ -0,0 +1,124 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+/**
+ * \file xmlconfig.h
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#ifndef __XMLCONFIG_H
+#define __XMLCONFIG_H
+
+/** \brief Option data types */
+typedef enum driOptionType {
+ DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT
+} driOptionType;
+
+/** \brief Option value */
+typedef union driOptionValue {
+ GLboolean _bool; /**< \brief Boolean */
+ GLint _int; /**< \brief Integer or Enum */
+ GLfloat _float; /**< \brief Floating-point */
+} driOptionValue;
+
+/** \brief Single range of valid values
+ *
+ * For empty ranges (a single value) start == end */
+typedef struct driOptionRange {
+ driOptionValue start; /**< \brief Start */
+ driOptionValue end; /**< \brief End */
+} driOptionRange;
+
+/** \brief Information about an option */
+typedef struct driOptionInfo {
+ char *name; /**< \brief Name */
+ driOptionType type; /**< \brief Type */
+ driOptionRange *ranges; /**< \brief Array of ranges */
+ GLuint nRanges; /**< \brief Number of ranges */
+} driOptionInfo;
+
+/** \brief Option cache
+ *
+ * \li One in <driver>Screen caching option info and the default values
+ * \li One in each <driver>Context with the actual values for that context */
+typedef struct driOptionCache {
+ driOptionInfo *info;
+ /**< \brief Array of option infos
+ *
+ * Points to the same array in the screen and all contexts */
+ driOptionValue *values;
+ /**< \brief Array of option values
+ *
+ * \li Default values in screen
+ * \li Actual values in contexts
+ */
+ GLuint tableSize;
+ /**< \brief Size of the arrays
+ *
+ * Depending on the hash function this may differ from __driNConfigOptions.
+ * In the current implementation it's not actually a size but log2(size).
+ * The value is the same in the screen and all contexts. */
+} driOptionCache;
+
+/** \brief Parse XML option info from configOptions
+ *
+ * To be called in <driver>CreateScreen
+ *
+ * \param info pointer to a driOptionCache that will store the option info
+ * \param configOptions XML document describing available configuration opts
+ * \param nConfigOptions number of options, used to choose a hash table size
+ *
+ * For the option information to be available to external configuration tools
+ * it must be a public symbol __driConfigOptions. It is also passed as a
+ * parameter to driParseOptionInfo in order to avoid driver-independent code
+ * depending on symbols in driver-specific code. */
+void driParseOptionInfo (driOptionCache *info,
+ const char *configOptions, GLuint nConfigOptions);
+/** \brief Initialize option cache from info and parse configuration files
+ *
+ * To be called in <driver>CreateContext. screenNum and driverName select
+ * device sections. */
+void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info,
+ GLint screenNum, const char *driverName);
+/** \brief Destroy option info
+ *
+ * To be called in <driver>DestroyScreen */
+void driDestroyOptionInfo (driOptionCache *info);
+/** \brief Destroy option cache
+ *
+ * To be called in <driver>DestroyContext */
+void driDestroyOptionCache (driOptionCache *cache);
+
+/** \brief Check if there exists a certain option */
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type);
+
+/** \brief Query a boolean option value */
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name);
+/** \brief Query an integer option value */
+GLint driQueryOptioni (const driOptionCache *cache, const char *name);
+/** \brief Query a floating-point option value */
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name);
+
+#endif
diff --git a/src/mesa/drivers/dri/common/xmlpool.h b/src/mesa/drivers/dri/common/xmlpool.h
new file mode 100644
index 0000000..7b8222e
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlpool.h
@@ -0,0 +1,297 @@
+/* -*- mode:C; coding: mult-utf-8-unix -*-
+ *
+ * !!! Important: This file is encoded in UTF-8 !!!
+ *
+ * Note (Emacs): You need Mule. In Debian the package is called
+ * mule-ucs.
+ *
+ * Note (Emacs): You may have to enable multibyte characters in the
+ * Mule customization group or by setting
+ * default-enable-multibyte-characters to t in your .emacs:
+ */
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ */
+/**
+ * \file xmlpool.h
+ * \brief Pool of common options
+ * \author Felix Kuehling
+ *
+ * This file defines macros that can be used to construct driConfigOptions
+ * in the drivers.
+ */
+
+#ifndef __XMLPOOL_H
+#define __XMLPOOL_H
+
+/*
+ * generic macros
+ */
+
+/** \brief Begin __driConfigOptions */
+#define DRI_CONF_BEGIN \
+"<driinfo>\n"
+
+/** \brief End __driConfigOptions */
+#define DRI_CONF_END \
+"</driinfo>\n"
+
+/** \brief Begin a section of related options */
+#define DRI_CONF_SECTION_BEGIN \
+"<section>\n"
+
+/** \brief End a section of related options */
+#define DRI_CONF_SECTION_END \
+"</section>\n"
+
+/** \brief Begin an option definition */
+#define DRI_CONF_OPT_BEGIN(name,type,def) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n"
+
+/** \brief Begin an option definition with restrictions on valid values */
+#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n"
+
+/** \brief End an option description */
+#define DRI_CONF_OPT_END \
+"</option>\n"
+
+/** \brief A verbal description in a specified language (empty version) */
+#define DRI_CONF_DESC(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\"/>\n"
+
+/** \brief A verbal description in a specified language */
+#define DRI_CONF_DESC_BEGIN(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\">\n"
+
+/** \brief End a description */
+#define DRI_CONF_DESC_END \
+"</description>\n"
+
+/** \brief A verbal description of an enum value */
+#define DRI_CONF_ENUM(value,text) \
+"<enum value=\""#value"\" text=\""text"\"/>\n"
+
+/*
+ * predefined option sections and options with multi-lingual descriptions
+ */
+
+/** \brief Debugging options */
+#define DRI_CONF_SECTION_DEBUG \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Debugging") \
+ DRI_CONF_DESC(de,"Fehlersuche")
+
+#define DRI_CONF_NO_RAST(def) \
+DRI_CONF_OPT_BEGIN(no_rast,bool,def) \
+ DRI_CONF_DESC(en,"Disable 3D acceleration") \
+ DRI_CONF_DESC(de,"3D-Beschleunigung abschalten") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_PERFORMANCE_BOXES(def) \
+DRI_CONF_OPT_BEGIN(performance_boxes,bool,def) \
+ DRI_CONF_DESC(en,"Show performance boxes") \
+ DRI_CONF_DESC(de,"Zeige Performanceboxen") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DEBUG_DMA(def) \
+DRI_CONF_OPT_BEGIN(debug_dma,bool,def) \
+ DRI_CONF_DESC(en,"Debug DMA buffers") \
+ DRI_CONF_DESC(de,"DMA Puffer debuggen") \
+DRI_CONF_OPT_END
+
+
+/** \brief Texture-related options */
+#define DRI_CONF_SECTION_QUALITY \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Image Quality") \
+ DRI_CONF_DESC(de,"Bildqualität")
+
+#define DRI_CONF_TEXTURE_DEPTH_FB 0
+#define DRI_CONF_TEXTURE_DEPTH_32 1
+#define DRI_CONF_TEXTURE_DEPTH_16 2
+#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3
+#define DRI_CONF_TEXTURE_DEPTH(def) \
+DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"Texture color depth") \
+ DRI_CONF_ENUM(0,"Prefer frame buffer color depth") \
+ DRI_CONF_ENUM(1,"Prefer 32 bits") \
+ DRI_CONF_ENUM(2,"Prefer 16 bits") \
+ DRI_CONF_ENUM(3,"Force 16 bits") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Texturfarbtiefe") \
+ DRI_CONF_ENUM(0,"Bevorzugt so wie Framebuffer") \
+ DRI_CONF_ENUM(1,"Bevorzugt 32 Bits") \
+ DRI_CONF_ENUM(2,"Bevorzugt 16 Bits") \
+ DRI_CONF_ENUM(3,"Höchstens 16 Bits") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \
+DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \
+ DRI_CONF_DESC(en,"Default maximum value for anisotropic texture filtering") \
+ DRI_CONF_DESC(de,"Standard Maximalwert für anisotropische Texturfilterung") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NO_NEG_LOD_BIAS(def) \
+DRI_CONF_OPT_BEGIN(no_neg_lod_bias,bool,def) \
+ DRI_CONF_DESC(en,"Forbid negative texture LOD bias") \
+ DRI_CONF_DESC(de,"Verbiete negativen Textur-LOD-Bias") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_COLOR_REDUCTION_ROUND 0
+#define DRI_CONF_COLOR_REDUCTION_DITHER 1
+#define DRI_CONF_COLOR_REDUCTION(def) \
+DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,"Default color reduction method") \
+ DRI_CONF_ENUM(0,"Round or truncate") \
+ DRI_CONF_ENUM(1,"Dither") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Standardmethode zur Farbreduktion") \
+ DRI_CONF_ENUM(0,"Runden oder Abschneiden") \
+ DRI_CONF_ENUM(1,"Rastern") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_ROUND_TRUNC 0
+#define DRI_CONF_ROUND_ROUND 1
+#define DRI_CONF_ROUND_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \
+ DRI_CONF_DESC_BEGIN(en,"Round or truncate colors") \
+ DRI_CONF_ENUM(0,"Truncate") \
+ DRI_CONF_ENUM(1,"Round") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Farben runden oder abschneiden") \
+ DRI_CONF_ENUM(0,"Abschneiden") \
+ DRI_CONF_ENUM(1,"Runden") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DITHER_XERRORDIFF 0
+#define DRI_CONF_DITHER_XERRORDIFFRESET 1
+#define DRI_CONF_DITHER_ORDERED 2
+#define DRI_CONF_DITHER_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Color dithering") \
+ DRI_CONF_ENUM(0,"Horizontal error diffusion") \
+ DRI_CONF_ENUM(1,"Horizontal error diffusion, reset error at line start") \
+ DRI_CONF_ENUM(2,"Ordered 2D dithering") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Farben rastern") \
+ DRI_CONF_ENUM(0,"Horizontale Fehlerstreuung") \
+ DRI_CONF_ENUM(1,"Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen") \
+ DRI_CONF_ENUM(2,"Geordnete 2D Farbrasterung") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+/** \brief Performance-related options */
+#define DRI_CONF_SECTION_PERFORMANCE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Performance") \
+ DRI_CONF_DESC(de,"Leistung")
+
+#define DRI_CONF_TCL_SW 0
+#define DRI_CONF_TCL_PIPELINED 1
+#define DRI_CONF_TCL_VTXFMT 2
+#define DRI_CONF_TCL_CODEGEN 3
+#define DRI_CONF_TCL_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"TCL mode (Transformation, Clipping, Lighting)") \
+ DRI_CONF_ENUM(0,"Software") \
+ DRI_CONF_ENUM(1,"TCL stage in MESA pipeline") \
+ DRI_CONF_ENUM(2,"Bypass MESA's pipeline") \
+ DRI_CONF_ENUM(3,"Bypass MESA's pipeline with state-based code generation") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"TCL Modus (Transformation, Clipping, Licht)") \
+ DRI_CONF_ENUM(0,"Software") \
+ DRI_CONF_ENUM(1,"TCL Stufe in MESA Pipeline") \
+ DRI_CONF_ENUM(2,"Umgehe MESAs Pipeline") \
+ DRI_CONF_ENUM(3,"Umgehe MESAs Pipeline mit zustandsbasierter Codegenerierung") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FTHROTTLE_BUSY 0
+#define DRI_CONF_FTHROTTLE_USLEEPS 1
+#define DRI_CONF_FTHROTTLE_IRQS 2
+#define DRI_CONF_FTHROTTLE_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Frame throttling") \
+ DRI_CONF_ENUM(0,"Busy waiting") \
+ DRI_CONF_ENUM(1,"Usleeps") \
+ DRI_CONF_ENUM(2,"Software interrupts") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Framethrottling") \
+ DRI_CONF_ENUM(0,"Aktives Warten") \
+ DRI_CONF_ENUM(1,"Usleeps") \
+ DRI_CONF_ENUM(2,"Software Interrutps") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+#define DRI_CONF_VBLANK_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"Synchronization with vertical refresh (swap intervals)") \
+ DRI_CONF_ENUM(0,"Never, FPS rulez!") \
+ DRI_CONF_ENUM(1,"Application preference, default interval 0") \
+ DRI_CONF_ENUM(2,"Application preference, default interval 1") \
+ DRI_CONF_ENUM(3,"Application preference, always synchronize with refresh") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Synchronisation mit dem vertikalen Bildaufbau (swap intervals)") \
+ DRI_CONF_ENUM(0,"Niemals, immer die maximale Framerate") \
+ DRI_CONF_ENUM(1,"Anwendung entscheidet, Standardinterval 0") \
+ DRI_CONF_ENUM(2,"Anwendung entscheidet, Standardinterval 1") \
+ DRI_CONF_ENUM(3,"Anwendung entscheidet, immer mit Bildaufbau synchronisieren") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \
+DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \
+ DRI_CONF_DESC(en,"Number of texture units") \
+ DRI_CONF_DESC(de,"Anzahl der Textureinheiten") \
+DRI_CONF_OPT_END
+
+/* Options for features that are not done in hardware by the driver (like GL_ARB_vertex_program
+ On cards where there is no documentation (r200) or on rasterization-only hardware). */
+#define DRI_CONF_SECTION_SOFTWARE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(de,"Funktionalität, die nicht durch die Hardware beschleunigt wird") \
+ DRI_CONF_DESC(en,"Features that are not hardware-accelerated")
+
+#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(arb_vertex_program,bool,def) \
+ DRI_CONF_DESC(de,"GL_ARB_vertex_program aktivieren") \
+ DRI_CONF_DESC(en,"Enable GL_ARB_vertex_program") \
+ DRI_CONF_DESC(fr,"Activer GL_ARB_vertex_program") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_NV_VERTEX_PROGRAM(def) \
+DRI_CONF_OPT_BEGIN(nv_vertex_program,bool,def) \
+ DRI_CONF_DESC(de,"GL_NV_vertex_program aktivieren") \
+ DRI_CONF_DESC(en,"Enable GL_NV_vertex_program") \
+ DRI_CONF_DESC(fr,"Activer GL_NV_vertex_program") \
+DRI_CONF_OPT_END
+
+#endif
diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c
new file mode 100644
index 0000000..cfb6a70
--- /dev/null
+++ b/src/mesa/drivers/fbdev/glfbdev.c
@@ -0,0 +1,791 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+/*
+ * OpenGL (Mesa) interface for fbdev.
+ * For info about fbdev:
+ * http://www.tldp.org/HOWTO/Framebuffer-HOWTO.html
+ *
+ * known VGA modes
+ * Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200
+ * --------+--------------------------------------------------------------
+ * 4 bits | ? ? 0x302 ? ? ? ?
+ * 8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C
+ * 15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D
+ * 16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E
+ * 24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F
+ * 32 bits | ? ? ? ? 0x164 ?
+ */
+
+
+#ifdef USE_GLFBDEV_DRIVER
+
+#include "glheader.h"
+#include <linux/fb.h>
+#include "GL/glfbdev.h"
+#include "context.h"
+#include "extensions.h"
+#include "imports.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+
+
+#define PF_B8G8R8 1
+#define PF_B8G8R8A8 2
+#define PF_B5G6R5 3
+#define PF_B5G5R5 4
+#define PF_CI8 5
+
+
+/*
+ * Derived from Mesa's GLvisual class.
+ */
+struct GLFBDevVisualRec {
+ GLvisual glvisual; /* base class */
+ struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;
+ int pixelFormat;
+};
+
+/*
+ * Derived from Mesa's GLframebuffer class.
+ */
+struct GLFBDevBufferRec {
+ GLframebuffer glframebuffer; /* base class */
+ GLFBDevVisualPtr visual;
+ struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;
+ void *frontStart;
+ void *backStart;
+ size_t size;
+ GLuint bytesPerPixel;
+ GLuint rowStride; /* in bytes */
+ GLubyte *frontBottom; /* pointer to last row */
+ GLubyte *backBottom; /* pointer to last row */
+ GLubyte *curBottom; /* = frontBottom or backBottom */
+ GLboolean mallocBackBuffer;
+};
+
+/*
+ * Derived from Mesa's GLcontext class.
+ */
+struct GLFBDevContextRec {
+ GLcontext glcontext; /* base class */
+ GLFBDevVisualPtr visual;
+ GLFBDevBufferPtr drawBuffer;
+ GLFBDevBufferPtr readBuffer;
+ GLFBDevBufferPtr curBuffer;
+};
+
+
+
+#define GLFBDEV_CONTEXT(CTX) ((GLFBDevContextPtr) (CTX))
+#define GLFBDEV_BUFFER(BUF) ((GLFBDevBufferPtr) (BUF))
+
+
+/**********************************************************************/
+/* Internal device driver functions */
+/**********************************************************************/
+
+
+static const GLubyte *
+get_string(GLcontext *ctx, GLenum pname)
+{
+ (void) ctx;
+ switch (pname) {
+ case GL_RENDERER:
+ return (const GLubyte *) "Mesa glfbdev";
+ default:
+ return NULL;
+ }
+}
+
+
+static void
+update_state( GLcontext *ctx, GLuint new_state )
+{
+ /* not much to do here - pass it on */
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+
+static void
+get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ const GLFBDevBufferPtr fbdevbuffer = (GLFBDevBufferPtr) buffer;
+ *width = fbdevbuffer->var.xres_virtual;
+ *height = fbdevbuffer->var.yres_virtual;
+}
+
+
+/* specifies the buffer for swrast span rendering/reading */
+static void
+set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
+{
+ GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx);
+ GLFBDevBufferPtr fbdevbuf = GLFBDEV_BUFFER(buffer);
+ fbdevctx->curBuffer = fbdevbuf;
+ switch (bufferBit) {
+ case DD_FRONT_LEFT_BIT:
+ fbdevbuf->curBottom = fbdevbuf->frontBottom;
+ break;
+ case DD_BACK_LEFT_BIT:
+ fbdevbuf->curBottom = fbdevbuf->backBottom;
+ break;
+ default:
+ _mesa_problem(ctx, "bad bufferBit in set_buffer()");
+ }
+}
+
+
+/*
+ * Generate code for span functions.
+ */
+
+/* 24-bit BGR */
+#define NAME(PREFIX) PREFIX##_B8G8R8
+#define SPAN_VARS \
+ const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
+ const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 3
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = B; P[1] = G; P[2] = R
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = B; P[1] = G; P[2] = R
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[2]; G = P[1]; B = P[0]; A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 32-bit BGRA */
+#define NAME(PREFIX) PREFIX##_B8G8R8A8
+#define SPAN_VARS \
+ const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
+ const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 4
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = B; P[1] = G; P[2] = R; P[3] = 255
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = B; P[1] = G; P[2] = R; P[3] = A
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[2]; G = P[1]; B = P[0]; A = P[3]
+
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G6R5
+#define SPAN_VARS \
+ const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
+ const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
+ G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
+ B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
+ A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 15-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G5R5
+#define SPAN_VARS \
+ const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
+ const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) (fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X) * 2)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
+ G = ( (((*P) >> 2) & 0xf8) | (((*P) >> 5) & 0x7) ); \
+ B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
+ A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit color index */
+#define NAME(PREFIX) PREFIX##_CI8
+#define SPAN_VARS \
+ const GLFBDevContextPtr fbdevctx = GLFBDEV_CONTEXT(ctx); \
+ const GLFBDevBufferPtr fbdevbuf = fbdevctx->curBuffer;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = fbdevbuf->curBottom - (Y) * fbdevbuf->rowStride + (X)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_CI_PIXEL(P, CI) \
+ P[0] = CI
+#define FETCH_CI_PIXEL(CI, P) \
+ CI = P[0]
+
+#include "swrast/s_spantemp.h"
+
+/**********************************************************************/
+/* Public API functions */
+/**********************************************************************/
+
+
+const char *
+glFBDevGetString( int str )
+{
+ switch (str) {
+ case GLFBDEV_VENDOR:
+ return "Mesa Project";
+ case GLFBDEV_VERSION:
+ return "1.0.0";
+ default:
+ return NULL;
+ }
+}
+
+
+const void *
+glFBDevGetProcAddress( const char *procName )
+{
+ struct name_address {
+ const char *name;
+ const void *func;
+ };
+ static const struct name_address functions[] = {
+ { "glFBDevGetString", (void *) glFBDevGetString },
+ { "glFBDevGetProcAddress", (void *) glFBDevGetProcAddress },
+ { "glFBDevCreateVisual", (void *) glFBDevCreateVisual },
+ { "glFBDevDestroyVisual", (void *) glFBDevDestroyVisual },
+ { "glFBDevGetVisualAttrib", (void *) glFBDevGetVisualAttrib },
+ { "glFBDevCreateBuffer", (void *) glFBDevCreateBuffer },
+ { "glFBDevDestroyBuffer", (void *) glFBDevDestroyBuffer },
+ { "glFBDevGetBufferAttrib", (void *) glFBDevGetBufferAttrib },
+ { "glFBDevGetCurrentDrawBuffer", (void *) glFBDevGetCurrentDrawBuffer },
+ { "glFBDevGetCurrentReadBuffer", (void *) glFBDevGetCurrentReadBuffer },
+ { "glFBDevSwapBuffers", (void *) glFBDevSwapBuffers },
+ { "glFBDevCreateContext", (void *) glFBDevCreateContext },
+ { "glFBDevDestroyContext", (void *) glFBDevDestroyContext },
+ { "glFBDevGetContextAttrib", (void *) glFBDevGetContextAttrib },
+ { "glFBDevGetCurrentContext", (void *) glFBDevGetCurrentContext },
+ { "glFBDevMakeCurrent", (void *) glFBDevMakeCurrent },
+ { NULL, NULL }
+ };
+ const struct name_address *entry;
+ for (entry = functions; entry->name; entry++) {
+ if (_mesa_strcmp(entry->name, procName) == 0) {
+ return entry->func;
+ }
+ }
+ return _glapi_get_proc_address(procName);
+}
+
+
+GLFBDevVisualPtr
+glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
+ const struct fb_var_screeninfo *varInfo,
+ const int *attribs )
+{
+ GLFBDevVisualPtr vis;
+ const int *attrib;
+ GLboolean rgbFlag = GL_TRUE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
+ GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
+ GLint indexBits = 0, depthBits = 0, stencilBits = 0;
+ GLint accumRedBits = 0, accumGreenBits = 0;
+ GLint accumBlueBits = 0, accumAlphaBits = 0;
+ GLint numSamples = 0;
+
+ ASSERT(fixInfo);
+ ASSERT(varInfo);
+
+ vis = CALLOC_STRUCT(GLFBDevVisualRec);
+ if (!vis)
+ return NULL;
+
+ vis->fix = *fixInfo; /* struct assignment */
+ vis->var = *varInfo; /* struct assignment */
+
+ for (attrib = attribs; attrib && *attrib != GLFBDEV_NONE; attrib++) {
+ switch (*attrib) {
+ case GLFBDEV_DOUBLE_BUFFER:
+ dbFlag = GL_TRUE;
+ break;
+ case GLFBDEV_COLOR_INDEX:
+ rgbFlag = GL_FALSE;
+ break;
+ case GLFBDEV_DEPTH_SIZE:
+ depthBits = attrib[1];
+ attrib++;
+ break;
+ case GLFBDEV_STENCIL_SIZE:
+ stencilBits = attrib[1];
+ attrib++;
+ break;
+ case GLFBDEV_ACCUM_SIZE:
+ accumRedBits = accumGreenBits = accumBlueBits = accumAlphaBits
+ = attrib[1];
+ attrib++;
+ break;
+ case GLFBDEV_LEVEL:
+ /* ignored for now */
+ break;
+ default:
+ /* unexpected token */
+ _mesa_free(vis);
+ return NULL;
+ }
+ }
+
+ if (rgbFlag) {
+ redBits = varInfo->red.length;
+ greenBits = varInfo->green.length;
+ blueBits = varInfo->blue.length;
+ alphaBits = varInfo->transp.length;
+
+ if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
+ fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
+ && varInfo->bits_per_pixel == 24
+ && varInfo->red.offset == 16
+ && varInfo->green.offset == 8
+ && varInfo->blue.offset == 0) {
+ vis->pixelFormat = PF_B8G8R8;
+ }
+ else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
+ fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
+ && varInfo->bits_per_pixel == 32
+ && varInfo->red.offset == 16
+ && varInfo->green.offset == 8
+ && varInfo->blue.offset == 0
+ && varInfo->transp.offset == 24) {
+ vis->pixelFormat = PF_B8G8R8A8;
+ }
+ else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
+ fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
+ && varInfo->bits_per_pixel == 16
+ && varInfo->red.offset == 11
+ && varInfo->green.offset == 5
+ && varInfo->blue.offset == 0) {
+ vis->pixelFormat = PF_B5G6R5;
+ }
+ else if ((fixInfo->visual == FB_VISUAL_TRUECOLOR ||
+ fixInfo->visual == FB_VISUAL_DIRECTCOLOR)
+ && varInfo->bits_per_pixel == 16
+ && varInfo->red.offset == 10
+ && varInfo->green.offset == 5
+ && varInfo->blue.offset == 0) {
+ vis->pixelFormat = PF_B5G5R5;
+ }
+ else {
+ _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
+ /*
+ printf("fixInfo->visual = 0x%x\n", fixInfo->visual);
+ printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel);
+ printf("varInfo->red.offset = %d\n", varInfo->red.offset);
+ printf("varInfo->green.offset = %d\n", varInfo->green.offset);
+ printf("varInfo->blue.offset = %d\n", varInfo->blue.offset);
+ */
+ _mesa_free(vis);
+ return NULL;
+ }
+ }
+ else {
+ indexBits = varInfo->bits_per_pixel;
+ if ((fixInfo->visual == FB_VISUAL_PSEUDOCOLOR ||
+ fixInfo->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ && varInfo->bits_per_pixel == 8) {
+ vis->pixelFormat = PF_CI8;
+ }
+ else {
+ _mesa_problem(NULL, "Unsupported fbdev CI visual/bitdepth!\n");
+ _mesa_free(vis);
+ return NULL;
+ }
+ }
+
+ if (!_mesa_initialize_visual(&vis->glvisual, rgbFlag, dbFlag, stereoFlag,
+ redBits, greenBits, blueBits, alphaBits,
+ indexBits, depthBits, stencilBits,
+ accumRedBits, accumGreenBits,
+ accumBlueBits, accumAlphaBits,
+ numSamples)) {
+ /* something was invalid */
+ _mesa_free(vis);
+ return NULL;
+ }
+
+ return vis;
+}
+
+
+void
+glFBDevDestroyVisual( GLFBDevVisualPtr visual )
+{
+ if (visual)
+ _mesa_free(visual);
+}
+
+
+int
+glFBDevGetVisualAttrib( const GLFBDevVisualPtr visual, int attrib)
+{
+ (void) visual;
+ (void) attrib;
+ return -1;
+}
+
+
+
+GLFBDevBufferPtr
+glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
+ const struct fb_var_screeninfo *varInfo,
+ const GLFBDevVisualPtr visual,
+ void *frontBuffer, void *backBuffer, size_t size )
+{
+ GLFBDevBufferPtr buf;
+
+ ASSERT(visual);
+ ASSERT(frontBuffer);
+ ASSERT(size > 0);
+
+ if (visual->fix.visual != fixInfo->visual ||
+ visual->fix.type != fixInfo->type ||
+ visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
+ visual->var.grayscale != varInfo->grayscale ||
+ visual->var.red.offset != varInfo->red.offset ||
+ visual->var.green.offset != varInfo->green.offset ||
+ visual->var.blue.offset != varInfo->blue.offset ||
+ visual->var.transp.offset != varInfo->transp.offset) {
+ /* visual mismatch! */
+ return NULL;
+ }
+
+ buf = CALLOC_STRUCT(GLFBDevBufferRec);
+ if (!buf)
+ return NULL;
+
+ _mesa_initialize_framebuffer(&buf->glframebuffer, &visual->glvisual,
+ visual->glvisual.haveDepthBuffer,
+ visual->glvisual.haveStencilBuffer,
+ visual->glvisual.haveAccumBuffer,
+ GL_FALSE);
+
+ buf->fix = *fixInfo; /* struct assignment */
+ buf->var = *varInfo; /* struct assignment */
+ buf->visual = visual; /* ptr assignment */
+ buf->frontStart = frontBuffer;
+ buf->size = size;
+ buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
+ buf->rowStride = visual->var.xres_virtual * buf->bytesPerPixel;
+ buf->frontBottom = (GLubyte *) buf->frontStart
+ + (visual->var.yres_virtual - 1) * buf->rowStride;
+
+ if (visual->glvisual.doubleBufferMode) {
+ if (backBuffer) {
+ buf->backStart = backBuffer;
+ buf->mallocBackBuffer = GL_FALSE;
+ }
+ else {
+ buf->backStart = _mesa_malloc(size);
+ if (!buf->backStart) {
+ _mesa_free_framebuffer_data(&buf->glframebuffer);
+ _mesa_free(buf);
+ return NULL;
+ }
+ buf->mallocBackBuffer = GL_TRUE;
+ }
+ buf->backBottom = (GLubyte *) buf->backStart
+ + (visual->var.yres_virtual - 1) * buf->rowStride;
+ buf->curBottom = buf->backBottom;
+ }
+ else {
+ buf->backStart = NULL;
+ buf->mallocBackBuffer = GL_FALSE;
+ buf->backBottom = NULL;
+ buf->curBottom = buf->frontBottom;
+ }
+
+ return buf;
+}
+
+
+void
+glFBDevDestroyBuffer( GLFBDevBufferPtr buffer )
+{
+ if (buffer) {
+ /* check if destroying the current buffer */
+ GLFBDevBufferPtr curDraw = glFBDevGetCurrentDrawBuffer();
+ GLFBDevBufferPtr curRead = glFBDevGetCurrentReadBuffer();
+ if (buffer == curDraw || buffer == curRead) {
+ glFBDevMakeCurrent( NULL, NULL, NULL);
+ }
+ if (buffer->mallocBackBuffer) {
+ _mesa_free(buffer->backStart);
+ }
+ /* free the software depth, stencil, accum buffers */
+ _mesa_free_framebuffer_data(&buffer->glframebuffer);
+ _mesa_free(buffer);
+ }
+}
+
+
+int
+glFBDevGetBufferAttrib( const GLFBDevBufferPtr buffer, int attrib)
+{
+ (void) buffer;
+ (void) attrib;
+ return -1;
+}
+
+
+GLFBDevBufferPtr
+glFBDevGetCurrentDrawBuffer( void )
+{
+ GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
+ if (fbdevctx)
+ return fbdevctx->drawBuffer;
+ else
+ return NULL;
+}
+
+
+GLFBDevBufferPtr
+glFBDevGetCurrentReadBuffer( void )
+{
+ GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
+ if (fbdevctx)
+ return fbdevctx->readBuffer;
+ else
+ return NULL;
+}
+
+
+void
+glFBDevSwapBuffers( GLFBDevBufferPtr buffer )
+{
+ GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
+
+ if (!buffer || !buffer->visual->glvisual.doubleBufferMode)
+ return;
+
+ /* check if swapping currently bound buffer */
+ if (fbdevctx->drawBuffer == buffer) {
+ /* flush pending rendering */
+ _mesa_notifySwapBuffers(&fbdevctx->glcontext);
+ }
+
+ ASSERT(buffer->frontStart);
+ ASSERT(buffer->backStart);
+ _mesa_memcpy(buffer->frontStart, buffer->backStart, buffer->size);
+}
+
+
+GLFBDevContextPtr
+glFBDevCreateContext( const GLFBDevVisualPtr visual, GLFBDevContextPtr share )
+{
+ GLFBDevContextPtr ctx;
+ GLcontext *glctx;
+ struct dd_function_table functions;
+
+ ASSERT(visual);
+
+ ctx = CALLOC_STRUCT(GLFBDevContextRec);
+ if (!ctx)
+ return NULL;
+
+ /* build table of device driver functions */
+ _mesa_init_driver_functions(&functions);
+ functions.GetString = get_string;
+ functions.UpdateState = update_state;
+ functions.GetBufferSize = get_buffer_size;
+
+ if (!_mesa_initialize_context(&ctx->glcontext, &visual->glvisual,
+ share ? &share->glcontext : NULL,
+ &functions, (void *) ctx)) {
+ _mesa_free(ctx);
+ return NULL;
+ }
+
+ ctx->visual = visual;
+
+ /* Create module contexts */
+ glctx = (GLcontext *) &ctx->glcontext;
+ _swrast_CreateContext( glctx );
+ _ac_CreateContext( glctx );
+ _tnl_CreateContext( glctx );
+ _swsetup_CreateContext( glctx );
+ _swsetup_Wakeup( glctx );
+
+ /* swrast init */
+ {
+ struct swrast_device_driver *swdd;
+ swdd = _swrast_GetDeviceDriverReference( glctx );
+ swdd->SetBuffer = set_buffer;
+ if (visual->pixelFormat == PF_B8G8R8) {
+ swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
+ swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
+ swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
+ swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
+ swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
+ }
+ else if (visual->pixelFormat == PF_B8G8R8A8) {
+ swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
+ swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
+ swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
+ swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
+ swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
+ }
+ else if (visual->pixelFormat == PF_B5G6R5) {
+ swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
+ swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
+ swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
+ swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
+ swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
+ }
+ else if (visual->pixelFormat == PF_B5G5R5) {
+ swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
+ swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
+ swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
+ swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
+ swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
+ }
+ else if (visual->pixelFormat == PF_CI8) {
+ swdd->WriteCI32Span = write_index32_span_CI8;
+ swdd->WriteCI8Span = write_index8_span_CI8;
+ swdd->WriteMonoCISpan = write_monoindex_span_CI8;
+ swdd->WriteCI32Pixels = write_index_pixels_CI8;
+ swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
+ swdd->ReadCI32Span = read_index_span_CI8;
+ swdd->ReadCI32Pixels = read_index_pixels_CI8;
+ }
+ else {
+ _mesa_printf("bad pixelformat: %d\n", visual->pixelFormat);
+ }
+ }
+
+ /* use default TCL pipeline */
+ {
+ TNLcontext *tnl = TNL_CONTEXT(glctx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ }
+
+ _mesa_enable_sw_extensions(glctx);
+
+ return ctx;
+}
+
+
+void
+glFBDevDestroyContext( GLFBDevContextPtr context )
+{
+ GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext();
+
+ if (context) {
+ if (fbdevctx == context) {
+ /* destroying current context */
+ _mesa_make_current2(NULL, NULL, NULL);
+ _mesa_notifyDestroy(&context->glcontext);
+ }
+ _mesa_free_context_data(&context->glcontext);
+ _mesa_free(context);
+ }
+}
+
+
+int
+glFBDevGetContextAttrib( const GLFBDevContextPtr context, int attrib)
+{
+ (void) context;
+ (void) attrib;
+ return -1;
+}
+
+
+GLFBDevContextPtr
+glFBDevGetCurrentContext( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return (GLFBDevContextPtr) ctx;
+}
+
+
+int
+glFBDevMakeCurrent( GLFBDevContextPtr context,
+ GLFBDevBufferPtr drawBuffer,
+ GLFBDevBufferPtr readBuffer )
+{
+ if (context && drawBuffer && readBuffer) {
+ /* Make sure the context's visual and the buffers' visuals match.
+ * XXX we might do this by comparing specific fields like bits_per_pixel,
+ * visual, etc. in the future.
+ */
+ if (context->visual != drawBuffer->visual ||
+ context->visual != readBuffer->visual) {
+ return 0;
+ }
+ _mesa_make_current2( &context->glcontext,
+ &drawBuffer->glframebuffer,
+ &readBuffer->glframebuffer );
+ context->drawBuffer = drawBuffer;
+ context->readBuffer = readBuffer;
+ context->curBuffer = drawBuffer;
+ }
+ else {
+ /* unbind */
+ _mesa_make_current2( NULL, NULL, NULL );
+ }
+
+ return 1;
+}
+
+#endif /* USE_GLFBDEV_DRIVER */
+
diff --git a/src/mesa/drivers/ggi/default/genkgi.conf.in b/src/mesa/drivers/ggi/default/genkgi.conf.in
new file mode 100644
index 0000000..02acad2
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/genkgi.conf.in
@@ -0,0 +1,4 @@
+# GGIMesa genkgi helper configuration
+.root: @ggi_libdir@/ggi/mesa/default
+
+tgt-fbdev-kgicon-d3dim-mesa d3dim.so
diff --git a/src/mesa/drivers/ggi/default/genkgi_mode.c b/src/mesa/drivers/ggi/default/genkgi_mode.c
new file mode 100644
index 0000000..9380247
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/genkgi_mode.c
@@ -0,0 +1,97 @@
+/* $Id: genkgi_mode.c,v 1.4 2000/01/07 08:34:44 jtaylor Exp $
+******************************************************************************
+
+ display-fbdev-kgicon-generic-mesa
+
+ Copyright (C) 1999 Jon Taylor [taylorj@ggi-project.org]
+
+ 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.
+
+******************************************************************************
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/debug.h>
+#include "genkgi.h"
+
+int GGIMesa_genkgi_getapi(ggi_visual *vis, int num, char *apiname, char *arguments)
+{
+ struct genkgi_priv_mesa *priv = GENKGI_PRIV_MESA(vis);
+
+ GGIMESADPRINT_CORE("Entered mesa_genkgi_getapi, num=%d\n", num);
+
+ strcpy(arguments, "");
+
+ switch(num)
+ {
+ case 0:
+ if (priv->have_accel)
+ {
+ strcpy(apiname, priv->accel);
+ return 0;
+ }
+ break;
+ }
+ return -1;
+}
+
+int GGIMesa_genkgi_flush(ggi_visual *vis, int x, int y, int w, int h, int tryflag)
+{
+ struct genkgi_priv_mesa *priv = GENKGI_PRIV_MESA(vis);
+ int junkval;
+
+ priv->oldpriv->kgicommand_ptr += getpagesize();
+ (kgiu32)(priv->oldpriv->kgicommand_ptr) &= 0xfffff000;
+ junkval = *((int *)(priv->oldpriv->kgicommand_ptr));
+
+ /* Check if we are now in the last page, and reset the
+ * FIFO if so. We can't use the last page to send
+ * more commands, since there's no page after it that
+ * we can touch to fault in the last page's commands.
+ *
+ * FIXME: This will be replaced with a flush-and-reset handler
+ * on the end-of-buffer pagefault at some point....
+ *
+ */
+ if ((priv->oldpriv->kgicommand_ptr - priv->oldpriv->mapped_kgicommand)
+ >= (priv->oldpriv->kgicommand_buffersize - getpagesize()))
+ {
+ munmap(priv->oldpriv->mapped_kgicommand, priv->oldpriv->kgicommand_buffersize);
+ if ((priv->oldpriv->mapped_kgicommand =
+ mmap(NULL,
+ priv->oldpriv->kgicommand_buffersize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ priv->oldpriv->fd_kgicommand,
+ 0)) == MAP_FAILED)
+ {
+ ggiPanic("Failed to remap kgicommand!");
+ }
+ priv->oldpriv->kgicommand_ptr = priv->oldpriv->mapped_kgicommand;
+ }
+ return 0;
+}
diff --git a/src/mesa/drivers/ggi/default/genkgi_visual.c b/src/mesa/drivers/ggi/default/genkgi_visual.c
new file mode 100644
index 0000000..17ef967
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/genkgi_visual.c
@@ -0,0 +1,190 @@
+/* $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
+
+ Copyright (C) 1999 Jon Taylor [taylorj@ggi-project.org]
+
+ 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.
+
+******************************************************************************
+*/
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/display_fbdev.h>
+#include <ggi/mesa/debug.h>
+#include "genkgi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_VT_H
+#include <sys/vt.h>
+#else
+#include <linux/vt.h>
+#endif
+#ifdef HAVE_LINUX_KDEV_T_H
+#include <linux/kdev_t.h>
+#endif
+#include <linux/tty.h>
+
+#define DEFAULT_FBNUM 0
+
+static char accel_prefix[] = "tgt-fbdev-kgicon-";
+#define PREFIX_LEN (sizeof(accel_prefix))
+
+typedef struct {
+ int async;
+ char *str;
+} accel_info;
+
+static accel_info accel_strings[] =
+{
+ { 0, "d3dim" }, /* Direct3D Immediate Mode */
+};
+
+#define NUM_ACCELS (sizeof(accel_strings)/sizeof(accel_info))
+
+/* FIXME: These should be defined in the makefile system */
+#define CONF_FILE "/usr/local/etc/ggi/mesa/targets/genkgi.conf"
+void *_configHandle;
+char confstub[512] = CONF_FILE;
+char *conffile = confstub;
+
+static int changed(ggi_visual_t vis, int whatchanged)
+{
+ GGIMESADPRINT_CORE("Entered ggimesa_genkgi_changed\n");
+
+ switch (whatchanged)
+ {
+ case GGI_CHG_APILIST:
+ {
+ char api[256];
+ char args[256];
+ int i;
+ const char *fname;
+ ggi_dlhandle *lib;
+
+ for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++)
+ {
+ strcat(api, "-mesa");
+ GGIMESADPRINT_CORE("ggimesa_genkgi_changed: api=%s, i=%d\n", api, i);
+ fname = ggMatchConfig(_configHandle, api, NULL);
+ if (fname == NULL)
+ {
+ /* No special implementation for this sublib */
+ continue;
+ }
+
+ lib = ggiExtensionLoadDL(vis, fname, args, NULL);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int GGIdlinit(ggi_visual *vis, struct ggi_dlhandle *dlh,
+ const char *args, void *argptr, uint32 *dlret)
+{
+ struct genkgi_priv_mesa *priv;
+ char libname[256], libargs[256];
+ int id, err;
+ struct stat junk;
+ ggifunc_getapi *oldgetapi;
+
+ GGIMESADPRINT_CORE("display-fbdev-kgicon-mesa: GGIdlinit start\n");
+
+ GENKGI_PRIV_MESA(vis) = priv = malloc(sizeof(struct genkgi_priv_mesa));
+ if (priv == NULL)
+ {
+ fprintf(stderr, "Failed to allocate genkgi private data\n");
+ return GGI_DL_ERROR;
+ }
+
+ priv->oldpriv = GENKGI_PRIV(vis);
+#if 0
+ err = ggLoadConfig(conffile, &_configHandle);
+ if (err != GGI_OK)
+ {
+ gl_ggiPrint("display-fbdev-kgicon-mesa: Couldn't open %s\n", conffile);
+ return err;
+ }
+
+ /* Hack city here. We need to probe the KGI driver properly for
+ * suggest-strings to discover the acceleration type(s).
+ */
+ priv->have_accel = 0;
+
+ if (stat("/proc/gfx0", &junk) == 0)
+ {
+ sprintf(priv->accel, "%s%s", accel_prefix, "d3dim");
+ priv->have_accel = 1;
+ GGIMESADPRINT_CORE("display-fbdev-kgicon-mesa: Using accel: \"%s\"\n", priv->accel);
+ }
+
+ /* Mode management */
+ vis->opdisplay->getapi = GGIMesa_genkgi_getapi;
+ ggiIndicateChange(vis, GGI_CHG_APILIST);
+
+ /* Give the accel sublibs a chance to set up a driver */
+ if (priv->have_accel == 1)
+ {
+ oldgetapi = vis->opdisplay->getapi;
+ vis->opdisplay->getapi = GGIMesa_genkgi_getapi;
+ changed(vis, GGI_CHG_APILIST);
+ /* If the accel sublibs didn't produce, back up
+ * and keep looking */
+ if ((LIBGGI_MESAEXT(vis)->update_state == NULL) ||
+ (LIBGGI_MESAEXT(vis)->setup_driver == NULL))
+ vis->opdisplay->getapi = oldgetapi;
+ }
+
+ LIBGGI_MESAEXT(vis)->update_state = genkgi_update_state;
+ LIBGGI_MESAEXT(vis)->setup_driver = genkgi_setup_driver;
+#endif
+ GGIMESADPRINT_CORE("display-fbdev-kgicon-mesa: GGIdlinit finished\n");
+
+ *dlret = GGI_DL_OPDRAW;
+ return 0;
+}
+
+int MesaGGIdl_fbdev(int func, void **funcptr)
+{
+ switch (func) {
+ case GGIFUNC_open:
+ *funcptr = GGIopen;
+ return 0;
+ case GGIFUNC_exit:
+ case GGIFUNC_close:
+ *funcptr = NULL;
+ return 0;
+ default:
+ *funcptr = NULL;
+ }
+ return GGI_ENOTFOUND;
+}
+
+#include <ggi/internal/ggidlinit.h>
diff --git a/src/mesa/drivers/ggi/default/linear.c b/src/mesa/drivers/ggi/default/linear.c
new file mode 100644
index 0000000..9d29761
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear.c
@@ -0,0 +1,409 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/debug.h>
+#include "swrast/swrast.h"
+
+#define RMASK ((1<<R)-1)
+#define GMASK ((1<<G)-1)
+#define BMASK ((1<<B)-1)
+
+#define RS (8-R)
+#define GS (8-G)
+#define BS (8-B)
+
+#define PACK(color) (((color[RCOMP]>>RS) << (G+B)) | \
+ ((color[GCOMP]>>GS) << B) | \
+ ((color[BCOMP]>>BS)))
+
+#define FLIP(coord) (LIBGGI_VIRTY(ggi_ctx->ggi_visual) - (coord) - 1)
+
+
+/**********************************************************************/
+/***** Write spans of pixels *****/
+/**********************************************************************/
+
+void GGIwrite_ci32_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint ci[], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask) {
+ while (n--) {
+ if (*mask++)
+ *fb = *ci;
+ fb++;
+ ci++;
+ }
+ } else {
+ while (n--) *fb++ = *ci++;
+ }
+}
+
+void GGIwrite_ci8_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte ci[], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask) {
+ while (n--) {
+ if (*mask++)
+ *fb = *ci;
+ fb++;
+ ci++;
+ }
+ } else {
+ while (n--) *fb++ = *ci++;
+ }
+}
+
+
+void GGIwrite_rgba_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLchan rgba[][4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask) {
+ while (n--) {
+ if (*mask++)
+ *fb = PACK(rgba[0]);
+ fb++;
+ rgba++;
+ }
+ } else {
+ while (n--) {
+ *fb++ = PACK(rgba[0]);
+ rgba++;
+ }
+ }
+}
+
+void GGIwrite_rgb_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLchan rgba[][3], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask) {
+ while (n--) {
+ if (*mask++)
+ *fb = PACK(rgba[0]);
+ fb++;
+ rgba++;
+ }
+ } else {
+ while (n--) {
+ *fb++ = PACK(rgba[0]);
+ rgba++;
+ }
+ }
+}
+
+
+void GGIwrite_mono_rgba_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask) {
+ while (n--){
+ if (*mask++)
+ *fb = PACK(color);
+ ++fb;
+ }
+ } else {
+ while (n--)
+ *fb++ = PACK(color);
+
+ /* Alternatively we could write a potentialy faster HLine
+ ggiSetGCForeground(ggi_ctx->ggi_visual, color);
+ ggiDrawHLine(ggi_ctx->ggi_visual,x,FLIP(y),n);
+ */
+ }
+}
+
+void GGIwrite_mono_ci_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint ci, const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ if (mask){
+ while (n--){
+ if (*mask++)
+ *fb = ci;
+ ++fb;
+ }
+ } else {
+ while (n--)
+ *fb++ = ci;
+
+ /* Alternatively we could write a potentialy faster HLine
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ci);
+ ggiDrawHLine(ggi_ctx->ggi_visual, x, FLIP(y), n);
+ */
+ }
+}
+
+
+/**********************************************************************/
+/***** Read spans of pixels *****/
+/**********************************************************************/
+
+
+void GGIread_ci32_span(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint ci[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ while (n--)
+ *ci++ = (GLuint)*fb++;
+}
+
+void GGIread_rgba_span(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLchan rgba[][4])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ FB_TYPE color;
+ FB_TYPE *fb;
+ fb = (FB_TYPE *)((char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual) +
+ FLIP(y)*LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual)) + x;
+
+ while (n--) {
+ color = *fb++;
+ rgba[0][RCOMP] = (GLubyte) (color>>(G+B))<<RS;
+ rgba[0][GCOMP] = (GLubyte) ((color>>B)& ((1<<G)-1))<<GS;
+ rgba[0][BCOMP] = (GLubyte) (color & ((1<<B)-1))<<BS;
+ rgba[0][ACOMP] = 0;
+ rgba++;
+ }
+}
+
+/**********************************************************************/
+/***** Write arrays of pixels *****/
+/**********************************************************************/
+
+void GGIwrite_ci32_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint ci[], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+
+ while (n--) {
+ if (*mask++){
+ FB_TYPE *dst = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ *dst = *ci;
+ }
+ ci++;
+ x++;
+ y++;
+ }
+}
+
+void GGIwrite_mono_ci_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint ci, const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+
+ while (n--) {
+ if (*mask++){
+ FB_TYPE *dst = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ *dst = ci;
+ }
+ x++;
+ y++;
+ }
+}
+
+void GGIwrite_rgba_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLchan rgba[][4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+
+ while (n--) {
+ if (*mask++){
+ FB_TYPE *dst = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ *dst = PACK(rgba[0]);
+ }
+ x++;
+ y++;
+ rgba++;
+ }
+}
+
+void GGIwrite_mono_rgba_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLchan rgba[4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+
+ while (n--) {
+ if (*mask++){
+ FB_TYPE *dst = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ *dst = PACK(rgba);
+ }
+
+ x++;
+ y++;
+ }
+}
+
+/**********************************************************************/
+/***** Read arrays of pixels *****/
+/**********************************************************************/
+
+void GGIread_ci32_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint ci[], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+
+ while (n--) {
+ if (*mask++){
+ FB_TYPE *src = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ *ci = *src;
+ }
+ ci++;
+ x++;
+ y++;
+ }
+}
+
+void GGIread_rgba_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ int stride = LIBGGI_FB_W_STRIDE(ggi_ctx->ggi_visual);
+ char *fb = (char *)LIBGGI_CURWRITE(ggi_ctx->ggi_visual);
+ FB_TYPE color;
+
+ while (n--) {
+ if (*mask++) {
+ FB_TYPE *src = (FB_TYPE*)(fb + FLIP(*y)*stride) + *x;
+ color = *src;
+
+ rgba[0][RCOMP] = (GLubyte)(color>>(G+B))<<RS;
+ rgba[0][GCOMP] = (GLubyte)((color>>B)& ((1<<G)-1))<<GS;
+ rgba[0][BCOMP] = (GLubyte) (color & ((1<<B)-1))<<BS;
+ rgba[0][ACOMP] = 0;
+ }
+ x++;
+ y++;
+ rgba++;
+ }
+}
+
+void GGIset_buffer(GLcontext *ctx, GLframebuffer *buffer, GLenum mode)
+{
+}
+
+int GGIsetup_driver(ggi_mesa_context_t ggi_ctx)
+{
+ struct swrast_device_driver *swdd =
+ _swrast_GetDeviceDriverReference(ggi_ctx->gl_ctx);
+
+ GGIMESADPRINT_LIBS("linear_%d: GGIsetup_driver\n", sizeof(FB_TYPE)*8);
+
+ swdd->WriteRGBASpan = GGIwrite_rgba_span;
+ swdd->WriteRGBSpan = GGIwrite_rgb_span;
+ swdd->WriteMonoRGBASpan = GGIwrite_mono_rgba_span;
+ swdd->WriteRGBAPixels = GGIwrite_rgba_pixels;
+ swdd->WriteMonoRGBAPixels = GGIwrite_mono_rgba_pixels;
+
+ swdd->WriteCI32Span = GGIwrite_ci32_span;
+ swdd->WriteCI8Span = GGIwrite_ci8_span;
+ swdd->WriteMonoCISpan = GGIwrite_mono_ci_span;
+ swdd->WriteCI32Pixels = GGIwrite_ci32_pixels;
+ swdd->WriteMonoCIPixels = GGIwrite_mono_ci_pixels;
+
+ swdd->ReadCI32Span = GGIread_ci32_span;
+ swdd->ReadRGBASpan = GGIread_rgba_span;
+ swdd->ReadCI32Pixels = GGIread_ci32_pixels;
+ swdd->ReadRGBAPixels = GGIread_rgba_pixels;
+
+ swdd->SetBuffer = GGIset_buffer;
+
+ return 0;
+}
+
+static int GGIopen(ggi_visual_t vis,struct ggi_dlhandle *dlh,
+ const char *args,void *argptr, uint32 *dlret)
+{
+ GGIMESADPRINT_CORE("linear_%d: GGIOpen\n", sizeof(FB_TYPE)*8);
+ LIBGGI_MESAEXT(vis)->setup_driver = GGIsetup_driver;
+
+ *dlret = GGI_DL_OPDRAW;
+ return 0;
+}
+
+int DLOPENFUNC(int func, void **funcptr)
+{
+ switch (func) {
+ case GGIFUNC_open:
+ *funcptr = GGIopen;
+ return 0;
+ case GGIFUNC_exit:
+ case GGIFUNC_close:
+ *funcptr = NULL;
+ return 0;
+ default:
+ *funcptr = NULL;
+ }
+ return GGI_ENOTFOUND;
+}
+
diff --git a/src/mesa/drivers/ggi/default/linear_15.c b/src/mesa/drivers/ggi/default/linear_15.c
new file mode 100644
index 0000000..ead7cc5
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear_15.c
@@ -0,0 +1,36 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+
+#define R 5
+#define G 5
+#define B 5
+
+#define FB_TYPE uint16
+#define FB_BITS 15
+#define DLOPENFUNC MesaGGIdl_linear_15
+
+#include "linear.c"
+
diff --git a/src/mesa/drivers/ggi/default/linear_16.c b/src/mesa/drivers/ggi/default/linear_16.c
new file mode 100644
index 0000000..6028699
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear_16.c
@@ -0,0 +1,36 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+
+#define R 5
+#define G 6
+#define B 5
+
+#define FB_TYPE uint16
+#define FB_BITS 16
+#define DLOPENFUNC MesaGGIdl_linear_16
+
+#include "linear.c"
+
diff --git a/src/mesa/drivers/ggi/default/linear_24.c b/src/mesa/drivers/ggi/default/linear_24.c
new file mode 100644
index 0000000..7a2236f
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear_24.c
@@ -0,0 +1,36 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+
+#define R 8
+#define G 8
+#define B 8
+
+#define FB_TYPE uint32
+#define FB_BITS 24
+#define DLOPENFUNC MesaGGIdl_linear_24
+
+#include "linear.c"
+
diff --git a/src/mesa/drivers/ggi/default/linear_32.c b/src/mesa/drivers/ggi/default/linear_32.c
new file mode 100644
index 0000000..7cbf945
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear_32.c
@@ -0,0 +1,36 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+
+#define R 8
+#define G 8
+#define B 8
+
+#define FB_TYPE uint32
+#define FB_BITS 32
+#define DLOPENFUNC MesaGGIdl_linear_32
+
+#include "linear.c"
+
diff --git a/src/mesa/drivers/ggi/default/linear_8.c b/src/mesa/drivers/ggi/default/linear_8.c
new file mode 100644
index 0000000..9c7b5d7
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/linear_8.c
@@ -0,0 +1,36 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <ggi/mesa/ggimesa.h>
+
+#define R 3
+#define G 3
+#define B 2
+
+#define FB_TYPE uint8
+#define FB_BITS 8
+#define DLOPENFUNC MesaGGIdl_linear_8
+
+#include "linear.c"
+
diff --git a/src/mesa/drivers/ggi/default/stubs.c b/src/mesa/drivers/ggi/default/stubs.c
new file mode 100644
index 0000000..7b442b6
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/stubs.c
@@ -0,0 +1,512 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#include <stdio.h>
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/debug.h>
+
+#include "swrast/swrast.h"
+//#include "swrast_setup/swrast_setup.h"
+//#include "swrast/s_context.h"
+//#include "swrast/s_depth.h"
+//#include "swrast/s_triangle.h"
+
+#define FLIP(coord) (LIBGGI_MODE(ggi_ctx->ggi_visual)->visible.y-(coord)-1)
+
+/**********************************************************************/
+/***** Write spans of pixels *****/
+/**********************************************************************/
+
+void GGIwrite_ci32_span(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint ci[],
+ const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ y = FLIP(y);
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, *ci);
+ x++;
+ ci++;
+ }
+ }
+ else
+ {
+ while (n--)
+ ggiPutPixel(ggi_ctx->ggi_visual, x++, y, *ci++);
+ }
+}
+
+void GGIwrite_ci8_span(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte ci[],
+ const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ y = FLIP(y);
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, *ci);
+ x++;
+ ci++;
+ }
+ }
+ else
+ {
+ while (n--)
+ ggiPutPixel(ggi_ctx->ggi_visual, x++, y, *ci++);
+ }
+}
+
+void GGIwrite_mono_ci_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint ci, const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ y = FLIP(y);
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, ci);
+ x++;
+ }
+ }
+ else
+ {
+ while (n--)
+ ggiPutPixel(ggi_ctx->ggi_visual, x++, y, ci);
+ }
+}
+
+void GGIwrite_mono_rgba_span(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLchan rgba[4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+
+ y = FLIP(y);
+
+ rgb.r = (uint16)(rgba[RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, col);
+ x++;
+ }
+ }
+ else
+ {
+ ggiDrawHLine(ggi_ctx->ggi_visual, x, y, n);
+ }
+}
+
+void GGIwrite_rgba_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+ y = FLIP(y);
+
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ {
+ rgb.r = (uint16)(rgba[0][RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[0][GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[0][BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, col);
+ }
+ x++;
+ rgba++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ rgb.r = (uint16)(rgba[0][RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[0][GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[0][BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiPutPixel(ggi_ctx->ggi_visual, x++, y, col);
+ rgba++;
+ }
+ }
+}
+
+void GGIwrite_rgb_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][3],
+ const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+ y = FLIP(y);
+
+ if (mask)
+ {
+ while (n--) {
+ if (*mask++)
+ {
+ rgb.r = (uint16)(rgba[0][RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[0][GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[0][BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiPutPixel(ggi_ctx->ggi_visual, x, y, col);
+ }
+ x++;
+ rgba++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ rgb.r = (uint16)(rgba[0][RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[0][GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[0][BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiPutPixel(ggi_ctx->ggi_visual, x++, y, col);
+ rgba++;
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Read spans of pixels *****/
+/**********************************************************************/
+
+
+void GGIread_ci32_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint ci[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ y = FLIP(y);
+ while (n--)
+ ggiGetPixel(ggi_ctx->ggi_visual, x++, y, ci++);
+}
+
+void GGIread_rgba_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+
+ y = FLIP(y);
+
+ while (n--)
+ {
+ ggiGetPixel(ggi_ctx->ggi_visual, x++, y, &col);
+ ggiUnmapPixel(ggi_ctx->ggi_visual, col, &rgb);
+ rgba[0][RCOMP] = (GLubyte) (rgb.r >> SHIFT);
+ rgba[0][GCOMP] = (GLubyte) (rgb.g >> SHIFT);
+ rgba[0][BCOMP] = (GLubyte) (rgb.b >> SHIFT);
+ rgba[0][ACOMP] = 0;
+ rgba++;
+ }
+}
+
+/**********************************************************************/
+/***** Write arrays of pixels *****/
+/**********************************************************************/
+
+void GGIwrite_ci32_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint ci[], const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), *ci);
+ ci++;
+ x++;
+ y++;
+ }
+}
+
+void GGIwrite_mono_ci_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint ci, const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), ci);
+ x++;
+ y++;
+ }
+}
+
+void GGIwrite_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_pixel col;
+ ggi_color rgb;
+ while (n--) {
+ if (*mask++) {
+ rgb.r = (uint16)(rgba[0][RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[0][GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[0][BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiPutPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), col);
+ }
+ x++;
+ y++;
+ rgba++;
+ }
+}
+
+void GGIwrite_mono_rgba_pixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLchan rgba[4], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+
+ rgb.r = (uint16)(rgba[RCOMP]) << SHIFT;
+ rgb.g = (uint16)(rgba[GCOMP]) << SHIFT;
+ rgb.b = (uint16)(rgba[BCOMP]) << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+
+ while (n--) {
+ if (*mask++)
+ ggiPutPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), col);
+ x++;
+ y++;
+ }
+}
+
+/**********************************************************************/
+/***** Read arrays of pixels *****/
+/**********************************************************************/
+
+void GGIread_ci32_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint ci[], const GLubyte mask[])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ while (n--) {
+ if (*mask++)
+ ggiGetPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), ci);
+ ci++;
+ x++;
+ y++;
+ }
+}
+
+void GGIread_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+
+ while (n--)
+ {
+ if (*mask++)
+ {
+ ggiGetPixel(ggi_ctx->ggi_visual, *x, FLIP(*y), &col);
+ ggiUnmapPixel(ggi_ctx->ggi_visual, col, &rgb);
+ rgba[0][RCOMP] = rgb.r >> SHIFT;
+ rgba[0][GCOMP] = rgb.g >> SHIFT;
+ rgba[0][BCOMP] = rgb.b >> SHIFT;
+ rgba[0][ACOMP] = 0;
+ }
+ x++;
+ y++;
+ rgba++;
+ }
+}
+
+int GGIextend_visual(ggi_visual_t vis)
+{
+ return 0;
+}
+
+//static swrast_tri_func ggimesa_stubs_get_triangle_func(GLcontext *ctx);
+
+int GGIsetup_driver(ggi_mesa_context_t ggi_ctx)
+{
+ struct swrast_device_driver *swdd =
+ _swrast_GetDeviceDriverReference(ggi_ctx->gl_ctx);
+
+ GGIMESADPRINT_CORE("stubs: setup_driver\n");
+
+ swdd->WriteRGBASpan = GGIwrite_rgba_span;
+ swdd->WriteRGBSpan = GGIwrite_rgb_span;
+ swdd->WriteMonoRGBASpan = GGIwrite_mono_rgba_span;
+ swdd->WriteRGBAPixels = GGIwrite_rgba_pixels;
+ swdd->WriteMonoRGBAPixels = GGIwrite_mono_rgba_pixels;
+
+ swdd->WriteCI32Span = GGIwrite_ci32_span;
+ swdd->WriteCI8Span = GGIwrite_ci8_span;
+ swdd->WriteMonoCISpan = GGIwrite_mono_ci_span;
+ swdd->WriteCI32Pixels = GGIwrite_ci32_pixels;
+ swdd->WriteMonoCIPixels = GGIwrite_mono_ci_pixels;
+
+ swdd->ReadCI32Span = GGIread_ci32_span;
+ swdd->ReadRGBASpan = GGIread_rgba_span;
+ swdd->ReadCI32Pixels = GGIread_ci32_pixels;
+ swdd->ReadRGBAPixels = GGIread_rgba_pixels;
+
+ return 0;
+}
+
+void GGIupdate_state(ggi_mesa_context_t *ctx)
+{
+ //ctx->Driver.TriangleFunc = _swsetup_Triangle;
+}
+
+/*
+void GGItriangle_flat(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2)
+{
+//#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+
+#define SETUP_CODE \
+ ggi_color color; \
+ color.r = v0->color[0]; \
+ color.g = v0->color[1]; \
+ color.b = v0->color[2]; \
+ color.a = v0->color[3]; \
+ ggiSetGCForeground(VIS, ggiMapColor(VIS, &color));
+
+#define INNER_LOOP(LEFT,RIGHT,Y) \
+ ggiDrawHLine(VIS,LEFT,FLIP(Y),RIGHT-LEFT);
+
+#include "swrast/s_tritemp.h"
+}
+
+
+static void GGItriangle_flat_depth(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1, const SWvertex *v2)
+{
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+
+#define SETUP_CODE \
+ ggi_color color; \
+ color.r = v0->color[0]; \
+ color.g = v0->color[1]; \
+ color.b = v0->color[2]; \
+ color.a = v0->color[3]; \
+ ggiSetGCForeground(VIS, ggiMapColor(VIS, &color));
+
+#define INNER_LOOP(LEFT,RIGHT,Y) \
+ { \
+ GLint i,xx=LEFT,yy=FLIP(Y),n=RIGHT-LEFT,length=0; \
+ GLint startx=xx; \
+ for (i=0;i<n;i++){ \
+ GLdepth z=FixedToDepth(ffz); \
+ if (z<zRow[i]) \
+ { \
+ zRow[i]=z; \
+ length++; \
+ } \
+ else \
+ { \
+ if (length) \
+ { \
+ ggiDrawHLine(VIS,startx,yy,length); \
+ length=0; \
+ } \
+ startx=xx+i+1; \
+ } \
+ ffz+=fdzdx; \
+ } \
+ if (length) ggiDrawHLine(VIS,startx,yy,length); \
+ }
+
+#include "swrast/s_tritemp.h"
+}
+
+
+static swrast_tri_func ggimesa_stubs_get_triangle_func(GLcontext *ctx)
+{
+ if (ctx->Stencil.Enabled) return NULL;
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Polygon.StippleFlag) return NULL;
+ if (ctx->Texture._ReallyEnabled) return NULL;
+ if (ctx->Light.ShadeModel==GL_SMOOTH) return NULL;
+ if (ctx->Depth.Test && ctx->Depth.Func != GL_LESS) return NULL;
+
+ if (ctx->Depth.Test)
+ return GGItriangle_flat_depth;
+
+ return GGItriangle_flat;
+}
+*/
+static int GGIopen(ggi_visual_t vis, struct ggi_dlhandle *dlh,
+ const char *args, void *argptr, uint32 *dlret)
+{
+ LIBGGI_MESAEXT(vis)->update_state = GGIupdate_state;
+ LIBGGI_MESAEXT(vis)->setup_driver = GGIsetup_driver;
+
+ *dlret = GGI_DL_OPDRAW;
+ return 0;
+}
+
+int MesaGGIdl_stubs(int func, void **funcptr)
+{
+ switch (func) {
+ case GGIFUNC_open:
+ *funcptr = GGIopen;
+ return 0;
+ case GGIFUNC_exit:
+ case GGIFUNC_close:
+ *funcptr = NULL;
+ return 0;
+ default:
+ *funcptr = NULL;
+ }
+ return GGI_ENOTFOUND;
+}
diff --git a/src/mesa/drivers/ggi/display/fbdev.conf.in b/src/mesa/drivers/ggi/display/fbdev.conf.in
new file mode 100644
index 0000000..2acb894
--- /dev/null
+++ b/src/mesa/drivers/ggi/display/fbdev.conf.in
@@ -0,0 +1,4 @@
+# GGIMesa fbdev target configuration
+.root: @ggi_libdir@/ggi/mesa/default
+
+tgt-fbdev-kgicon-generic-mesa genkgi.so
diff --git a/src/mesa/drivers/ggi/display/fbdev_mode.c b/src/mesa/drivers/ggi/display/fbdev_mode.c
new file mode 100644
index 0000000..85c35ff
--- /dev/null
+++ b/src/mesa/drivers/ggi/display/fbdev_mode.c
@@ -0,0 +1,130 @@
+/******************************************************************************
+
+ display-fbdev-mesa
+
+ Copyright (C) 1999 Jon Taylor [taylorj@ggi-project.org]
+
+ 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.
+
+******************************************************************************
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/fb.h>
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/display_fbdev.h>
+#include <ggi/mesa/debug.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void*)-1)
+#endif
+
+#define FB_KLUDGE_FONTX 8
+#define FB_KLUDGE_FONTY 16
+#define FB_KLUDGE_TEXTMODE 13
+#define TIMINGFILE "/etc/fb.modes"
+
+int GGIMesa_fbdev_getapi(ggi_visual *vis, int num, char *apiname, char *arguments)
+{
+ struct fbdev_priv_mesa *priv = GGIMESA_PRIV(vis);
+
+ arguments = '\0';
+
+ switch(num) {
+ case 0:
+ if (priv->oldpriv->have_accel) {
+ strcpy(apiname, priv->oldpriv->accel);
+ return 0;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+static int do_setmode(ggi_visual *vis)
+{
+ struct fbdev_priv_mesa *priv = GGIMESA_PRIV(vis);
+ int err, id;
+ char libname[GGI_API_MAXLEN], libargs[GGI_API_MAXLEN];
+ ggi_graphtype gt;
+
+ _ggiZapMode(vis, ~GGI_DL_OPDISPLAY);
+ priv->have_accel = 0;
+
+ for (id = 1; GGIMesa_fbdev_getapi(vis, id, libname, libargs) == 0; id++) {
+ if (_ggiOpenDL(vis, libname, libargs, NULL) == 0) {
+ GGIMESADPRINT_LIBS(stderr, "display-fbdev-mesa: Error opening the "
+ "%s (%s) library.\n", libname, libargs);
+ return GGI_EFATAL;
+ }
+
+ GGIMESADPRINT_CORE("Success in loading %s (%s)\n",
+ libname, libargs);
+ }
+
+ if (priv->oldpriv->accel &&
+ _ggiOpenDL(vis, priv->accel, NULL, NULL) != 0) {
+ priv->have_accel = 1;
+ } else {
+ priv->have_accel = 0;
+ }
+ vis->accelactive = 0;
+
+ ggiIndicateChange(vis, GGI_CHG_APILIST);
+
+ GGIMESADPRINT_CORE("display-fbdev-mesa: do_setmode SUCCESS\n");
+
+ return 0;
+}
+
+
+int GGIMesa_fbdev_setmode(ggi_visual *vis, ggi_mode *mode)
+{
+ int err;
+
+ if ((err = ggiCheckMode(vis, mode)) != 0) {
+ return err;
+ }
+
+ GGIMESADPRINT_CORE("display-fbdev-mesa: setmode %dx%d#%dx%dF%d[0x%02x]\n",
+ mode->visible.x, mode->visible.y,
+ mode->virt.x, mode->virt.y,
+ mode->frames, mode->graphtype);
+
+ memcpy(LIBGGI_MODE(vis), mode, sizeof(ggi_mode));
+
+ /* Now actually set the mode */
+ err = do_setmode(vis);
+ if (err != 0) {
+ return err;
+ }
+
+ GGIMESADPRINT_CORE("display-fbdev-mesa: setmode success.\n");
+
+ return 0;
+}
diff --git a/src/mesa/drivers/ggi/display/fbdev_visual.c b/src/mesa/drivers/ggi/display/fbdev_visual.c
new file mode 100644
index 0000000..f0c1771
--- /dev/null
+++ b/src/mesa/drivers/ggi/display/fbdev_visual.c
@@ -0,0 +1,138 @@
+/******************************************************************************
+
+ display-fbdev-mesa: visual handling
+
+ Copyright (C) 1999 Jon Taylor [taylorj@ggi-project.org]
+
+ 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.
+
+******************************************************************************
+*/
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/display_fbdev.h>
+#include <ggi/mesa/debug.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+
+#ifdef HAVE_SYS_VT_H
+#include <sys/vt.h>
+#else
+#include <linux/vt.h>
+#endif
+#ifdef HAVE_LINUX_KDEV_T_H
+#include <linux/kdev_t.h>
+#endif
+#include <linux/tty.h>
+
+#define MAX_DEV_LEN 63
+#define DEFAULT_FBNUM 0
+
+static char accel_prefix[] = "tgt-fbdev-";
+#define PREFIX_LEN (sizeof(accel_prefix))
+
+typedef struct {
+ int async;
+ char *str;
+} accel_info;
+
+static accel_info accel_strings[] = {
+ { 0, "kgicon-generic",}, /* no accel - check for KGIcon */
+ { 0, NULL }, /* Atari Blitter */
+};
+
+#define NUM_ACCELS (sizeof(accel_strings)/sizeof(accel_info))
+
+
+
+static int GGIopen(ggi_visual *vis, struct ggi_dlhandle *dlh,
+ const char *args, void *argptr, uint32 *dlret)
+{
+ int err;
+ struct fbdev_priv_mesa *priv;
+ ggifunc_getapi *oldgetapi;
+
+
+ priv->oldpriv = LIBGGI_PRIVATE(vis); /* Hook back */
+
+ GGIMESA_PRIV(vis) = priv = malloc(sizeof(struct fbdev_priv_mesa));
+ if (priv == NULL) {
+ fprintf(stderr, "GGIMesa: Failed to allocate fbdev private data\n");
+ return GGI_ENOMEM;
+ }
+
+ oldgetapi = vis->opdisplay->getapi;
+ vis->opdisplay->getapi = GGIMesa_fbdev_getapi;
+ changed(vis, GGI_CHG_APILIST);
+
+ /* If the accel sublibs didn't sucessfuly hook a driver,
+ * back up and keep looking */
+ if ((LIBGGI_MESAEXT(vis)->update_state == NULL) ||
+ (LIBGGI_MESAEXT(vis)->setup_driver == NULL))
+ {
+ vis->opdisplay->getapi = oldgetapi;
+ }
+
+ *dlret = GGI_DL_EXTENSION;
+ return 0;
+}
+
+
+static int GGIclose(ggi_visual *vis, struct ggi_dlhandle *dlh)
+{
+ struct fbdev_priv_mesa *priv = GGIMESA_PRIV(vis);
+
+ if (priv) {
+ LIBGGI_PRIVATE(vis) = priv->oldpriv;
+ free(priv);
+ }
+
+ return 0;
+}
+
+
+int MesaGGIdl_fbdev_mesa(int func, void **funcptr)
+{
+ switch (func) {
+ case GGIFUNC_open:
+ *funcptr = GGIopen;
+ return 0;
+ case GGIFUNC_exit:
+ *funcptr = NULL;
+ return 0;
+ case GGIFUNC_close:
+ *funcptr = GGIclose;
+ return 0;
+ default:
+ *funcptr = NULL;
+ }
+
+ return GGI_ENOTFOUND;
+}
+
+
+#include <ggi/internal/ggidlinit.h>
diff --git a/src/mesa/drivers/ggi/ggimesa.c b/src/mesa/drivers/ggi/ggimesa.c
new file mode 100644
index 0000000..cb34c1a
--- /dev/null
+++ b/src/mesa/drivers/ggi/ggimesa.c
@@ -0,0 +1,696 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997-1998 Uwe Maurer - uwe_maurer@t-online.de
+ * 2002 Filip Spacek
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#include <ggi/mesa/ggimesa_int.h>
+#include <ggi/mesa/debug.h>
+#include "extensions.h"
+#include "colormac.h"
+#include "imports.h"
+#include "matrix.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 "array_cache/acache.h"
+#include "teximage.h"
+#include "texformat.h"
+#include "texstore.h"
+
+/* We use LibGG to manage config files */
+#include <ggi/gg.h>
+
+
+/* XXX: Those #defines should be provided via
+ * config.h
+ */
+#define GGIMESAPATHTAG "pAtHTAg"
+#define GGIMESACONFDIR "pAtHTAg/usr/local/etc/ggi"
+#define GGIMESATAGLEN 7
+#define GGIMESACONFFILE "ggimesa.conf"
+
+
+/* Static variables
+ */
+static int _ggimesaLibIsUp = 0;
+static void *_ggimesaConfigHandle;
+static char _ggimesaconfstub[512] = GGIMESACONFDIR;
+static char *_ggimesaconfdir = _ggimesaconfstub+GGIMESATAGLEN;
+
+int _ggimesaDebugSync = 0;
+uint32 _ggimesaDebugState = 0;
+
+
+
+/* Extension ID. Defaulting to -1 should make segfault on abuse more likely...
+ */
+ggi_extid _ggiMesaID = -1;
+
+
+#define SUBLIB_PREFIX "MesaGGIdl_"
+
+
+/*
+ * Returns the directory where global config files are kept
+ */
+
+const char *ggiMesaGetConfDir(void)
+{
+#ifdef __WIN32__
+ /* On Win32 we allow overriding of the compiled in path. */
+ const char *envdir = getenv("GGI_CONFDIR");
+ if (envdir) return envdir;
+#endif
+ return _ggimesaconfdir;
+}
+
+
+/* Dummy function which returns -1
+ We use this to reset the function pointers */
+static int _ggi_error(void)
+{
+ GGIMESADPRINT_CORE("_ggi_error() called\n");
+
+ return -1;
+}
+
+
+static int changed(ggi_visual_t vis, int whatchanged)
+{
+ GLcontext *ctx;
+ ctx = _mesa_get_current_context();
+
+ GGIMESADPRINT_CORE("changed() called\n");
+
+ switch (whatchanged) {
+ case GGI_CHG_APILIST:
+ {
+ char api[GGI_MAX_APILEN];
+ char args[GGI_MAX_APILEN];
+ int i;
+ const char *fname;
+ ggi_dlhandle *lib;
+
+ GLvisual *gl_vis = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ GLframebuffer *gl_fb = &(LIBGGI_MESAEXT(vis)->mesa_buffer);
+
+ /* Initialize the framebuffer to provide all necessary
+ buffers in software. The target libraries that are loaded
+ next are free to modify this according to their
+ capabilities.
+ */
+ /* FIXME: if the target changes capabilities we'll leak
+ swrast's memory !!! Need to deallocate first */
+ _mesa_initialize_framebuffer(gl_fb, gl_vis,
+ gl_vis->depthBits > 0,
+ gl_vis->stencilBits > 0,
+ gl_vis->accumRedBits > 0,
+ gl_vis->alphaBits > 0);
+
+ for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++) {
+ strcat(api, "-mesa");
+ GGIMESADPRINT_CORE("GGIMesa: looking for"
+ "a sublib named %s\n", api);
+ fname = ggMatchConfig(_ggimesaConfigHandle, api, NULL);
+ if (fname == NULL) {
+ /* No special implementation for this sublib */
+ continue;
+ }
+ lib = ggiExtensionLoadDL(vis, fname, args, NULL,
+ SUBLIB_PREFIX);
+ }
+
+ /* The targets have cleared everything they can do from
+ the framebuffer structure so we provide the rest in sw
+ */
+ _swrast_alloc_buffers(gl_fb);
+
+ break;
+ }
+ }
+ return 0;
+}
+
+
+int ggiMesaInit()
+{
+ int err;
+ char *str;
+ char *conffile;
+
+ GGIMESADPRINT_CORE("ggiMesaInit() called\n");
+
+ _ggimesaLibIsUp++;
+ if (_ggimesaLibIsUp > 1) return 0; /* Initialize only at first call */
+
+ str = getenv("GGIMESA_DEBUGSYNC");
+ if (str != NULL) {
+ _ggimesaDebugSync = 1;
+ }
+
+ str = getenv("GGIMESA_DEBUG");
+ if (str != NULL) {
+ _ggimesaDebugState = atoi(str);
+ GGIMESADPRINT_CORE("%s Debugging=%d\n",
+ _ggimesaDebugSync ? "sync" : "async",
+ _ggimesaDebugState);
+ }
+
+
+ conffile = malloc(strlen(ggiMesaGetConfDir()) + 1
+ + strlen(GGIMESACONFFILE) +1);
+ if (conffile == NULL) {
+ fprintf(stderr, "GGIMesa: unable to allocate memory for config filename.\n");
+ return GGI_ENOMEM;
+ }
+ sprintf(conffile, "%s%c%s",
+ ggiMesaGetConfDir(), '/', GGIMESACONFFILE);
+ err = ggLoadConfig(conffile, &_ggimesaConfigHandle);
+ if (err != GGI_OK) {
+ fprintf(stderr, "GGIMesa: Couldn't open %s\n",
+ conffile);
+ free(conffile);
+ _ggimesaLibIsUp--;
+ return err;
+ }
+ free(conffile);
+
+ _ggiMesaID = ggiExtensionRegister("GGIMesa",
+ sizeof(struct ggi_mesa_ext), changed);
+ if (_ggiMesaID < 0) {
+ fprintf(stderr, "GGIMesa: failed to register as extension\n");
+ _ggimesaLibIsUp--;
+ ggFreeConfig(_ggimesaConfigHandle);
+ return _ggiMesaID;
+ }
+
+ return 0;
+}
+
+int ggiMesaExit(void)
+{
+ int rc;
+
+ GGIMESADPRINT_CORE("ggiMesaExit() called\n");
+
+ if (!_ggimesaLibIsUp) return -1;
+
+ if (_ggimesaLibIsUp > 1) {
+ /* Exit only at last call */
+ _ggimesaLibIsUp--;
+ return 0;
+ }
+
+ rc = ggiExtensionUnregister(_ggiMesaID);
+ ggFreeConfig(_ggimesaConfigHandle);
+
+ _ggimesaLibIsUp = 0;
+
+ return rc;
+}
+
+
+
+
+static void gl_ggiUpdateState(GLcontext *ctx, GLuint new_state);
+
+
+static void gl_ggiGetSize(GLframebuffer *fb, GLuint *width, GLuint *height)
+{
+ /* FIXME: this is a hack to work around the new interface */
+ GLcontext *ctx;
+ ggi_mesa_context_t ggi_ctx;
+ ctx = _mesa_get_current_context();
+ ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
+
+ *width = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ *height = LIBGGI_VIRTY(ggi_ctx->ggi_visual);
+ printf("returning %d, %d\n", *width, *height);
+}
+
+static void gl_ggiSetIndex(GLcontext *ctx, GLuint ci)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
+
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ci);
+ ggi_ctx->color = (ggi_pixel)ci;
+}
+
+static void gl_ggiSetClearIndex(GLcontext *ctx, GLuint ci)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
+
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ci);
+ ggi_ctx->clearcolor = (ggi_pixel)ci;
+}
+
+static void gl_ggiSetClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+ ggi_color rgb;
+ ggi_pixel col;
+ GLubyte byteColor[3];
+
+ GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
+
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(byteColor[2], color[2]);
+
+ rgb.r = (uint16)byteColor[0] << SHIFT;
+ rgb.g = (uint16)byteColor[1] << SHIFT;
+ rgb.b = (uint16)byteColor[2] << SHIFT;
+ col = ggiMapColor(ggi_ctx->ggi_visual, &rgb);
+ ggiSetGCForeground(ggi_ctx->ggi_visual, col);
+ ggi_ctx->clearcolor = col;
+}
+
+static void gl_ggiClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiClear() called\n");
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ggi_ctx->clearcolor);
+
+ if (all) {
+ int w, h;
+ w = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ h = LIBGGI_VIRTX(ggi_ctx->ggi_visual);
+ ggiDrawBox(ggi_ctx->ggi_visual, 0, 0, w, h);
+ } else {
+ ggiDrawBox(ggi_ctx->ggi_visual, x, y, //FLIP(y),
+ width, height);
+ }
+ ggiSetGCForeground(ggi_ctx->ggi_visual, ggi_ctx->color);
+
+ mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
+ }
+ _swrast_Clear(ctx, mask, all, x, y, width, height);
+
+}
+
+
+/* Set the buffer used for reading */
+/* XXX support for separate read/draw buffers hasn't been tested */
+static GLboolean gl_ggiSetBuffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ printf("set read %d\n", bufferBit);
+ GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
+
+ if (bufferBit == DD_FRONT_LEFT_BIT)
+ {
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ return GL_TRUE;
+ }
+ else if (bufferBit == DD_BACK_LEFT_BIT)
+ {
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual)?0 : 1);
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual)?0 : 1);
+ return GL_TRUE;
+ }
+ else
+ return GL_FALSE;
+}
+
+
+static const GLubyte * gl_ggiGetString(GLcontext *ctx, GLenum name)
+{
+ GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
+
+ if (name == GL_RENDERER) {
+ return (GLubyte *) "Mesa GGI";
+ } else {
+ return NULL;
+ }
+}
+
+static void gl_ggiFlush(GLcontext *ctx)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
+
+ ggiFlush(ggi_ctx->ggi_visual);
+}
+
+static void gl_ggiIndexMask(GLcontext *ctx, GLuint mask)
+{
+ GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
+}
+
+static void gl_ggiColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
+{
+ GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
+}
+
+static void gl_ggiEnable(GLcontext *ctx, GLenum pname, GLboolean state)
+{
+ GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
+}
+
+static void gl_ggiSetupPointers(GLcontext *ctx)
+{
+ TNLcontext *tnl;
+
+ GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
+
+ /* General information */
+ ctx->Driver.GetString = gl_ggiGetString;
+ ctx->Driver.GetBufferSize = gl_ggiGetSize;
+ ctx->Driver.Finish = gl_ggiFlush;
+ ctx->Driver.Flush = gl_ggiFlush;
+
+ /* Software rasterizer pixel paths */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.Clear = gl_ggiClear;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+ ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
+
+ /* Software texturing */
+ 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.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+ ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+ ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+ ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+ ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+ ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+
+ 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;
+
+ /* Imaging extensions */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ /* State change callbacks */
+ ctx->Driver.ClearIndex = gl_ggiSetClearIndex;
+ ctx->Driver.ClearColor = gl_ggiSetClearColor;
+ ctx->Driver.IndexMask = gl_ggiIndexMask;
+ ctx->Driver.ColorMask = gl_ggiColorMask;
+ ctx->Driver.Enable = gl_ggiEnable;
+
+ ctx->Driver.UpdateState = gl_ggiUpdateState;
+
+ /* Initialize TNL driver interface */
+ tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ /* Install setup for tnl */
+ _swsetup_Wakeup(ctx);
+}
+
+static void get_mode_info(ggi_visual_t vis, int *r, int *g, int *b,
+ GLboolean *rgb, GLboolean *db, int *ci)
+{
+ unsigned int i;
+
+ *r = 0;
+ *g = 0;
+ *b = 0;
+
+ for(i = 0; i < sizeof(ggi_pixel)*8; ++i) {
+ int mask = 1 << i;
+ if (LIBGGI_PIXFMT(vis)->red_mask & mask)
+ ++(*r);
+ if (LIBGGI_PIXFMT(vis)->green_mask & mask)
+ ++(*g);
+ if (LIBGGI_PIXFMT(vis)->blue_mask & mask)
+ ++(*b);
+ }
+
+ *rgb = GT_SCHEME(LIBGGI_MODE(vis)->graphtype) == GT_TRUECOLOR;
+ *db = LIBGGI_MODE(vis)->frames > 1;
+ *ci = GT_SIZE(LIBGGI_MODE(vis)->graphtype);
+
+ printf("rgb (%d, %d, %d) db %d, rgb %d ci %d\n",*r,*g,*b,*db,*rgb,*ci);
+}
+
+
+int ggiMesaAttach(ggi_visual_t vis)
+{
+ int rc;
+
+ GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
+
+ rc = ggiExtensionAttach(vis, _ggiMesaID);
+ if (rc == 0)
+ {
+ int r, g, b, ci;
+ GLboolean rgb, db;
+ GLvisual *gl_visual;
+
+ /* We are creating the primary instance */
+ memset(LIBGGI_MESAEXT(vis), 0, sizeof(struct ggi_mesa_ext));
+ LIBGGI_MESAEXT(vis)->update_state = (void *)_ggi_error;
+ LIBGGI_MESAEXT(vis)->setup_driver = (void *)_ggi_error;
+
+ /* Initialize default mesa visual */
+ get_mode_info(vis, &r, &g, &b, &rgb, &db, &ci);
+ gl_visual = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ _mesa_initialize_visual(gl_visual,
+ rgb, db, 0 /* No stereo */,
+ r, g, b, 0 /* No alpha */, ci,
+ 0 /* No depth */, 0 /* No stencil */,
+ 0, 0, 0, 0 /* No accum */, 0);
+
+ /* Now fake an "API change" so the right libs get loaded */
+ changed(vis, GGI_CHG_APILIST);
+ }
+
+ return rc;
+}
+
+int ggiMesaDetach(ggi_visual_t vis)
+{
+ GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
+
+ return ggiExtensionDetach(vis, _ggiMesaID);
+}
+
+int ggiMesaExtendVisual(ggi_visual_t vis, GLboolean alpha_flag,
+ GLboolean stereo_flag, GLint depth_size,
+ GLint stencil_size, GLint accum_red_size,
+ GLint accum_green_size, GLint accum_blue_size,
+ GLint accum_alpha_size, GLint num_samples)
+{
+ GLvisual *gl_vis = &(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual);
+ int r, g, b, ci;
+ GLboolean db, rgb;
+
+ get_mode_info(vis, &r, &g, &b, &rgb, &db, &ci);
+
+ /* Initialize the visual with the provided information */
+ _mesa_initialize_visual(gl_vis,
+ rgb, db, stereo_flag,
+ r, g, b, 0 /* FIXME */, ci,
+ depth_size, stencil_size,
+ accum_red_size, accum_green_size,
+ accum_blue_size, accum_alpha_size, 0);
+
+ /* Now fake an "API change" so the right libs get loaded. After all,
+ extending the visual by all these new buffers could be considered
+ a "mode change" which requires an "API change".
+ */
+ changed(vis, GGI_CHG_APILIST);
+
+ return 0;
+}
+
+
+ggi_mesa_context_t ggiMesaCreateContext(ggi_visual_t vis)
+{
+ ggi_mesa_context_t ctx;
+ int err;
+
+ GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
+
+ ctx = (ggi_mesa_context_t)malloc(sizeof(struct ggi_mesa_context));
+ if (!ctx)
+ return NULL;
+
+ ctx->ggi_visual = vis;
+ ctx->color = 0;
+
+ ctx->gl_ctx =
+ _mesa_create_context(&(LIBGGI_MESAEXT(vis)->mesa_visual.gl_visual),
+ NULL, (void *) ctx, GL_FALSE);
+ if (!ctx->gl_ctx)
+ goto free_context;
+
+ _mesa_enable_sw_extensions(ctx->gl_ctx);
+
+ _swrast_CreateContext(ctx->gl_ctx);
+ _ac_CreateContext(ctx->gl_ctx);
+ _tnl_CreateContext(ctx->gl_ctx);
+ _swsetup_CreateContext(ctx->gl_ctx);
+
+ gl_ggiSetupPointers(ctx->gl_ctx);
+
+ /* Make sure that an appropriate sublib has been loaded */
+ if (!LIBGGI_MESAEXT(ctx->ggi_visual)->setup_driver){
+ GGIMESADPRINT_CORE("setup_driver==NULL!\n");
+ GGIMESADPRINT_CORE("Please check your config files!\n");
+ goto free_context;
+ }
+
+ /* Set up the sublib driver */
+ err = LIBGGI_MESAEXT(ctx->ggi_visual)->setup_driver(ctx);
+ if (err){
+ GGIMESADPRINT_CORE("setup_driver failed (err = %d)", err);
+ goto free_gl_context;
+ }
+
+ return ctx;
+
+free_gl_context:
+ _mesa_destroy_context(ctx->gl_ctx);
+free_context:
+ free(ctx);
+
+ return NULL;
+}
+
+void ggiMesaDestroyContext(ggi_mesa_context_t ctx)
+{
+ GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
+
+ if(!ctx)
+ return;
+
+ _mesa_destroy_context(ctx->gl_ctx);
+ free(ctx);
+}
+
+void ggiMesaMakeCurrent(ggi_mesa_context_t ctx, ggi_visual_t vis)
+{
+ GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx);
+
+ /* FIXME: clean up where are ggi_vis */
+ if (ctx->ggi_visual != vis) {
+ GGIMESADPRINT_CORE("Cannot migrate GL contexts\n");
+ return;
+ }
+
+ _mesa_make_current(ctx->gl_ctx, &LIBGGI_MESAEXT(vis)->mesa_buffer);
+
+ if (ctx->gl_ctx->Viewport.Width == 0)
+ {
+ _mesa_Viewport(0, 0,
+ LIBGGI_VIRTX(vis),
+ LIBGGI_VIRTY(vis));
+ ctx->gl_ctx->Scissor.Width = LIBGGI_VIRTX(vis);
+ ctx->gl_ctx->Scissor.Height = LIBGGI_VIRTY(vis);
+ }
+}
+
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void ggiMesaSwapBuffers(void)
+{
+ GLcontext *ctx;
+ ggi_mesa_context_t ggi_ctx;
+ ctx = _mesa_get_current_context();
+ ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
+
+ _mesa_notifySwapBuffers(ctx);
+ gl_ggiFlush(ctx);
+
+ ggiSetDisplayFrame(ggi_ctx->ggi_visual,
+ !ggiGetDisplayFrame(ggi_ctx->ggi_visual));
+ ggiSetWriteFrame(ggi_ctx->ggi_visual,
+ !ggiGetWriteFrame(ggi_ctx->ggi_visual));
+ ggiSetReadFrame(ggi_ctx->ggi_visual,
+ !ggiGetReadFrame(ggi_ctx->ggi_visual));
+
+ GGIMESADPRINT_CORE("swap disp: %d, write %d\n",
+ ggiGetDisplayFrame(ggi_ctx->ggi_visual),
+ ggiGetWriteFrame(ggi_ctx->ggi_visual));
+}
+
+static void gl_ggiUpdateState(GLcontext *ctx, GLuint new_state)
+{
+ ggi_mesa_context_t ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx;
+
+ GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
+
+ /* Propogate statechange information to swrast and swrast_setup
+ * modules. The GGI driver has no internal GL-dependent state.
+ */
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /* XXX: Better use an assertion that bails out here on failure */
+ if (!LIBGGI_MESAEXT(ggi_ctx->ggi_visual)->update_state) {
+ GGIMESADPRINT_CORE("update_state == NULL!\n");
+ GGIMESADPRINT_CORE("Please check your config files!\n");
+ ggiPanic("");
+ }
+
+ LIBGGI_MESAEXT(ggi_ctx->ggi_visual)->update_state(ggi_ctx);
+}
+
diff --git a/src/mesa/drivers/ggi/ggimesa.conf.in b/src/mesa/drivers/ggi/ggimesa.conf.in
new file mode 100644
index 0000000..7213233
--- /dev/null
+++ b/src/mesa/drivers/ggi/ggimesa.conf.in
@@ -0,0 +1,13 @@
+# GGIMesa global configuration
+.root: @ggi_libdir@/ggi/mesa
+
+generic-stubs-mesa default/stubs.so
+generic-linear-8-mesa default/linear_8.so
+generic-linear-15-mesa default/linear_15.so
+generic-linear-16-mesa default/linear_16.so
+generic-linear-24-mesa default/linear_24.so
+generic-linear-32-mesa default/linear_32.so
+
+display-fbdev-mesa display/fbdev.so
+
+# .include @ggi_confdir@/ggi/mesa/targets/fbdev.conf
diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/debug.h b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h
new file mode 100644
index 0000000..35d1162
--- /dev/null
+++ b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h
@@ -0,0 +1,260 @@
+/* $Id: debug.h,v 1.5 2003/09/22 15:18:51 brianp Exp $
+******************************************************************************
+
+ GGIMesa debugging macros
+
+ Copyright (C) 1998-1999 Marcus Sundberg [marcus@ggi-project.org]
+ Copyright (C) 1999-2000 Jon Taylor [taylorj@ggi-project.org]
+
+ 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 _GGI_MESA_INTERNAL_DEBUG_H
+#define _GGI_MESA_INTERNAL_DEBUG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ggi/types.h>
+#include <ggi/gg.h>
+
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+__BEGIN_DECLS
+
+/* Exported variables */
+#ifdef BUILDING_GGIMESA
+extern uint32 _ggimesaDebugState;
+extern int _ggimesaDebugSync;
+#else
+IMPORTVAR uint32 _ggimesaDebugState;
+IMPORTVAR int _ggimesaDebugSync;
+#endif
+
+__END_DECLS
+
+
+/* Debugging types
+ * bit 0 is reserved! */
+
+#define GGIMESADEBUG_CORE (1<<1) /* 2 */
+#define GGIMESADEBUG_MODE (1<<2) /* 4 */
+#define GGIMESADEBUG_COLOR (1<<3) /* 8 */
+#define GGIMESADEBUG_DRAW (1<<4) /* 16 */
+#define GGIMESADEBUG_MISC (1<<5) /* 32 */
+#define GGIMESADEBUG_LIBS (1<<6) /* 64 */
+#define GGIMESADEBUG_EVENTS (1<<7) /* 128 */
+
+#define GGIMESADEBUG_ALL 0xffffffff
+
+#ifdef __GNUC__
+
+#ifdef DEBUG
+#define GGIMESADPRINT(args...) if (_ggimesaDebugState) { ggDPrintf(_ggimesaDebugSync, "GGIMesa",args); }
+#define GGIMESADPRINT_CORE(args...) if (_ggimesaDebugState & GGIMESADEBUG_CORE) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_MODE(args...) if (_ggimesaDebugState & GGIMESADEBUG_MODE) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_COLOR(args...) if (_ggimesaDebugState & GGIMESADEBUG_COLOR) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_DRAW(args...) if (_ggimesaDebugState & GGIMESADEBUG_DRAW) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_MISC(args...) if (_ggimesaDebugState & GGIMESADEBUG_MISC) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_LIBS(args...) if (_ggimesaDebugState & GGIMESADEBUG_LIBS) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#define GGIMESADPRINT_EVENTS(args...) if (_ggimesaDebugState & GGIMESADEBUG_EVENTS) { ggDPrintf(_ggimesaDebugSync,"GGIMesa",args); }
+#else /* DEBUG */
+#define GGIMESADPRINT(args...) do{}while(0)
+#define GGIMESADPRINT_CORE(args...) do{}while(0)
+#define GGIMESADPRINT_MODE(args...) do{}while(0)
+#define GGIMESADPRINT_COLOR(args...) do{}while(0)
+#define GGIMESADPRINT_DRAW(args...) do{}while(0)
+#define GGIMESADPRINT_MISC(args...) do{}while(0)
+#define GGIMESADPRINT_LIBS(args...) do{}while(0)
+#define GGIMESADPRINT_EVENTS(args...) do{}while(0)
+#endif /* DEBUG */
+
+#else /* __GNUC__ */
+
+__BEGIN_DECLS
+
+static inline void GGIMESADPRINT(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_CORE(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_CORE) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_MODE(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_MODE) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_COLOR(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_COLOR) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_DRAW(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_DRAW) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_MISC(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_MISC) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_LIBS(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_LIBS) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+static inline void GGIMESADPRINT_EVENTS(const char *form,...)
+{
+#ifdef DEBUG
+ if (_ggiDebugState & GGIDEBUG_EVENTS) {
+ va_list args;
+
+ fprintf(stderr, "GGIMesa: ");
+ va_start(args, form);
+ vfprintf(stderr, form, args);
+ va_end(args);
+ if (_ggimesaDebugSync) fflush(stderr);
+ }
+#endif
+}
+
+__END_DECLS
+
+#endif /* __GNUC__ */
+
+#ifdef DEBUG
+#define GGIMESA_ASSERT(x,str) \
+{ if (!(x)) { \
+ fprintf(stderr,"GGIMESA:%s:%d: INTERNAL ERROR: %s\n",__FILE__,__LINE__,str); \
+ exit(1); \
+} }
+#define GGIMESA_APPASSERT(x,str) \
+{ if (!(x)) { \
+ fprintf(stderr,"GGIMESA:%s:%d: APPLICATION ERROR: %s\n",__FILE__,__LINE__,str); \
+ exit(1); \
+} }
+#else /* DEBUG */
+#define GGIMESA_ASSERT(x,str) do{}while(0)
+#define GGIMESA_APPASSERT(x,str) do{}while(0)
+#endif /* DEBUG */
+
+#ifdef DEBUG
+# define GGIMESAD0(x) x
+#else
+# define GGIMESAD0(x) /* empty */
+#endif
+
+#ifdef GGIMESADLEV
+# if GGIMESADLEV == 1
+# define GGIMESAD1(x) x
+# define GGIMESAD2(x) /* empty */
+# define GGIMESAD3(x) /* empty */
+# elif GGIMESADLEV == 2
+# define GGIMESAD1(x) x
+# define GGIMESAD2(x) x
+# define GGIMESAD3(x) /* empty */
+# elif GGIMESADLEV > 2
+# define GGIMESAD1(x) x
+# define GGIMESAD2(x) x
+# define GGIMESAD3(x) x
+# endif
+#else
+# define GGIMESAD1(x) /* empty */
+# define GGIMESAD2(x) /* empty */
+# define GGIMESAD3(x) /* empty */
+#endif
+
+#endif /* _GGI_MESA_INTERNAL_DEBUG_H */
diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/display_fbdev.h b/src/mesa/drivers/ggi/include/ggi/mesa/display_fbdev.h
new file mode 100644
index 0000000..5c3c1e2
--- /dev/null
+++ b/src/mesa/drivers/ggi/include/ggi/mesa/display_fbdev.h
@@ -0,0 +1,20 @@
+#ifndef _GGIMESA_DISPLAY_FBDEV_H
+#define _GGIMESA_DISPLAY_FBDEV_H
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/display/fbdev.h>
+
+ggifunc_setmode GGIMesa_fbdev_setmode;
+ggifunc_getapi GGIMesa_fbdev_getapi;
+
+#define FBDEV_PRIV_MESA(vis) ((struct fbdev_priv_mesa *)(FBDEV_PRIV(vis)->accelpriv))
+
+struct fbdev_priv_mesa
+{
+ char *accel;
+ int have_accel;
+ void *accelpriv;
+ ggi_fbdev_priv *oldpriv; /* Hooks back to the LibGGI fbdev target's private data */
+};
+
+#endif /* _GGIMESA_DISPLAY_FBDEV_H */
diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa.h b/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa.h
new file mode 100644
index 0000000..ecdbe41
--- /dev/null
+++ b/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa.h
@@ -0,0 +1,84 @@
+/* GGI-Driver for MESA
+ *
+ * Copyright (C) 1997 Uwe Maurer
+ *
+ * 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.
+ * ---------------------------------------------------------------------
+ * This code was derived from the following source of information:
+ *
+ * svgamesa.c and ddsample.c by Brian Paul
+ *
+ */
+
+#ifndef _GGIMESA_H
+#define _GGIMESA_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "config.h"
+#include "context.h"
+#include "drawpix.h"
+#include "imports.h"
+#include "matrix.h"
+#include "state.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "depth.h"
+
+#undef ASSERT /* ASSERT is redefined */
+
+#include <ggi/internal/internal.h>
+#include <ggi/ggi_ext.h>
+#include <ggi/ggi.h>
+#include "GL/ggimesa.h"
+
+/*
+ * GGIMesa visual configuration.
+ *
+ * This structure "derives" from Mesa's GLvisual and extends it by
+ * GGI's visual. Combination of these two structures is enough to fully
+ * describe the mode the application is currently running in. GGI
+ * visual provides information about color configuration and buffering
+ * method, GLvisual fills the rest.
+ */
+struct ggi_mesa_visual {
+ GLvisual gl_visual;
+ ggi_visual_t ggi_visual;
+};
+
+/*
+ * GGIMesa context.
+ *
+ * GGIMesa context expands the Mesa's context (it doesn't actualy derive
+ * from it, but this ability isn't needed, and it is best if GL context
+ * creation is left up to Mesa). It also contains a reference to the GGI
+ * visual it is attached to, which is very useful for all Mesa callbacks.
+ */
+struct ggi_mesa_context
+{
+ GLcontext *gl_ctx;
+ ggi_visual_t ggi_visual;
+
+ ggi_pixel color; /* Current color or index*/
+ ggi_pixel clearcolor;
+
+ void *priv;
+};
+
+#define SHIFT (GGI_COLOR_PRECISION - 8)
+
+#endif
+
diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa_int.h b/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa_int.h
new file mode 100644
index 0000000..faafc77
--- /dev/null
+++ b/src/mesa/drivers/ggi/include/ggi/mesa/ggimesa_int.h
@@ -0,0 +1,44 @@
+#ifndef _GGI_MESA_INT_H
+#define _GGI_MESA_INT_H
+
+#include <ggi/internal/internal.h>
+#include "ggimesa.h"
+
+
+extern ggi_extid _ggiMesaID;
+
+ggifunc_setmode GGIMesa_setmode;
+ggifunc_getapi GGIMesa_getapi;
+
+typedef struct ggi_mesa_ext
+{
+ /*
+ * How mesa extends this visual; i.e., size of the depth buffer etc.
+ *
+ * By default (upon attaching) this structure is initialized to what
+ * libggi is guaranteed to handle without any help: single buffered
+ * visual without any ancilary buffers.
+ */
+ struct ggi_mesa_visual mesa_visual;
+
+ /*
+ * Mesa framebuffer is a collection of all ancilary buffers required.
+ *
+ * This structure contains the ancilary buffers provided in in
+ * software. On each mode change it is loaded with the list of
+ * required buffers and the target is expected to clear the ones
+ * it can provide in hw. The remaining ones are then provided in sw.
+ *
+ */
+ GLframebuffer mesa_buffer;
+
+ void (*update_state)(ggi_mesa_context_t ctx);
+ int (*setup_driver)(ggi_mesa_context_t ctx);
+
+ void *private;
+} ggi_mesa_ext_t;
+
+#define LIBGGI_MESAEXT(vis) ((ggi_mesa_ext_t *)LIBGGI_EXT(vis,_ggiMesaID))
+#define GGIMESA_PRIV(vis) ((LIBGGI_MESAEXT(vis)->priv))
+
+#endif /* _GGI_MISC_INT_H */
diff --git a/src/mesa/drivers/glide/fx.rc b/src/mesa/drivers/glide/fx.rc
new file mode 100644
index 0000000..853e508
--- /dev/null
+++ b/src/mesa/drivers/glide/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.2.0.2"
+#define MANVERSION 6
+#define MANREVISION 2
+#define BUILD_NUMBER 2
+
+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/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c
new file mode 100644
index 0000000..9367b8a
--- /dev/null
+++ b/src/mesa/drivers/glide/fxapi.c
@@ -0,0 +1,946 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+
+/* fxapi.c - public interface to FX/Mesa functions (fxmesa.h) */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "fxdrv.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#ifndef TDFX_DEBUG
+int TDFX_DEBUG = (0
+/* | VERBOSE_VARRAY */
+/* | VERBOSE_TEXTURE */
+/* | VERBOSE_IMMEDIATE */
+/* | VERBOSE_PIPELINE */
+/* | VERBOSE_DRIVER */
+/* | VERBOSE_STATE */
+/* | VERBOSE_API */
+/* | VERBOSE_DISPLAY_LIST */
+/* | VERBOSE_LIGHTING */
+/* | VERBOSE_PRIMS */
+/* | VERBOSE_VERTS */
+ );
+#endif
+
+static fxMesaContext fxMesaCurrentCtx = NULL;
+
+/*
+ * Status of 3Dfx hardware initialization
+ */
+
+static int glbGlideInitialized = 0;
+static int glb3DfxPresent = 0;
+static int glbTotNumCtx = 0;
+
+static GrHwConfiguration glbHWConfig;
+static int glbCurrentBoard = 0;
+
+
+#if defined(__WIN32__)
+static int
+cleangraphics(void)
+{
+ glbTotNumCtx = 1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+
+ return 0;
+}
+#elif defined(__linux__)
+static void
+cleangraphics(void)
+{
+ glbTotNumCtx = 1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+}
+
+static void
+cleangraphics_handler(int s)
+{
+ fprintf(stderr, "fxmesa: ERROR: received a not handled signal %d\n", s);
+
+ cleangraphics();
+/* abort(); */
+ exit(1);
+}
+#endif
+
+
+/*
+ * Query 3Dfx hardware presence/kind
+ */
+static GLboolean GLAPIENTRY fxQueryHardware (void)
+{
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxQueryHardware()\n");
+ }
+
+ if (!glbGlideInitialized) {
+ grGlideInit();
+ glb3DfxPresent = FX_grSstQueryHardware(&glbHWConfig);
+
+ glbGlideInitialized = 1;
+
+#if defined(__WIN32__)
+ _onexit((_onexit_t) cleangraphics);
+#elif defined(__linux__)
+ /* Only register handler if environment variable is not defined. */
+ if (!getenv("MESA_FX_NO_SIGNALS")) {
+ atexit(cleangraphics);
+ }
+#endif
+ }
+
+ return glb3DfxPresent;
+}
+
+
+/*
+ * Select the Voodoo board to use when creating
+ * a new context.
+ */
+GLint GLAPIENTRY fxMesaSelectCurrentBoard (int n)
+{
+ fxQueryHardware();
+
+ if ((n < 0) || (n >= glbHWConfig.num_sst))
+ return -1;
+
+ return glbHWConfig.SSTs[glbCurrentBoard = n].type;
+}
+
+
+fxMesaContext GLAPIENTRY fxMesaGetCurrentContext (void)
+{
+ return fxMesaCurrentCtx;
+}
+
+
+void GLAPIENTRY fxGetScreenGeometry (GLint *w, GLint *h)
+{
+ GLint width = 0;
+ GLint height = 0;
+
+ if (fxMesaCurrentCtx != NULL) {
+ width = fxMesaCurrentCtx->screen_width;
+ height = fxMesaCurrentCtx->screen_height;
+ }
+
+ if (w != NULL) {
+ *w = width;
+ }
+ if (h != NULL) {
+ *h = height;
+ }
+}
+
+
+/*
+ * The 3Dfx Global Palette extension for GLQuake.
+ * More a trick than a real extesion, use the shared global
+ * palette extension.
+ */
+extern void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint * pal); /* silence warning */
+void GLAPIENTRY
+gl3DfxSetPaletteEXT(GLuint * pal)
+{
+ fxMesaContext fxMesa = fxMesaCurrentCtx;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ int i;
+
+ fprintf(stderr, "gl3DfxSetPaletteEXT(...)\n");
+
+ for (i = 0; i < 256; i++) {
+ fprintf(stderr, "\t%x\n", pal[i]);
+ }
+ }
+
+ if (fxMesa) {
+ fxMesa->haveGlobalPaletteTexture = 1;
+
+ grTexDownloadTable(GR_TEXTABLE_PALETTE, (GuTexPalette *) pal);
+ }
+}
+
+
+static GrScreenResolution_t fxBestResolution (int width, int height)
+{
+ static const int resolutions[][3] = {
+ { GR_RESOLUTION_320x200, 320, 200 },
+ { GR_RESOLUTION_320x240, 320, 240 },
+ { GR_RESOLUTION_400x256, 400, 256 },
+ { GR_RESOLUTION_512x384, 512, 384 },
+ { GR_RESOLUTION_640x200, 640, 200 },
+ { GR_RESOLUTION_640x350, 640, 350 },
+ { GR_RESOLUTION_640x400, 640, 400 },
+ { GR_RESOLUTION_640x480, 640, 480 },
+ { GR_RESOLUTION_800x600, 800, 600 },
+ { GR_RESOLUTION_960x720, 960, 720 },
+ { GR_RESOLUTION_856x480, 856, 480 },
+ { GR_RESOLUTION_512x256, 512, 256 },
+ { GR_RESOLUTION_1024x768, 1024, 768 },
+ { GR_RESOLUTION_1280x1024, 1280, 1024 },
+ { GR_RESOLUTION_1600x1200, 1600, 1200 },
+ { GR_RESOLUTION_400x300, 400, 300 },
+ { GR_RESOLUTION_1152x864, 1152, 864 },
+ { GR_RESOLUTION_1280x960, 1280, 960 },
+ { GR_RESOLUTION_1600x1024, 1600, 1024 },
+ { GR_RESOLUTION_1792x1344, 1792, 1344 },
+ { GR_RESOLUTION_1856x1392, 1856, 1392 },
+ { GR_RESOLUTION_1920x1440, 1920, 1440 },
+ { GR_RESOLUTION_2048x1536, 2048, 1536 },
+ { GR_RESOLUTION_2048x2048, 2048, 2048 }
+ };
+
+ int i, size;
+ int lastvalidres = GR_RESOLUTION_640x480;
+ int min = 2048 * 2048; /* max is GR_RESOLUTION_2048x2048 */
+ GrResolution resTemplate = {
+ GR_QUERY_ANY,
+ GR_QUERY_ANY,
+ 2 /*GR_QUERY_ANY */,
+ GR_QUERY_ANY
+ };
+ GrResolution *presSupported;
+
+ if (!fxQueryHardware()) {
+ return lastvalidres;
+ }
+
+ size = grQueryResolutions(&resTemplate, NULL);
+ presSupported = malloc(size);
+
+ size /= sizeof(GrResolution);
+ grQueryResolutions(&resTemplate, presSupported);
+
+ for (i = 0; i < size; i++) {
+ int r = presSupported[i].resolution;
+ if ((width <= resolutions[r][1]) && (height <= resolutions[r][2])) {
+ if (min > (resolutions[r][1] * resolutions[r][2])) {
+ min = resolutions[r][1] * resolutions[r][2];
+ lastvalidres = r;
+ }
+ }
+ }
+
+ free(presSupported);
+
+ return resolutions[lastvalidres][0];
+}
+
+
+fxMesaContext GLAPIENTRY
+fxMesaCreateBestContext(GLuint win, GLint width, GLint height,
+ const GLint attribList[])
+{
+ /* fxMesaCreateContext() handles fxQueryHardware() error returns */
+ int res = fxBestResolution(width, height);
+ return fxMesaCreateContext(win, res, GR_REFRESH_60Hz, attribList);
+}
+
+
+/*
+ * Create a new FX/Mesa context and return a handle to it.
+ */
+fxMesaContext GLAPIENTRY
+fxMesaCreateContext(GLuint win,
+ GrScreenResolution_t res,
+ GrScreenRefresh_t ref, const GLint attribList[])
+{
+ fxMesaContext fxMesa = NULL;
+ GLcontext *ctx = NULL, *shareCtx = NULL;
+ struct dd_function_table functions;
+
+ int i;
+ const char *str;
+ int sliaa, numSLI, samplesPerChip;
+ struct SstCard_St *voodoo;
+ struct tdfx_glide *Glide;
+
+ GLboolean aux;
+ GLboolean doubleBuffer;
+ GLuint colDepth;
+ GLuint depthSize, alphaSize, stencilSize, accumSize;
+ GLuint redBits, greenBits, blueBits, alphaBits;
+ GrPixelFormat_t pixFmt;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaCreateContext(...)\n");
+ }
+
+ /* Okay, first process the user flags */
+ aux = GL_FALSE;
+ doubleBuffer = GL_FALSE;
+ colDepth = 16;
+ depthSize = alphaSize = stencilSize = accumSize = 0;
+
+ i = 0;
+ while (attribList[i] != FXMESA_NONE) {
+ switch (attribList[i]) {
+ case FXMESA_COLORDEPTH:
+ colDepth = attribList[++i];
+ break;
+ case FXMESA_DOUBLEBUFFER:
+ doubleBuffer = GL_TRUE;
+ break;
+ case FXMESA_ALPHA_SIZE:
+ if ((alphaSize = attribList[++i])) {
+ aux = GL_TRUE;
+ }
+ break;
+ case FXMESA_DEPTH_SIZE:
+ if ((depthSize = attribList[++i])) {
+ aux = GL_TRUE;
+ }
+ break;
+ case FXMESA_STENCIL_SIZE:
+ stencilSize = attribList[++i];
+ break;
+ case FXMESA_ACCUM_SIZE:
+ accumSize = attribList[++i];
+ break;
+ /* XXX ugly hack here for sharing display lists */
+ case FXMESA_SHARE_CONTEXT:
+ shareCtx = (GLcontext *)attribList[++i];
+ break;
+ default:
+ fprintf(stderr, "fxMesaCreateContext: ERROR: wrong parameter (%d) passed\n", attribList[i]);
+ return NULL;
+ }
+ i++;
+ }
+
+ if (!fxQueryHardware()) {
+ str = "no Voodoo hardware!";
+ goto errorhandler;
+ }
+
+ grSstSelect(glbCurrentBoard);
+ /*grEnable(GR_OPENGL_MODE_EXT);*/ /* [koolsmoky] */
+ voodoo = &glbHWConfig.SSTs[glbCurrentBoard];
+
+ fxMesa = (fxMesaContext)CALLOC_STRUCT(tfxMesaContext);
+ if (!fxMesa) {
+ str = "private context";
+ goto errorhandler;
+ }
+
+ if (getenv("MESA_FX_INFO")) {
+ fxMesa->verbose = GL_TRUE;
+ }
+
+ fxMesa->type = voodoo->type;
+ fxMesa->HavePalExt = voodoo->HavePalExt && !getenv("MESA_FX_IGNORE_PALEXT");
+ fxMesa->HavePixExt = voodoo->HavePixExt && !getenv("MESA_FX_IGNORE_PIXEXT");
+ fxMesa->HaveTexFmt = voodoo->HaveTexFmt && !getenv("MESA_FX_IGNORE_TEXFMT");
+ fxMesa->HaveCmbExt = voodoo->HaveCmbExt && !getenv("MESA_FX_IGNORE_CMBEXT");
+ fxMesa->HaveMirExt = voodoo->HaveMirExt && !getenv("MESA_FX_IGNORE_MIREXT");
+ fxMesa->HaveTexUma = voodoo->HaveTexUma && !getenv("MESA_FX_IGNORE_TEXUMA");
+ fxMesa->Glide = glbHWConfig.Glide;
+ Glide = &fxMesa->Glide;
+ fxMesa->HaveTexus2 = Glide->txImgQuantize &&
+ Glide->txMipQuantize &&
+ Glide->txPalToNcc && !getenv("MESA_FX_IGNORE_TEXUS2");
+
+ /* Determine if we need vertex swapping, RGB order and SLI/AA */
+ sliaa = 0;
+ switch (fxMesa->type) {
+ case GR_SSTTYPE_VOODOO:
+ case GR_SSTTYPE_SST96:
+ case GR_SSTTYPE_Banshee:
+ fxMesa->bgrOrder = GL_TRUE;
+ fxMesa->snapVertices = (getenv("MESA_FX_NOSNAP") == NULL);
+ break;
+ case GR_SSTTYPE_Voodoo2:
+ fxMesa->bgrOrder = GL_TRUE;
+ fxMesa->snapVertices = GL_FALSE;
+ break;
+ case GR_SSTTYPE_Voodoo4:
+ case GR_SSTTYPE_Voodoo5:
+ /* number of SLI units and AA Samples per chip */
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("SSTH3_SLI_AA_CONFIGURATION")) != NULL) {
+ sliaa = atoi(str);
+ }
+ case GR_SSTTYPE_Voodoo3:
+ default:
+ fxMesa->bgrOrder = GL_FALSE;
+ fxMesa->snapVertices = GL_FALSE;
+ break;
+ }
+ /* XXX todo - Add the old SLI/AA settings for Napalm. */
+ switch(voodoo->numChips) {
+ case 4: /* 4 chips */
+ switch(sliaa) {
+ case 8: /* 8 Sample AA */
+ numSLI = 1;
+ samplesPerChip = 2;
+ break;
+ case 7: /* 4 Sample AA */
+ numSLI = 1;
+ samplesPerChip = 1;
+ break;
+ case 6: /* 2 Sample AA */
+ numSLI = 2;
+ samplesPerChip = 1;
+ break;
+ default:
+ numSLI = 4;
+ samplesPerChip = 1;
+ }
+ break;
+ case 2: /* 2 chips */
+ switch(sliaa) {
+ case 4: /* 4 Sample AA */
+ numSLI = 1;
+ samplesPerChip = 2;
+ break;
+ case 3: /* 2 Sample AA */
+ numSLI = 1;
+ samplesPerChip = 1;
+ break;
+ default:
+ numSLI = 2;
+ samplesPerChip = 1;
+ }
+ break;
+ default: /* 1 chip */
+ switch(sliaa) {
+ case 1: /* 2 Sample AA */
+ numSLI = 1;
+ samplesPerChip = 2;
+ break;
+ default:
+ numSLI = 1;
+ samplesPerChip = 1;
+ }
+ }
+
+ fxMesa->fsaa = samplesPerChip * voodoo->numChips / numSLI; /* 1:noFSAA, 2:2xFSAA, 4:4xFSAA, 8:8xFSAA */
+
+ switch (fxMesa->colDepth = colDepth) {
+ case 15:
+ redBits = 5;
+ greenBits = 5;
+ blueBits = 5;
+ alphaBits = depthSize ? 1 : 8;
+ switch(fxMesa->fsaa) {
+ case 8:
+ pixFmt = GR_PIXFMT_AA_8_ARGB_1555;
+ break;
+ case 4:
+ pixFmt = GR_PIXFMT_AA_4_ARGB_1555;
+ break;
+ case 2:
+ pixFmt = GR_PIXFMT_AA_2_ARGB_1555;
+ break;
+ default:
+ pixFmt = GR_PIXFMT_ARGB_1555;
+ }
+ break;
+ case 16:
+ redBits = 5;
+ greenBits = 6;
+ blueBits = 5;
+ alphaBits = depthSize ? 0 : 8;
+ switch(fxMesa->fsaa) {
+ case 8:
+ pixFmt = GR_PIXFMT_AA_8_RGB_565;
+ break;
+ case 4:
+ pixFmt = GR_PIXFMT_AA_4_RGB_565;
+ break;
+ case 2:
+ pixFmt = GR_PIXFMT_AA_2_RGB_565;
+ break;
+ default:
+ pixFmt = GR_PIXFMT_RGB_565;
+ }
+ break;
+ case 24:
+ fxMesa->colDepth = 32;
+ case 32:
+ redBits = 8;
+ greenBits = 8;
+ blueBits = 8;
+ alphaBits = 8;
+ switch(fxMesa->fsaa) {
+ case 8:
+ pixFmt = GR_PIXFMT_AA_8_ARGB_8888;
+ break;
+ case 4:
+ pixFmt = GR_PIXFMT_AA_4_ARGB_8888;
+ break;
+ case 2:
+ pixFmt = GR_PIXFMT_AA_2_ARGB_8888;
+ break;
+ default:
+ pixFmt = GR_PIXFMT_ARGB_8888;
+ }
+ break;
+ default:
+ str = "pixelFormat";
+ goto errorhandler;
+ }
+
+ /* Tips:
+ * 1. we don't bother setting/checking AUX for stencil, because we'll decide
+ * later whether we have HW stencil, based on depth buffer (thus AUX is
+ * properly set)
+ * 2. when both DEPTH and ALPHA are enabled, depth should win. However, it is
+ * not clear whether 15bpp and 32bpp require AUX alpha buffer. Furthermore,
+ * 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.
+ * 3. `alphaBits' is what we can provide
+ * `alphaSize' is what app requests
+ * if we cannot provide enough bits for alpha buffer, we should fallback to
+ * SW alpha. However, setting `alphaBits' to `alphaSize' might confuse some
+ * of the span functions...
+ */
+
+ fxMesa->haveHwAlpha = GL_FALSE;
+ if (alphaSize && (alphaSize <= alphaBits)) {
+ alphaSize = alphaBits;
+ fxMesa->haveHwAlpha = GL_TRUE;
+ }
+
+ fxMesa->haveHwStencil = (fxMesa->HavePixExt && stencilSize && depthSize == 24);
+
+ fxMesa->haveZBuffer = depthSize > 0;
+ fxMesa->haveDoubleBuffer = doubleBuffer;
+ fxMesa->haveGlobalPaletteTexture = GL_FALSE;
+ fxMesa->board = glbCurrentBoard;
+
+ fxMesa->haveTwoTMUs = (voodoo->nTexelfx > 1);
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_NUM_TMU"))) {
+ if (atoi(str) <= 1) {
+ fxMesa->haveTwoTMUs = GL_FALSE;
+ }
+ }
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPPENDINGCOUNT"))) {
+ fxMesa->maxPendingSwapBuffers = atoi(str);
+ if (fxMesa->maxPendingSwapBuffers > 6) {
+ fxMesa->maxPendingSwapBuffers = 6;
+ } else if (fxMesa->maxPendingSwapBuffers < 0) {
+ fxMesa->maxPendingSwapBuffers = 0;
+ }
+ } else {
+ fxMesa->maxPendingSwapBuffers = 2;
+ }
+
+ if ((str = Glide->grGetRegistryOrEnvironmentStringExt("FX_GLIDE_SWAPINTERVAL"))) {
+ fxMesa->swapInterval = atoi(str);
+ } else {
+ fxMesa->swapInterval = 0;
+ }
+
+ BEGIN_BOARD_LOCK();
+ if (fxMesa->HavePixExt) {
+ fxMesa->glideContext = Glide->grSstWinOpenExt((FxU32)win, res, ref,
+ GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
+ pixFmt,
+ 2, aux);
+ } else if (pixFmt == GR_PIXFMT_RGB_565) {
+ fxMesa->glideContext = grSstWinOpen((FxU32)win, res, ref,
+ GR_COLORFORMAT_ABGR, GR_ORIGIN_LOWER_LEFT,
+ 2, aux);
+ } else {
+ fxMesa->glideContext = 0;
+ }
+ END_BOARD_LOCK();
+ if (!fxMesa->glideContext) {
+ str = "grSstWinOpen";
+ goto errorhandler;
+ }
+
+ /* screen */
+ fxMesa->screen_width = FX_grSstScreenWidth();
+ fxMesa->screen_height = FX_grSstScreenHeight();
+
+ /* window inside screen */
+ fxMesa->width = fxMesa->screen_width;
+ fxMesa->height = fxMesa->screen_height;
+
+ /* scissor inside window */
+ fxMesa->clipMinX = 0;
+ fxMesa->clipMaxX = fxMesa->width;
+ fxMesa->clipMinY = 0;
+ fxMesa->clipMaxY = fxMesa->height;
+
+ if (fxMesa->verbose) {
+ FxI32 tmuRam, fbRam;
+
+ /* Not that it matters, but tmuRam and fbRam change after grSstWinOpen. */
+ tmuRam = voodoo->tmuConfig[GR_TMU0].tmuRam;
+ fbRam = voodoo->fbRam;
+ BEGIN_BOARD_LOCK();
+ grGet(GR_MEMORY_TMU, 4, &tmuRam);
+ grGet(GR_MEMORY_FB, 4, &fbRam);
+ END_BOARD_LOCK();
+
+ fprintf(stderr, "Voodoo Using Glide %s\n", grGetString(GR_VERSION));
+ fprintf(stderr, "Voodoo Board: %d/%d, %s, %d GPU\n",
+ fxMesa->board + 1,
+ glbHWConfig.num_sst,
+ grGetString(GR_HARDWARE),
+ voodoo->numChips);
+ fprintf(stderr, "Voodoo Memory: FB = %ld, TM = %d x %ld\n",
+ fbRam,
+ voodoo->nTexelfx,
+ tmuRam);
+ fprintf(stderr, "Voodoo Screen: %dx%d:%d %s, %svertex snapping\n",
+ fxMesa->screen_width,
+ fxMesa->screen_height,
+ colDepth,
+ fxMesa->bgrOrder ? "BGR" : "RGB",
+ fxMesa->snapVertices ? "" : "no ");
+ }
+
+ sprintf(fxMesa->rendererString, "Mesa %s v0.62 %s%s",
+ grGetString(GR_RENDERER),
+ grGetString(GR_HARDWARE),
+ ((fxMesa->type < GR_SSTTYPE_Voodoo4) && (voodoo->numChips > 1)) ? " SLI" : "");
+
+ fxMesa->glVis = _mesa_create_visual(GL_TRUE, /* RGB mode */
+ doubleBuffer,
+ GL_FALSE, /* stereo */
+ redBits, /* RGBA.R bits */
+ greenBits, /* RGBA.G bits */
+ blueBits, /* RGBA.B bits */
+ alphaSize, /* RGBA.A bits */
+ 0, /* index bits */
+ depthSize, /* depth_size */
+ stencilSize, /* stencil_size */
+ accumSize,
+ accumSize,
+ accumSize,
+ alphaSize ? accumSize : 0,
+ 1);
+ if (!fxMesa->glVis) {
+ str = "_mesa_create_visual";
+ goto errorhandler;
+ }
+
+ _mesa_init_driver_functions(&functions);
+ ctx = fxMesa->glCtx = _mesa_create_context(fxMesa->glVis, shareCtx,
+ &functions, (void *) fxMesa);
+ if (!ctx) {
+ str = "_mesa_create_context";
+ goto errorhandler;
+ }
+
+
+ if (!fxDDInitFxMesaContext(fxMesa)) {
+ str = "fxDDInitFxMesaContext";
+ goto errorhandler;
+ }
+
+
+ fxMesa->glBuffer = _mesa_create_framebuffer(fxMesa->glVis,
+ GL_FALSE, /* no software depth */
+ stencilSize && !fxMesa->haveHwStencil,
+ fxMesa->glVis->accumRedBits > 0,
+ alphaSize && !fxMesa->haveHwAlpha);
+ if (!fxMesa->glBuffer) {
+ str = "_mesa_create_framebuffer";
+ goto errorhandler;
+ }
+
+ glbTotNumCtx++;
+
+ /* install signal handlers */
+#if defined(__linux__)
+ /* Only install if environment var. is not set. */
+ if (!getenv("MESA_FX_NO_SIGNALS")) {
+ signal(SIGINT, cleangraphics_handler);
+ signal(SIGHUP, cleangraphics_handler);
+ signal(SIGPIPE, cleangraphics_handler);
+ signal(SIGFPE, cleangraphics_handler);
+ signal(SIGBUS, cleangraphics_handler);
+ signal(SIGILL, cleangraphics_handler);
+ signal(SIGSEGV, cleangraphics_handler);
+ signal(SIGTERM, cleangraphics_handler);
+ }
+#endif
+
+ return fxMesa;
+
+errorhandler:
+ if (fxMesa) {
+ if (fxMesa->glideContext) {
+ grSstWinClose(fxMesa->glideContext);
+ fxMesa->glideContext = 0;
+ }
+
+ if (fxMesa->state) {
+ FREE(fxMesa->state);
+ }
+ if (fxMesa->fogTable) {
+ FREE(fxMesa->fogTable);
+ }
+ if (fxMesa->glBuffer) {
+ _mesa_destroy_framebuffer(fxMesa->glBuffer);
+ }
+ if (fxMesa->glVis) {
+ _mesa_destroy_visual(fxMesa->glVis);
+ }
+ if (fxMesa->glCtx) {
+ _mesa_destroy_context(fxMesa->glCtx);
+ }
+ FREE(fxMesa);
+ }
+
+ fprintf(stderr, "fxMesaCreateContext: ERROR: %s\n", str);
+ return NULL;
+}
+
+
+/*
+ * Function to set the new window size in the context (mainly for the Voodoo Rush)
+ */
+void GLAPIENTRY
+fxMesaUpdateScreenSize(fxMesaContext fxMesa)
+{
+ fxMesa->width = FX_grSstScreenWidth();
+ fxMesa->height = FX_grSstScreenHeight();
+}
+
+
+/*
+ * Destroy the given FX/Mesa context.
+ */
+void GLAPIENTRY
+fxMesaDestroyContext(fxMesaContext fxMesa)
+{
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaDestroyContext(...)\n");
+ }
+
+ if (!fxMesa)
+ return;
+
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Misc Stats:\n");
+ fprintf(stderr, " # swap buffer: %u\n", fxMesa->stats.swapBuffer);
+
+ if (!fxMesa->stats.swapBuffer)
+ fxMesa->stats.swapBuffer = 1;
+
+ fprintf(stderr, "Textures Stats:\n");
+ fprintf(stderr, " Free texture memory on TMU0: %d\n",
+ fxMesa->freeTexMem[FX_TMU0]);
+ if (fxMesa->haveTwoTMUs)
+ fprintf(stderr, " Free texture memory on TMU1: %d\n",
+ fxMesa->freeTexMem[FX_TMU1]);
+ fprintf(stderr, " # request to TMM to upload a texture objects: %u\n",
+ fxMesa->stats.reqTexUpload);
+ fprintf(stderr,
+ " # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
+ fxMesa->stats.reqTexUpload / (float) fxMesa->stats.swapBuffer);
+ fprintf(stderr, " # texture objects uploaded: %u\n",
+ fxMesa->stats.texUpload);
+ fprintf(stderr, " # texture objects uploaded per swapbuffer: %.2f\n",
+ fxMesa->stats.texUpload / (float) fxMesa->stats.swapBuffer);
+ fprintf(stderr, " # MBs uploaded to texture memory: %.2f\n",
+ fxMesa->stats.memTexUpload / (float) (1 << 20));
+ fprintf(stderr,
+ " # MBs uploaded to texture memory per swapbuffer: %.2f\n",
+ (fxMesa->stats.memTexUpload /
+ (float) fxMesa->stats.swapBuffer) / (float) (1 << 20));
+ }
+
+ glbTotNumCtx--;
+
+ if (!glbTotNumCtx && getenv("MESA_FX_INFO")) {
+ GrSstPerfStats_t st;
+
+ FX_grSstPerfStats(&st);
+
+ fprintf(stderr, "Pixels Stats:\n");
+ fprintf(stderr, " # pixels processed (minus buffer clears): %u\n",
+ (unsigned) st.pixelsIn);
+ fprintf(stderr, " # pixels not drawn due to chroma key test failure: %u\n",
+ (unsigned) st.chromaFail);
+ fprintf(stderr, " # pixels not drawn due to depth test failure: %u\n",
+ (unsigned) st.zFuncFail);
+ fprintf(stderr,
+ " # pixels not drawn due to alpha test failure: %u\n",
+ (unsigned) st.aFuncFail);
+ fprintf(stderr, " # pixels drawn (including buffer clears and LFB writes): %u\n",
+ (unsigned) st.pixelsOut);
+ }
+
+ /* close the hardware first,
+ * so we can debug atexit problems (memory leaks, etc).
+ */
+ grSstWinClose(fxMesa->glideContext);
+ fxCloseHardware();
+
+ fxDDDestroyFxMesaContext(fxMesa); /* must be before _mesa_destroy_context */
+ _mesa_destroy_visual(fxMesa->glVis);
+ _mesa_destroy_context(fxMesa->glCtx);
+ _mesa_destroy_framebuffer(fxMesa->glBuffer);
+ fxTMClose(fxMesa); /* must be after _mesa_destroy_context */
+
+ FREE(fxMesa);
+
+ if (fxMesa == fxMesaCurrentCtx)
+ fxMesaCurrentCtx = NULL;
+}
+
+
+/*
+ * Make the specified FX/Mesa context the current one.
+ */
+void GLAPIENTRY
+fxMesaMakeCurrent(fxMesaContext fxMesa)
+{
+ if (!fxMesa) {
+ _mesa_make_current(NULL, NULL);
+ fxMesaCurrentCtx = NULL;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaMakeCurrent(NULL)\n");
+ }
+
+ return;
+ }
+
+ /* if this context is already the current one, we can return early */
+ if (fxMesaCurrentCtx == fxMesa
+ && fxMesaCurrentCtx->glCtx == _mesa_get_current_context()) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaMakeCurrent(NOP)\n");
+ }
+
+ return;
+ }
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaMakeCurrent(...)\n");
+ }
+
+ if (fxMesaCurrentCtx)
+ grGlideGetState((GrState *) fxMesaCurrentCtx->state);
+
+ fxMesaCurrentCtx = fxMesa;
+
+ grSstSelect(fxMesa->board);
+ grGlideSetState((GrState *) fxMesa->state);
+
+ _mesa_make_current(fxMesa->glCtx, fxMesa->glBuffer);
+
+ fxSetupDDPointers(fxMesa->glCtx);
+
+ /* The first time we call MakeCurrent we set the initial viewport size */
+ if (fxMesa->glCtx->Viewport.Width == 0)
+ _mesa_set_viewport(fxMesa->glCtx, 0, 0, fxMesa->width, fxMesa->height);
+}
+
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void GLAPIENTRY
+fxMesaSwapBuffers(void)
+{
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxMesaSwapBuffers()\n");
+ }
+
+ if (fxMesaCurrentCtx) {
+ _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx);
+
+ if (fxMesaCurrentCtx->haveDoubleBuffer) {
+
+ grBufferSwap(fxMesaCurrentCtx->swapInterval);
+
+#if 0
+ /*
+ * Don't allow swap buffer commands to build up!
+ */
+ while (FX_grGetInteger(GR_PENDING_BUFFERSWAPS) >
+ fxMesaCurrentCtx->maxPendingSwapBuffers)
+ /* The driver is able to sleep when waiting for the completation
+ of multiple swapbuffer operations instead of wasting
+ CPU time (NOTE: you must uncomment the following line in the
+ in order to enable this option) */
+ /* usleep(10000); */
+ ;
+#endif
+
+ fxMesaCurrentCtx->stats.swapBuffer++;
+ }
+ }
+}
+
+
+/*
+ * Shutdown Glide library
+ */
+void GLAPIENTRY
+fxCloseHardware(void)
+{
+ if (glbGlideInitialized) {
+ if (glbTotNumCtx == 0) {
+ grGlideShutdown();
+ glbGlideInitialized = 0;
+ }
+ }
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+extern int gl_fx_dummy_function_api(void);
+int
+gl_fx_dummy_function_api(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c
new file mode 100644
index 0000000..3f1c92b
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdd.c
@@ -0,0 +1,2200 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxdd.c - 3Dfx VooDoo Mesa device driver functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "image.h"
+#include "mtypes.h"
+#include "fxdrv.h"
+#include "enums.h"
+#include "extensions.h"
+#include "macros.h"
+#include "texstore.h"
+#include "teximage.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "array_cache/acache.h"
+
+
+
+/* lookup table for scaling 4 bit colors up to 8 bits */
+GLuint FX_rgb_scale_4[16] = {
+ 0, 17, 34, 51, 68, 85, 102, 119,
+ 136, 153, 170, 187, 204, 221, 238, 255
+};
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+GLuint FX_rgb_scale_5[32] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+GLuint FX_rgb_scale_6[64] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 45, 49, 53, 57, 61,
+ 65, 69, 73, 77, 81, 85, 89, 93,
+ 97, 101, 105, 109, 113, 117, 121, 125,
+ 130, 134, 138, 142, 146, 150, 154, 158,
+ 162, 166, 170, 174, 178, 182, 186, 190,
+ 194, 198, 202, 206, 210, 215, 219, 223,
+ 227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+/*
+ * Disable color by masking out R, G, B, A
+ */
+static void fxDisableColor (fxMesaContext fxMesa)
+{
+ if (fxMesa->colDepth == 32) {
+ /* 32bpp mode */
+ fxMesa->Glide.grColorMaskExt(FXFALSE, FXFALSE, FXFALSE, FXFALSE);
+ } else {
+ /* 15/16 bpp mode */
+ grColorMask(FXFALSE, FXFALSE);
+ }
+}
+
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+/* Return buffer size information */
+static void
+fxDDBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx && FX_CONTEXT(ctx)) {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDBufferSize(...)\n");
+ }
+
+ *width = fxMesa->width;
+ *height = fxMesa->height;
+ }
+}
+
+
+/* Implements glClearColor() */
+static void
+fxDDClearColor(GLcontext * ctx, const GLfloat color[4])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLubyte col[4];
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDClearColor(%f, %f, %f, %f)\n",
+ color[0], color[1], color[2], color[3]);
+ }
+
+ 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]);
+
+ fxMesa->clearC = FXCOLOR4(col);
+ fxMesa->clearA = col[3];
+}
+
+
+/* Clear the color and/or depth buffers */
+static void fxDDClear( GLcontext *ctx,
+ GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLbitfield softwareMask = mask & (DD_ACCUM_BIT);
+ const GLuint stencil_size = fxMesa->haveHwStencil ? ctx->Visual.stencilBits : 0;
+ const FxU32 clearD = (FxU32) (ctx->DepthMaxF * ctx->Depth.Clear);
+ const FxU8 clearS = (FxU8) (ctx->Stencil.Clear & 0xff);
+
+ if ( TDFX_DEBUG & MESA_VERBOSE ) {
+ fprintf( stderr, "fxDDClear( %d, %d, %d, %d )\n",
+ (int) x, (int) y, (int) width, (int) height );
+ }
+
+ /* we can't clear accum buffers nor stereo */
+ mask &= ~(DD_ACCUM_BIT | DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT);
+
+ /* Need this check to respond to certain HW updates */
+ if (fxMesa->new_state & (FX_NEW_SCISSOR | FX_NEW_COLOR_MASK)) {
+ fxSetupScissor(ctx);
+ fxSetupColorMask(ctx);
+ fxMesa->new_state &= ~(FX_NEW_SCISSOR | FX_NEW_COLOR_MASK);
+ }
+
+ /*
+ * As per GL spec, color masking should be obeyed when clearing
+ */
+ if (ctx->Visual.greenBits != 8) {
+ /* can only do color masking if running in 24/32bpp on Napalm */
+ if (ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP] ||
+ ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]) {
+ softwareMask |= (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
+ mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
+ }
+ }
+
+ if (fxMesa->haveHwStencil) {
+ /*
+ * If we want to clear stencil, it must be enabled
+ * in the HW, even if the stencil test is not enabled
+ * in the OGL state.
+ */
+ BEGIN_BOARD_LOCK();
+ if (mask & DD_STENCIL_BIT) {
+ fxMesa->Glide.grStencilMaskExt(fxMesa->unitsState.stencilWriteMask);
+ /* set stencil ref value = desired clear value */
+ fxMesa->Glide.grStencilFuncExt(GR_CMP_ALWAYS, clearS, 0xff);
+ fxMesa->Glide.grStencilOpExt(GR_STENCILOP_REPLACE,
+ GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE);
+ grEnable(GR_STENCIL_MODE_EXT);
+ }
+ else {
+ grDisable(GR_STENCIL_MODE_EXT);
+ }
+ END_BOARD_LOCK();
+ } else if (mask & DD_STENCIL_BIT) {
+ softwareMask |= (mask & (DD_STENCIL_BIT));
+ mask &= ~(DD_STENCIL_BIT);
+ }
+
+ /*
+ * This may be ugly, but it's needed in order to work around a number
+ * of Glide bugs.
+ */
+ BEGIN_CLIP_LOOP();
+ {
+ /*
+ * This could probably be done fancier but doing each possible case
+ * explicitly is less error prone.
+ */
+ switch (mask & ~DD_STENCIL_BIT) {
+ case DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
+ /* back buffer & depth */
+ grDepthMask(FXTRUE);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0) {
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ }
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_FRONT_LEFT_BIT | DD_DEPTH_BIT:
+ /* XXX it appears that the depth buffer isn't cleared when
+ * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
+ * This is a work-around/
+ */
+ /* clear depth */
+ grDepthMask(FXTRUE);
+ fxDisableColor(fxMesa);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ fxSetupColorMask(ctx);
+ grDepthMask(FXFALSE);
+ /* clear front */
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_BACK_LEFT_BIT:
+ /* back buffer only */
+ grDepthMask(FXFALSE);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_FRONT_LEFT_BIT:
+ /* front buffer only */
+ grDepthMask(FXFALSE);
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT:
+ /* front and back */
+ grDepthMask(FXFALSE);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
+ /* clear back and depth */
+ grDepthMask(FXTRUE);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ /* clear front */
+ grDepthMask(FXFALSE);
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ break;
+ case DD_DEPTH_BIT:
+ /* just the depth buffer */
+ grDepthMask(FXTRUE);
+ fxDisableColor(fxMesa);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ if (stencil_size > 0)
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ else
+ grBufferClear(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD);
+ fxSetupColorMask(ctx);
+ break;
+ default:
+ /* clear no color buffers or depth buffer but might clear stencil */
+ if ((stencil_size > 0) && (mask & DD_STENCIL_BIT)) {
+ /* XXX need this RenderBuffer call to work around Glide bug */
+ grDepthMask(FXFALSE);
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ fxDisableColor(fxMesa);
+ fxMesa->Glide.grBufferClearExt(fxMesa->clearC,
+ fxMesa->clearA,
+ clearD, clearS);
+ fxSetupColorMask(ctx);
+ }
+ }
+ }
+ END_CLIP_LOOP();
+
+ if (fxMesa->haveHwStencil) {
+ /* We changed the stencil state above. Restore it! */
+ fxSetupStencil(ctx);
+ }
+ fxSetupDepthTest(ctx);
+ grRenderBuffer(fxMesa->currentFB);
+
+ if (softwareMask)
+ _swrast_Clear( ctx, softwareMask, all, x, y, width, height );
+}
+
+
+/* Set the buffer used for drawing */
+/* XXX support for separate read/draw buffers hasn't been tested */
+/* XXX GL_NONE disables color, but fails to correctly maintain state */
+static void
+fxDDSetDrawBuffer(GLcontext * ctx, GLenum mode)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDSetDrawBuffer(%x)\n", (int)mode);
+ }
+
+ if (mode == GL_FRONT_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ }
+ else if (mode == GL_BACK_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ }
+ else if (mode == GL_NONE) {
+ fxDisableColor(fxMesa);
+ }
+ else {
+ /* we'll need a software fallback */
+ /* XXX not implemented */
+ }
+
+ /* update s/w fallback state */
+ _swrast_DrawBuffer(ctx, mode);
+}
+
+
+static void
+fxDDDrawBitmap2 (GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ GrLfbWriteMode_t mode;
+ FxU16 color;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ /* check if there's any raster operations enabled which we can't handle */
+ if (swrast->_RasterMask & (ALPHATEST_BIT |
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ MASKING_BIT |
+ ALPHABUF_BIT | /* nope! see 565 span kludge */
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT)) {
+ _swrast_Bitmap(ctx, px, py, width, height, unpack, bitmap);
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (px < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
+ width -= (ctx->Scissor.X - px);
+ px = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (py < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
+ height -= (ctx->Scissor.Y - py);
+ py = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ /* compute pixel value */
+ {
+ GLint r = (GLint) (ctx->Current.RasterColor[RCOMP] * 255.0f);
+ GLint g = (GLint) (ctx->Current.RasterColor[GCOMP] * 255.0f);
+ GLint b = (GLint) (ctx->Current.RasterColor[BCOMP] * 255.0f);
+ GLint a = (GLint) (ctx->Current.RasterColor[ACOMP] * 255.0f);
+ if (fxMesa->colDepth == 15) {
+ color = TDFXPACKCOLOR1555(b, g, r, a);
+ mode = GR_LFBWRITEMODE_1555;
+ } else {
+ color = fxMesa->bgrOrder ? TDFXPACKCOLOR565(r, g, b) : TDFXPACKCOLOR565(b, g, r);
+ mode = GR_LFBWRITEMODE_565;
+ }
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ mode,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_Bitmap(ctx, px, py, width, height, finalUnpack, bitmap);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+ /* The dest stride depends on the hardware and whether we're drawing
+ * to the front or back buffer. This compile-time test seems to do
+ * the job for now.
+ */
+ const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
+
+ GLint row;
+ /* compute dest address of bottom-left pixel in bitmap */
+ GLushort *dst = (GLushort *) info.lfbPtr
+ + (winY + py) * dstStride + (winX + px);
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src =
+ (const GLubyte *) _mesa_image_address(finalUnpack,
+ bitmap, width, height,
+ GL_COLOR_INDEX, GL_BITMAP,
+ 0, row, 0);
+ if (finalUnpack->LsbFirst) {
+ /* least significan bit first */
+ GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ dst[col] = color;
+ }
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* most significan bit first */
+ GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ dst[col] = color;
+ }
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+ if (mask != 128)
+ src++;
+ }
+ dst += dstStride;
+ }
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+static void
+fxDDDrawBitmap4 (GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ FxU32 color;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ /* check if there's any raster operations enabled which we can't handle */
+ if ((swrast->_RasterMask & (/*ALPHATEST_BIT |*/
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ /*MASKING_BIT |*/ /* masking ok, we're in 32bpp */
+ /*ALPHABUF_BIT |*//* alpha ok, we're in 32bpp */
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT))
+ ) {
+ _swrast_Bitmap(ctx, px, py, width, height, unpack, bitmap);
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (px < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
+ width -= (ctx->Scissor.X - px);
+ px = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (py < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
+ height -= (ctx->Scissor.Y - py);
+ py = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ /* compute pixel value */
+ {
+ GLint r = (GLint) (ctx->Current.RasterColor[RCOMP] * 255.0f);
+ GLint g = (GLint) (ctx->Current.RasterColor[GCOMP] * 255.0f);
+ GLint b = (GLint) (ctx->Current.RasterColor[BCOMP] * 255.0f);
+ GLint a = (GLint) (ctx->Current.RasterColor[ACOMP] * 255.0f);
+ color = TDFXPACKCOLOR8888(b, g, r, a);
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_8888,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_Bitmap(ctx, px, py, width, height, finalUnpack, bitmap);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+ /* The dest stride depends on the hardware and whether we're drawing
+ * to the front or back buffer. This compile-time test seems to do
+ * the job for now.
+ */
+ const GLint dstStride = info.strideInBytes / 4; /* stride in GLuints */
+
+ GLint row;
+ /* compute dest address of bottom-left pixel in bitmap */
+ GLuint *dst = (GLuint *) info.lfbPtr
+ + (winY + py) * dstStride + (winX + px);
+
+ for (row = 0; row < height; row++) {
+ const GLubyte *src =
+ (const GLubyte *) _mesa_image_address(finalUnpack,
+ bitmap, width, height,
+ GL_COLOR_INDEX, GL_BITMAP,
+ 0, row, 0);
+ if (finalUnpack->LsbFirst) {
+ /* least significan bit first */
+ GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ dst[col] = color;
+ }
+ if (mask == 128U) {
+ src++;
+ mask = 1U;
+ }
+ else {
+ mask = mask << 1;
+ }
+ }
+ if (mask != 1)
+ src++;
+ }
+ else {
+ /* most significan bit first */
+ GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ if (*src & mask) {
+ dst[col] = color;
+ }
+ if (mask == 1U) {
+ src++;
+ mask = 128U;
+ }
+ else {
+ mask = mask >> 1;
+ }
+ }
+ if (mask != 128)
+ src++;
+ }
+ dst += dstStride;
+ }
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+
+static void
+fxDDReadPixels565 (GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *dstImage)
+{
+ if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+ else {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrLfbInfo_t info;
+
+ BEGIN_BOARD_LOCK();
+ info.size = sizeof(info);
+ if (grLfbLock(GR_LFB_READ_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_ANY,
+ GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
+ const GLint winX = 0;
+ const GLint winY = fxMesa->height - 1;
+ const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
+ const GLushort *src = (const GLushort *) info.lfbPtr
+ + (winY - y) * srcStride + (winX + x);
+ GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
+ width, height, format,
+ type, 0, 0, 0);
+ GLint dstStride =
+ _mesa_image_row_stride(packing, width, format, type);
+
+ if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ /* convert 5R6G5B into 8R8G8B */
+ GLint row, col;
+ const GLint halfWidth = width >> 1;
+ const GLint extraPixel = (width & 1);
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < halfWidth; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 27) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 21) & 0x3f];
+ *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
+ }
+ if (extraPixel) {
+ GLushort pixel = src[width - 1];
+ *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ /* convert 5R6G5B into 8R8G8B8A */
+ GLint row, col;
+ const GLint halfWidth = width >> 1;
+ const GLint extraPixel = (width & 1);
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < halfWidth; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = 255;
+ *d++ = FX_rgb_scale_5[(pixel >> 27) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 21) & 0x3f];
+ *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
+ *d++ = 255;
+ }
+ if (extraPixel) {
+ const GLushort pixel = src[width - 1];
+ *d++ = FX_rgb_scale_5[(pixel >> 11) & 0x1f];
+ *d++ = FX_rgb_scale_6[(pixel >> 5) & 0x3f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = 255;
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
+ /* directly memcpy 5R6G5B pixels into client's buffer */
+ const GLint widthInBytes = width * 2;
+ GLint row;
+ for (row = 0; row < height; row++) {
+ MEMCPY(dst, src, widthInBytes);
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ END_BOARD_LOCK();
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ }
+ END_BOARD_LOCK();
+ }
+}
+
+static void
+fxDDReadPixels555 (GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *dstImage)
+{
+ if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+ else {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrLfbInfo_t info;
+
+ BEGIN_BOARD_LOCK();
+ info.size = sizeof(info);
+ if (grLfbLock(GR_LFB_READ_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_ANY,
+ GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
+ const GLint winX = 0;
+ const GLint winY = fxMesa->height - 1;
+ const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
+ const GLushort *src = (const GLushort *) info.lfbPtr
+ + (winY - y) * srcStride + (winX + x);
+ GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
+ width, height, format,
+ type, 0, 0, 0);
+ GLint dstStride =
+ _mesa_image_row_stride(packing, width, format, type);
+
+ if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ /* convert 5R5G5B into 8R8G8B */
+ GLint row, col;
+ const GLint halfWidth = width >> 1;
+ const GLint extraPixel = (width & 1);
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < halfWidth; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 26) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 21) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
+ }
+ if (extraPixel) {
+ GLushort pixel = src[width - 1];
+ *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ /* convert 5R6G5B into 8R8G8B8A */
+ GLint row, col;
+ const GLint halfWidth = width >> 1;
+ const GLint extraPixel = (width & 1);
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < halfWidth; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = (pixel & 0x8000) ? 255 : 0;
+ *d++ = FX_rgb_scale_5[(pixel >> 26) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 21) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 16) & 0x1f];
+ *d++ = (pixel & 0x80000000) ? 255 : 0;
+ }
+ if (extraPixel) {
+ const GLushort pixel = src[width - 1];
+ *d++ = FX_rgb_scale_5[(pixel >> 10) & 0x1f];
+ *d++ = FX_rgb_scale_5[(pixel >> 5) & 0x1f];
+ *d++ = FX_rgb_scale_5[ pixel & 0x1f];
+ *d++ = (pixel & 0x8000) ? 255 : 0;
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
+ /* directly memcpy 5R5G5B pixels into client's buffer */
+ const GLint widthInBytes = width * 2;
+ GLint row;
+ for (row = 0; row < height; row++) {
+ MEMCPY(dst, src, widthInBytes);
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ END_BOARD_LOCK();
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ }
+ END_BOARD_LOCK();
+ }
+}
+
+static void
+fxDDReadPixels8888 (GLcontext * ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ GLvoid *dstImage)
+{
+ if (ctx->_ImageTransferState/* & (IMAGE_SCALE_BIAS_BIT|IMAGE_MAP_COLOR_BIT)*/) {
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+ else {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrLfbInfo_t info;
+
+ BEGIN_BOARD_LOCK();
+ info.size = sizeof(info);
+ if (grLfbLock(GR_LFB_READ_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_ANY,
+ GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
+ const GLint winX = 0;
+ const GLint winY = fxMesa->height - 1;
+ const GLint srcStride = info.strideInBytes / 4; /* stride in GLuints */
+ const GLuint *src = (const GLuint *) info.lfbPtr
+ + (winY - y) * srcStride + (winX + x);
+ GLubyte *dst = (GLubyte *) _mesa_image_address(packing, dstImage,
+ width, height, format,
+ type, 0, 0, 0);
+ GLint dstStride =
+ _mesa_image_row_stride(packing, width, format, type);
+
+ if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ /* convert 8A8R8G8B into 8R8G8B */
+ GLint row, col;
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < width; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = pixel >> 16;
+ *d++ = pixel >> 8;
+ *d++ = pixel;
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ /* 8A8R8G8B pixels into client's buffer */
+ GLint row, col;
+ for (row = 0; row < height; row++) {
+ GLubyte *d = dst;
+ for (col = 0; col < width; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = pixel >> 16;
+ *d++ = pixel >> 8;
+ *d++ = pixel;
+ *d++ = pixel >> 24;
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) {
+ /* convert 8A8R8G8B into 5R6G5B */
+ GLint row, col;
+ for (row = 0; row < height; row++) {
+ GLushort *d = (GLushort *)dst;
+ for (col = 0; col < width; col++) {
+ const GLuint pixel = ((const GLuint *) src)[col];
+ *d++ = (((pixel >> 16) & 0xf8) << 8) |
+ (((pixel >> 8) & 0xfc) << 3) |
+ ((pixel & 0xf8) >> 3);
+ }
+ dst += dstStride;
+ src -= srcStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ END_BOARD_LOCK();
+ _swrast_ReadPixels(ctx, x, y, width, height, format, type,
+ packing, dstImage);
+ return;
+ }
+
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ }
+ END_BOARD_LOCK();
+ }
+}
+
+
+static void
+fxDDDrawPixels555 (GLcontext * ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ if (ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F ||
+ (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
+ IMAGE_MAP_COLOR_BIT)) ||
+ (swrast->_RasterMask & (ALPHATEST_BIT |
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ MASKING_BIT |
+ ALPHABUF_BIT |
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT)) ||
+ fxMesa->fallback)
+ {
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (x < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
+ width -= (ctx->Scissor.X - x);
+ x = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (y < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
+ height -= (ctx->Scissor.Y - y);
+ y = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_1555,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+
+ const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
+ GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
+
+ if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR1555(src[2], src[1], src[0], src[3]);
+ src += 4;
+ }
+ dst += dstStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR1555(src[2], src[1], src[0], 255);
+ src += 3;
+ }
+ dst += dstStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+
+static void
+fxDDDrawPixels565 (GLcontext * ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ if (ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F ||
+ (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
+ IMAGE_MAP_COLOR_BIT)) ||
+ (swrast->_RasterMask & (ALPHATEST_BIT |
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ MASKING_BIT |
+ ALPHABUF_BIT |
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT)) ||
+ fxMesa->fallback)
+ {
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (x < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
+ width -= (ctx->Scissor.X - x);
+ x = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (y < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
+ height -= (ctx->Scissor.Y - y);
+ y = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_565,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+
+ const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
+ GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
+
+ if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR565(src[2], src[1], src[0]);
+ src += 4;
+ }
+ dst += dstStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR565(src[2], src[1], src[0]);
+ src += 3;
+ }
+ dst += dstStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+
+static void
+fxDDDrawPixels565_rev (GLcontext * ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ if (ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F ||
+ (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
+ IMAGE_MAP_COLOR_BIT)) ||
+ (swrast->_RasterMask & (ALPHATEST_BIT |
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ MASKING_BIT |
+ ALPHABUF_BIT |
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT)) ||
+ fxMesa->fallback)
+ {
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (x < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
+ width -= (ctx->Scissor.X - x);
+ x = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (y < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
+ height -= (ctx->Scissor.Y - y);
+ y = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_565,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+
+ const GLint dstStride = info.strideInBytes / 2; /* stride in GLushorts */
+ GLushort *dst = (GLushort *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
+
+ if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR565(src[0], src[1], src[2]);
+ src += 4;
+ }
+ dst += dstStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR565(src[0], src[1], src[2]);
+ src += 3;
+ }
+ dst += dstStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+
+static void
+fxDDDrawPixels8888 (GLcontext * ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid * pixels)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ const struct gl_pixelstore_attrib *finalUnpack;
+ struct gl_pixelstore_attrib scissoredUnpack;
+
+ if (ctx->Pixel.ZoomX != 1.0F ||
+ ctx->Pixel.ZoomY != 1.0F ||
+ (ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
+ IMAGE_MAP_COLOR_BIT)) ||
+ (swrast->_RasterMask & (/*ALPHATEST_BIT |*/
+ /*BLEND_BIT |*/ /* blending ok, through pixpipe */
+ DEPTH_BIT | /* could be done with RGB:DEPTH */
+ FOG_BIT | /* could be done with RGB:DEPTH */
+ LOGIC_OP_BIT |
+ /*CLIP_BIT |*/ /* clipping ok, below */
+ STENCIL_BIT |
+ /*MASKING_BIT |*/ /* masking ok, we're in 32bpp */
+ /*ALPHABUF_BIT |*//* alpha ok, we're in 32bpp */
+ MULTI_DRAW_BIT |
+ OCCLUSION_BIT | /* nope! at least not yet */
+ TEXTURE_BIT |
+ FRAGPROG_BIT)) ||
+ fxMesa->fallback)
+ {
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+ return;
+ }
+
+ /* make sure the pixelpipe is configured correctly */
+ fxSetupFXUnits(ctx);
+
+ /* FIXME! _RasterMask & CLIP_BIT gets set if we're out of Viewport, also! */
+ if (ctx->Scissor.Enabled) {
+ /* This is a bit tricky, but by carefully adjusting the px, py,
+ * width, height, skipPixels and skipRows values we can do
+ * scissoring without special code in the rendering loop.
+ */
+
+ /* we'll construct a new pixelstore struct */
+ finalUnpack = &scissoredUnpack;
+ scissoredUnpack = *unpack;
+ if (scissoredUnpack.RowLength == 0)
+ scissoredUnpack.RowLength = width;
+
+ /* clip left */
+ if (x < ctx->Scissor.X) {
+ scissoredUnpack.SkipPixels += (ctx->Scissor.X - x);
+ width -= (ctx->Scissor.X - x);
+ x = ctx->Scissor.X;
+ }
+ /* clip right */
+ if (x + width >= ctx->Scissor.X + ctx->Scissor.Width) {
+ width -= (x + width - (ctx->Scissor.X + ctx->Scissor.Width));
+ }
+ /* clip bottom */
+ if (y < ctx->Scissor.Y) {
+ scissoredUnpack.SkipRows += (ctx->Scissor.Y - y);
+ height -= (ctx->Scissor.Y - y);
+ y = ctx->Scissor.Y;
+ }
+ /* clip top */
+ if (y + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
+ height -= (y + height - (ctx->Scissor.Y + ctx->Scissor.Height));
+ }
+
+ if (width <= 0 || height <= 0)
+ return;
+ }
+ else {
+ finalUnpack = unpack;
+ }
+
+ info.size = sizeof(info);
+ if (!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_8888,
+ GR_ORIGIN_LOWER_LEFT, FXTRUE, &info)) {
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ {
+ const GLint winX = 0;
+ const GLint winY = 0;
+
+ const GLint dstStride = info.strideInBytes / 4; /* stride in GLuints */
+ GLuint *dst = (GLuint *) info.lfbPtr + (winY + y) * dstStride + (winX + x);
+
+ if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ /* directly memcpy 8A8R8G8B pixels to screen */
+ const GLint widthInBytes = width * 4;
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ MEMCPY(dst, src, widthInBytes);
+ dst += dstStride;
+ }
+ }
+ else if (format == GL_RGB && type == GL_UNSIGNED_BYTE) {
+ GLint row;
+ for (row = 0; row < height; row++) {
+ GLubyte *src = (GLubyte *) _mesa_image_address(finalUnpack, pixels,
+ width, height, format,
+ type, 0, row, 0);
+ GLint col;
+ for (col = 0; col < width; col++) {
+ dst[col] = TDFXPACKCOLOR8888(src[2], src[1], src[0], 255);
+ src += 3;
+ }
+ dst += dstStride;
+ }
+ }
+ else {
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, finalUnpack, pixels);
+ return;
+ }
+
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->currentFB);
+}
+
+
+static void
+fxDDFinish(GLcontext * ctx)
+{
+ grFlush();
+}
+
+
+
+
+
+/* KW: Put the word Mesa in the render string because quakeworld
+ * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
+ * Why?
+ */
+static const GLubyte *
+fxDDGetString(GLcontext * ctx, GLenum name)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ switch (name) {
+ case GL_RENDERER:
+ return (GLubyte *)fxMesa->rendererString;
+#if __WIN32__ /* hack to advertise vanilla extension names */
+ case GL_EXTENSIONS:
+ if (ctx->Extensions.String == NULL) {
+ GLubyte *ext = _mesa_make_extension_string(ctx);
+ if (ext != NULL) {
+ ctx->Extensions.String = _mesa_malloc(strlen((char *)ext) + 256);
+ if (ctx->Extensions.String != NULL) {
+ strcpy((char *)ctx->Extensions.String, (char *)ext);
+ /* put any additional extension names here */
+#if 0
+ strcat((char *)ctx->Extensions.String, " 3DFX_set_global_palette");
+#endif
+#if __WIN32__
+ strcat((char *)ctx->Extensions.String, " WGL_3DFX_gamma_control");
+ strcat((char *)ctx->Extensions.String, " WGL_EXT_swap_control");
+ strcat((char *)ctx->Extensions.String, " WGL_EXT_extensions_string WGL_ARB_extensions_string");
+#endif
+ /* put any additional extension names here */
+ _mesa_free(ext);
+ } else {
+ ctx->Extensions.String = ext;
+ }
+ }
+ }
+ return ctx->Extensions.String;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+static const struct tnl_pipeline_stage *fx_pipeline[] = {
+ &_tnl_vertex_transform_stage, /* XXX todo - Add the fastpath here */
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+#if defined(FEATURE_NV_vertex_program) || defined(FEATURE_ARB_vertex_program)
+ &_tnl_vertex_program_stage,
+#endif
+ &_tnl_render_stage,
+ 0,
+};
+
+
+
+
+int
+fxDDInitFxMesaContext(fxMesaContext fxMesa)
+{
+/* int i;*/
+ GLcontext *ctx = fxMesa->glCtx;
+
+ FX_setupGrVertexLayout();
+
+ fxMesa->color = 0xffffffff;
+ fxMesa->clearC = 0;
+ fxMesa->clearA = 0;
+
+ fxMesa->stats.swapBuffer = 0;
+ fxMesa->stats.reqTexUpload = 0;
+ fxMesa->stats.texUpload = 0;
+ fxMesa->stats.memTexUpload = 0;
+
+ fxMesa->tmuSrc = FX_TMU_NONE;
+ fxMesa->lastUnitsMode = FX_UM_NONE;
+ fxTMInit(fxMesa);
+
+ /* FX units setup */
+
+ fxMesa->unitsState.alphaTestEnabled = GL_FALSE;
+ fxMesa->unitsState.alphaTestFunc = GL_ALWAYS;
+ fxMesa->unitsState.alphaTestRefValue = 0.0;
+
+ fxMesa->unitsState.blendEnabled = GL_FALSE;
+ fxMesa->unitsState.blendSrcFuncRGB = GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncRGB = GR_BLEND_ZERO;
+ fxMesa->unitsState.blendSrcFuncAlpha = GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncAlpha = GR_BLEND_ZERO;
+ fxMesa->unitsState.blendEqRGB = GR_BLEND_OP_ADD;
+ fxMesa->unitsState.blendEqAlpha = GR_BLEND_OP_ADD;
+
+ fxMesa->unitsState.depthTestEnabled = GL_FALSE;
+ fxMesa->unitsState.depthMask = GL_TRUE;
+ fxMesa->unitsState.depthTestFunc = GL_LESS;
+ fxMesa->unitsState.depthBias = 0;
+
+ fxMesa->unitsState.stencilWriteMask = 0xff;
+
+ if (fxMesa->colDepth == 32) {
+ /* 32bpp */
+ fxMesa->Glide.grColorMaskExt(FXTRUE, FXTRUE, FXTRUE, fxMesa->haveHwAlpha);
+ } else {
+ /* 15/16 bpp mode */
+ grColorMask(FXTRUE, fxMesa->haveHwAlpha);
+ }
+
+ fxMesa->currentFB = fxMesa->haveDoubleBuffer ? GR_BUFFER_BACKBUFFER : GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+
+ fxMesa->state = MALLOC(FX_grGetInteger(GR_GLIDE_STATE_SIZE));
+ fxMesa->fogTable = (GrFog_t *) MALLOC(FX_grGetInteger(GR_FOG_TABLE_ENTRIES) *
+ sizeof(GrFog_t));
+
+ if (!fxMesa->state || !fxMesa->fogTable) {
+ if (fxMesa->state)
+ FREE(fxMesa->state);
+ if (fxMesa->fogTable)
+ FREE(fxMesa->fogTable);
+ return 0;
+ }
+
+ if (fxMesa->haveZBuffer) {
+ grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
+ }
+
+ if (!fxMesa->bgrOrder) {
+ grLfbWriteColorFormat(GR_COLORFORMAT_ABGR);
+ }
+
+ if (fxMesa->Glide.grSetNumPendingBuffers != NULL) {
+ fxMesa->Glide.grSetNumPendingBuffers(fxMesa->maxPendingSwapBuffers);
+ }
+
+ fxMesa->textureAlign = FX_grGetInteger(GR_TEXTURE_ALIGN);
+ /* [koolsmoky] */
+ {
+ char *env;
+ int textureLevels = 0;
+ int textureSize = FX_grGetInteger(GR_MAX_TEXTURE_SIZE);
+ do {
+ textureLevels++;
+ } while ((textureSize >>= 0x1) & 0x7ff);
+ ctx->Const.MaxTextureLevels = textureLevels;
+ ctx->Const.MaxTextureLodBias = /*textureLevels - 1*/8; /* Glide bug */
+#if FX_RESCALE_BIG_TEXURES_HACK
+ fxMesa->textureMaxLod = textureLevels - 1;
+ if ((env = getenv("MESA_FX_MAXLOD")) != NULL) {
+ int maxLevels = atoi(env) + 1;
+ if ((maxLevels <= MAX_TEXTURE_LEVELS) && (maxLevels > textureLevels)) {
+ ctx->Const.MaxTextureLevels = maxLevels;
+ }
+ }
+#endif
+ }
+ ctx->Const.MaxTextureCoordUnits =
+ ctx->Const.MaxTextureImageUnits = fxMesa->haveTwoTMUs ? 2 : 1;
+ ctx->Const.MaxTextureUnits = MAX2(ctx->Const.MaxTextureImageUnits, ctx->Const.MaxTextureCoordUnits);
+
+ fxMesa->new_state = _NEW_ALL;
+ if (!fxMesa->haveHwStencil) {
+ /* don't touch stencil if there is none */
+ fxMesa->new_state &= ~FX_NEW_STENCIL;
+ }
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext(ctx);
+ _ac_CreateContext(ctx);
+ _tnl_CreateContext(ctx);
+ _swsetup_CreateContext(ctx);
+
+ /* Install customized pipeline */
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, fx_pipeline);
+
+ fxAllocVB(ctx);
+
+ fxSetupDDPointers(ctx);
+ fxDDInitTriFuncs(ctx);
+
+ /* Tell the software rasterizer to use pixel fog always.
+ */
+ _swrast_allow_vertex_fog(ctx, GL_FALSE);
+ _swrast_allow_pixel_fog(ctx, GL_TRUE);
+ _tnl_allow_vertex_fog( ctx, GL_FALSE );
+ _tnl_allow_pixel_fog( ctx, GL_TRUE );
+
+ /* Tell tnl not to calculate or use vertex fog factors. (Needed to
+ * tell render stage not to clip fog coords).
+ */
+/* _tnl_calculate_vertex_fog( ctx, GL_FALSE ); */
+
+ fxDDInitExtensions(ctx);
+
+#if 0
+ /* do we want dither? It just looks bad... */
+ grEnable(GR_ALLOW_MIPMAP_DITHER);
+#endif
+ grGlideGetState((GrState *) fxMesa->state);
+
+ return 1;
+}
+
+/* Undo the above.
+ */
+void
+fxDDDestroyFxMesaContext(fxMesaContext fxMesa)
+{
+ _swsetup_DestroyContext(fxMesa->glCtx);
+ _tnl_DestroyContext(fxMesa->glCtx);
+ _ac_DestroyContext(fxMesa->glCtx);
+ _swrast_DestroyContext(fxMesa->glCtx);
+
+ if (fxMesa->state)
+ FREE(fxMesa->state);
+ if (fxMesa->fogTable)
+ FREE(fxMesa->fogTable);
+ fxFreeVB(fxMesa->glCtx);
+}
+
+
+
+
+void
+fxDDInitExtensions(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+#if 1 /* multipass ColorSum stage */
+ _mesa_enable_extension(ctx, "GL_EXT_secondary_color");
+#endif
+
+ _mesa_enable_extension(ctx, "GL_ARB_point_sprite");
+ _mesa_enable_extension(ctx, "GL_EXT_point_parameters");
+ _mesa_enable_extension(ctx, "GL_EXT_paletted_texture");
+ _mesa_enable_extension(ctx, "GL_EXT_texture_lod_bias");
+ _mesa_enable_extension(ctx, "GL_EXT_shared_texture_palette");
+ _mesa_enable_extension(ctx, "GL_EXT_blend_func_separate");
+ _mesa_enable_extension(ctx, "GL_EXT_texture_env_add");
+ _mesa_enable_extension(ctx, "GL_EXT_stencil_wrap");
+
+ if (fxMesa->haveTwoTMUs) {
+ _mesa_enable_extension(ctx, "GL_ARB_multitexture");
+ }
+
+ if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
+ _mesa_enable_extension(ctx, "GL_ARB_texture_compression");
+ _mesa_enable_extension(ctx, "GL_3DFX_texture_compression_FXT1");
+ _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
+ _mesa_enable_extension(ctx, "GL_S3_s3tc");
+ _mesa_enable_extension(ctx, "GL_NV_blend_square");
+ } else {
+ /* [dBorca]
+ * We should enable generic texture compression functions,
+ * but some poorly written apps automatically assume S3TC.
+ * Binding NCC to GL_COMPRESSED_RGB[A] is an unnecessary hassle,
+ * since it's slow and ugly (better with palette textures, then).
+ * Moreover, NCC is not an OpenGL standard, so we can't use
+ * precompressed textures. Last, but not least, NCC runs amok
+ * when multitexturing on a Voodoo3 and up (see POINTCAST vs UMA).
+ * Note: this is also a problem with palette textures, but
+ * faking multitex by multipass is evil...
+ * Implementing NCC requires three stages:
+ * fxDDChooseTextureFormat:
+ * bind GL_COMPRESSED_RGB[A] to _mesa_texformat_argb8888,
+ * so we can quantize properly, at a later time
+ * fxDDTexImage:
+ * if GL_COMPRESSED_RGB
+ * use _mesa_texformat_l8 to get 1bpt and set GR_TEXFMT_YIQ_422
+ * if GL_COMPRESSED_RGBA
+ * use _mesa_texformat_al88 to get 2bpt and set GR_TEXFMT_AYIQ_8422
+ * txMipQuantize(...);
+ * if (level == 0) {
+ * txPalToNcc((GuNccTable *)(&(ti->palette)), pxMip.pal);
+ * }
+ * fxSetupSingleTMU_NoLock/fxSetupDoubleTMU_NoLock:
+ * grTexDownloadTable(GR_TEXTABLE_NCC0, &(ti->palette));
+ */
+ /*_mesa_enable_extension(ctx, "GL_ARB_texture_compression");*/
+ _mesa_enable_extension(ctx, "GL_SGIS_generate_mipmap");
+ }
+
+ if (fxMesa->HaveCmbExt) {
+ _mesa_enable_extension(ctx, "GL_ARB_texture_env_combine");
+ _mesa_enable_extension(ctx, "GL_EXT_texture_env_combine");
+ }
+
+ if (fxMesa->HavePixExt) {
+ _mesa_enable_extension(ctx, "GL_EXT_blend_subtract");
+ _mesa_enable_extension(ctx, "GL_EXT_blend_equation_separate");
+ }
+
+ if (fxMesa->HaveMirExt) {
+ _mesa_enable_extension(ctx, "GL_ARB_texture_mirrored_repeat");
+ }
+
+ if (fxMesa->type >= GR_SSTTYPE_Voodoo2) {
+ _mesa_enable_extension(ctx, "GL_EXT_fog_coord");
+ }
+
+ /* core-level extensions */
+ _mesa_enable_extension(ctx, "GL_EXT_multi_draw_arrays");
+ _mesa_enable_extension(ctx, "GL_IBM_multimode_draw_arrays");
+ _mesa_enable_extension(ctx, "GL_ARB_vertex_buffer_object");
+ /* dangerous */
+ if (getenv("MESA_FX_ALLOW_VP")) {
+ _mesa_enable_extension(ctx, "GL_ARB_vertex_program");
+ _mesa_enable_extension(ctx, "GL_NV_vertex_program");
+ _mesa_enable_extension(ctx, "GL_NV_vertex_program1_1");
+ _mesa_enable_extension(ctx, "GL_MESA_program_debug");
+ }
+#if 0
+ /* this requires _tnl_vertex_cull_stage in the pipeline */
+ _mesa_enable_extension(ctx, "EXT_cull_vertex");
+#endif
+}
+
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* Check if the hardware supports the current context
+ *
+ * Performs similar work to fxDDChooseRenderState() - should be merged.
+ */
+GLuint
+fx_check_IsInHardware(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (ctx->RenderMode != GL_RENDER) {
+ return FX_FALLBACK_RENDER_MODE;
+ }
+
+ if (ctx->Stencil.Enabled && !fxMesa->haveHwStencil) {
+ return FX_FALLBACK_STENCIL;
+ }
+
+ if (ctx->Color._DrawDestMask != DD_FRONT_LEFT_BIT &&
+ ctx->Color._DrawDestMask != DD_BACK_LEFT_BIT) {
+ return FX_FALLBACK_DRAW_BUFFER;
+ }
+
+ if (ctx->Color.BlendEnabled) {
+ if (ctx->Color.BlendEquationRGB != GL_FUNC_ADD) {
+ if (!fxMesa->HavePixExt ||
+ ((ctx->Color.BlendEquationRGB != GL_FUNC_SUBTRACT) &&
+ (ctx->Color.BlendEquationRGB != GL_FUNC_REVERSE_SUBTRACT))) {
+ return FX_FALLBACK_BLEND;
+ }
+ }
+
+ if (ctx->Color.BlendEquationA != GL_FUNC_ADD) {
+ if (!fxMesa->HavePixExt ||
+ ((ctx->Color.BlendEquationA != GL_FUNC_SUBTRACT) &&
+ (ctx->Color.BlendEquationA != GL_FUNC_REVERSE_SUBTRACT))) {
+ return FX_FALLBACK_BLEND;
+ }
+ }
+
+#if 0
+ /* [dBorca]
+ * We fail the spec here, unless certain blending modes:
+ * RGB: (GL_ONE + GL_*) or (GL_ZERO + GL_*) or ...
+ */
+ if (NEED_SECONDARY_COLOR(ctx)) {
+ if ((ctx->Color.BlendEquationRGB != GL_FUNC_ADD) &&
+ (ctx->Color.BlendSrcRGB != GL_ONE)) {
+ /* Can't use multipass to blend ColorSum stage */
+ return FX_FALLBACK_SPECULAR;
+ }
+ }
+#endif
+ }
+
+ /* [dBorca]
+ * We could avoid this for certain `sfactor/dfactor'
+ * I do not think that is even worthwhile to check
+ * because if someone is using blending they use more
+ * interesting settings and also it would add more
+ * state tracking to a lot of the code.
+ */
+ if (ctx->Color.ColorLogicOpEnabled && (ctx->Color.LogicOp != GL_COPY)) {
+ return FX_FALLBACK_LOGICOP;
+ }
+
+ if ((fxMesa->colDepth != 32) &&
+ ((ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP]) ||
+ (ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]))) {
+ return FX_FALLBACK_COLORMASK;
+ }
+
+ /* Unsupported texture/multitexture cases */
+
+ /* we can only do 1D/2D textures */
+ if (ctx->Texture.Unit[0]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
+ return FX_FALLBACK_TEXTURE_MAP;
+
+ if (fxMesa->haveTwoTMUs) {
+ if (ctx->Texture.Unit[1]._ReallyEnabled & ~(TEXTURE_1D_BIT|TEXTURE_2D_BIT))
+ return FX_FALLBACK_TEXTURE_MAP;
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled) {
+ if (fxMesa->type < GR_SSTTYPE_Voodoo2)
+ if (ctx->Texture.Unit[0].EnvMode == GL_BLEND &&
+ (ctx->Texture.Unit[1]._ReallyEnabled ||
+ ctx->Texture.Unit[0].EnvColor[0] != 0 ||
+ ctx->Texture.Unit[0].EnvColor[1] != 0 ||
+ ctx->Texture.Unit[0].EnvColor[2] != 0 ||
+ ctx->Texture.Unit[0].EnvColor[3] != 1)) {
+ return FX_FALLBACK_TEXTURE_ENV;
+ }
+ if (ctx->Texture.Unit[0]._Current->Image[0][0]->Border > 0)
+ return FX_FALLBACK_TEXTURE_BORDER;
+ }
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled) {
+ if (fxMesa->type < GR_SSTTYPE_Voodoo2)
+ if (ctx->Texture.Unit[1].EnvMode == GL_BLEND)
+ return FX_FALLBACK_TEXTURE_ENV;
+ if (ctx->Texture.Unit[1]._Current->Image[0][0]->Border > 0)
+ return FX_FALLBACK_TEXTURE_BORDER;
+ }
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fx_check_IsInHardware: envmode is %s/%s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+ /* KW: This was wrong (I think) and I changed it... which doesn't mean
+ * it is now correct...
+ * BP: The old condition just seemed to test if both texture units
+ * were enabled. That's easy!
+ */
+ if (ctx->Texture._EnabledUnits == 0x3) {
+#if 0
+ /* Can't use multipass to blend a multitextured triangle - fall
+ * back to software.
+ */
+ if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled) {
+ return FX_FALLBACK_TEXTURE_MULTI;
+ }
+#endif
+
+ if (!fxMesa->HaveCmbExt &&
+ (ctx->Texture.Unit[0].EnvMode != ctx->Texture.Unit[1].EnvMode) &&
+ (ctx->Texture.Unit[0].EnvMode != GL_MODULATE) &&
+ (ctx->Texture.Unit[0].EnvMode != GL_REPLACE)) { /* q2, seems ok... */
+ if (TDFX_DEBUG & VERBOSE_DRIVER)
+ fprintf(stderr, "fx_check_IsInHardware: unsupported multitex env mode\n");
+ return FX_FALLBACK_TEXTURE_MULTI;
+ }
+ }
+ }
+ else {
+ /* we have just one texture unit */
+ if (ctx->Texture._EnabledUnits > 0x1) {
+ return FX_FALLBACK_TEXTURE_MULTI;
+ }
+
+ if (fxMesa->type < GR_SSTTYPE_Voodoo2)
+ if (ctx->Texture.Unit[0]._ReallyEnabled &&
+ (ctx->Texture.Unit[0].EnvMode == GL_BLEND)) {
+ return FX_FALLBACK_TEXTURE_ENV;
+ }
+ }
+
+ return 0;
+}
+
+
+
+static void
+fxDDUpdateDDPointers(GLcontext * ctx, GLuint new_state)
+{
+ /* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDUpdateDDPointers(%08x)\n", new_state);
+ }
+
+ _swrast_InvalidateState(ctx, new_state);
+ _ac_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+
+ fxMesa->new_gl_state |= new_state;
+}
+
+
+
+
+void
+fxSetupDDPointers(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+/* TNLcontext *tnl = TNL_CONTEXT(ctx);*/
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDDPointers()\n");
+ }
+
+ ctx->Driver.UpdateState = fxDDUpdateDDPointers;
+ ctx->Driver.GetString = fxDDGetString;
+ ctx->Driver.ClearIndex = NULL;
+ ctx->Driver.ClearColor = fxDDClearColor;
+ ctx->Driver.Clear = fxDDClear;
+ ctx->Driver.DrawBuffer = fxDDSetDrawBuffer;
+ ctx->Driver.GetBufferSize = fxDDBufferSize;
+ switch (fxMesa->colDepth) {
+ case 15:
+ ctx->Driver.DrawPixels = fxDDDrawPixels555;
+ ctx->Driver.ReadPixels = fxDDReadPixels555;
+ ctx->Driver.Bitmap = fxDDDrawBitmap2;
+ break;
+ case 16:
+ ctx->Driver.DrawPixels = !fxMesa->bgrOrder ? fxDDDrawPixels565 : fxDDDrawPixels565_rev;
+ ctx->Driver.ReadPixels = fxDDReadPixels565;
+ ctx->Driver.Bitmap = fxDDDrawBitmap2;
+ break;
+ case 32:
+ ctx->Driver.DrawPixels = fxDDDrawPixels8888;
+ ctx->Driver.ReadPixels = fxDDReadPixels8888;
+ ctx->Driver.Bitmap = fxDDDrawBitmap4;
+ break;
+ }
+ ctx->Driver.Finish = fxDDFinish;
+ ctx->Driver.Flush = NULL;
+ ctx->Driver.ChooseTextureFormat = fxDDChooseTextureFormat;
+ ctx->Driver.TexImage1D = fxDDTexImage1D;
+ ctx->Driver.TexImage2D = fxDDTexImage2D;
+ ctx->Driver.TexSubImage1D = fxDDTexSubImage1D;
+ ctx->Driver.TexSubImage2D = fxDDTexSubImage2D;
+ ctx->Driver.CompressedTexImage2D = fxDDCompressedTexImage2D;
+ ctx->Driver.CompressedTexSubImage2D = fxDDCompressedTexSubImage2D;
+ ctx->Driver.TestProxyTexImage = fxDDTestProxyTexImage;
+ ctx->Driver.TexEnv = fxDDTexEnv;
+ ctx->Driver.TexParameter = fxDDTexParam;
+ ctx->Driver.BindTexture = fxDDTexBind;
+ ctx->Driver.DeleteTexture = fxDDTexDel;
+ ctx->Driver.IsTextureResident = fxDDIsTextureResident;
+ ctx->Driver.UpdateTexturePalette = fxDDTexPalette;
+ ctx->Driver.AlphaFunc = fxDDAlphaFunc;
+ ctx->Driver.BlendFuncSeparate = fxDDBlendFuncSeparate;
+ ctx->Driver.BlendEquationSeparate = fxDDBlendEquationSeparate;
+ ctx->Driver.DepthFunc = fxDDDepthFunc;
+ ctx->Driver.DepthMask = fxDDDepthMask;
+ ctx->Driver.ColorMask = fxDDColorMask;
+ ctx->Driver.Fogfv = fxDDFogfv;
+ ctx->Driver.Scissor = fxDDScissor;
+ ctx->Driver.FrontFace = fxDDFrontFace;
+ ctx->Driver.CullFace = fxDDCullFace;
+ ctx->Driver.ShadeModel = fxDDShadeModel;
+ ctx->Driver.Enable = fxDDEnable;
+ if (fxMesa->haveHwStencil) {
+ ctx->Driver.StencilFunc = fxDDStencilFunc;
+ ctx->Driver.StencilMask = fxDDStencilMask;
+ ctx->Driver.StencilOp = fxDDStencilOp;
+ }
+
+ fxSetupDDSpanPointers(ctx);
+ fxDDUpdateDDPointers(ctx, ~0);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_dd(void);
+int
+gl_fx_dummy_function_dd(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddspan.c b/src/mesa/drivers/glide/fxddspan.c
new file mode 100644
index 0000000..ff52252
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddspan.c
@@ -0,0 +1,659 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+
+/* fxdd.c - 3Dfx VooDoo Mesa span and pixel functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "fxglidew.h"
+#include "swrast/swrast.h"
+
+
+/************************************************************************/
+/***** Span functions *****/
+/************************************************************************/
+
+#define DBG 0
+
+
+#define LOCAL_VARS \
+ GLuint pitch = info.strideInBytes; \
+ GLuint height = fxMesa->height; \
+ char *buf = (char *)((char *)info.lfbPtr + 0 /* x, y offset */); \
+ GLuint p; \
+ (void) buf; (void) p;
+
+#define CLIPPIXEL( _x, _y ) ( _x >= minx && _x < maxx && \
+ _y >= miny && _y < maxy )
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx;\
+ if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
+ }
+
+#define Y_FLIP(_y) (height - _y - 1)
+
+#define HW_WRITE_LOCK() \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GrLfbInfo_t info; \
+ info.size = sizeof(GrLfbInfo_t); \
+ if ( grLfbLock( GR_LFB_WRITE_ONLY, \
+ fxMesa->currentFB, LFB_MODE, \
+ GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) {
+
+#define HW_WRITE_UNLOCK() \
+ grLfbUnlock( GR_LFB_WRITE_ONLY, fxMesa->currentFB ); \
+ }
+
+#define HW_READ_LOCK() \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GrLfbInfo_t info; \
+ info.size = sizeof(GrLfbInfo_t); \
+ if ( grLfbLock( GR_LFB_READ_ONLY, fxMesa->currentFB, \
+ LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) {
+
+#define HW_READ_UNLOCK() \
+ grLfbUnlock( GR_LFB_READ_ONLY, fxMesa->currentFB ); \
+ }
+
+#define HW_WRITE_CLIPLOOP() \
+ do { \
+ /* remember, we need to flip the scissor, too */ \
+ /* is it better to do it inside fxDDScissor? */ \
+ const int minx = fxMesa->clipMinX; \
+ const int maxy = Y_FLIP(fxMesa->clipMinY); \
+ const int maxx = fxMesa->clipMaxX; \
+ const int miny = Y_FLIP(fxMesa->clipMaxY);
+
+#define HW_READ_CLIPLOOP() \
+ do { \
+ /* remember, we need to flip the scissor, too */ \
+ /* is it better to do it inside fxDDScissor? */ \
+ const int minx = fxMesa->clipMinX; \
+ const int maxy = Y_FLIP(fxMesa->clipMinY); \
+ const int maxx = fxMesa->clipMaxX; \
+ const int miny = Y_FLIP(fxMesa->clipMaxY);
+
+#define HW_ENDCLIPLOOP() \
+ } while (0)
+
+
+/* 16 bit, ARGB1555 color spanline and pixel functions */
+
+#undef LFB_MODE
+#define LFB_MODE GR_LFBWRITEMODE_1555
+
+#undef BYTESPERPIXEL
+#define BYTESPERPIXEL 2
+
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = TDFXPACKCOLOR1555( color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch) = \
+ TDFXPACKCOLOR1555( r, g, b, a )
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch); \
+ rgba[0] = FX_rgb_scale_5[(p >> 10) & 0x1F]; \
+ rgba[1] = FX_rgb_scale_5[(p >> 5) & 0x1F]; \
+ rgba[2] = FX_rgb_scale_5[ p & 0x1F]; \
+ rgba[3] = (p & 0x8000) ? 255 : 0; \
+ } while (0)
+
+#define TAG(x) tdfx##x##_ARGB1555
+#include "../dri/common/spantmp.h"
+
+
+/* 16 bit, RGB565 color spanline and pixel functions */
+/* [dBorca] Hack alert:
+ * This is wrong. The alpha value is lost, even when we provide
+ * HW alpha (565 w/o depth buffering). To really update alpha buffer,
+ * we would need to do the 565 writings via 8888 colorformat and rely
+ * on the Voodoo to perform color scaling. In which case our 565 span
+ * would look nicer! But this violates FSAA rules...
+ */
+
+#undef LFB_MODE
+#define LFB_MODE GR_LFBWRITEMODE_565
+
+#undef BYTESPERPIXEL
+#define BYTESPERPIXEL 2
+
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = TDFXPACKCOLOR565( color[RCOMP], color[GCOMP], color[BCOMP] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch) = \
+ TDFXPACKCOLOR565( r, g, b )
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch); \
+ rgba[0] = FX_rgb_scale_5[(p >> 11) & 0x1F]; \
+ rgba[1] = FX_rgb_scale_6[(p >> 5) & 0x3F]; \
+ rgba[2] = FX_rgb_scale_5[ p & 0x1F]; \
+ rgba[3] = 0xff; \
+ } while (0)
+
+#define TAG(x) tdfx##x##_RGB565
+#include "../dri/common/spantmp.h"
+
+
+/* 32 bit, ARGB8888 color spanline and pixel functions */
+
+#undef LFB_MODE
+#define LFB_MODE GR_LFBWRITEMODE_8888
+
+#undef BYTESPERPIXEL
+#define BYTESPERPIXEL 4
+
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = TDFXPACKCOLOR8888( color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLuint *)(buf + _x*BYTESPERPIXEL + _y*pitch) = \
+ TDFXPACKCOLOR8888( r, g, b, a )
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLuint *)(buf + _x*BYTESPERPIXEL + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLuint p = *(GLuint *)(buf + _x*BYTESPERPIXEL + _y*pitch); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+ } while (0)
+
+#define TAG(x) tdfx##x##_ARGB8888
+#include "../dri/common/spantmp.h"
+
+
+/************************************************************************/
+/***** Depth functions *****/
+/************************************************************************/
+
+#define DBG 0
+
+#undef HW_WRITE_LOCK
+#undef HW_WRITE_UNLOCK
+#undef HW_READ_LOCK
+#undef HW_READ_UNLOCK
+
+#define HW_CLIPLOOP HW_WRITE_CLIPLOOP
+
+#define LOCAL_DEPTH_VARS \
+ GLuint pitch = info.strideInBytes; \
+ GLuint height = fxMesa->height; \
+ char *buf = (char *)((char *)info.lfbPtr + 0 /* x, y offset */); \
+ (void) buf;
+
+#define HW_WRITE_LOCK() \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GrLfbInfo_t info; \
+ info.size = sizeof(GrLfbInfo_t); \
+ if ( grLfbLock( GR_LFB_WRITE_ONLY, \
+ GR_BUFFER_AUXBUFFER, LFB_MODE, \
+ GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) {
+
+#define HW_WRITE_UNLOCK() \
+ grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_AUXBUFFER); \
+ }
+
+#define HW_READ_LOCK() \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GrLfbInfo_t info; \
+ info.size = sizeof(GrLfbInfo_t); \
+ if ( grLfbLock( GR_LFB_READ_ONLY, GR_BUFFER_AUXBUFFER, \
+ LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) {
+
+#define HW_READ_UNLOCK() \
+ grLfbUnlock( GR_LFB_READ_ONLY, GR_BUFFER_AUXBUFFER); \
+ }
+
+
+/* 16 bit, depth spanline and pixel functions */
+
+#undef LFB_MODE
+#define LFB_MODE GR_LFBWRITEMODE_ZA16
+
+#undef BYTESPERPIXEL
+#define BYTESPERPIXEL 2
+
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch) = d
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLushort *)(buf + _x*BYTESPERPIXEL + _y*pitch)
+
+#define TAG(x) tdfx##x##_Z16
+#include "../dri/common/depthtmp.h"
+
+
+/* 24 bit, depth spanline and pixel functions (for use w/ stencil) */
+/* [dBorca] Hack alert:
+ * This is evil. The incoming Mesa's 24bit depth value
+ * is shifted left 8 bits, to obtain a full 32bit value,
+ * which will be thrown into the framebuffer. We rely on
+ * the fact that Voodoo hardware transforms a 32bit value
+ * into 24bit value automatically and, MOST IMPORTANT, won't
+ * alter the upper 8bits of the value already existing in the
+ * framebuffer (where stencil resides).
+ */
+
+#undef LFB_MODE
+#define LFB_MODE GR_LFBWRITEMODE_Z32
+
+#undef BYTESPERPIXEL
+#define BYTESPERPIXEL 4
+
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLuint *)(buf + _x*BYTESPERPIXEL + _y*pitch) = d << 8
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = (*(GLuint *)(buf + _x*BYTESPERPIXEL + _y*pitch)) & 0xffffff
+
+#define TAG(x) tdfx##x##_Z24
+#include "../dri/common/depthtmp.h"
+
+
+/* 32 bit, depth spanline and pixel functions (for use w/o stencil) */
+/* [dBorca] Hack alert:
+ * This is more evil. We make Mesa run in 32bit depth, but
+ * tha Voodoo HW can only handle 24bit depth. Well, exploiting
+ * the pixel pipeline, we can achieve 24:8 format for greater
+ * precision...
+ * If anyone tells me how to really store 32bit values into the
+ * depth buffer, I'll write the *_Z32 routines. Howver, bear in
+ * mind that means running without stencil!
+ */
+
+/************************************************************************/
+/***** Span functions (optimized) *****/
+/************************************************************************/
+
+/*
+ * Read a span of 15-bit RGB pixels. Note, we don't worry about cliprects
+ * since OpenGL says obscured pixels have undefined values.
+ */
+static void fxReadRGBASpan_ARGB1555 (const GLcontext * ctx,
+ GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ info.size = sizeof(GrLfbInfo_t);
+ if (grLfbLock(GR_LFB_READ_ONLY, fxMesa->currentFB,
+ GR_LFBWRITEMODE_ANY, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
+ const GLint winX = 0;
+ const GLint winY = fxMesa->height - 1;
+ const GLushort *data16 = (const GLushort *)((const GLubyte *)info.lfbPtr +
+ (winY - y) * info.strideInBytes +
+ (winX + x) * 2);
+ const GLuint *data32 = (const GLuint *) data16;
+ GLuint i, j;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+
+ for (i = j = 0; i < n; i += 2, j++) {
+ GLuint pixel = data32[j];
+ rgba[i][0] = FX_rgb_scale_5[(pixel >> 10) & 0x1F];
+ rgba[i][1] = FX_rgb_scale_5[(pixel >> 5) & 0x1F];
+ rgba[i][2] = FX_rgb_scale_5[ pixel & 0x1F];
+ rgba[i][3] = (pixel & 0x8000) ? 255 : 0;
+ rgba[i+1][0] = FX_rgb_scale_5[(pixel >> 26) & 0x1F];
+ rgba[i+1][1] = FX_rgb_scale_5[(pixel >> 21) & 0x1F];
+ rgba[i+1][2] = FX_rgb_scale_5[(pixel >> 16) & 0x1F];
+ rgba[i+1][3] = (pixel & 0x80000000) ? 255 : 0;
+ }
+ if (extraPixel) {
+ GLushort pixel = data16[n];
+ rgba[n][0] = FX_rgb_scale_5[(pixel >> 10) & 0x1F];
+ rgba[n][1] = FX_rgb_scale_5[(pixel >> 5) & 0x1F];
+ rgba[n][2] = FX_rgb_scale_5[ pixel & 0x1F];
+ rgba[n][3] = (pixel & 0x8000) ? 255 : 0;
+ }
+
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ }
+}
+
+/*
+ * Read a span of 16-bit RGB pixels. Note, we don't worry about cliprects
+ * since OpenGL says obscured pixels have undefined values.
+ */
+static void fxReadRGBASpan_RGB565 (const GLcontext * ctx,
+ GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrLfbInfo_t info;
+ info.size = sizeof(GrLfbInfo_t);
+ if (grLfbLock(GR_LFB_READ_ONLY, fxMesa->currentFB,
+ GR_LFBWRITEMODE_ANY, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
+ const GLint winX = 0;
+ const GLint winY = fxMesa->height - 1;
+ const GLushort *data16 = (const GLushort *)((const GLubyte *)info.lfbPtr +
+ (winY - y) * info.strideInBytes +
+ (winX + x) * 2);
+ const GLuint *data32 = (const GLuint *) data16;
+ GLuint i, j;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+
+ for (i = j = 0; i < n; i += 2, j++) {
+ GLuint pixel = data32[j];
+ rgba[i][0] = FX_rgb_scale_5[(pixel >> 11) & 0x1F];
+ rgba[i][1] = FX_rgb_scale_6[(pixel >> 5) & 0x3F];
+ rgba[i][2] = FX_rgb_scale_5[ pixel & 0x1F];
+ rgba[i][3] = 255;
+ rgba[i+1][0] = FX_rgb_scale_5[(pixel >> 27) & 0x1F];
+ rgba[i+1][1] = FX_rgb_scale_6[(pixel >> 21) & 0x3F];
+ rgba[i+1][2] = FX_rgb_scale_5[(pixel >> 16) & 0x1F];
+ rgba[i+1][3] = 255;
+ }
+ if (extraPixel) {
+ GLushort pixel = data16[n];
+ rgba[n][0] = FX_rgb_scale_5[(pixel >> 11) & 0x1F];
+ rgba[n][1] = FX_rgb_scale_6[(pixel >> 5) & 0x3F];
+ rgba[n][2] = FX_rgb_scale_5[ pixel & 0x1F];
+ rgba[n][3] = 255;
+ }
+
+ grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
+ }
+}
+
+/*
+ * Read a span of 32-bit RGB pixels. Note, we don't worry about cliprects
+ * since OpenGL says obscured pixels have undefined values.
+ */
+static void fxReadRGBASpan_ARGB8888 (const GLcontext * ctx,
+ GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint i;
+ grLfbReadRegion(fxMesa->currentFB, x, fxMesa->height - 1 - y, n, 1, n * 4, rgba);
+ for (i = 0; i < n; i++) {
+ GLubyte c = rgba[i][0];
+ rgba[i][0] = rgba[i][2];
+ rgba[i][2] = c;
+ }
+}
+
+
+/************************************************************************/
+/***** Depth functions (optimized) *****/
+/************************************************************************/
+
+static void
+fxReadDepthSpan_Z16(GLcontext * ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLint bottom = fxMesa->height - 1;
+ GLushort depth16[MAX_WIDTH];
+ GLuint i;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxReadDepthSpan_Z16(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth16);
+ for (i = 0; i < n; i++) {
+ depth[i] = depth16[i];
+ }
+}
+
+
+static void
+fxReadDepthSpan_Z24(GLcontext * ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLint bottom = fxMesa->height - 1;
+ GLuint i;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxReadDepthSpan_Z24(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth);
+ for (i = 0; i < n; i++) {
+ depth[i] &= 0xffffff;
+ }
+}
+
+
+/************************************************************************/
+/***** Stencil functions (optimized) *****/
+/************************************************************************/
+
+static void
+fxWriteStencilSpan (GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLstencil stencil[], const GLubyte mask[])
+{
+ /*
+ * XXX todo
+ */
+}
+
+static void
+fxReadStencilSpan(GLcontext * ctx,
+ GLuint n, GLint x, GLint y, GLstencil stencil[])
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLint bottom = fxMesa->height - 1;
+ GLuint zs32[MAX_WIDTH];
+ GLuint i;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxReadStencilSpan(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, zs32);
+ for (i = 0; i < n; i++) {
+ stencil[i] = zs32[i] >> 24;
+ }
+}
+
+static void
+fxWriteStencilPixels (GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLstencil stencil[],
+ const GLubyte mask[])
+{
+ /*
+ * XXX todo
+ */
+}
+
+static void
+fxReadStencilPixels (GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLstencil stencil[])
+{
+ /*
+ * XXX todo
+ */
+}
+
+
+
+/*
+ * 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
+fxDDSetBuffer(GLcontext * ctx, GLframebuffer * buffer, GLuint bufferBit)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ (void) buffer;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDSetBuffer(%x)\n", (int)bufferBit);
+ }
+
+ if (bufferBit == DD_FRONT_LEFT_BIT) {
+ fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ }
+ else if (bufferBit == DD_BACK_LEFT_BIT) {
+ fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ }
+}
+
+
+/************************************************************************/
+
+
+
+void
+fxSetupDDSpanPointers(GLcontext * ctx)
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ swdd->SetBuffer = fxDDSetBuffer;
+
+ switch (fxMesa->colDepth) {
+ case 15:
+ swdd->WriteRGBASpan = tdfxWriteRGBASpan_ARGB1555;
+ swdd->WriteRGBSpan = tdfxWriteRGBSpan_ARGB1555;
+ swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_ARGB1555;
+ swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_ARGB1555;
+ swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_ARGB1555;
+ swdd->ReadRGBASpan = /*td*/fxReadRGBASpan_ARGB1555;
+ swdd->ReadRGBAPixels = tdfxReadRGBAPixels_ARGB1555;
+
+ swdd->WriteDepthSpan = tdfxWriteDepthSpan_Z16;
+ swdd->WriteDepthPixels = tdfxWriteDepthPixels_Z16;
+ swdd->ReadDepthSpan = /*td*/fxReadDepthSpan_Z16;
+ swdd->ReadDepthPixels = tdfxReadDepthPixels_Z16;
+ break;
+ case 16:
+ swdd->WriteRGBASpan = tdfxWriteRGBASpan_RGB565;
+ swdd->WriteRGBSpan = tdfxWriteRGBSpan_RGB565;
+ swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_RGB565;
+ swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_RGB565;
+ swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_RGB565;
+ swdd->ReadRGBASpan = /*td*/fxReadRGBASpan_RGB565;
+ swdd->ReadRGBAPixels = tdfxReadRGBAPixels_RGB565;
+
+ swdd->WriteDepthSpan = tdfxWriteDepthSpan_Z16;
+ swdd->WriteDepthPixels = tdfxWriteDepthPixels_Z16;
+ swdd->ReadDepthSpan = /*td*/fxReadDepthSpan_Z16;
+ swdd->ReadDepthPixels = tdfxReadDepthPixels_Z16;
+ break;
+ case 32:
+ swdd->WriteRGBASpan = tdfxWriteRGBASpan_ARGB8888;
+ swdd->WriteRGBSpan = tdfxWriteRGBSpan_ARGB8888;
+ swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_ARGB8888;
+ swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_ARGB8888;
+ swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_ARGB8888;
+ swdd->ReadRGBASpan = /*td*/fxReadRGBASpan_ARGB8888;
+ swdd->ReadRGBAPixels = tdfxReadRGBAPixels_ARGB8888;
+
+ swdd->WriteDepthSpan = tdfxWriteDepthSpan_Z24;
+ swdd->WriteDepthPixels = tdfxWriteDepthPixels_Z24;
+ swdd->ReadDepthSpan = /*td*/fxReadDepthSpan_Z24;
+ swdd->ReadDepthPixels = tdfxReadDepthPixels_Z24;
+ break;
+ }
+
+ if (fxMesa->haveHwStencil) {
+ swdd->WriteStencilSpan = fxWriteStencilSpan;
+ swdd->ReadStencilSpan = fxReadStencilSpan;
+ swdd->WriteStencilPixels = fxWriteStencilPixels;
+ swdd->ReadStencilPixels = fxReadStencilPixels;
+ }
+#if 0
+ swdd->WriteCI8Span = NULL;
+ swdd->WriteCI32Span = NULL;
+ swdd->WriteMonoCISpan = NULL;
+ swdd->WriteCI32Pixels = NULL;
+ swdd->WriteMonoCIPixels = NULL;
+ swdd->ReadCI32Span = NULL;
+ swdd->ReadCI32Pixels = NULL;
+
+ swdd->SpanRenderStart = tdfxSpanRenderStart; /* BEGIN_BOARD_LOCK */
+ swdd->SpanRenderFinish = tdfxSpanRenderFinish; /* END_BOARD_LOCK */
+#endif
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_span(void);
+int
+gl_fx_dummy_function_span(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddtex.c b/src/mesa/drivers/glide/fxddtex.c
new file mode 100644
index 0000000..ea9bb1d
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddtex.c
@@ -0,0 +1,1849 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+#include "image.h"
+#include "teximage.h"
+#include "texformat.h"
+#include "texcompress.h"
+#include "texobj.h"
+#include "texstore.h"
+
+
+/* no borders! can't halve 1x1! (stride > width * comp) not allowed */
+static void
+_mesa_halve2x2_teximage2d ( GLcontext *ctx,
+ struct gl_texture_image *texImage,
+ GLuint bytesPerPixel,
+ GLint srcWidth, GLint srcHeight,
+ const GLvoid *srcImage, GLvoid *dstImage )
+{
+ GLint i, j, k;
+ GLint dstWidth = srcWidth / 2;
+ GLint dstHeight = srcHeight / 2;
+ GLint srcRowStride = srcWidth * bytesPerPixel;
+ GLubyte *src = (GLubyte *)srcImage;
+ GLubyte *dst = dstImage;
+
+ GLuint bpt = 0;
+ GLubyte *_s = NULL;
+ GLubyte *_d = NULL;
+ GLenum _t = 0;
+
+ if (texImage->TexFormat->MesaFormat == MESA_FORMAT_RGB565) {
+ _t = GL_UNSIGNED_SHORT_5_6_5_REV;
+ bpt = bytesPerPixel;
+ } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB4444) {
+ _t = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+ bpt = bytesPerPixel;
+ } else if (texImage->TexFormat->MesaFormat == MESA_FORMAT_ARGB1555) {
+ _t = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ bpt = bytesPerPixel;
+ }
+ if (bpt) {
+ bytesPerPixel = 4;
+ srcRowStride = srcWidth * bytesPerPixel;
+ if (dstWidth == 0) {
+ dstWidth = 1;
+ }
+ if (dstHeight == 0) {
+ dstHeight = 1;
+ }
+ _s = src = MALLOC(srcRowStride * srcHeight);
+ _d = dst = MALLOC(dstWidth * bytesPerPixel * dstHeight);
+ _mesa_texstore_rgba8888(ctx, 2, GL_RGBA,
+ &_mesa_texformat_rgba8888_rev, src,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ srcRowStride, /* dstRowStride */
+ 0, /* dstImageStride */
+ srcWidth, srcHeight, 1,
+ texImage->Format, _t, srcImage, &ctx->DefaultPacking);
+ }
+
+ if (srcHeight == 1) {
+ for (i = 0; i < dstWidth; i++) {
+ for (k = 0; k < bytesPerPixel; k++) {
+ dst[0] = (src[0] + src[bytesPerPixel] + 1) / 2;
+ src++;
+ dst++;
+ }
+ src += bytesPerPixel;
+ }
+ } else if (srcWidth == 1) {
+ for (j = 0; j < dstHeight; j++) {
+ for (k = 0; k < bytesPerPixel; k++) {
+ dst[0] = (src[0] + src[srcRowStride] + 1) / 2;
+ src++;
+ dst++;
+ }
+ src += srcRowStride;
+ }
+ } else {
+ for (j = 0; j < dstHeight; j++) {
+ for (i = 0; i < dstWidth; i++) {
+ for (k = 0; k < bytesPerPixel; k++) {
+ dst[0] = (src[0] +
+ src[bytesPerPixel] +
+ src[srcRowStride] +
+ src[srcRowStride + bytesPerPixel] + 2) / 4;
+ src++;
+ dst++;
+ }
+ src += bytesPerPixel;
+ }
+ src += srcRowStride;
+ }
+ }
+
+ if (bpt) {
+ src = _s;
+ dst = _d;
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ texImage->TexFormat, dstImage,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstWidth * bpt,
+ 0, /* dstImageStride */
+ dstWidth, dstHeight, 1,
+ GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking);
+ FREE(dst);
+ FREE(src);
+ }
+}
+
+
+#if 0
+void
+fxPrintTextureData(tfxTexInfo * ti)
+{
+ fprintf(stderr, "Texture Data:\n");
+ if (ti->tObj) {
+ fprintf(stderr, "\tName: %d\n", ti->tObj->Name);
+ fprintf(stderr, "\tBaseLevel: %d\n", ti->tObj->BaseLevel);
+ fprintf(stderr, "\tSize: %d x %d\n",
+ ti->tObj->Image[0][ti->tObj->BaseLevel]->Width,
+ ti->tObj->Image[0][ti->tObj->BaseLevel]->Height);
+ }
+ else
+ fprintf(stderr, "\tName: UNNAMED\n");
+ fprintf(stderr, "\tLast used: %d\n", ti->lastTimeUsed);
+ fprintf(stderr, "\tTMU: %ld\n", ti->whichTMU);
+ fprintf(stderr, "\t%s\n", (ti->isInTM) ? "In TMU" : "Not in TMU");
+ if (ti->tm[0])
+ fprintf(stderr, "\tMem0: %x-%x\n", (unsigned) ti->tm[0]->startAddr,
+ (unsigned) ti->tm[0]->endAddr);
+ if (ti->tm[1])
+ fprintf(stderr, "\tMem1: %x-%x\n", (unsigned) ti->tm[1]->startAddr,
+ (unsigned) ti->tm[1]->endAddr);
+ fprintf(stderr, "\tMipmaps: %d-%d\n", ti->minLevel, ti->maxLevel);
+ fprintf(stderr, "\tFilters: min %d max %d\n",
+ (int) ti->minFilt, (int) ti->maxFilt);
+ fprintf(stderr, "\tClamps: s %d t %d\n", (int) ti->sClamp,
+ (int) ti->tClamp);
+ fprintf(stderr, "\tScales: s %f t %f\n", ti->sScale, ti->tScale);
+ fprintf(stderr, "\t%s\n",
+ (ti->fixedPalette) ? "Fixed palette" : "Non fixed palette");
+ fprintf(stderr, "\t%s\n", (ti->validated) ? "Validated" : "Not validated");
+}
+#endif
+
+
+/************************************************************************/
+/*************************** Texture Mapping ****************************/
+/************************************************************************/
+
+static void
+fxTexInvalidate(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+
+ ti = fxTMGetTexInfo(tObj);
+ if (ti->isInTM)
+ fxTMMoveOutTM(fxMesa, tObj); /* TO DO: SLOW but easy to write */
+
+ ti->validated = GL_FALSE;
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+}
+
+static tfxTexInfo *
+fxAllocTexObjData(fxMesaContext fxMesa)
+{
+ tfxTexInfo *ti;
+
+ if (!(ti = CALLOC(sizeof(tfxTexInfo)))) {
+ fprintf(stderr, "fxAllocTexObjData: ERROR: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->validated = GL_FALSE;
+ ti->isInTM = GL_FALSE;
+
+ ti->whichTMU = FX_TMU_NONE;
+
+ ti->tm[FX_TMU0] = NULL;
+ ti->tm[FX_TMU1] = NULL;
+
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
+
+ ti->sClamp = GR_TEXTURECLAMP_WRAP;
+ ti->tClamp = GR_TEXTURECLAMP_WRAP;
+
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXFALSE;
+
+ return ti;
+}
+
+void
+fxDDTexBind(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexBind(%d, %x)\n", tObj->Name, (GLuint)tObj->DriverData);
+ }
+
+ if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
+ return;
+
+ if (!tObj->DriverData) {
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ }
+ ti = fxTMGetTexInfo(tObj);
+
+ fxMesa->texBindNumber++;
+ ti->lastTimeUsed = fxMesa->texBindNumber;
+
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+}
+
+void
+fxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
+ const GLfloat * param)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ if (param)
+ fprintf(stderr, "fxDDTexEnv(%x, %x)\n", pname, (GLint) (*param));
+ else
+ fprintf(stderr, "fxDDTexEnv(%x)\n", pname);
+ }
+
+ /* apply any lod biasing right now */
+ if (pname == GL_TEXTURE_LOD_BIAS_EXT) {
+ GLfloat bias = *param;
+ CLAMP_SELF(bias, -ctx->Const.MaxTextureLodBias,
+ ctx->Const.MaxTextureLodBias - 0.25);
+
+ grTexLodBiasValue(GR_TMU0, bias);
+
+ if (fxMesa->haveTwoTMUs) {
+ grTexLodBiasValue(GR_TMU1, bias);
+ }
+
+ }
+
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+}
+
+void
+fxDDTexParam(GLcontext * ctx, GLenum target, struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat * params)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLenum param = (GLenum) (GLint) params[0];
+ tfxTexInfo *ti;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexParam(%d, %x, %s, %s)\n",
+ tObj->Name, (GLuint) tObj->DriverData,
+ _mesa_lookup_enum_by_nr(pname),
+ _mesa_lookup_enum_by_nr(param));
+ }
+
+ if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
+ return;
+
+ if (!tObj->DriverData)
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ ti = fxTMGetTexInfo(tObj);
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ switch (param) {
+ case GL_NEAREST:
+ ti->mmMode = GR_MIPMAP_DISABLE;
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_LINEAR:
+ ti->mmMode = GR_MIPMAP_DISABLE;
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ /* [dBorca]
+ * currently Napalm can't do single-pass trilinear,
+ * because the way its combiners are set. So we fall back
+ * to GL_NEAREST_MIPMAP_NEAREST. We'll let true trilinear
+ * enabled for V2, V3.
+ */
+ if (!fxMesa->HaveCmbExt) {
+ if (fxMesa->haveTwoTMUs) {
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXTRUE;
+ } else {
+ ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend = FXFALSE;
+ }
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ }
+ case GL_NEAREST_MIPMAP_NEAREST:
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->minFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend = FXFALSE;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ /* [dBorca]
+ * currently Napalm can't do single-pass trilinear,
+ * because the way its combiners are set. So we fall back
+ * to GL_LINEAR_MIPMAP_NEAREST. We'll let true trilinear
+ * enabled for V2, V3.
+ */
+ if (!fxMesa->HaveCmbExt) {
+ if (fxMesa->haveTwoTMUs) {
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->LODblend = FXTRUE;
+ } else {
+ ti->mmMode = GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend = FXFALSE;
+ }
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ break;
+ }
+ case GL_LINEAR_MIPMAP_NEAREST:
+ ti->mmMode = GR_MIPMAP_NEAREST;
+ ti->minFilt = GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend = FXFALSE;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx, tObj);
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ switch (param) {
+ case GL_NEAREST:
+ ti->maxFilt = GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR:
+ ti->maxFilt = GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ switch (param) {
+ case GL_MIRRORED_REPEAT:
+ ti->sClamp = GR_TEXTURECLAMP_MIRROR_EXT;
+ break;
+ case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
+ case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
+ case GL_CLAMP:
+ ti->sClamp = GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->sClamp = GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ break;
+
+ case GL_TEXTURE_WRAP_T:
+ switch (param) {
+ case GL_MIRRORED_REPEAT:
+ ti->tClamp = GR_TEXTURECLAMP_MIRROR_EXT;
+ break;
+ case GL_CLAMP_TO_BORDER: /* no-no, but don't REPEAT, either */
+ case GL_CLAMP_TO_EDGE: /* CLAMP discarding border */
+ case GL_CLAMP:
+ ti->tClamp = GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->tClamp = GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ /* TO DO */
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ fxTexInvalidate(ctx, tObj);
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ fxTexInvalidate(ctx, tObj);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+fxDDTexDel(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexDel(%d, %p)\n", tObj->Name, (void *) ti);
+ }
+
+ if (!ti)
+ return;
+
+ fxTMFreeTexture(fxMesa, tObj);
+
+ FREE(ti);
+ tObj->DriverData = NULL;
+
+ /* Free mipmap images and the texture object itself */
+ _mesa_delete_texture_object(ctx, tObj);
+}
+
+
+/**
+ * Allocate a new texture object.
+ * Called via ctx->Driver.NewTextureObject.
+ * Note: this function will be called during context creation to
+ * allocate the default texture objects.
+ */
+struct gl_texture_object *
+fxDDNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct gl_texture_object *obj;
+ obj = _mesa_new_texture_object(ctx, name, target);
+ return obj;
+}
+
+
+/*
+ * Return true if texture is resident, false otherwise.
+ */
+GLboolean
+fxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ return (ti && ti->isInTM);
+}
+
+
+
+/*
+ * Convert a gl_color_table texture palette to Glide's format.
+ */
+static GrTexTable_t
+convertPalette(const fxMesaContext fxMesa, FxU32 data[256], const struct gl_color_table *table)
+{
+ const GLubyte *tableUB = (const GLubyte *) table->Table;
+ GLint width = table->Size;
+ FxU32 r, g, b, a;
+ GLint i;
+
+ ASSERT(table->Type == GL_UNSIGNED_BYTE);
+
+ switch (table->Format) {
+ case GL_INTENSITY:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i];
+ g = tableUB[i];
+ b = tableUB[i];
+ a = tableUB[i];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
+ case GL_LUMINANCE:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i];
+ g = tableUB[i];
+ b = tableUB[i];
+ a = 255;
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return GR_TEXTABLE_PALETTE;
+ case GL_ALPHA:
+ for (i = 0; i < width; i++) {
+ r = g = b = 255;
+ a = tableUB[i];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
+ case GL_LUMINANCE_ALPHA:
+ for (i = 0; i < width; i++) {
+ r = g = b = tableUB[i * 2 + 0];
+ a = tableUB[i * 2 + 1];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
+ default:
+ case GL_RGB:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i * 3 + 0];
+ g = tableUB[i * 3 + 1];
+ b = tableUB[i * 3 + 2];
+ a = 255;
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return GR_TEXTABLE_PALETTE;
+ case GL_RGBA:
+ for (i = 0; i < width; i++) {
+ r = tableUB[i * 4 + 0];
+ g = tableUB[i * 4 + 1];
+ b = tableUB[i * 4 + 2];
+ a = tableUB[i * 4 + 3];
+ data[i] = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ return fxMesa->HavePalExt ? GR_TEXTABLE_PALETTE_6666_EXT : GR_TEXTABLE_PALETTE;
+ }
+}
+
+
+void
+fxDDTexPalette(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (tObj) {
+ /* per-texture palette */
+ tfxTexInfo *ti;
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexPalette(%d, %x)\n",
+ tObj->Name, (GLuint) tObj->DriverData);
+ }
+ /* This might be a proxy texture. */
+ if (!tObj->Palette.Table)
+ return;
+ if (!tObj->DriverData)
+ tObj->DriverData = fxAllocTexObjData(fxMesa);
+ ti = fxTMGetTexInfo(tObj);
+ ti->paltype = convertPalette(fxMesa, ti->palette.data, &tObj->Palette);
+ fxTexInvalidate(ctx, tObj);
+ }
+ else {
+ /* global texture palette */
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexPalette(global)\n");
+ }
+ fxMesa->glbPalType = convertPalette(fxMesa, fxMesa->glbPalette.data, &ctx->Texture.Palette);
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+
+ grTexDownloadTable(fxMesa->glbPalType, &(fxMesa->glbPalette));
+ }
+}
+
+
+void
+fxDDTexUseGlbPalette(GLcontext * ctx, GLboolean state)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxDDTexUseGlbPalette(%d)\n", state);
+ }
+
+ fxMesa->haveGlobalPaletteTexture = state;
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+}
+
+
+static int
+logbase2(int n)
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n < 0) {
+ return -1;
+ }
+
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return -1;
+ }
+ else {
+ return log2;
+ }
+}
+
+
+/* fxTexGetInfo
+ * w, h - source texture width and height
+ * lodlevel - Glide lod level token for the larger texture dimension
+ * ar - Glide aspect ratio token
+ * sscale - S scale factor used during triangle setup
+ * tscale - T scale factor used during triangle setup
+ * wscale - OpenGL -> Glide image width scale factor
+ * hscale - OpenGL -> Glide image height scale factor
+ */
+int
+fxTexGetInfo(int w, int h, GrLOD_t * lodlevel, GrAspectRatio_t * ar,
+ float *sscale, float *tscale,
+ int *wscale, int *hscale)
+{
+ int logw, logh, ws, hs;
+ GrLOD_t l;
+ GrAspectRatio_t aspectratio;
+ float s, t;
+
+ logw = logbase2(w);
+ logh = logbase2(h);
+
+ l = MAX2(logw, logh);
+ aspectratio = logw - logh;
+ ws = hs = 1;
+ s = t = 256.0f;
+
+ /* hardware only allows a maximum aspect ratio of 8x1, so handle
+ * |aspectratio| > 3 by scaling the image and using an 8x1 aspect
+ * ratio
+ */
+ switch (aspectratio) {
+ case 0:
+ break;
+ case 1:
+ t = 128.0f;
+ break;
+ case 2:
+ t = 64.0f;
+ break;
+ case 3:
+ t = 32.0f;
+ break;
+ case -1:
+ s = 128.0f;
+ break;
+ case -2:
+ s = 64.0f;
+ break;
+ case -3:
+ s = 32.0f;
+ break;
+ default:
+ if (aspectratio > 3) {
+ t = 32.0f;
+ hs = 1 << (aspectratio - 3);
+ aspectratio = GR_ASPECT_LOG2_8x1;
+ } else /*if (aspectratio < -3)*/ {
+ s = 32.0f;
+ ws = 1 << (-aspectratio - 3);
+ aspectratio = GR_ASPECT_LOG2_1x8;
+ }
+ }
+
+ if (lodlevel)
+ (*lodlevel) = l;
+
+ if (ar)
+ (*ar) = aspectratio;
+
+ if (sscale)
+ (*sscale) = s;
+
+ if (tscale)
+ (*tscale) = t;
+
+ if (wscale)
+ (*wscale) = ws;
+
+ if (hscale)
+ (*hscale) = hs;
+
+
+ return 1;
+}
+
+static GLboolean
+fxIsTexSupported(GLenum target, GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ if ((target != GL_TEXTURE_1D) && (target != GL_TEXTURE_2D))
+ return GL_FALSE;
+
+#if 0
+ if (!fxTexGetInfo(image->Width, image->Height, NULL, NULL, NULL, NULL, NULL, NULL))
+ return GL_FALSE;
+#endif
+
+ if (image->Border > 0)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**********************************************************************/
+/**** NEW TEXTURE IMAGE FUNCTIONS ****/
+/**********************************************************************/
+extern void
+fxt1_decode_1 (const void *texture, int width,
+ int i, int j, unsigned char *rgba);
+
+/* Texel-fetch functions for software texturing and glGetTexImage().
+ * We should have been able to use some "standard" fetch functions (which
+ * may get defined in texutil.c) but we have to account for scaled texture
+ * images on tdfx hardware (the 8:1 aspect ratio limit).
+ * Hence, we need special functions here.
+ */
+
+static void
+fetch_intensity8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLubyte *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = *texel;
+ rgba[GCOMP] = *texel;
+ rgba[BCOMP] = *texel;
+ rgba[ACOMP] = *texel;
+}
+
+
+static void
+fetch_luminance8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLubyte *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = *texel;
+ rgba[GCOMP] = *texel;
+ rgba[BCOMP] = *texel;
+ rgba[ACOMP] = 255;
+}
+
+
+static void
+fetch_alpha8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLubyte *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = 255;
+ rgba[GCOMP] = 255;
+ rgba[BCOMP] = 255;
+ rgba[ACOMP] = *texel;
+}
+
+
+static void
+fetch_index8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *indexOut)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLubyte *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLubyte *) texImage->Data) + j * mml->width + i;
+ *indexOut = *texel;
+}
+
+
+static void
+fetch_luminance8_alpha8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLubyte *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLubyte *) texImage->Data) + (j * mml->width + i) * 2;
+ rgba[RCOMP] = texel[0];
+ rgba[GCOMP] = texel[0];
+ rgba[BCOMP] = texel[0];
+ rgba[ACOMP] = texel[1];
+}
+
+
+static void
+fetch_r5g6b5(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLushort *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLushort *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 11) & 0x1F];
+ rgba[GCOMP] = FX_rgb_scale_6[(*texel >> 5) & 0x3F];
+ rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
+ rgba[ACOMP] = 255;
+}
+
+
+static void
+fetch_r4g4b4a4(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLushort *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLushort *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = FX_rgb_scale_4[(*texel >> 8) & 0xF];
+ rgba[GCOMP] = FX_rgb_scale_4[(*texel >> 4) & 0xF];
+ rgba[BCOMP] = FX_rgb_scale_4[ *texel & 0xF];
+ rgba[ACOMP] = FX_rgb_scale_4[(*texel >> 12) & 0xF];
+}
+
+
+static void
+fetch_r5g5b5a1(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLushort *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLushort *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = FX_rgb_scale_5[(*texel >> 10) & 0x1F];
+ rgba[GCOMP] = FX_rgb_scale_5[(*texel >> 5) & 0x1F];
+ rgba[BCOMP] = FX_rgb_scale_5[ *texel & 0x1F];
+ rgba[ACOMP] = (*texel >> 15) * 255;
+}
+
+
+static void
+fetch_a8r8g8b8(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ const GLuint *texel;
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ texel = ((GLuint *) texImage->Data) + j * mml->width + i;
+ rgba[RCOMP] = (((*texel) >> 16) & 0xff);
+ rgba[GCOMP] = (((*texel) >> 8) & 0xff);
+ rgba[BCOMP] = (((*texel) ) & 0xff);
+ rgba[ACOMP] = (((*texel) >> 24) & 0xff);
+}
+
+
+static void
+fetch_rgb_fxt1(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
+ rgba[ACOMP] = 255;
+}
+
+
+static void
+fetch_rgba_fxt1(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ fxt1_decode_1(texImage->Data, mml->width, i, j, rgba);
+}
+
+
+static void
+fetch_rgb_dxt1(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ _mesa_texformat_rgb_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt1(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ _mesa_texformat_rgba_dxt1.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt3(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ _mesa_texformat_rgba_dxt3.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+static void
+fetch_rgba_dxt5(const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *rgba)
+{
+ const tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ i = i * mml->wScale;
+ j = j * mml->hScale;
+
+ _mesa_texformat_rgba_dxt5.FetchTexel2D(texImage, i, j, k, rgba);
+}
+
+
+#if 0
+static void
+PrintTexture(int w, int h, int c, const GLubyte * data)
+{
+ int i, j;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ if (c == 2)
+ fprintf(stderr, "%02x %02x ", data[0], data[1]);
+ else if (c == 3)
+ fprintf(stderr, "%02x %02x %02x ", data[0], data[1], data[2]);
+ data += c;
+ }
+ fprintf(stderr, "\n");
+ }
+}
+#endif
+
+
+const struct gl_texture_format *
+fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum srcFormat, GLenum srcType )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLboolean allow32bpt = fxMesa->HaveTexFmt;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxDDChooseTextureFormat(...)\n");
+ }
+
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB:
+ /* intentional fall through */
+ case 3:
+ case GL_RGB:
+ if ( srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5 ) {
+ return &_mesa_texformat_rgb565;
+ }
+ /* intentional fall through */
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return (allow32bpt) ? &_mesa_texformat_argb8888
+ : &_mesa_texformat_rgb565;
+ case GL_RGBA2:
+ case GL_RGBA4:
+ return &_mesa_texformat_argb4444;
+ case GL_COMPRESSED_RGBA:
+ /* intentional fall through */
+ case 4:
+ case GL_RGBA:
+ if ( srcFormat == GL_BGRA ) {
+ if ( srcType == GL_UNSIGNED_INT_8_8_8_8_REV ) {
+ return &_mesa_texformat_argb8888;
+ }
+ else if ( srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+ return &_mesa_texformat_argb4444;
+ }
+ else if ( srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+ return &_mesa_texformat_argb1555;
+ }
+ }
+ /* intentional fall through */
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return (allow32bpt) ? &_mesa_texformat_argb8888
+ : &_mesa_texformat_argb4444;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ return &_mesa_texformat_i8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ return &_mesa_texformat_l8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ return &_mesa_texformat_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_ci8;
+ 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:
+ case GL_COMPRESSED_LUMINANCE_ALPHA:
+ return &_mesa_texformat_al88;
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ return &_mesa_texformat_rgb565;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ /* GL_EXT_texture_compression_s3tc */
+ /* GL_S3_s3tc */
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ return &_mesa_texformat_rgb_dxt1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return &_mesa_texformat_rgba_dxt1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ return &_mesa_texformat_rgba_dxt3;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return &_mesa_texformat_rgba_dxt5;
+ /* GL_3DFX_texture_compression_FXT1 */
+ case GL_COMPRESSED_RGB_FXT1_3DFX:
+ return &_mesa_texformat_rgb_fxt1;
+ case GL_COMPRESSED_RGBA_FXT1_3DFX:
+ return &_mesa_texformat_rgba_fxt1;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+
+static GrTextureFormat_t
+fxGlideFormat(GLint mesaFormat)
+{
+ switch (mesaFormat) {
+ case MESA_FORMAT_I8:
+ return GR_TEXFMT_ALPHA_8;
+ case MESA_FORMAT_A8:
+ return GR_TEXFMT_ALPHA_8;
+ case MESA_FORMAT_L8:
+ return GR_TEXFMT_INTENSITY_8;
+ case MESA_FORMAT_CI8:
+ return GR_TEXFMT_P_8;
+ case MESA_FORMAT_AL88:
+ return GR_TEXFMT_ALPHA_INTENSITY_88;
+ case MESA_FORMAT_RGB565:
+ return GR_TEXFMT_RGB_565;
+ case MESA_FORMAT_ARGB4444:
+ return GR_TEXFMT_ARGB_4444;
+ case MESA_FORMAT_ARGB1555:
+ return GR_TEXFMT_ARGB_1555;
+ case MESA_FORMAT_ARGB8888:
+ return GR_TEXFMT_ARGB_8888;
+ case MESA_FORMAT_RGB_FXT1:
+ case MESA_FORMAT_RGBA_FXT1:
+ return GR_TEXFMT_ARGB_CMP_FXT1;
+ case MESA_FORMAT_RGB_DXT1:
+ case MESA_FORMAT_RGBA_DXT1:
+ return GR_TEXFMT_ARGB_CMP_DXT1;
+ case MESA_FORMAT_RGBA_DXT3:
+ return GR_TEXFMT_ARGB_CMP_DXT3;
+ case MESA_FORMAT_RGBA_DXT5:
+ return GR_TEXFMT_ARGB_CMP_DXT5;
+ default:
+ _mesa_problem(NULL, "Unexpected format in fxGlideFormat");
+ return 0;
+ }
+}
+
+
+static FetchTexelFuncC
+fxFetchFunction(GLint mesaFormat)
+{
+ switch (mesaFormat) {
+ case MESA_FORMAT_I8:
+ return &fetch_intensity8;
+ case MESA_FORMAT_A8:
+ return &fetch_alpha8;
+ case MESA_FORMAT_L8:
+ return &fetch_luminance8;
+ case MESA_FORMAT_CI8:
+ return &fetch_index8;
+ case MESA_FORMAT_AL88:
+ return &fetch_luminance8_alpha8;
+ case MESA_FORMAT_RGB565:
+ return &fetch_r5g6b5;
+ case MESA_FORMAT_ARGB4444:
+ return &fetch_r4g4b4a4;
+ case MESA_FORMAT_ARGB1555:
+ return &fetch_r5g5b5a1;
+ case MESA_FORMAT_ARGB8888:
+ return &fetch_a8r8g8b8;
+ case MESA_FORMAT_RGB_FXT1:
+ return &fetch_rgb_fxt1;
+ case MESA_FORMAT_RGBA_FXT1:
+ return &fetch_rgba_fxt1;
+ case MESA_FORMAT_RGB_DXT1:
+ return &fetch_rgb_dxt1;
+ case MESA_FORMAT_RGBA_DXT1:
+ return &fetch_rgba_dxt1;
+ case MESA_FORMAT_RGBA_DXT3:
+ return &fetch_rgba_dxt3;
+ case MESA_FORMAT_RGBA_DXT5:
+ return &fetch_rgba_dxt5;
+ default:
+ _mesa_problem(NULL, "Unexpected format in fxFetchFunction");
+ return NULL;
+ }
+}
+
+
+static GLboolean
+adjust2DRatio (GLcontext *ctx,
+ GLint xoffset, GLint yoffset,
+ GLint width, GLint height,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ tfxMipMapLevel *mml,
+ struct gl_texture_image *texImage,
+ GLint texelBytes,
+ GLint dstRowStride)
+{
+ const GLint newWidth = width * mml->wScale;
+ const GLint newHeight = height * mml->hScale;
+ GLvoid *tempImage;
+
+ if (!texImage->IsCompressed) {
+ GLubyte *destAddr;
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ return GL_FALSE;
+ }
+
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ texImage->TexFormat, tempImage,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ width * texelBytes, /* dstRowStride */
+ 0, /* dstImageStride */
+ width, height, 1,
+ format, type, pixels, packing);
+
+ /* now rescale */
+ /* compute address of dest subimage within the overal tex image */
+ destAddr = (GLubyte *) texImage->Data
+ + (yoffset * mml->hScale * mml->width
+ + xoffset * mml->wScale) * texelBytes;
+
+ _mesa_rescale_teximage2d(texelBytes,
+ dstRowStride, /* dst stride */
+ width, height,
+ newWidth, newHeight,
+ tempImage, destAddr);
+ } else {
+ const GLint rawBytes = 4;
+ GLvoid *rawImage = MALLOC(width * height * rawBytes);
+ if (!rawImage) {
+ return GL_FALSE;
+ }
+ tempImage = MALLOC(newWidth * newHeight * rawBytes);
+ if (!tempImage) {
+ return GL_FALSE;
+ }
+ /* unpack image, apply transfer ops and store in rawImage */
+ _mesa_texstore_rgba8888(ctx, 2, GL_RGBA,
+ &_mesa_texformat_rgba8888_rev, rawImage,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ width * rawBytes, /* dstRowStride */
+ 0, /* dstImageStride */
+ width, height, 1,
+ format, type, pixels, packing);
+ _mesa_rescale_teximage2d(rawBytes,
+ newWidth * rawBytes, /* dst stride */
+ width, height, /* src */
+ newWidth, newHeight, /* dst */
+ rawImage /*src*/, tempImage /*dst*/ );
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ texImage->TexFormat, texImage->Data,
+ xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ 0, /* dstImageStride */
+ newWidth, newHeight, 1,
+ GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
+ FREE(rawImage);
+ }
+
+ FREE(tempImage);
+
+ return GL_TRUE;
+}
+
+
+void
+fxDDTexImage2D(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 *texObj,
+ struct gl_texture_image *texImage)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ GLint texelBytes, dstRowStride;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxDDTexImage2D: id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
+ texObj->Name, texImage->IntFormat, format, type,
+ texImage->Width, texImage->Height);
+ }
+
+ if (!fxIsTexSupported(target, internalFormat, texImage)) {
+ _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDTexImg()\n");
+ return;
+ }
+
+ if (!texObj->DriverData) {
+ texObj->DriverData = fxAllocTexObjData(fxMesa);
+ if (!texObj->DriverData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+ ti = fxTMGetTexInfo(texObj);
+
+ if (!texImage->DriverData) {
+ texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
+ if (!texImage->DriverData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+ mml = FX_MIPMAP_DATA(texImage);
+
+ fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
+ &mml->wScale, &mml->hScale);
+
+ mml->width = width * mml->wScale;
+ mml->height = height * mml->hScale;
+
+#if FX_COMPRESS_S3TC_AS_FXT1_HACK
+ /* [koolsmoky] substitute FXT1 for DXTn and Legacy S3TC */
+ if (texImage->IsCompressed) {
+ switch (internalFormat) {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_RGB_S3TC:
+ case GL_RGB4_S3TC:
+ internalFormat = GL_COMPRESSED_RGB_FXT1_3DFX;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_RGBA_S3TC:
+ case GL_RGBA4_S3TC:
+ internalFormat = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ }
+ texImage->IntFormat = internalFormat;
+ }
+#endif
+#if FX_TC_NAPALM
+ if (fxMesa->type >= GR_SSTTYPE_Voodoo4) {
+ GLenum texNapalm = 0;
+ if (internalFormat == GL_COMPRESSED_RGB) {
+ texNapalm = GL_COMPRESSED_RGB_FXT1_3DFX;
+ } else if (internalFormat == GL_COMPRESSED_RGBA) {
+ texNapalm = GL_COMPRESSED_RGBA_FXT1_3DFX;
+ }
+ if (texNapalm) {
+ texImage->IntFormat = internalFormat = texNapalm;
+ texImage->IsCompressed = GL_TRUE;
+ }
+ }
+#endif
+
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, format, type);
+ assert(texImage->TexFormat);
+ texelBytes = texImage->TexFormat->TexelBytes;
+ /*if (!fxMesa->HaveTexFmt) assert(texelBytes == 1 || texelBytes == 2);*/
+
+ mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
+
+ /* allocate mipmap buffer */
+ assert(!texImage->Data);
+ if (texImage->IsCompressed) {
+ texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
+ mml->width,
+ mml->height,
+ 1,
+ internalFormat);
+ dstRowStride = _mesa_compressed_row_stride(internalFormat, mml->width);
+ texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
+ } else {
+ dstRowStride = mml->width * texelBytes;
+ texImage->Data = MESA_PBUFFER_ALLOC(mml->width * mml->height * texelBytes);
+ }
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+
+ if (pixels != NULL) {
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ /* rescale image to overcome 1:8 aspect limitation */
+ if (!adjust2DRatio(ctx,
+ 0, 0,
+ width, height,
+ format, type, pixels,
+ packing,
+ mml,
+ texImage,
+ texelBytes,
+ dstRowStride)
+ ) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ return;
+ }
+ }
+ else {
+ /* no rescaling needed */
+ /* unpack image, apply transfer ops and store in texImage->Data */
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ texImage->TexFormat, texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ 0, /* dstImageStride */
+ width, height, 1,
+ format, type, pixels, packing);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ GLint mipWidth, mipHeight;
+ tfxMipMapLevel *mip;
+ struct gl_texture_image *mipImage;
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
+
+ assert(!texImage->IsCompressed);
+
+ while (level < texObj->MaxLevel && level < maxLevels - 1) {
+ mipWidth = width / 2;
+ if (!mipWidth) {
+ mipWidth = 1;
+ }
+ mipHeight = height / 2;
+ if (!mipHeight) {
+ mipHeight = 1;
+ }
+ if ((mipWidth == width) && (mipHeight == height)) {
+ break;
+ }
+ _mesa_TexImage2D(target, ++level, internalFormat,
+ mipWidth, mipHeight, border,
+ format, type,
+ NULL);
+ mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+ mip = FX_MIPMAP_DATA(mipImage);
+ _mesa_halve2x2_teximage2d(ctx,
+ texImage,
+ texelBytes,
+ mml->width, mml->height,
+ texImage->Data, mipImage->Data);
+ texImage = mipImage;
+ mml = mip;
+ width = mipWidth;
+ height = mipHeight;
+ }
+ }
+ }
+
+ ti->info.format = mml->glideFormat;
+ texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
+
+ fxTexInvalidate(ctx, texObj);
+}
+
+
+void
+fxDDTexSubImage2D(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)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ GLint texelBytes, dstRowStride;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxDDTexSubImage2D: id=%d\n", texObj->Name);
+ }
+
+ if (!texObj->DriverData) {
+ _mesa_problem(ctx, "problem in fxDDTexSubImage2D");
+ return;
+ }
+
+ ti = fxTMGetTexInfo(texObj);
+ assert(ti);
+ mml = FX_MIPMAP_DATA(texImage);
+ assert(mml);
+
+ assert(texImage->Data); /* must have an existing texture image! */
+ assert(texImage->Format);
+
+ texelBytes = texImage->TexFormat->TexelBytes;
+ if (texImage->IsCompressed) {
+ dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat, mml->width);
+ } else {
+ dstRowStride = mml->width * texelBytes;
+ }
+
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ /* need to rescale subimage to match mipmap level's rescale factors */
+ if (!adjust2DRatio(ctx,
+ xoffset, yoffset,
+ width, height,
+ format, type, pixels,
+ packing,
+ mml,
+ texImage,
+ texelBytes,
+ dstRowStride)
+ ) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
+ return;
+ }
+ }
+ else {
+ /* no rescaling needed */
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ texImage->TexFormat, (GLubyte *) texImage->Data,
+ xoffset, yoffset, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ 0, /* dstImageStride */
+ width, height, 1,
+ format, type, pixels, packing);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ GLint mipWidth, mipHeight;
+ tfxMipMapLevel *mip;
+ struct gl_texture_image *mipImage;
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ const GLint maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
+
+ assert(!texImage->IsCompressed);
+
+ width = texImage->Width;
+ height = texImage->Height;
+ while (level < texObj->MaxLevel && level < maxLevels - 1) {
+ mipWidth = width / 2;
+ if (!mipWidth) {
+ mipWidth = 1;
+ }
+ mipHeight = height / 2;
+ if (!mipHeight) {
+ mipHeight = 1;
+ }
+ if ((mipWidth == width) && (mipHeight == height)) {
+ break;
+ }
+ ++level;
+ mipImage = _mesa_select_tex_image(ctx, texUnit, target, level);
+ mip = FX_MIPMAP_DATA(mipImage);
+ _mesa_halve2x2_teximage2d(ctx,
+ texImage,
+ texelBytes,
+ mml->width, mml->height,
+ texImage->Data, mipImage->Data);
+ texImage = mipImage;
+ mml = mip;
+ width = mipWidth;
+ height = mipHeight;
+ }
+ }
+
+ if (ti->validated && ti->isInTM && !texObj->GenerateMipmap)
+ fxTMReloadMipMapLevel(fxMesa, texObj, level);
+ else
+ fxTexInvalidate(ctx, texObj);
+}
+
+
+void
+fxDDCompressedTexImage2D (GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxDDCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
+ texObj->Name, internalFormat,
+ width, height);
+ }
+
+ assert(texImage->IsCompressed);
+
+ if (!fxIsTexSupported(target, internalFormat, texImage)) {
+ _mesa_problem(NULL, "fx Driver: unsupported texture in fxDDCompressedTexImg()\n");
+ return;
+ }
+
+ if (!texObj->DriverData) {
+ texObj->DriverData = fxAllocTexObjData(fxMesa);
+ if (!texObj->DriverData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ return;
+ }
+ }
+ ti = fxTMGetTexInfo(texObj);
+
+ if (!texImage->DriverData) {
+ texImage->DriverData = CALLOC(sizeof(tfxMipMapLevel));
+ if (!texImage->DriverData) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ return;
+ }
+ }
+ mml = FX_MIPMAP_DATA(texImage);
+
+ fxTexGetInfo(width, height, NULL, NULL, NULL, NULL,
+ &mml->wScale, &mml->hScale);
+
+ mml->width = width * mml->wScale;
+ mml->height = height * mml->hScale;
+
+
+ /* choose the texture format */
+ assert(ctx->Driver.ChooseTextureFormat);
+ texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
+ internalFormat, -1/*format*/, -1/*type*/);
+ assert(texImage->TexFormat);
+
+ /* Determine the appropriate Glide texel format,
+ * given the user's internal texture format hint.
+ */
+ mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
+
+ /* allocate new storage for texture image, if needed */
+ if (!texImage->Data) {
+ texImage->CompressedSize = _mesa_compressed_texture_size(ctx,
+ mml->width,
+ mml->height,
+ 1,
+ internalFormat);
+ texImage->Data = MESA_PBUFFER_ALLOC(texImage->CompressedSize);
+ if (!texImage->Data) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
+ return;
+ }
+ }
+
+ /* save the texture data */
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ /* [dBorca] Hack alert:
+ * now we're screwed. We can't decompress,
+ * unless we do it in HW (via textureBuffer).
+ * We still have some chances:
+ * 1) we got FXT1 textures - we CAN decompress, rescale for
+ * aspectratio, then compress back.
+ * 2) there is a chance that MIN("s", "t") won't be overflowed.
+ * Thus, we don't care about textureclamp and we could lower
+ * MIN("uscale", "vscale") below 32. We still have to have
+ * our data aligned inside a 8:1 rectangle.
+ * 3) just in case if MIN("s", "t") gets overflowed with GL_REPEAT,
+ * 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);
+
+ GLuint destRowStride = _mesa_compressed_row_stride(internalFormat,
+ mml->width);
+
+ _mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
+ destRowStride, (mml->height+3) / 4,
+ 1, data, srcRowStride,
+ texImage->Data);
+ ti->padded = GL_TRUE;
+ } else {
+ MEMCPY(texImage->Data, data, texImage->CompressedSize);
+ }
+
+ ti->info.format = mml->glideFormat;
+ texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ assert(!texImage->IsCompressed);
+ }
+
+ fxTexInvalidate(ctx, texObj);
+}
+
+
+void
+fxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
+ GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLint height, GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti;
+ tfxMipMapLevel *mml;
+ GLint destRowStride, srcRowStride;
+ GLint i, rows;
+ GLubyte *dest;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxDDCompressedTexSubImage2D: id=%d\n", texObj->Name);
+ }
+
+ ti = fxTMGetTexInfo(texObj);
+ assert(ti);
+ mml = FX_MIPMAP_DATA(texImage);
+ assert(mml);
+
+ srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
+
+ destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
+ mml->width);
+ dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
+ texImage->IntFormat,
+ mml->width,
+ (GLubyte*) texImage->Data);
+
+ rows = height / 4; /* hardcoded 4, but works for FXT1/DXTC */
+
+ for (i = 0; i < rows; i++) {
+ MEMCPY(dest, data, srcRowStride);
+ dest += destRowStride;
+ data = (GLvoid *)((GLuint)data + (GLuint)srcRowStride);
+ }
+
+ /* [dBorca] Hack alert:
+ * see fxDDCompressedTexImage2D for caveats
+ */
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, texImage->Width);
+
+ destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
+ mml->width);
+ _mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
+ destRowStride, mml->height / 4,
+ 1, texImage->Data, destRowStride,
+ texImage->Data);
+ }
+
+ /* GL_SGIS_generate_mipmap */
+ if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
+ assert(!texImage->IsCompressed);
+ }
+
+ if (ti->validated && ti->isInTM)
+ fxTMReloadMipMapLevel(fxMesa, texObj, level);
+ else
+ fxTexInvalidate(ctx, texObj);
+}
+
+
+void
+fxDDTexImage1D (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)
+{
+ fxDDTexImage2D(ctx, target, level,
+ internalFormat, width, 1, border,
+ format, type, pixels,
+ packing,
+ texObj,
+ texImage);
+}
+
+
+void
+fxDDTexSubImage1D(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)
+{
+ fxDDTexSubImage2D(ctx, target, level,
+ xoffset, 0, width, 1,
+ format, type, pixels,
+ packing,
+ texObj,
+ texImage);
+}
+
+
+GLboolean
+fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLint width, GLint height,
+ GLint depth, GLint border)
+{
+ /* XXX todo - maybe through fxTexValidate() */
+ return _mesa_test_proxy_teximage(ctx, target,
+ level, internalFormat,
+ format, type,
+ width, height,
+ depth, border);
+}
+
+
+#else /* FX */
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_ddtex(void);
+int
+gl_fx_dummy_function_ddtex(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h
new file mode 100644
index 0000000..3f12844
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdrv.h
@@ -0,0 +1,772 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */
+
+
+#ifndef FXDRV_H
+#define FXDRV_H
+
+/* If you comment out this define, a variable takes its place, letting
+ * you turn debugging on/off from the debugger.
+ */
+
+#include "glheader.h"
+
+
+#if defined(__linux__)
+#include <signal.h>
+#endif
+
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mtypes.h"
+
+#include "GL/fxmesa.h"
+#include "fxglidew.h"
+
+#include "math/m_vector.h"
+
+
+/* Define some shorter names for these things.
+ */
+#define XCOORD GR_VERTEX_X_OFFSET
+#define YCOORD GR_VERTEX_Y_OFFSET
+#define ZCOORD GR_VERTEX_OOZ_OFFSET
+#define OOWCOORD GR_VERTEX_OOW_OFFSET
+
+#define S0COORD GR_VERTEX_SOW_TMU0_OFFSET
+#define T0COORD GR_VERTEX_TOW_TMU0_OFFSET
+#define S1COORD GR_VERTEX_SOW_TMU1_OFFSET
+#define T1COORD GR_VERTEX_TOW_TMU1_OFFSET
+
+
+
+#ifdef __i386__
+#define FXCOLOR4( c ) (* (int *)c)
+#else
+#define FXCOLOR4( c ) ( \
+ ( ((unsigned int)(c[3]))<<24 ) | \
+ ( ((unsigned int)(c[2]))<<16 ) | \
+ ( ((unsigned int)(c[1]))<<8 ) | \
+ ( (unsigned int)(c[0])) )
+#endif
+
+#define TDFXPACKCOLOR1555( r, g, b, a ) \
+ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+ ((a) ? 0x8000 : 0))
+#define TDFXPACKCOLOR565( r, g, b ) \
+ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+#define TDFXPACKCOLOR8888( r, g, b, a ) \
+ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+
+
+/* fastpath flags first
+ */
+#define SETUP_TMU0 0x1
+#define SETUP_TMU1 0x2
+#define SETUP_RGBA 0x4
+#define SETUP_SNAP 0x8
+#define SETUP_XYZW 0x10
+#define SETUP_PTEX 0x20
+#define SETUP_PSIZ 0x40
+#define SETUP_SPEC 0x80
+#define SETUP_FOGC 0x100
+#define MAX_SETUP 0x200
+
+
+#define FX_NUM_TMU 2
+
+#define FX_TMU0 GR_TMU0
+#define FX_TMU1 GR_TMU1
+#define FX_TMU_SPLIT 98
+#define FX_TMU_BOTH 99
+#define FX_TMU_NONE 100
+
+/* Used for fxMesa->lastUnitsMode */
+
+#define FX_UM_NONE 0x00000000
+
+#define FX_UM_E0_REPLACE 0x00000001
+#define FX_UM_E0_MODULATE 0x00000002
+#define FX_UM_E0_DECAL 0x00000004
+#define FX_UM_E0_BLEND 0x00000008
+#define FX_UM_E0_ADD 0x00000010
+
+#define FX_UM_E1_REPLACE 0x00000020
+#define FX_UM_E1_MODULATE 0x00000040
+#define FX_UM_E1_DECAL 0x00000080
+#define FX_UM_E1_BLEND 0x00000100
+#define FX_UM_E1_ADD 0x00000200
+
+#define FX_UM_E_ENVMODE 0x000003ff
+
+#define FX_UM_E0_ALPHA 0x00001000
+#define FX_UM_E0_LUMINANCE 0x00002000
+#define FX_UM_E0_LUMINANCE_ALPHA 0x00004000
+#define FX_UM_E0_INTENSITY 0x00008000
+#define FX_UM_E0_RGB 0x00010000
+#define FX_UM_E0_RGBA 0x00020000
+
+#define FX_UM_E1_ALPHA 0x00040000
+#define FX_UM_E1_LUMINANCE 0x00080000
+#define FX_UM_E1_LUMINANCE_ALPHA 0x00100000
+#define FX_UM_E1_INTENSITY 0x00200000
+#define FX_UM_E1_RGB 0x00400000
+#define FX_UM_E1_RGBA 0x00800000
+
+#define FX_UM_E_IFMT 0x00fff000
+
+#define FX_UM_COLOR_ITERATED 0x01000000
+#define FX_UM_COLOR_CONSTANT 0x02000000
+#define FX_UM_ALPHA_ITERATED 0x04000000
+#define FX_UM_ALPHA_CONSTANT 0x08000000
+
+
+/* for Voodoo3/Banshee's grColorCombine() and grAlphaCombine() */
+struct tdfx_combine {
+ GrCombineFunction_t Function; /* Combine function */
+ GrCombineFactor_t Factor; /* Combine scale factor */
+ GrCombineLocal_t Local; /* Local combine source */
+ GrCombineOther_t Other; /* Other combine source */
+ FxBool Invert; /* Combine result inversion flag */
+};
+
+/* for Voodoo3's grTexCombine() */
+struct tdfx_texcombine {
+ GrCombineFunction_t FunctionRGB;
+ GrCombineFactor_t FactorRGB;
+ GrCombineFunction_t FunctionAlpha;
+ GrCombineFactor_t FactorAlpha;
+ FxBool InvertRGB;
+ FxBool InvertAlpha;
+};
+
+
+/* for Voodoo5's grColorCombineExt() */
+struct tdfx_combine_color_ext {
+ GrCCUColor_t SourceA;
+ GrCombineMode_t ModeA;
+ GrCCUColor_t SourceB;
+ GrCombineMode_t ModeB;
+ GrCCUColor_t SourceC;
+ FxBool InvertC;
+ GrCCUColor_t SourceD;
+ FxBool InvertD;
+ FxU32 Shift;
+ FxBool Invert;
+};
+
+/* for Voodoo5's grAlphaCombineExt() */
+struct tdfx_combine_alpha_ext {
+ GrACUColor_t SourceA;
+ GrCombineMode_t ModeA;
+ GrACUColor_t SourceB;
+ GrCombineMode_t ModeB;
+ GrACUColor_t SourceC;
+ FxBool InvertC;
+ GrACUColor_t SourceD;
+ FxBool InvertD;
+ FxU32 Shift;
+ FxBool Invert;
+};
+
+/* for Voodoo5's grTexColorCombineExt() */
+struct tdfx_color_texenv {
+ GrTCCUColor_t SourceA;
+ GrCombineMode_t ModeA;
+ GrTCCUColor_t SourceB;
+ GrCombineMode_t ModeB;
+ GrTCCUColor_t SourceC;
+ FxBool InvertC;
+ GrTCCUColor_t SourceD;
+ FxBool InvertD;
+ FxU32 Shift;
+ FxBool Invert;
+};
+
+/* for Voodoo5's grTexAlphaCombineExt() */
+struct tdfx_alpha_texenv {
+ GrTACUColor_t SourceA;
+ GrCombineMode_t ModeA;
+ GrTACUColor_t SourceB;
+ GrCombineMode_t ModeB;
+ GrTACUColor_t SourceC;
+ FxBool InvertC;
+ GrTCCUColor_t SourceD;
+ FxBool InvertD;
+ FxU32 Shift;
+ FxBool Invert;
+};
+
+/* Voodoo5's texture combine environment */
+struct tdfx_texcombine_ext {
+ struct tdfx_alpha_texenv Alpha;
+ struct tdfx_color_texenv Color;
+ GrColor_t EnvColor;
+};
+
+
+/*
+ Memory range from startAddr to endAddr-1
+*/
+typedef struct MemRange_t
+{
+ struct MemRange_t *next;
+ FxU32 startAddr, endAddr;
+}
+MemRange;
+
+typedef struct
+{
+ GLsizei width, height; /* image size */
+ GLint wScale, hScale; /* image scale factor */
+ GrTextureFormat_t glideFormat; /* Glide image format */
+}
+tfxMipMapLevel;
+
+/*
+ * TDFX-specific texture object data. This hangs off of the
+ * struct gl_texture_object DriverData pointer.
+ */
+typedef struct tfxTexInfo_t
+{
+ struct tfxTexInfo_t *next;
+ struct gl_texture_object *tObj;
+
+ GLuint lastTimeUsed;
+ FxU32 whichTMU;
+ GLboolean isInTM;
+
+ MemRange *tm[FX_NUM_TMU];
+
+ GLint minLevel, maxLevel;
+ GLint baseLevelInternalFormat;
+
+ GrTexInfo info;
+
+ GrTextureFilterMode_t minFilt;
+ GrTextureFilterMode_t maxFilt;
+ FxBool LODblend;
+
+ GrTextureClampMode_t sClamp;
+ GrTextureClampMode_t tClamp;
+
+ GrMipMapMode_t mmMode;
+
+ GLfloat sScale, tScale;
+
+ GrTexTable_t paltype;
+ GuTexPalette palette;
+
+ GLboolean fixedPalette;
+ GLboolean validated;
+
+ GLboolean padded;
+}
+tfxTexInfo;
+
+typedef struct
+{
+ GLuint swapBuffer;
+ GLuint reqTexUpload;
+ GLuint texUpload;
+ GLuint memTexUpload;
+}
+tfxStats;
+
+
+
+typedef struct
+{
+ /* Alpha test */
+
+ GLboolean alphaTestEnabled;
+ GrCmpFnc_t alphaTestFunc;
+ GLfloat alphaTestRefValue;
+
+ /* Blend function */
+
+ GLboolean blendEnabled;
+ GrAlphaBlendFnc_t blendSrcFuncRGB;
+ GrAlphaBlendFnc_t blendDstFuncRGB;
+ GrAlphaBlendFnc_t blendSrcFuncAlpha;
+ GrAlphaBlendFnc_t blendDstFuncAlpha;
+ GrAlphaBlendOp_t blendEqRGB;
+ GrAlphaBlendOp_t blendEqAlpha;
+
+ /* Depth test */
+
+ GLboolean depthTestEnabled;
+ GLboolean depthMask;
+ GrCmpFnc_t depthTestFunc;
+ FxI32 depthBias;
+
+ /* Stencil */
+
+ GLboolean stencilEnabled;
+ GrCmpFnc_t stencilFunction; /* Stencil function */
+ GrStencil_t stencilRefValue; /* Stencil reference value */
+ GrStencil_t stencilValueMask; /* Value mask */
+ GrStencil_t stencilWriteMask; /* Write mask */
+ GrCmpFnc_t stencilFailFunc; /* Stencil fail function */
+ GrCmpFnc_t stencilZFailFunc; /* Stencil pass, depth fail function */
+ GrCmpFnc_t stencilZPassFunc; /* Stencil pass, depth pass function */
+ GrStencil_t stencilClear; /* Buffer clear value */
+}
+tfxUnitsState;
+
+
+
+
+/* Flags for fxMesa->new_state
+ */
+#define FX_NEW_TEXTURING 0x1
+#define FX_NEW_BLEND 0x2
+#define FX_NEW_ALPHA 0x4
+#define FX_NEW_DEPTH 0x8
+#define FX_NEW_FOG 0x10
+#define FX_NEW_SCISSOR 0x20
+#define FX_NEW_COLOR_MASK 0x40
+#define FX_NEW_CULL 0x80
+#define FX_NEW_STENCIL 0x100
+
+
+#define FX_CONTEXT(ctx) ((fxMesaContext)((ctx)->DriverCtx))
+
+#define FX_TEXTURE_DATA(texUnit) fxTMGetTexInfo((texUnit)->_Current)
+
+#define fxTMGetTexInfo(o) ((tfxTexInfo*)((o)->DriverData))
+
+#define FX_MIPMAP_DATA(img) ((tfxMipMapLevel *) (img)->DriverData)
+
+#define BEGIN_BOARD_LOCK()
+#define END_BOARD_LOCK()
+#define BEGIN_CLIP_LOOP()
+#define END_CLIP_LOOP()
+
+
+
+
+/* Covers the state referenced by IsInHardware:
+ */
+#define _FX_NEW_IS_IN_HARDWARE (_NEW_TEXTURE| \
+ _NEW_HINT| \
+ _NEW_STENCIL| \
+ _NEW_BUFFERS| \
+ _NEW_COLOR| \
+ _NEW_LIGHT)
+
+/* Covers the state referenced by fxDDChooseRenderState
+ */
+#define _FX_NEW_RENDERSTATE (_FX_NEW_IS_IN_HARDWARE | \
+ _DD_NEW_FLATSHADE | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE| \
+ _DD_NEW_TRI_OFFSET | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_SMOOTH | \
+ _DD_NEW_TRI_STIPPLE | \
+ _DD_NEW_LINE_SMOOTH | \
+ _DD_NEW_LINE_STIPPLE | \
+ _DD_NEW_LINE_WIDTH | \
+ _DD_NEW_POINT_SMOOTH | \
+ _DD_NEW_POINT_SIZE | \
+ _NEW_LINE)
+
+
+/* Covers the state referenced by fxDDChooseSetupFunction.
+ */
+#define _FX_NEW_SETUP_FUNCTION (_NEW_LIGHT| \
+ _NEW_FOG| \
+ _NEW_TEXTURE| \
+ _NEW_COLOR) \
+
+
+/* lookup table for scaling y bit colors up to 8 bits */
+extern GLuint FX_rgb_scale_4[16];
+extern GLuint FX_rgb_scale_5[32];
+extern GLuint FX_rgb_scale_6[64];
+
+typedef void (*fx_tri_func) (fxMesaContext, GrVertex *, GrVertex *, GrVertex *);
+typedef void (*fx_line_func) (fxMesaContext, GrVertex *, GrVertex *);
+typedef void (*fx_point_func) (fxMesaContext, GrVertex *);
+
+struct tfxMesaContext
+{
+ GrTexTable_t glbPalType;
+ GuTexPalette glbPalette;
+
+ GLcontext *glCtx; /* the core Mesa context */
+ GLvisual *glVis; /* describes the color buffer */
+ GLframebuffer *glBuffer; /* the ancillary buffers */
+
+ GLint board; /* the board used for this context */
+ GLint width, height; /* size of color buffer */
+
+ GrBuffer_t currentFB;
+
+ GLboolean bgrOrder;
+ GrColor_t color;
+ GrColor_t clearC;
+ GrAlpha_t clearA;
+ GLuint constColor;
+ GrCullMode_t cullMode;
+
+ tfxUnitsState unitsState;
+ tfxUnitsState restoreUnitsState; /* saved during multipass */
+
+
+ GLuint new_state;
+ GLuint new_gl_state;
+
+ /* Texture Memory Manager Data
+ */
+ GLuint texBindNumber;
+ GLint tmuSrc;
+ GLuint lastUnitsMode;
+ GLuint freeTexMem[FX_NUM_TMU];
+ MemRange *tmPool;
+ MemRange *tmFree[FX_NUM_TMU];
+
+ GLenum fogTableMode;
+ GLfloat fogDensity;
+ GLfloat fogStart, fogEnd;
+ GrFog_t *fogTable;
+ GLint textureAlign;
+ GLint textureMaxLod;
+
+ /* Vertex building and storage:
+ */
+ GLuint tmu_source[FX_NUM_TMU];
+ GLuint SetupIndex;
+ GLuint stw_hint_state; /* for grHints */
+ GrVertex *verts;
+ GLboolean snapVertices; /* needed for older Voodoo hardware */
+
+ /* Rasterization:
+ */
+ GLuint render_index;
+ GLuint fallback;
+ GLenum render_primitive;
+ GLenum raster_primitive;
+
+ /* Current rasterization functions
+ */
+ fx_point_func draw_point;
+ fx_line_func draw_line;
+ fx_tri_func draw_tri;
+
+
+ /* Keep texture scales somewhere handy:
+ */
+ GLfloat s0scale;
+ GLfloat s1scale;
+ GLfloat t0scale;
+ GLfloat t1scale;
+
+ GLfloat inv_s0scale;
+ GLfloat inv_s1scale;
+ GLfloat inv_t0scale;
+ GLfloat inv_t1scale;
+
+ /* Glide stuff
+ */
+ tfxStats stats;
+ void *state;
+
+ /* Options */
+
+ GLboolean verbose;
+ GLboolean haveTwoTMUs; /* True if we really have 2 tmu's */
+ GLboolean haveHwAlpha;
+ GLboolean haveHwStencil;
+ GLboolean haveZBuffer;
+ GLboolean haveDoubleBuffer;
+ GLboolean haveGlobalPaletteTexture;
+ GLint swapInterval;
+ GLint maxPendingSwapBuffers;
+
+ GrContext_t glideContext;
+
+ int screen_width;
+ int screen_height;
+ int clipMinX;
+ int clipMaxX;
+ int clipMinY;
+ int clipMaxY;
+
+ int colDepth;
+ GLboolean fsaa;
+
+ /* Glide (per card) capabilities. These get mirrored
+ * from `glbHWConfig' when creating a new context...
+ */
+ GrSstType type;
+ FxBool HavePalExt; /* PALETTE6666 */
+ FxBool HavePixExt; /* PIXEXT */
+ FxBool HaveTexFmt; /* TEXFMT */
+ FxBool HaveCmbExt; /* COMBINE */
+ FxBool HaveMirExt; /* TEXMIRROR */
+ FxBool HaveTexUma; /* TEXUMA */
+ FxBool HaveTexus2; /* Texus 2 - FXT1 */
+ struct tdfx_glide Glide;
+ char rendererString[64];
+};
+
+
+extern void fxSetupFXUnits(GLcontext *);
+extern void fxSetupDDPointers(GLcontext *);
+
+/* fxvb.c:
+ */
+extern void fxAllocVB(GLcontext * ctx);
+extern void fxFreeVB(GLcontext * ctx);
+#if 0
+extern void fxPrintSetupFlags(char *msg, GLuint flags );
+#endif
+extern void fxCheckTexSizes( GLcontext *ctx );
+extern void fxBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint newinputs );
+extern void fxChooseVertexState( GLcontext *ctx );
+
+
+
+
+
+
+/* fxtrifuncs:
+ */
+extern void fxDDInitTriFuncs(GLcontext *);
+extern void fxDDChooseRenderState(GLcontext * ctx);
+
+
+extern void fxUpdateDDSpanPointers(GLcontext *);
+extern void fxSetupDDSpanPointers(GLcontext *);
+
+extern void fxPrintTextureData(tfxTexInfo * ti);
+
+extern const struct gl_texture_format *
+fxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum srcFormat, GLenum srcType );
+extern void fxDDTexImage2D(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 *texObj,
+ struct gl_texture_image *texImage);
+extern void fxDDTexSubImage2D(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);
+extern void fxDDCompressedTexImage2D(GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+extern void fxDDCompressedTexSubImage2D(GLcontext *ctx, GLenum target,
+ GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width,
+ GLint height, GLenum format,
+ GLsizei imageSize, const GLvoid *data,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+extern void fxDDTexImage1D(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);
+extern void fxDDTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+ GLint xoffset, GLint width,
+ GLenum format, GLenum type,
+ const GLvoid * pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage);
+extern GLboolean fxDDTestProxyTexImage (GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLint width, GLint height,
+ GLint depth, GLint border);
+extern void fxDDTexEnv(GLcontext *, GLenum, GLenum, const GLfloat *);
+extern void fxDDTexParam(GLcontext *, GLenum, struct gl_texture_object *,
+ GLenum, const GLfloat *);
+extern void fxDDTexBind(GLcontext *, GLenum, struct gl_texture_object *);
+extern struct gl_texture_object *fxDDNewTextureObject( GLcontext *ctx, GLuint name, GLenum target );
+extern void fxDDTexDel(GLcontext *, struct gl_texture_object *);
+extern GLboolean fxDDIsTextureResident(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexPalette(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexUseGlbPalette(GLcontext *, GLboolean);
+
+extern void fxDDEnable(GLcontext *, GLenum, GLboolean);
+extern void fxDDAlphaFunc(GLcontext *, GLenum, GLfloat);
+extern void fxDDBlendFuncSeparate(GLcontext *, GLenum, GLenum, GLenum, GLenum);
+extern void fxDDBlendEquationSeparate(GLcontext *, GLenum, GLenum);
+extern void fxDDDepthMask(GLcontext *, GLboolean);
+extern void fxDDDepthFunc(GLcontext *, GLenum);
+extern void fxDDStencilFunc (GLcontext *ctx, GLenum func, GLint ref, GLuint mask);
+extern void fxDDStencilMask (GLcontext *ctx, GLuint mask);
+extern void fxDDStencilOp (GLcontext *ctx, GLenum sfail, GLenum zfail, GLenum zpass);
+
+extern void fxDDInitExtensions(GLcontext * ctx);
+
+extern void fxTMInit(fxMesaContext ctx);
+extern void fxTMClose(fxMesaContext ctx);
+extern void fxTMRestoreTextures_NoLock(fxMesaContext ctx);
+extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint);
+extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *);
+#define fxTMMoveOutTM_NoLock fxTMMoveOutTM
+extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *);
+extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *,
+ GLint);
+extern void fxTMReloadSubMipMapLevel(fxMesaContext,
+ struct gl_texture_object *, GLint, GLint,
+ GLint);
+extern int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti);
+
+extern void fxTexGetFormat(GLcontext *, GLenum, GrTextureFormat_t *, GLint *); /* [koolsmoky] */
+
+extern int fxTexGetInfo(int, int, GrLOD_t *, GrAspectRatio_t *,
+ float *, float *, int *, int *);
+
+extern void fxDDScissor(GLcontext * ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h);
+extern void fxDDFogfv(GLcontext * ctx, GLenum pname, const GLfloat * params);
+extern void fxDDColorMask(GLcontext * ctx,
+ GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+
+extern void fxDDWriteDepthSpan(GLcontext * ctx, GLuint n, GLint x, GLint y,
+ const GLdepth depth[], const GLubyte mask[]);
+
+extern void fxDDReadDepthSpan(GLcontext * ctx, GLuint n, GLint x, GLint y,
+ GLdepth depth[]);
+
+extern void fxDDWriteDepthPixels(GLcontext * ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLdepth depth[], const GLubyte mask[]);
+
+extern void fxDDReadDepthPixels(GLcontext * ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLdepth depth[]);
+
+extern void fxDDShadeModel(GLcontext * ctx, GLenum mode);
+
+extern void fxDDCullFace(GLcontext * ctx, GLenum mode);
+extern void fxDDFrontFace(GLcontext * ctx, GLenum mode);
+
+extern void fxPrintRenderState(const char *msg, GLuint state);
+extern void fxPrintHintState(const char *msg, GLuint state);
+
+extern int fxDDInitFxMesaContext(fxMesaContext fxMesa);
+extern void fxDDDestroyFxMesaContext(fxMesaContext fxMesa);
+
+
+extern void fxSetScissorValues(GLcontext * ctx);
+extern void fxTMMoveInTM_NoLock(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj, GLint where);
+
+extern void fxCheckIsInHardware(GLcontext *ctx);
+
+/* fxsetup:
+ * semi-private functions
+ */
+void fxSetupCull (GLcontext * ctx);
+void fxSetupScissor (GLcontext * ctx);
+void fxSetupColorMask (GLcontext * ctx);
+void fxSetupBlend (GLcontext *ctx);
+void fxSetupDepthTest (GLcontext *ctx);
+void fxSetupTexture (GLcontext *ctx);
+void fxSetupStencil (GLcontext *ctx);
+
+/* Flags for software fallback cases */
+#define FX_FALLBACK_TEXTURE_MAP 0x0001
+#define FX_FALLBACK_DRAW_BUFFER 0x0002
+#define FX_FALLBACK_SPECULAR 0x0004
+#define FX_FALLBACK_STENCIL 0x0008
+#define FX_FALLBACK_RENDER_MODE 0x0010
+#define FX_FALLBACK_LOGICOP 0x0020
+#define FX_FALLBACK_TEXTURE_ENV 0x0040
+#define FX_FALLBACK_TEXTURE_BORDER 0x0080
+#define FX_FALLBACK_COLORMASK 0x0100
+#define FX_FALLBACK_BLEND 0x0200
+#define FX_FALLBACK_TEXTURE_MULTI 0x0400
+
+extern GLuint fx_check_IsInHardware(GLcontext *ctx);
+
+/***
+ *** CNORM: clamp float to [0,1] and map to float in [0,255]
+ ***/
+#if defined(USE_IEEE) && !defined(DEBUG)
+#define IEEE_0996 0x3f7f0000 /* 0.996 or so */
+#define CNORM(N, F) \
+ do { \
+ fi_type __tmp; \
+ __tmp.f = (F); \
+ if (__tmp.i < 0) \
+ N = 0; \
+ else if (__tmp.i >= IEEE_0996) \
+ N = 255.0f; \
+ else { \
+ N = (F) * 255.0f; \
+ } \
+ } while (0)
+#else
+#define CNORM(n, f) \
+ n = (CLAMP((f), 0.0F, 1.0F) * 255.0F)
+#endif
+
+/* run-time debugging */
+#ifndef FX_DEBUG
+#define FX_DEBUG 0
+#endif
+#if FX_DEBUG
+extern int TDFX_DEBUG;
+#else
+#define TDFX_DEBUG 0
+#endif
+
+/* dirty hacks */
+#define FX_RESCALE_BIG_TEXURES_HACK 1
+#define FX_COMPRESS_S3TC_AS_FXT1_HACK 1
+
+#endif
diff --git a/src/mesa/drivers/glide/fxg.c b/src/mesa/drivers/glide/fxg.c
new file mode 100644
index 0000000..afb9441
--- /dev/null
+++ b/src/mesa/drivers/glide/fxg.c
@@ -0,0 +1,2309 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0.1
+ *
+ * Copyright (C) 1999-2003 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.
+ */
+
+/*
+ * Mesa/FX device driver. Interface to Glide3.
+ *
+ * Copyright (c) 2003 - Daniel Borca
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifdef FX
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#define FX_TRAP_GLIDE_internal
+#include "fxg.h"
+
+
+
+/****************************************************************************\
+* logging *
+\****************************************************************************/
+#if FX_TRAP_GLIDE
+#define TRAP_LOG trp_printf
+#ifdef __GNUC__
+__attribute__ ((format(printf, 1, 2)))
+#endif /* __GNUC__ */
+int trp_printf (const char *format, ...)
+{
+ va_list arg;
+ int n;
+ FILE *trap_file;
+ va_start(arg, format);
+ trap_file = fopen("trap.log", "a");
+ if (trap_file == NULL) {
+ trap_file = stderr;
+ }
+ n = vfprintf(trap_file, format, arg);
+ fclose(trap_file);
+ va_end(arg);
+ return n;
+}
+#else /* FX_TRAP_GLIDE */
+#ifdef __GNUC__
+#define TRAP_LOG(format, ...) do {} while (0)
+#else /* __GNUC__ */
+#define TRAP_LOG 0 && (unsigned long)
+#endif /* __GNUC__ */
+#endif /* FX_TRAP_GLIDE */
+
+
+
+#if FX_TRAP_GLIDE
+/****************************************************************************\
+* helpers *
+\****************************************************************************/
+
+#define GOT "\t"
+
+const char *TRP_BOOL (FxBool b)
+{
+ return b ? "FXTRUE" : "FXFALSE";
+}
+
+#define TRAP_CASE_STRING(name) case name: return #name
+#define TRAP_NODEFAULT default: assert(0)
+
+const char *TRP_PARAM (FxU32 mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_PARAM_DISABLE);
+ TRAP_CASE_STRING(GR_PARAM_ENABLE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_VTX (FxU32 param)
+{
+ switch (param) {
+ TRAP_CASE_STRING(GR_PARAM_XY);
+ TRAP_CASE_STRING(GR_PARAM_Z);
+ TRAP_CASE_STRING(GR_PARAM_W);
+ TRAP_CASE_STRING(GR_PARAM_Q);
+ TRAP_CASE_STRING(GR_PARAM_FOG_EXT);
+ TRAP_CASE_STRING(GR_PARAM_A);
+ TRAP_CASE_STRING(GR_PARAM_RGB);
+ TRAP_CASE_STRING(GR_PARAM_PARGB);
+ TRAP_CASE_STRING(GR_PARAM_ST0);
+ TRAP_CASE_STRING(GR_PARAM_ST1);
+ TRAP_CASE_STRING(GR_PARAM_ST2);
+ TRAP_CASE_STRING(GR_PARAM_Q0);
+ TRAP_CASE_STRING(GR_PARAM_Q1);
+ TRAP_CASE_STRING(GR_PARAM_Q2);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_ARRAY (FxU32 mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_POINTS);
+ TRAP_CASE_STRING(GR_LINE_STRIP);
+ TRAP_CASE_STRING(GR_LINES);
+ TRAP_CASE_STRING(GR_POLYGON);
+ TRAP_CASE_STRING(GR_TRIANGLE_STRIP);
+ TRAP_CASE_STRING(GR_TRIANGLE_FAN);
+ TRAP_CASE_STRING(GR_TRIANGLES);
+ TRAP_CASE_STRING(GR_TRIANGLE_STRIP_CONTINUE);
+ TRAP_CASE_STRING(GR_TRIANGLE_FAN_CONTINUE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_BUFFER (GrBuffer_t buffer)
+{
+ switch (buffer) {
+ TRAP_CASE_STRING(GR_BUFFER_FRONTBUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_BACKBUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_AUXBUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_DEPTHBUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_ALPHABUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_TRIPLEBUFFER);
+ TRAP_CASE_STRING(GR_BUFFER_TEXTUREBUFFER_EXT);
+ TRAP_CASE_STRING(GR_BUFFER_TEXTUREAUXBUFFER_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_ORIGIN (GrOriginLocation_t origin_location)
+{
+ switch (origin_location) {
+ TRAP_CASE_STRING(GR_ORIGIN_UPPER_LEFT);
+ TRAP_CASE_STRING(GR_ORIGIN_LOWER_LEFT);
+ TRAP_CASE_STRING(GR_ORIGIN_ANY);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_REFRESH (GrScreenRefresh_t refresh_rate)
+{
+ switch (refresh_rate) {
+ TRAP_CASE_STRING(GR_REFRESH_60Hz);
+ TRAP_CASE_STRING(GR_REFRESH_70Hz);
+ TRAP_CASE_STRING(GR_REFRESH_72Hz);
+ TRAP_CASE_STRING(GR_REFRESH_75Hz);
+ TRAP_CASE_STRING(GR_REFRESH_80Hz);
+ TRAP_CASE_STRING(GR_REFRESH_90Hz);
+ TRAP_CASE_STRING(GR_REFRESH_100Hz);
+ TRAP_CASE_STRING(GR_REFRESH_85Hz);
+ TRAP_CASE_STRING(GR_REFRESH_120Hz);
+ TRAP_CASE_STRING(GR_REFRESH_NONE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_COLFMT (GrColorFormat_t color_format)
+{
+ switch (color_format) {
+ TRAP_CASE_STRING(GR_COLORFORMAT_ARGB);
+ TRAP_CASE_STRING(GR_COLORFORMAT_ABGR);
+ TRAP_CASE_STRING(GR_COLORFORMAT_RGBA);
+ TRAP_CASE_STRING(GR_COLORFORMAT_BGRA);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_RESOLUTION (GrScreenResolution_t screen_resolution)
+{
+ switch (screen_resolution) {
+ TRAP_CASE_STRING(GR_RESOLUTION_320x200);
+ TRAP_CASE_STRING(GR_RESOLUTION_320x240);
+ TRAP_CASE_STRING(GR_RESOLUTION_400x256);
+ TRAP_CASE_STRING(GR_RESOLUTION_512x384);
+ TRAP_CASE_STRING(GR_RESOLUTION_640x200);
+ TRAP_CASE_STRING(GR_RESOLUTION_640x350);
+ TRAP_CASE_STRING(GR_RESOLUTION_640x400);
+ TRAP_CASE_STRING(GR_RESOLUTION_640x480);
+ TRAP_CASE_STRING(GR_RESOLUTION_800x600);
+ TRAP_CASE_STRING(GR_RESOLUTION_960x720);
+ TRAP_CASE_STRING(GR_RESOLUTION_856x480);
+ TRAP_CASE_STRING(GR_RESOLUTION_512x256);
+ TRAP_CASE_STRING(GR_RESOLUTION_1024x768);
+ TRAP_CASE_STRING(GR_RESOLUTION_1280x1024);
+ TRAP_CASE_STRING(GR_RESOLUTION_1600x1200);
+ TRAP_CASE_STRING(GR_RESOLUTION_400x300);
+ TRAP_CASE_STRING(GR_RESOLUTION_1152x864);
+ TRAP_CASE_STRING(GR_RESOLUTION_1280x960);
+ TRAP_CASE_STRING(GR_RESOLUTION_1600x1024);
+ TRAP_CASE_STRING(GR_RESOLUTION_1792x1344);
+ TRAP_CASE_STRING(GR_RESOLUTION_1856x1392);
+ TRAP_CASE_STRING(GR_RESOLUTION_1920x1440);
+ TRAP_CASE_STRING(GR_RESOLUTION_2048x1536);
+ TRAP_CASE_STRING(GR_RESOLUTION_2048x2048);
+ TRAP_CASE_STRING(GR_RESOLUTION_NONE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_BLEND (GrAlphaBlendFnc_t func)
+{
+ switch (func) {
+ TRAP_CASE_STRING(GR_BLEND_ZERO);
+ TRAP_CASE_STRING(GR_BLEND_SRC_ALPHA);
+ TRAP_CASE_STRING(GR_BLEND_SRC_COLOR);
+ /*TRAP_CASE_STRING(GR_BLEND_DST_COLOR); ==GR_BLEND_SRC_COLOR*/
+ TRAP_CASE_STRING(GR_BLEND_DST_ALPHA);
+ TRAP_CASE_STRING(GR_BLEND_ONE);
+ TRAP_CASE_STRING(GR_BLEND_ONE_MINUS_SRC_ALPHA);
+ TRAP_CASE_STRING(GR_BLEND_ONE_MINUS_SRC_COLOR);
+ /*TRAP_CASE_STRING(GR_BLEND_ONE_MINUS_DST_COLOR); ==GR_BLEND_ONE_MINUS_SRC_COLOR*/
+ TRAP_CASE_STRING(GR_BLEND_ONE_MINUS_DST_ALPHA);
+ TRAP_CASE_STRING(GR_BLEND_SAME_COLOR_EXT);
+ /*TRAP_CASE_STRING(GR_BLEND_RESERVED_8); ==GR_BLEND_SAME_COLOR_EXT*/
+ TRAP_CASE_STRING(GR_BLEND_ONE_MINUS_SAME_COLOR_EXT);
+ /*TRAP_CASE_STRING(GR_BLEND_RESERVED_9); ==GR_BLEND_ONE_MINUS_SAME_COLOR_EXT*/
+ TRAP_CASE_STRING(GR_BLEND_RESERVED_A);
+ TRAP_CASE_STRING(GR_BLEND_RESERVED_B);
+ TRAP_CASE_STRING(GR_BLEND_RESERVED_C);
+ TRAP_CASE_STRING(GR_BLEND_RESERVED_D);
+ TRAP_CASE_STRING(GR_BLEND_RESERVED_E);
+ TRAP_CASE_STRING(GR_BLEND_ALPHA_SATURATE);
+ /*TRAP_CASE_STRING(GR_BLEND_PREFOG_COLOR); ==GR_BLEND_ALPHA_SATURATE*/
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMBFUNC (GrCombineFunction_t cfunc)
+{
+ switch (cfunc) {
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_ZERO);
+ /*TRAP_CASE_STRING(GR_COMBINE_FUNCTION_NONE); ==GR_COMBINE_FUNCTION_ZERO*/
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_LOCAL);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_LOCAL_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER);
+ /*TRAP_CASE_STRING(GR_COMBINE_FUNCTION_BLEND_OTHER); ==GR_COMBINE_FUNCTION_SCALE_OTHER*/
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL);
+ /*TRAP_CASE_STRING(GR_COMBINE_FUNCTION_BLEND); ==GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL*/
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL);
+ /*TRAP_CASE_STRING(GR_COMBINE_FUNCTION_BLEND_LOCAL); ==GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL*/
+ TRAP_CASE_STRING(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMBFACT (GrCombineFactor_t cfactor)
+{
+ switch (cfactor) {
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ZERO);
+ /*TRAP_CASE_STRING(GR_COMBINE_FACTOR_NONE); ==GR_COMBINE_FACTOR_ZERO*/
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_LOCAL);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_OTHER_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_LOCAL_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_TEXTURE_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_TEXTURE_RGB);
+ /*TRAP_CASE_STRING(GR_COMBINE_FACTOR_DETAIL_FACTOR); ==GR_COMBINE_FACTOR_TEXTURE_ALPHA*/
+ /*TRAP_CASE_STRING(GR_COMBINE_FACTOR_LOD_FRACTION); ==GR_COMBINE_FACTOR_TEXTURE_RGB ???*/
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_LOCAL);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA);
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA);
+ /*TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR); ==GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA*/
+ TRAP_CASE_STRING(GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMBLOCAL (GrCombineLocal_t clocal)
+{
+ switch (clocal) {
+ TRAP_CASE_STRING(GR_COMBINE_LOCAL_ITERATED);
+ TRAP_CASE_STRING(GR_COMBINE_LOCAL_CONSTANT);
+ /*TRAP_CASE_STRING(GR_COMBINE_LOCAL_NONE); ==GR_COMBINE_LOCAL_CONSTANT*/
+ TRAP_CASE_STRING(GR_COMBINE_LOCAL_DEPTH);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMBOTHER (GrCombineOther_t cother)
+{
+ switch (cother) {
+ TRAP_CASE_STRING(GR_COMBINE_OTHER_ITERATED);
+ TRAP_CASE_STRING(GR_COMBINE_OTHER_TEXTURE);
+ TRAP_CASE_STRING(GR_COMBINE_OTHER_CONSTANT);
+ /*TRAP_CASE_STRING(GR_COMBINE_OTHER_NONE); ==GR_COMBINE_OTHER_CONSTANT*/
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMPFUNC (GrCmpFnc_t function)
+{
+ switch (function) {
+ TRAP_CASE_STRING(GR_CMP_NEVER);
+ TRAP_CASE_STRING(GR_CMP_LESS);
+ TRAP_CASE_STRING(GR_CMP_EQUAL);
+ TRAP_CASE_STRING(GR_CMP_LEQUAL);
+ TRAP_CASE_STRING(GR_CMP_GREATER);
+ TRAP_CASE_STRING(GR_CMP_NOTEQUAL);
+ TRAP_CASE_STRING(GR_CMP_GEQUAL);
+ TRAP_CASE_STRING(GR_CMP_ALWAYS);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CKMODE (GrChromakeyMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_CHROMAKEY_DISABLE);
+ TRAP_CASE_STRING(GR_CHROMAKEY_ENABLE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CULLMODE (GrCullMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_CULL_DISABLE);
+ TRAP_CASE_STRING(GR_CULL_NEGATIVE);
+ TRAP_CASE_STRING(GR_CULL_POSITIVE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_DEPTHMODE (GrDepthBufferMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_DEPTHBUFFER_DISABLE);
+ TRAP_CASE_STRING(GR_DEPTHBUFFER_ZBUFFER);
+ TRAP_CASE_STRING(GR_DEPTHBUFFER_WBUFFER);
+ TRAP_CASE_STRING(GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS);
+ TRAP_CASE_STRING(GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_DITHERMODE (GrDitherMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_DITHER_DISABLE);
+ TRAP_CASE_STRING(GR_DITHER_2x2);
+ TRAP_CASE_STRING(GR_DITHER_4x4);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_FOGMODE (GrFogMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_FOG_DISABLE);
+ TRAP_CASE_STRING(GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+ TRAP_CASE_STRING(GR_FOG_WITH_TABLE_ON_Q);
+ /*TRAP_CASE_STRING(GR_FOG_WITH_TABLE_ON_W); ==GR_FOG_WITH_TABLE_ON_Q*/
+ TRAP_CASE_STRING(GR_FOG_WITH_ITERATED_Z);
+ TRAP_CASE_STRING(GR_FOG_WITH_ITERATED_ALPHA_EXT);
+ TRAP_CASE_STRING(GR_FOG_MULT2);
+ TRAP_CASE_STRING(GR_FOG_ADD2);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_GETNAME (FxU32 pname)
+{
+ switch (pname) {
+ TRAP_CASE_STRING(GR_BITS_DEPTH);
+ TRAP_CASE_STRING(GR_BITS_RGBA);
+ TRAP_CASE_STRING(GR_FIFO_FULLNESS);
+ TRAP_CASE_STRING(GR_FOG_TABLE_ENTRIES);
+ TRAP_CASE_STRING(GR_GAMMA_TABLE_ENTRIES);
+ TRAP_CASE_STRING(GR_GLIDE_STATE_SIZE);
+ TRAP_CASE_STRING(GR_GLIDE_VERTEXLAYOUT_SIZE);
+ TRAP_CASE_STRING(GR_IS_BUSY);
+ TRAP_CASE_STRING(GR_LFB_PIXEL_PIPE);
+ TRAP_CASE_STRING(GR_MAX_TEXTURE_SIZE);
+ TRAP_CASE_STRING(GR_MAX_TEXTURE_ASPECT_RATIO);
+ TRAP_CASE_STRING(GR_MEMORY_FB);
+ TRAP_CASE_STRING(GR_MEMORY_TMU);
+ TRAP_CASE_STRING(GR_MEMORY_UMA);
+ TRAP_CASE_STRING(GR_NUM_BOARDS);
+ TRAP_CASE_STRING(GR_NON_POWER_OF_TWO_TEXTURES);
+ TRAP_CASE_STRING(GR_NUM_FB);
+ TRAP_CASE_STRING(GR_NUM_SWAP_HISTORY_BUFFER);
+ TRAP_CASE_STRING(GR_NUM_TMU);
+ TRAP_CASE_STRING(GR_PENDING_BUFFERSWAPS);
+ TRAP_CASE_STRING(GR_REVISION_FB);
+ TRAP_CASE_STRING(GR_REVISION_TMU);
+ TRAP_CASE_STRING(GR_STATS_LINES);
+ TRAP_CASE_STRING(GR_STATS_PIXELS_AFUNC_FAIL);
+ TRAP_CASE_STRING(GR_STATS_PIXELS_CHROMA_FAIL);
+ TRAP_CASE_STRING(GR_STATS_PIXELS_DEPTHFUNC_FAIL);
+ TRAP_CASE_STRING(GR_STATS_PIXELS_IN);
+ TRAP_CASE_STRING(GR_STATS_PIXELS_OUT);
+ TRAP_CASE_STRING(GR_STATS_PIXELS);
+ TRAP_CASE_STRING(GR_STATS_POINTS);
+ TRAP_CASE_STRING(GR_STATS_TRIANGLES_IN);
+ TRAP_CASE_STRING(GR_STATS_TRIANGLES_OUT);
+ TRAP_CASE_STRING(GR_STATS_TRIANGLES);
+ TRAP_CASE_STRING(GR_SWAP_HISTORY);
+ TRAP_CASE_STRING(GR_SUPPORTS_PASSTHRU);
+ TRAP_CASE_STRING(GR_TEXTURE_ALIGN);
+ TRAP_CASE_STRING(GR_VIDEO_POSITION);
+ TRAP_CASE_STRING(GR_VIEWPORT);
+ TRAP_CASE_STRING(GR_WDEPTH_MIN_MAX);
+ TRAP_CASE_STRING(GR_ZDEPTH_MIN_MAX);
+ TRAP_CASE_STRING(GR_VERTEX_PARAMETER);
+ TRAP_CASE_STRING(GR_BITS_GAMMA);
+ TRAP_CASE_STRING(GR_GET_RESERVED_1);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_GETSTRING (FxU32 pname)
+{
+ switch (pname) {
+ TRAP_CASE_STRING(GR_EXTENSION);
+ TRAP_CASE_STRING(GR_HARDWARE);
+ TRAP_CASE_STRING(GR_RENDERER);
+ TRAP_CASE_STRING(GR_VENDOR);
+ TRAP_CASE_STRING(GR_VERSION);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_ENABLE (GrEnableMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_AA_ORDERED);
+ TRAP_CASE_STRING(GR_ALLOW_MIPMAP_DITHER);
+ TRAP_CASE_STRING(GR_PASSTHRU);
+ TRAP_CASE_STRING(GR_SHAMELESS_PLUG);
+ TRAP_CASE_STRING(GR_VIDEO_SMOOTHING);
+ TRAP_CASE_STRING(GR_TEXTURE_UMA_EXT);
+ TRAP_CASE_STRING(GR_STENCIL_MODE_EXT);
+ TRAP_CASE_STRING(GR_OPENGL_MODE_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_COORD (GrCoordinateSpaceMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_WINDOW_COORDS);
+ TRAP_CASE_STRING(GR_CLIP_COORDS);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_STIPPLEMODE (GrStippleMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_STIPPLE_DISABLE);
+ TRAP_CASE_STRING(GR_STIPPLE_PATTERN);
+ TRAP_CASE_STRING(GR_STIPPLE_ROTATE);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_LODLEVEL (GrLOD_t lod)
+{
+ switch (lod) {
+ TRAP_CASE_STRING(GR_LOD_LOG2_2048);
+ TRAP_CASE_STRING(GR_LOD_LOG2_1024);
+ TRAP_CASE_STRING(GR_LOD_LOG2_512);
+ TRAP_CASE_STRING(GR_LOD_LOG2_256);
+ TRAP_CASE_STRING(GR_LOD_LOG2_128);
+ TRAP_CASE_STRING(GR_LOD_LOG2_64);
+ TRAP_CASE_STRING(GR_LOD_LOG2_32);
+ TRAP_CASE_STRING(GR_LOD_LOG2_16);
+ TRAP_CASE_STRING(GR_LOD_LOG2_8);
+ TRAP_CASE_STRING(GR_LOD_LOG2_4);
+ TRAP_CASE_STRING(GR_LOD_LOG2_2);
+ TRAP_CASE_STRING(GR_LOD_LOG2_1);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_ASPECTRATIO (GrAspectRatio_t aspect)
+{
+ switch (aspect) {
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_8x1);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_4x1);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_2x1);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_1x1);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_1x2);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_1x4);
+ TRAP_CASE_STRING(GR_ASPECT_LOG2_1x8);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TEXFMT (GrTextureFormat_t fmt)
+{
+ switch (fmt) {
+ TRAP_CASE_STRING(GR_TEXFMT_8BIT);
+ /*TRAP_CASE_STRING(GR_TEXFMT_RGB_332); ==GR_TEXFMT_8BIT*/
+ TRAP_CASE_STRING(GR_TEXFMT_YIQ_422);
+ TRAP_CASE_STRING(GR_TEXFMT_ALPHA_8);
+ TRAP_CASE_STRING(GR_TEXFMT_INTENSITY_8);
+ TRAP_CASE_STRING(GR_TEXFMT_ALPHA_INTENSITY_44);
+ TRAP_CASE_STRING(GR_TEXFMT_P_8);
+ TRAP_CASE_STRING(GR_TEXFMT_RSVD0);
+ /*TRAP_CASE_STRING(GR_TEXFMT_P_8_6666); ==GR_TEXFMT_RSVD0*/
+ /*TRAP_CASE_STRING(GR_TEXFMT_P_8_6666_EXT); ==GR_TEXFMT_RSVD0*/
+ TRAP_CASE_STRING(GR_TEXFMT_RSVD1);
+ TRAP_CASE_STRING(GR_TEXFMT_16BIT);
+ /*TRAP_CASE_STRING(GR_TEXFMT_ARGB_8332); ==GR_TEXFMT_16BIT*/
+ TRAP_CASE_STRING(GR_TEXFMT_AYIQ_8422);
+ TRAP_CASE_STRING(GR_TEXFMT_RGB_565);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_1555);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_4444);
+ TRAP_CASE_STRING(GR_TEXFMT_ALPHA_INTENSITY_88);
+ TRAP_CASE_STRING(GR_TEXFMT_AP_88);
+ TRAP_CASE_STRING(GR_TEXFMT_RSVD2);
+ /*TRAP_CASE_STRING(GR_TEXFMT_RSVD4); ==GR_TEXFMT_RSVD2*/
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_FXT1);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_8888);
+ TRAP_CASE_STRING(GR_TEXFMT_YUYV_422);
+ TRAP_CASE_STRING(GR_TEXFMT_UYVY_422);
+ TRAP_CASE_STRING(GR_TEXFMT_AYUV_444);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_DXT1);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_DXT2);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_DXT3);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_DXT4);
+ TRAP_CASE_STRING(GR_TEXFMT_ARGB_CMP_DXT5);
+ TRAP_CASE_STRING(GR_TEXTFMT_RGB_888);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_EVENODD (FxU32 evenOdd)
+{
+ switch (evenOdd) {
+ TRAP_CASE_STRING(GR_MIPMAPLEVELMASK_EVEN);
+ TRAP_CASE_STRING(GR_MIPMAPLEVELMASK_ODD);
+ TRAP_CASE_STRING(GR_MIPMAPLEVELMASK_BOTH);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_NCC (GrNCCTable_t table)
+{
+ switch (table) {
+ TRAP_CASE_STRING(GR_NCCTABLE_NCC0);
+ TRAP_CASE_STRING(GR_NCCTABLE_NCC1);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CLAMPMODE (GrTextureClampMode_t clampmode)
+{
+ switch (clampmode) {
+ TRAP_CASE_STRING(GR_TEXTURECLAMP_WRAP);
+ TRAP_CASE_STRING(GR_TEXTURECLAMP_CLAMP);
+ TRAP_CASE_STRING(GR_TEXTURECLAMP_MIRROR_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TEXFILTER (GrTextureFilterMode_t filter_mode)
+{
+ switch (filter_mode) {
+ TRAP_CASE_STRING(GR_TEXTUREFILTER_POINT_SAMPLED);
+ TRAP_CASE_STRING(GR_TEXTUREFILTER_BILINEAR);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TABLE (GrTexTable_t type)
+{
+ switch (type) {
+ TRAP_CASE_STRING(GR_TEXTABLE_NCC0);
+ TRAP_CASE_STRING(GR_TEXTABLE_NCC1);
+ TRAP_CASE_STRING(GR_TEXTABLE_PALETTE);
+ TRAP_CASE_STRING(GR_TEXTABLE_PALETTE_6666_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_MIPMODE (GrMipMapMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_MIPMAP_DISABLE);
+ TRAP_CASE_STRING(GR_MIPMAP_NEAREST);
+ TRAP_CASE_STRING(GR_MIPMAP_NEAREST_DITHER);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TEXBASERANGE (GrTexBaseRange_t range)
+{
+ switch (range) {
+ TRAP_CASE_STRING(GR_TEXBASE_2048);
+ TRAP_CASE_STRING(GR_TEXBASE_1024);
+ TRAP_CASE_STRING(GR_TEXBASE_512);
+ TRAP_CASE_STRING(GR_TEXBASE_256_TO_1);
+ TRAP_CASE_STRING(GR_TEXBASE_256);
+ TRAP_CASE_STRING(GR_TEXBASE_128);
+ TRAP_CASE_STRING(GR_TEXBASE_64);
+ TRAP_CASE_STRING(GR_TEXBASE_32_TO_1);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_LOCKTYPE (GrLock_t type)
+{
+ switch (type) {
+ TRAP_CASE_STRING(GR_LFB_READ_ONLY);
+ TRAP_CASE_STRING(GR_LFB_WRITE_ONLY);
+ /*TRAP_CASE_STRING(GR_LFB_IDLE); ==GR_LFB_READ_ONLY*/
+ TRAP_CASE_STRING(GR_LFB_NOIDLE);
+ TRAP_CASE_STRING(GR_LFB_WRITE_ONLY_EXPLICIT_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_WRITEMODE (GrLfbWriteMode_t writeMode)
+{
+ switch (writeMode) {
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_565);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_555);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_1555);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED1);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_888);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_8888);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED2);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED3);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_Z32);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED5);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED6);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_RESERVED7);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_565_DEPTH);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_555_DEPTH);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_1555_DEPTH);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_ZA16);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_ANY);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_SRCFMT (GrLfbSrcFmt_t src_format)
+{
+ switch (src_format) {
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_565);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_555);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_1555);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_888);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_8888);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_565_DEPTH);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_555_DEPTH);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_1555_DEPTH);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_ZA16);
+ TRAP_CASE_STRING(GR_LFB_SRC_FMT_RLE16);
+ TRAP_CASE_STRING(GR_LFBWRITEMODE_Z32); /*???*/
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CRMODE (GrChromaRangeMode_t mode)
+{
+ switch (mode) {
+ TRAP_CASE_STRING(GR_CHROMARANGE_DISABLE_EXT);
+ /*TRAP_CASE_STRING(GR_CHROMARANGE_RGB_ALL_EXT); ==GR_CHROMARANGE_DISABLE_EXT*/
+ TRAP_CASE_STRING(GR_CHROMARANGE_ENABLE_EXT);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_PIXFMT (GrPixelFormat_t pixelformat)
+{
+ switch (pixelformat) {
+ TRAP_CASE_STRING(GR_PIXFMT_I_8);
+ TRAP_CASE_STRING(GR_PIXFMT_AI_88);
+ TRAP_CASE_STRING(GR_PIXFMT_RGB_565);
+ TRAP_CASE_STRING(GR_PIXFMT_ARGB_1555);
+ TRAP_CASE_STRING(GR_PIXFMT_ARGB_8888);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_2_RGB_565);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_2_ARGB_1555);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_2_ARGB_8888);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_4_RGB_565);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_4_ARGB_1555);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_4_ARGB_8888);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_8_RGB_565);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_8_ARGB_1555);
+ TRAP_CASE_STRING(GR_PIXFMT_AA_8_ARGB_8888);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_STENCILOP (GrStencilOp_t op)
+{
+ switch (op) {
+ TRAP_CASE_STRING(GR_STENCILOP_KEEP);
+ TRAP_CASE_STRING(GR_STENCILOP_ZERO);
+ TRAP_CASE_STRING(GR_STENCILOP_REPLACE);
+ TRAP_CASE_STRING(GR_STENCILOP_INCR_CLAMP);
+ TRAP_CASE_STRING(GR_STENCILOP_DECR_CLAMP);
+ TRAP_CASE_STRING(GR_STENCILOP_INVERT);
+ TRAP_CASE_STRING(GR_STENCILOP_INCR_WRAP);
+ TRAP_CASE_STRING(GR_STENCILOP_DECR_WRAP);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_BLENDOP (GrAlphaBlendOp_t op)
+{
+ switch (op) {
+ TRAP_CASE_STRING(GR_BLEND_OP_ADD);
+ TRAP_CASE_STRING(GR_BLEND_OP_SUB);
+ TRAP_CASE_STRING(GR_BLEND_OP_REVSUB);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CU (GrCCUColor_t a)
+{
+ switch (a) {
+ TRAP_CASE_STRING(GR_CMBX_ZERO);
+ TRAP_CASE_STRING(GR_CMBX_TEXTURE_ALPHA);
+ TRAP_CASE_STRING(GR_CMBX_ALOCAL);
+ TRAP_CASE_STRING(GR_CMBX_AOTHER);
+ TRAP_CASE_STRING(GR_CMBX_B);
+ TRAP_CASE_STRING(GR_CMBX_CONSTANT_ALPHA);
+ TRAP_CASE_STRING(GR_CMBX_CONSTANT_COLOR);
+ TRAP_CASE_STRING(GR_CMBX_DETAIL_FACTOR);
+ TRAP_CASE_STRING(GR_CMBX_ITALPHA);
+ TRAP_CASE_STRING(GR_CMBX_ITRGB);
+ TRAP_CASE_STRING(GR_CMBX_LOCAL_TEXTURE_ALPHA);
+ TRAP_CASE_STRING(GR_CMBX_LOCAL_TEXTURE_RGB);
+ TRAP_CASE_STRING(GR_CMBX_LOD_FRAC);
+ TRAP_CASE_STRING(GR_CMBX_OTHER_TEXTURE_ALPHA);
+ TRAP_CASE_STRING(GR_CMBX_OTHER_TEXTURE_RGB);
+ TRAP_CASE_STRING(GR_CMBX_TEXTURE_RGB);
+ TRAP_CASE_STRING(GR_CMBX_TMU_CALPHA);
+ TRAP_CASE_STRING(GR_CMBX_TMU_CCOLOR);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_CMBMODE (GrCombineMode_t a_mode)
+{
+ switch (a_mode) {
+ TRAP_CASE_STRING(GR_FUNC_MODE_ZERO);
+ TRAP_CASE_STRING(GR_FUNC_MODE_X);
+ TRAP_CASE_STRING(GR_FUNC_MODE_ONE_MINUS_X);
+ TRAP_CASE_STRING(GR_FUNC_MODE_NEGATIVE_X);
+ TRAP_CASE_STRING(GR_FUNC_MODE_X_MINUS_HALF);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TMU (GrChipID_t tmu)
+{
+ switch (tmu) {
+ TRAP_CASE_STRING(GR_TMU0);
+ TRAP_CASE_STRING(GR_TMU1);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TXDITHER (FxU32 dither)
+{
+ switch (dither) {
+ TRAP_CASE_STRING(TX_DITHER_NONE);
+ TRAP_CASE_STRING(TX_DITHER_4x4);
+ TRAP_CASE_STRING(TX_DITHER_ERR);
+ TRAP_NODEFAULT;
+ }
+}
+
+const char *TRP_TXCOMPRESS (FxU32 compress)
+{
+ switch (compress) {
+ TRAP_CASE_STRING(TX_COMPRESSION_STATISTICAL);
+ TRAP_CASE_STRING(TX_COMPRESSION_HEURISTIC);
+ TRAP_NODEFAULT;
+ }
+}
+
+
+
+/****************************************************************************\
+* REAL POINTERS *
+\****************************************************************************/
+
+/*
+** glide extensions
+*/
+void (FX_CALL *real_grSetNumPendingBuffers) (FxI32 NumPendingBuffers);
+char * (FX_CALL *real_grGetRegistryOrEnvironmentStringExt) (char *theEntry);
+void (FX_CALL *real_grGetGammaTableExt) (FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue);
+void (FX_CALL *real_grChromaRangeModeExt) (GrChromakeyMode_t mode);
+void (FX_CALL *real_grChromaRangeExt) (GrColor_t color, GrColor_t range, GrChromaRangeMode_t match_mode);
+void (FX_CALL *real_grTexChromaModeExt) (GrChipID_t tmu, GrChromakeyMode_t mode);
+void (FX_CALL *real_grTexChromaRangeExt) (GrChipID_t tmu, GrColor_t min, GrColor_t max, GrTexChromakeyMode_t mode);
+
+/* pointcast */
+void (FX_CALL *real_grTexDownloadTableExt) (GrChipID_t tmu, GrTexTable_t type, void *data);
+void (FX_CALL *real_grTexDownloadTablePartialExt) (GrChipID_t tmu, GrTexTable_t type, void *data, int start, int end);
+void (FX_CALL *real_grTexNCCTableExt) (GrChipID_t tmu, GrNCCTable_t table);
+
+/* tbext */
+void (FX_CALL *real_grTextureBufferExt) (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLOD, GrLOD_t largeLOD, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 odd_even_mask);
+void (FX_CALL *real_grTextureAuxBufferExt) (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLOD, GrLOD_t largeLOD, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 odd_even_mask);
+void (FX_CALL *real_grAuxBufferExt) (GrBuffer_t buffer);
+
+/* napalm */
+GrContext_t (FX_CALL *real_grSstWinOpenExt) (FxU32 hWnd, GrScreenResolution_t resolution, GrScreenRefresh_t refresh, GrColorFormat_t format, GrOriginLocation_t origin, GrPixelFormat_t pixelformat, int nColBuffers, int nAuxBuffers);
+void (FX_CALL *real_grStencilFuncExt) (GrCmpFnc_t fnc, GrStencil_t ref, GrStencil_t mask);
+void (FX_CALL *real_grStencilMaskExt) (GrStencil_t value);
+void (FX_CALL *real_grStencilOpExt) (GrStencilOp_t stencil_fail, GrStencilOp_t depth_fail, GrStencilOp_t depth_pass);
+void (FX_CALL *real_grLfbConstantStencilExt) (GrStencil_t value);
+void (FX_CALL *real_grBufferClearExt) (GrColor_t color, GrAlpha_t alpha, FxU32 depth, GrStencil_t stencil);
+void (FX_CALL *real_grColorCombineExt) (GrCCUColor_t a, GrCombineMode_t a_mode, GrCCUColor_t b, GrCombineMode_t b_mode, GrCCUColor_t c, FxBool c_invert, GrCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+void (FX_CALL *real_grAlphaCombineExt) (GrACUColor_t a, GrCombineMode_t a_mode, GrACUColor_t b, GrCombineMode_t b_mode, GrACUColor_t c, FxBool c_invert, GrACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+void (FX_CALL *real_grTexColorCombineExt) (GrChipID_t tmu, GrTCCUColor_t a, GrCombineMode_t a_mode, GrTCCUColor_t b, GrCombineMode_t b_mode, GrTCCUColor_t c, FxBool c_invert, GrTCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+void (FX_CALL *real_grTexAlphaCombineExt) (GrChipID_t tmu, GrTACUColor_t a, GrCombineMode_t a_mode, GrTACUColor_t b, GrCombineMode_t b_mode, GrTACUColor_t c, FxBool c_invert, GrTACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+void (FX_CALL *real_grConstantColorValueExt) (GrChipID_t tmu, GrColor_t value);
+void (FX_CALL *real_grColorMaskExt) (FxBool r, FxBool g, FxBool b, FxBool a);
+void (FX_CALL *real_grAlphaBlendFunctionExt) (GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendOp_t rgb_op, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df, GrAlphaBlendOp_t alpha_op);
+void (FX_CALL *real_grTBufferWriteMaskExt) (FxU32 tmask);
+
+/*
+** texus
+*/
+void (FX_CALL *real_txImgQuantize) (char *dst, char *src, int w, int h, FxU32 format, FxU32 dither);
+void (FX_CALL *real_txMipQuantize) (TxMip *pxMip, TxMip *txMip, int fmt, FxU32 d, FxU32 comp);
+void (FX_CALL *real_txPalToNcc) (GuNccTable *ncc_table, const FxU32 *pal);
+
+
+
+/****************************************************************************\
+* DEBUG HOOKS *
+\****************************************************************************/
+
+/*
+** rendering functions
+*/
+void FX_CALL trap_grDrawPoint (const void *pt)
+{
+#define FN_NAME "grDrawPoint"
+ TRAP_LOG("%s(%p)\n", FN_NAME, pt);
+ grDrawPoint(pt);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDrawLine (const void *v1,
+ const void *v2)
+{
+#define FN_NAME "grDrawLine"
+ TRAP_LOG("%s(%p, %p)\n", FN_NAME, v1, v2);
+ grDrawLine(v1, v2);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDrawTriangle (const void *a,
+ const void *b,
+ const void *c)
+{
+#define FN_NAME "grDrawTriangle"
+ TRAP_LOG("%s(%p, %p, %p)\n", FN_NAME, a, b, c);
+ grDrawTriangle(a, b, c);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grVertexLayout (FxU32 param,
+ FxI32 offset,
+ FxU32 mode)
+{
+#define FN_NAME "grVertexLayout"
+ TRAP_LOG("%s(%s, %ld, %s)\n", FN_NAME, TRP_VTX(param), offset, TRP_PARAM(mode));
+ grVertexLayout(param, offset, mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDrawVertexArray (FxU32 mode,
+ FxU32 Count,
+ void *pointers)
+{
+#define FN_NAME "grDrawVertexArray"
+ TRAP_LOG("%s(%s, %lu, %p)\n", FN_NAME, TRP_ARRAY(mode), Count, pointers);
+ grDrawVertexArray(mode, Count, pointers);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDrawVertexArrayContiguous (FxU32 mode,
+ FxU32 Count,
+ void *pointers,
+ FxU32 stride)
+{
+#define FN_NAME "grDrawVertexArrayContiguous"
+ TRAP_LOG("%s(%s, %lu, %p, %lu)\n", FN_NAME, TRP_ARRAY(mode), Count, pointers, stride);
+ grDrawVertexArrayContiguous(mode, Count, pointers, stride);
+#undef FN_NAME
+}
+
+/*
+** Antialiasing Functions
+*/
+void FX_CALL trap_grAADrawTriangle (const void *a,
+ const void *b,
+ const void *c,
+ FxBool ab_antialias,
+ FxBool bc_antialias,
+ FxBool ca_antialias)
+{
+#define FN_NAME "grAADrawTriangle"
+ TRAP_LOG("%s(%p, %p, %p, %s, %s, %s)\n", FN_NAME, a, b, c, TRP_BOOL(ab_antialias), TRP_BOOL(bc_antialias), TRP_BOOL(ca_antialias));
+ grAADrawTriangle(a, b, c, ab_antialias, bc_antialias, ca_antialias);
+#undef FN_NAME
+}
+
+/*
+** buffer management
+*/
+void FX_CALL trap_grBufferClear (GrColor_t color,
+ GrAlpha_t alpha,
+ FxU32 depth)
+{
+#define FN_NAME "grBufferClear"
+ TRAP_LOG("%s(%08lx, %02x, %08lx)\n", FN_NAME, color, alpha, depth);
+ grBufferClear(color, alpha, depth);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grBufferSwap (FxU32 swap_interval)
+{
+#define FN_NAME "grBufferSwap"
+ TRAP_LOG("%s(%lu)\n", FN_NAME, swap_interval);
+ grBufferSwap(swap_interval);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grRenderBuffer (GrBuffer_t buffer)
+{
+#define FN_NAME "grRenderBuffer"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_BUFFER(buffer));
+ grRenderBuffer(buffer);
+#undef FN_NAME
+}
+
+/*
+** error management
+*/
+void FX_CALL trap_grErrorSetCallback (GrErrorCallbackFnc_t fnc)
+{
+#define FN_NAME "grErrorSetCallback"
+ TRAP_LOG("%s(%p)\n", FN_NAME, (void *)fnc);
+ grErrorSetCallback(fnc);
+#undef FN_NAME
+}
+
+/*
+** SST routines
+*/
+void FX_CALL trap_grFinish (void)
+{
+#define FN_NAME "grFinish"
+ TRAP_LOG("%s()\n", FN_NAME);
+ grFinish();
+#undef FN_NAME
+}
+
+void FX_CALL trap_grFlush (void)
+{
+#define FN_NAME "grFlush"
+ TRAP_LOG("%s()\n", FN_NAME);
+ grFlush();
+#undef FN_NAME
+}
+
+GrContext_t FX_CALL trap_grSstWinOpen (FxU32 hWnd,
+ GrScreenResolution_t screen_resolution,
+ GrScreenRefresh_t refresh_rate,
+ GrColorFormat_t color_format,
+ GrOriginLocation_t origin_location,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+#define FN_NAME "grSstWinOpen"
+ GrContext_t rv;
+ TRAP_LOG("%s(%08lx, %s, %s, %s, %s, %d, %d)\n", FN_NAME, hWnd, TRP_RESOLUTION(screen_resolution), TRP_REFRESH(refresh_rate), TRP_COLFMT(color_format), TRP_ORIGIN(origin_location), nColBuffers, nAuxBuffers);
+ rv = grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+ TRAP_LOG(GOT "%p\n", (void *)rv);
+ return rv;
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grSstWinClose (GrContext_t context)
+{
+#define FN_NAME "grSstWinClose"
+ FxBool rv;
+ TRAP_LOG("%s(%p)\n", FN_NAME, (void *)context);
+ rv = grSstWinClose(context);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grSelectContext (GrContext_t context)
+{
+#define FN_NAME "grSelectContext"
+ FxBool rv;
+ TRAP_LOG("%s(%p)\n", FN_NAME, (void *)context);
+ rv = grSelectContext(context);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grSstOrigin (GrOriginLocation_t origin)
+{
+#define FN_NAME "grSstOrigin"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_ORIGIN(origin));
+ grSstOrigin(origin);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grSstSelect (int which_sst)
+{
+#define FN_NAME "grSstSelect"
+ TRAP_LOG("%s(%d)\n", FN_NAME, which_sst);
+ grSstSelect(which_sst);
+#undef FN_NAME
+}
+
+/*
+** Glide configuration and special effect maintenance functions
+*/
+void FX_CALL trap_grAlphaBlendFunction (GrAlphaBlendFnc_t rgb_sf,
+ GrAlphaBlendFnc_t rgb_df,
+ GrAlphaBlendFnc_t alpha_sf,
+ GrAlphaBlendFnc_t alpha_df)
+{
+#define FN_NAME "grAlphaBlendFunction"
+ TRAP_LOG("%s(%s, %s, %s, %s)\n", FN_NAME, TRP_BLEND(rgb_sf), TRP_BLEND(rgb_df), TRP_BLEND(alpha_sf), TRP_BLEND(alpha_df));
+ grAlphaBlendFunction(rgb_sf, rgb_df, alpha_sf, alpha_df);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaCombine (GrCombineFunction_t function,
+ GrCombineFactor_t factor,
+ GrCombineLocal_t local,
+ GrCombineOther_t other,
+ FxBool invert)
+{
+#define FN_NAME "grAlphaCombine"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s)\n", FN_NAME, TRP_CMBFUNC(function), TRP_CMBFACT(factor), TRP_CMBLOCAL(local), TRP_CMBOTHER(other), TRP_BOOL(invert));
+ grAlphaCombine(function, factor, local, other, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaControlsITRGBLighting (FxBool enable)
+{
+#define FN_NAME "grAlphaControlsITRGBLighting"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_BOOL(enable));
+ grAlphaControlsITRGBLighting(enable);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaTestFunction (GrCmpFnc_t function)
+{
+#define FN_NAME "grAlphaTestFunction"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_CMPFUNC(function));
+ grAlphaTestFunction(function);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaTestReferenceValue (GrAlpha_t value)
+{
+#define FN_NAME "grAlphaTestReferenceValue"
+ TRAP_LOG("%s(%02x)\n", FN_NAME, value);
+ grAlphaTestReferenceValue(value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grChromakeyMode (GrChromakeyMode_t mode)
+{
+#define FN_NAME "grChromakeyMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_CKMODE(mode));
+ grChromakeyMode(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grChromakeyValue (GrColor_t value)
+{
+#define FN_NAME "grChromakeyValue"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, value);
+ grChromakeyValue(value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grClipWindow (FxU32 minx,
+ FxU32 miny,
+ FxU32 maxx,
+ FxU32 maxy)
+{
+#define FN_NAME "grClipWindow"
+ TRAP_LOG("%s(%lu, %lu, %lu, %lu)\n", FN_NAME, minx, miny, maxx, maxy);
+ grClipWindow(minx, miny, maxx, maxy);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grColorCombine (GrCombineFunction_t function,
+ GrCombineFactor_t factor,
+ GrCombineLocal_t local,
+ GrCombineOther_t other,
+ FxBool invert)
+{
+#define FN_NAME "grColorCombine"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s)\n", FN_NAME, TRP_CMBFUNC(function), TRP_CMBFACT(factor), TRP_CMBLOCAL(local), TRP_CMBOTHER(other), TRP_BOOL(invert));
+ grColorCombine(function, factor, local, other, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grColorMask (FxBool rgb,
+ FxBool a)
+{
+#define FN_NAME "grColorMask"
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_BOOL(rgb), TRP_BOOL(a));
+ grColorMask(rgb, a);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grCullMode (GrCullMode_t mode)
+{
+#define FN_NAME "grCullMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_CULLMODE(mode));
+ grCullMode(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grConstantColorValue (GrColor_t value)
+{
+#define FN_NAME "grConstantColorValue"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, value);
+ grConstantColorValue(value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDepthBiasLevel (FxI32 level)
+{
+#define FN_NAME "grDepthBiasLevel"
+ TRAP_LOG("%s(%ld)\n", FN_NAME, level);
+ grDepthBiasLevel(level);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDepthBufferFunction (GrCmpFnc_t function)
+{
+#define FN_NAME "grDepthBufferFunction"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_CMPFUNC(function));
+ grDepthBufferFunction(function);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDepthBufferMode (GrDepthBufferMode_t mode)
+{
+#define FN_NAME "grDepthBufferMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_DEPTHMODE(mode));
+ grDepthBufferMode(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDepthMask (FxBool mask)
+{
+#define FN_NAME "grDepthMask"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_BOOL(mask));
+ grDepthMask(mask);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDisableAllEffects (void)
+{
+#define FN_NAME "grDisableAllEffects"
+ TRAP_LOG("%s()\n", FN_NAME);
+ grDisableAllEffects();
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDitherMode (GrDitherMode_t mode)
+{
+#define FN_NAME "grDitherMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_DITHERMODE(mode));
+ grDitherMode(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grFogColorValue (GrColor_t fogcolor)
+{
+#define FN_NAME "grFogColorValue"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, fogcolor);
+ grFogColorValue(fogcolor);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grFogMode (GrFogMode_t mode)
+{
+#define FN_NAME "grFogMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_FOGMODE(mode));
+ grFogMode(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grFogTable (const GrFog_t ft[])
+{
+#define FN_NAME "grFogTable"
+ TRAP_LOG("%s(%p)\n", FN_NAME, ft);
+ grFogTable(ft);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLoadGammaTable (FxU32 nentries,
+ FxU32 *red,
+ FxU32 *green,
+ FxU32 *blue)
+{
+#define FN_NAME "grLoadGammaTable"
+ TRAP_LOG("%s(%lu, %p, %p, %p)\n", FN_NAME, nentries, (void *)red, (void *)green, (void *)blue);
+ grLoadGammaTable(nentries, red, green, blue);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grSplash (float x,
+ float y,
+ float width,
+ float height,
+ FxU32 frame)
+{
+#define FN_NAME "grSplash"
+ TRAP_LOG("%s(%f, %f, %f, %f, %lu)\n", FN_NAME, x, y, width, height, frame);
+ grSplash(x, y, width, height, frame);
+#undef FN_NAME
+}
+
+FxU32 FX_CALL trap_grGet (FxU32 pname,
+ FxU32 plength,
+ FxI32 *params)
+{
+#define FN_NAME "grGet"
+ FxU32 rv, i;
+ TRAP_LOG("%s(%s, %lu, %p)\n", FN_NAME, TRP_GETNAME(pname), plength, (void *)params);
+ rv = grGet(pname, plength, params);
+ TRAP_LOG(GOT "[");
+ for (i = 0; i < (rv/sizeof(FxI32)); i++) {
+ TRAP_LOG("%s%ld", i ? ", " : "", params[i]);
+ }
+ TRAP_LOG("]\n");
+ return rv;
+#undef FN_NAME
+}
+
+const char *FX_CALL trap_grGetString (FxU32 pname)
+{
+#define FN_NAME "grGetString"
+ const char *rv;
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_GETSTRING(pname));
+ rv = grGetString(pname);
+ if (rv) {
+ TRAP_LOG(GOT "\"%s\"\n", rv);
+ } else {
+ TRAP_LOG(GOT "NULL\n");
+ }
+ return rv;
+#undef FN_NAME
+}
+
+FxI32 FX_CALL trap_grQueryResolutions (const GrResolution *resTemplate,
+ GrResolution *output)
+{
+#define FN_NAME "grQueryResolutions"
+ FxI32 rv;
+ TRAP_LOG("%s(%p, %p)\n", FN_NAME, (void *)resTemplate, (void *)output);
+ rv = grQueryResolutions(resTemplate, output);
+ TRAP_LOG(GOT "%ld\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grReset (FxU32 what)
+{
+#define FN_NAME "grReset"
+ FxBool rv;
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_GETNAME(what));
+ rv = grReset(what);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+GrProc FX_CALL trap_grGetProcAddress (char *procName)
+{
+#define FN_NAME "grGetProcAddress"
+ GrProc rv;
+ TRAP_LOG("%s(%s)\n", FN_NAME, procName);
+ rv = grGetProcAddress(procName);
+ TRAP_LOG(GOT "%p\n", (void *)rv);
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grEnable (GrEnableMode_t mode)
+{
+#define FN_NAME "grEnable"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_ENABLE(mode));
+ grEnable(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDisable (GrEnableMode_t mode)
+{
+#define FN_NAME "grDisable"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_ENABLE(mode));
+ grDisable(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grCoordinateSpace (GrCoordinateSpaceMode_t mode)
+{
+#define FN_NAME "grCoordinateSpace"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_COORD(mode));
+ grCoordinateSpace(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grDepthRange (FxFloat n,
+ FxFloat f)
+{
+#define FN_NAME "grDepthRange"
+ TRAP_LOG("%s(%f, %f)\n", FN_NAME, n, f);
+ grDepthRange(n, f);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grStippleMode (GrStippleMode_t mode)
+{
+#define FN_NAME "grStippleMode"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_STIPPLEMODE(mode));
+ grStippleMode(mode); /* some Glide libs don't have it; not used anyway */
+#undef FN_NAME
+}
+
+void FX_CALL trap_grStipplePattern (GrStipplePattern_t mode)
+{
+#define FN_NAME "grStipplePattern"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, mode);
+ grStipplePattern(mode); /* some Glide libs don't have it; not used anyway */
+#undef FN_NAME
+}
+
+void FX_CALL trap_grViewport (FxI32 x,
+ FxI32 y,
+ FxI32 width,
+ FxI32 height)
+{
+#define FN_NAME "grViewport"
+ TRAP_LOG("%s(%ld, %ld, %ld, %ld)\n", FN_NAME, x, y, width, height);
+ grViewport(x, y, width, height);
+#undef FN_NAME
+}
+
+/*
+** texture mapping control functions
+*/
+FxU32 FX_CALL trap_grTexCalcMemRequired (GrLOD_t lodmin,
+ GrLOD_t lodmax,
+ GrAspectRatio_t aspect,
+ GrTextureFormat_t fmt)
+{
+#define FN_NAME "grTexCalcMemRequired"
+ FxU32 rv;
+ TRAP_LOG("%s(%s, %s, %s, %s)\n", FN_NAME, TRP_LODLEVEL(lodmin), TRP_LODLEVEL(lodmax), TRP_ASPECTRATIO(aspect), TRP_TEXFMT(fmt));
+ rv = grTexCalcMemRequired(lodmin, lodmax, aspect, fmt);
+ TRAP_LOG(GOT "%lu\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+FxU32 FX_CALL trap_grTexTextureMemRequired (FxU32 evenOdd,
+ GrTexInfo *info)
+{
+#define FN_NAME "grTexTextureMemRequired"
+ FxU32 rv;
+ TRAP_LOG("%s(%s, %p)\n", FN_NAME, TRP_EVENODD(evenOdd), (void *)info);
+ rv = grTexTextureMemRequired(evenOdd, info);
+ TRAP_LOG(GOT "%lu\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+FxU32 FX_CALL trap_grTexMinAddress (GrChipID_t tmu)
+{
+#define FN_NAME "grTexMinAddress"
+ FxU32 rv;
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_TMU(tmu));
+ rv = grTexMinAddress(tmu);
+ TRAP_LOG(GOT "%lu\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+FxU32 FX_CALL trap_grTexMaxAddress (GrChipID_t tmu)
+{
+#define FN_NAME "grTexMaxAddress"
+ FxU32 rv;
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_TMU(tmu));
+ rv = grTexMaxAddress(tmu);
+ TRAP_LOG(GOT "%lu\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexNCCTable (GrNCCTable_t table)
+{
+#define FN_NAME "grTexNCCTable"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_NCC(table));
+ grTexNCCTable(table);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexSource (GrChipID_t tmu,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info)
+{
+#define FN_NAME "grTexSource"
+ TRAP_LOG("%s(%s, %08lx, %s, %p)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_EVENODD(evenOdd), (void *)info);
+ grTexSource(tmu, startAddress, evenOdd, info);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexClampMode (GrChipID_t tmu,
+ GrTextureClampMode_t s_clampmode,
+ GrTextureClampMode_t t_clampmode)
+{
+#define FN_NAME "grTexClampMode"
+ TRAP_LOG("%s(%s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_CLAMPMODE(s_clampmode), TRP_CLAMPMODE(t_clampmode));
+ grTexClampMode(tmu, s_clampmode, t_clampmode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexCombine (GrChipID_t tmu,
+ GrCombineFunction_t rgb_function,
+ GrCombineFactor_t rgb_factor,
+ GrCombineFunction_t alpha_function,
+ GrCombineFactor_t alpha_factor,
+ FxBool rgb_invert,
+ FxBool alpha_invert)
+{
+#define FN_NAME "grTexCombine"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_CMBFUNC(rgb_function), TRP_CMBFACT(rgb_factor), TRP_CMBFUNC(alpha_function), TRP_CMBFACT(alpha_factor), TRP_BOOL(rgb_invert), TRP_BOOL(alpha_invert));
+ grTexCombine(tmu, rgb_function, rgb_factor, alpha_function, alpha_factor, rgb_invert, alpha_invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDetailControl (GrChipID_t tmu,
+ int lod_bias,
+ FxU8 detail_scale,
+ float detail_max)
+{
+#define FN_NAME "grTexDetailControl"
+ TRAP_LOG("%s(%s, %u, %d, %f)\n", FN_NAME, TRP_TMU(tmu), lod_bias, detail_scale, detail_max);
+ grTexDetailControl(tmu, lod_bias, detail_scale, detail_max);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexFilterMode (GrChipID_t tmu,
+ GrTextureFilterMode_t minfilter_mode,
+ GrTextureFilterMode_t magfilter_mode)
+{
+#define FN_NAME "grTexFilterMode"
+ TRAP_LOG("%s(%s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_TEXFILTER(minfilter_mode), TRP_TEXFILTER(magfilter_mode));
+ grTexFilterMode(tmu, minfilter_mode, magfilter_mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexLodBiasValue (GrChipID_t tmu,
+ float bias)
+{
+#define FN_NAME "grTexLodBiasValue"
+ TRAP_LOG("%s(%s, %f)\n", FN_NAME, TRP_TMU(tmu), bias);
+ grTexLodBiasValue(tmu, bias);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDownloadMipMap (GrChipID_t tmu,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info)
+{
+#define FN_NAME "grTexDownloadMipMap"
+ TRAP_LOG("%s(%s, %08lx, %s, %p)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_EVENODD(evenOdd), (void *)info);
+ grTexDownloadMipMap(tmu, startAddress, evenOdd, info);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDownloadMipMapLevel (GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data)
+{
+#define FN_NAME "grTexDownloadMipMapLevel"
+ TRAP_LOG("%s(%s, %08lx, %s, %s, %s, %s, %s, %p)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_LODLEVEL(thisLod), TRP_LODLEVEL(largeLod), TRP_ASPECTRATIO(aspectRatio), TRP_TEXFMT(format), TRP_EVENODD(evenOdd), data);
+ grTexDownloadMipMapLevel(tmu, startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, data);
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grTexDownloadMipMapLevelPartial (GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data,
+ int start,
+ int end)
+{
+#define FN_NAME "grTexDownloadMipMapLevelPartial"
+ FxBool rv;
+ TRAP_LOG("%s(%s, %08lx, %s, %s, %s, %s, %s, %p, %d, %d)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_LODLEVEL(thisLod), TRP_LODLEVEL(largeLod), TRP_ASPECTRATIO(aspectRatio), TRP_TEXFMT(format), TRP_EVENODD(evenOdd), data, start, end);
+ rv = grTexDownloadMipMapLevelPartial(tmu, startAddress, thisLod, largeLod, aspectRatio, format, evenOdd, data, start, end);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDownloadTable (GrTexTable_t type,
+ void *data)
+{
+#define FN_NAME "grTexDownloadTable"
+ TRAP_LOG("%s(%s, %p)\n", FN_NAME, TRP_TABLE(type), data);
+ grTexDownloadTable(type, data);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDownloadTablePartial (GrTexTable_t type,
+ void *data,
+ int start,
+ int end)
+{
+#define FN_NAME "grTexDownloadTablePartial"
+ TRAP_LOG("%s(%s, %p, %d, %d)\n", FN_NAME, TRP_TABLE(type), data, start, end);
+ grTexDownloadTablePartial(type, data, start, end);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexMipMapMode (GrChipID_t tmu,
+ GrMipMapMode_t mode,
+ FxBool lodBlend)
+{
+#define FN_NAME "grTexMipMapMode"
+ TRAP_LOG("%s(%s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_MIPMODE(mode), TRP_BOOL(lodBlend));
+ grTexMipMapMode(tmu, mode, lodBlend);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexMultibase (GrChipID_t tmu,
+ FxBool enable)
+{
+#define FN_NAME "grTexMultibase"
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_BOOL(enable));
+ grTexMultibase(tmu, enable);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexMultibaseAddress (GrChipID_t tmu,
+ GrTexBaseRange_t range,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info)
+{
+#define FN_NAME "grTexMultibaseAddress"
+ TRAP_LOG("%s(%s, %s, %08lx, %s, %p)\n", FN_NAME, TRP_TMU(tmu), TRP_TEXBASERANGE(range), startAddress, TRP_EVENODD(evenOdd), (void *)info);
+ grTexMultibaseAddress(tmu, range, startAddress, evenOdd, info);
+#undef FN_NAME
+}
+
+/*
+** linear frame buffer functions
+*/
+FxBool FX_CALL trap_grLfbLock (GrLock_t type,
+ GrBuffer_t buffer,
+ GrLfbWriteMode_t writeMode,
+ GrOriginLocation_t origin,
+ FxBool pixelPipeline,
+ GrLfbInfo_t *info)
+{
+#define FN_NAME "grLfbLock"
+ FxBool rv;
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %p)\n", FN_NAME, TRP_LOCKTYPE(type), TRP_BUFFER(buffer), TRP_WRITEMODE(writeMode), TRP_ORIGIN(origin), TRP_BOOL(pixelPipeline), (void *)info);
+ rv = grLfbLock(type, buffer, writeMode, origin, pixelPipeline, info);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grLfbUnlock (GrLock_t type,
+ GrBuffer_t buffer)
+{
+#define FN_NAME "grLfbUnlock"
+ FxBool rv;
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_LOCKTYPE(type), TRP_BUFFER(buffer));
+ rv = grLfbUnlock(type, buffer);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLfbConstantAlpha (GrAlpha_t alpha)
+{
+#define FN_NAME "grLfbConstantAlpha"
+ TRAP_LOG("%s(%02x)\n", FN_NAME, alpha);
+ grLfbConstantAlpha(alpha);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLfbConstantDepth (FxU32 depth)
+{
+#define FN_NAME "grLfbConstantDepth"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, depth);
+ grLfbConstantDepth(depth);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLfbWriteColorSwizzle (FxBool swizzleBytes,
+ FxBool swapWords)
+{
+#define FN_NAME "grLfbWriteColorSwizzle"
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_BOOL(swizzleBytes), TRP_BOOL(swapWords));
+ grLfbWriteColorSwizzle(swizzleBytes, swapWords);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLfbWriteColorFormat (GrColorFormat_t colorFormat)
+{
+#define FN_NAME "grLfbWriteColorFormat"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_COLFMT(colorFormat));
+ grLfbWriteColorFormat(colorFormat);
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grLfbWriteRegion (GrBuffer_t dst_buffer,
+ FxU32 dst_x,
+ FxU32 dst_y,
+ GrLfbSrcFmt_t src_format,
+ FxU32 src_width,
+ FxU32 src_height,
+ FxBool pixelPipeline,
+ FxI32 src_stride,
+ void *src_data)
+{
+#define FN_NAME "grLfbWriteRegion"
+ FxBool rv;
+ TRAP_LOG("%s(%s, %lu, %lu, %s, %lu, %lu, %s, %ld, %p)\n", FN_NAME, TRP_BUFFER(dst_buffer), dst_x, dst_y, TRP_SRCFMT(src_format), src_width, src_height, TRP_BOOL(pixelPipeline), src_stride, src_data);
+ rv = grLfbWriteRegion(dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride, src_data);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+FxBool FX_CALL trap_grLfbReadRegion (GrBuffer_t src_buffer,
+ FxU32 src_x,
+ FxU32 src_y,
+ FxU32 src_width,
+ FxU32 src_height,
+ FxU32 dst_stride,
+ void *dst_data)
+{
+#define FN_NAME "grLfbReadRegion"
+ FxBool rv;
+ TRAP_LOG("%s(%s, %lu, %lu, %lu, %lu, %ld, %p)\n", FN_NAME, TRP_BUFFER(src_buffer), src_x, src_y, src_width, src_height, dst_stride, dst_data);
+ rv = grLfbReadRegion(src_buffer, src_x, src_y, src_width, src_height, dst_stride, dst_data);
+ TRAP_LOG(GOT "%s\n", TRP_BOOL(rv));
+ return rv;
+#undef FN_NAME
+}
+
+/*
+** glide management functions
+*/
+void FX_CALL trap_grGlideInit (void)
+{
+#define FN_NAME "grGlideInit"
+ TRAP_LOG("%s()\n", FN_NAME);
+ grGlideInit();
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGlideShutdown (void)
+{
+#define FN_NAME "grGlideShutdown"
+ TRAP_LOG("%s()\n", FN_NAME);
+ grGlideShutdown();
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGlideGetState (void *state)
+{
+#define FN_NAME "grGlideGetState"
+ TRAP_LOG("%s(%p)\n", FN_NAME, state);
+ grGlideGetState(state);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGlideSetState (const void *state)
+{
+#define FN_NAME "grGlideSetState"
+ TRAP_LOG("%s(%p)\n", FN_NAME, state);
+ grGlideSetState(state);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGlideGetVertexLayout (void *layout)
+{
+#define FN_NAME "grGlideGetVertexLayout"
+ TRAP_LOG("%s(%p)\n", FN_NAME, layout);
+ grGlideGetVertexLayout(layout);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGlideSetVertexLayout (const void *layout)
+{
+#define FN_NAME "grGlideSetVertexLayout"
+ TRAP_LOG("%s(%p)\n", FN_NAME, layout);
+ grGlideSetVertexLayout(layout);
+#undef FN_NAME
+}
+
+/*
+** glide utility functions
+*/
+void FX_CALL trap_guGammaCorrectionRGB (FxFloat red,
+ FxFloat green,
+ FxFloat blue)
+{
+#define FN_NAME "guGammaCorrectionRGB"
+ TRAP_LOG("%s(%f, %f, %f)\n", FN_NAME, red, green, blue);
+ guGammaCorrectionRGB(red, green, blue);
+#undef FN_NAME
+}
+
+float FX_CALL trap_guFogTableIndexToW (int i)
+{
+#define FN_NAME "guFogTableIndexToW"
+ float rv;
+ TRAP_LOG("%s(%d)\n", FN_NAME, i);
+ rv = guFogTableIndexToW(i);
+ TRAP_LOG(GOT "%f\n", rv);
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_guFogGenerateExp (GrFog_t *fogtable,
+ float density)
+{
+#define FN_NAME "guFogGenerateExp"
+ TRAP_LOG("%s(%p, %f)\n", FN_NAME, fogtable, density);
+ guFogGenerateExp(fogtable, density);
+#undef FN_NAME
+}
+
+void FX_CALL trap_guFogGenerateExp2 (GrFog_t *fogtable,
+ float density)
+{
+#define FN_NAME "guFogGenerateExp2"
+ TRAP_LOG("%s(%p, %f)\n", FN_NAME, fogtable, density);
+ guFogGenerateExp2(fogtable, density);
+#undef FN_NAME
+}
+
+void FX_CALL trap_guFogGenerateLinear (GrFog_t *fogtable,
+ float nearZ,
+ float farZ)
+{
+#define FN_NAME "guFogGenerateLinear"
+ TRAP_LOG("%s(%p, %f, %f)\n", FN_NAME, fogtable, nearZ, farZ);
+ guFogGenerateLinear(fogtable, nearZ, farZ);
+#undef FN_NAME
+}
+
+/*
+** glide extensions
+*/
+void FX_CALL trap_grSetNumPendingBuffers (FxI32 NumPendingBuffers)
+{
+#define FN_NAME "grSetNumPendingBuffers"
+ TRAP_LOG("%s(%ld)\n", FN_NAME, NumPendingBuffers);
+ assert(real_grSetNumPendingBuffers);
+ (*real_grSetNumPendingBuffers)(NumPendingBuffers);
+#undef FN_NAME
+}
+
+char *FX_CALL trap_grGetRegistryOrEnvironmentStringExt (char *theEntry)
+{
+#define FN_NAME "grGetRegistryOrEnvironmentStringExt"
+ char *rv;
+ TRAP_LOG("%s(\"%s\")\n", FN_NAME, theEntry);
+ assert(real_grGetRegistryOrEnvironmentStringExt);
+ rv = (*real_grGetRegistryOrEnvironmentStringExt)(theEntry);
+ if (rv) {
+ TRAP_LOG(GOT "\"%s\"\n", rv);
+ } else {
+ TRAP_LOG(GOT "NULL\n");
+ }
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grGetGammaTableExt (FxU32 nentries,
+ FxU32 *red,
+ FxU32 *green,
+ FxU32 *blue)
+{
+#define FN_NAME "grGetGammaTableExt"
+ TRAP_LOG("%s(%lu, %p, %p, %p)\n", FN_NAME, nentries, (void *)red, (void *)green, (void *)blue);
+ assert(real_grGetGammaTableExt);
+ (*real_grGetGammaTableExt)(nentries, red, green, blue);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grChromaRangeModeExt (GrChromakeyMode_t mode)
+{
+#define FN_NAME "grChromaRangeModeExt"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_CKMODE(mode));
+ assert(real_grChromaRangeModeExt);
+ (*real_grChromaRangeModeExt)(mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grChromaRangeExt (GrColor_t color,
+ GrColor_t range,
+ GrChromaRangeMode_t match_mode)
+{
+#define FN_NAME "grChromaRangeExt"
+ TRAP_LOG("%s(%08lx, %08lx, %s)\n", FN_NAME, color, range, TRP_CRMODE(match_mode));
+ assert(real_grChromaRangeExt);
+ (*real_grChromaRangeExt)(color, range, match_mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexChromaModeExt (GrChipID_t tmu,
+ GrChromakeyMode_t mode)
+{
+#define FN_NAME "grTexChromaModeExt"
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_CKMODE(mode));
+ assert(real_grTexChromaModeExt);
+ (*real_grTexChromaModeExt)(tmu, mode);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexChromaRangeExt (GrChipID_t tmu,
+ GrColor_t min,
+ GrColor_t max,
+ GrTexChromakeyMode_t mode)
+{
+#define FN_NAME "grTexChromaRangeExt"
+ TRAP_LOG("%s(%s, %08lx, %08lx, %s)\n", FN_NAME, TRP_TMU(tmu), min, max, TRP_CRMODE(mode));
+ assert(real_grTexChromaRangeExt);
+ (*real_grTexChromaRangeExt)(tmu, min, max, mode);
+#undef FN_NAME
+}
+
+ /* pointcast */
+void FX_CALL trap_grTexDownloadTableExt (GrChipID_t tmu,
+ GrTexTable_t type,
+ void *data)
+{
+#define FN_NAME "grTexDownloadTableExt"
+ TRAP_LOG("%s(%s, %s, %p)\n", FN_NAME, TRP_TMU(tmu), TRP_TABLE(type), data);
+ assert(real_grTexDownloadTableExt);
+ (*real_grTexDownloadTableExt)(tmu, type, data);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexDownloadTablePartialExt (GrChipID_t tmu,
+ GrTexTable_t type,
+ void *data,
+ int start,
+ int end)
+{
+#define FN_NAME "grTexDownloadTablePartialExt"
+ TRAP_LOG("%s(%s, %s, %p, %d, %d)\n", FN_NAME, TRP_TMU(tmu), TRP_TABLE(type), data, start, end);
+ assert(real_grTexDownloadTablePartialExt);
+ (*real_grTexDownloadTablePartialExt)(tmu, type, data, start, end);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexNCCTableExt (GrChipID_t tmu,
+ GrNCCTable_t table)
+{
+#define FN_NAME "grTexNCCTableExt"
+ TRAP_LOG("%s(%s, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_NCC(table));
+ assert(real_grTexNCCTableExt);
+ (*real_grTexNCCTableExt)(tmu, table);
+#undef FN_NAME
+}
+
+ /* tbext */
+void FX_CALL trap_grTextureBufferExt (GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLOD,
+ GrLOD_t largeLOD,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 odd_even_mask)
+{
+#define FN_NAME "grTextureBufferExt"
+ TRAP_LOG("%s(%s, %08lx, %s, %s, %s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_LODLEVEL(thisLOD), TRP_LODLEVEL(largeLOD), TRP_ASPECTRATIO(aspectRatio), TRP_TEXFMT(format), TRP_EVENODD(odd_even_mask));
+ assert(real_grTextureBufferExt);
+ (*real_grTextureBufferExt)(tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTextureAuxBufferExt (GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLOD,
+ GrLOD_t largeLOD,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 odd_even_mask)
+{
+#define FN_NAME "grTextureAuxBufferExt"
+ TRAP_LOG("%s(%s, %08lx, %s, %s, %s, %s, %s)\n", FN_NAME, TRP_TMU(tmu), startAddress, TRP_LODLEVEL(thisLOD), TRP_LODLEVEL(largeLOD), TRP_ASPECTRATIO(aspectRatio), TRP_TEXFMT(format), TRP_EVENODD(odd_even_mask));
+ assert(real_grTextureAuxBufferExt);
+ (*real_grTextureAuxBufferExt)(tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAuxBufferExt (GrBuffer_t buffer)
+{
+#define FN_NAME "grAuxBufferExt"
+ TRAP_LOG("%s(%s)\n", FN_NAME, TRP_BUFFER(buffer));
+ assert(real_grAuxBufferExt);
+ (*real_grAuxBufferExt)(buffer);
+#undef FN_NAME
+}
+
+ /* napalm */
+GrContext_t FX_CALL trap_grSstWinOpenExt (FxU32 hWnd,
+ GrScreenResolution_t resolution,
+ GrScreenRefresh_t refresh,
+ GrColorFormat_t format,
+ GrOriginLocation_t origin,
+ GrPixelFormat_t pixelformat,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+#define FN_NAME "grSstWinOpenExt"
+ GrContext_t rv;
+ TRAP_LOG("%s(%08lx, %s, %s, %s, %s, %s, %d, %d)\n", FN_NAME, hWnd, TRP_RESOLUTION(resolution), TRP_REFRESH(refresh), TRP_COLFMT(format), TRP_ORIGIN(origin), TRP_PIXFMT(pixelformat), nColBuffers, nAuxBuffers);
+ assert(real_grSstWinOpenExt);
+ rv = (*real_grSstWinOpenExt)(hWnd, resolution, refresh, format, origin, pixelformat, nColBuffers, nAuxBuffers);
+ TRAP_LOG(GOT "%p\n", (void *)rv);
+ return rv;
+#undef FN_NAME
+}
+
+void FX_CALL trap_grStencilFuncExt (GrCmpFnc_t fnc,
+ GrStencil_t ref,
+ GrStencil_t mask)
+{
+#define FN_NAME "grStencilFuncExt"
+ TRAP_LOG("%s(%s, %02x, %02x)\n", FN_NAME, TRP_CMPFUNC(fnc), ref, mask);
+ assert(real_grStencilFuncExt);
+ (*real_grStencilFuncExt)(fnc, ref, mask);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grStencilMaskExt (GrStencil_t value)
+{
+#define FN_NAME "grStencilMaskExt"
+ TRAP_LOG("%s(%02x)\n", FN_NAME, value);
+ assert(real_grStencilMaskExt);
+ (*real_grStencilMaskExt)(value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grStencilOpExt (GrStencilOp_t stencil_fail,
+ GrStencilOp_t depth_fail,
+ GrStencilOp_t depth_pass)
+{
+#define FN_NAME "grStencilOpExt"
+ TRAP_LOG("%s(%s, %s, %s)\n", FN_NAME, TRP_STENCILOP(stencil_fail), TRP_STENCILOP(depth_fail), TRP_STENCILOP(depth_pass));
+ assert(real_grStencilOpExt);
+ (*real_grStencilOpExt)(stencil_fail, depth_fail, depth_pass);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grLfbConstantStencilExt (GrStencil_t value)
+{
+#define FN_NAME "grLfbConstantStencilExt"
+ TRAP_LOG("%s(%02x)\n", FN_NAME, value);
+ assert(real_grLfbConstantStencilExt);
+ (*real_grLfbConstantStencilExt)(value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grBufferClearExt (GrColor_t color,
+ GrAlpha_t alpha,
+ FxU32 depth,
+ GrStencil_t stencil)
+{
+#define FN_NAME "grBufferClearExt"
+ TRAP_LOG("%s(%08lx, %02x, %08lx, %02x)\n", FN_NAME, color, alpha, depth, stencil);
+ assert(real_grBufferClearExt);
+ (*real_grBufferClearExt)(color, alpha, depth, stencil);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grColorCombineExt (GrCCUColor_t a,
+ GrCombineMode_t a_mode,
+ GrCCUColor_t b,
+ GrCombineMode_t b_mode,
+ GrCCUColor_t c,
+ FxBool c_invert,
+ GrCCUColor_t d,
+ FxBool d_invert,
+ FxU32 shift,
+ FxBool invert)
+{
+#define FN_NAME "grColorCombineExt"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s, %s, %s, %lu, %s)\n", FN_NAME, TRP_CU(a), TRP_CMBMODE(a_mode), TRP_CU(b), TRP_CMBMODE(b_mode), TRP_CU(c), TRP_BOOL(c_invert), TRP_CU(d), TRP_BOOL(d_invert), shift, TRP_BOOL(invert));
+ assert(real_grColorCombineExt);
+ (*real_grColorCombineExt)(a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaCombineExt (GrACUColor_t a,
+ GrCombineMode_t a_mode,
+ GrACUColor_t b,
+ GrCombineMode_t b_mode,
+ GrACUColor_t c,
+ FxBool c_invert,
+ GrACUColor_t d,
+ FxBool d_invert,
+ FxU32 shift,
+ FxBool invert)
+{
+#define FN_NAME "grAlphaCombineExt"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s, %s, %s, %lu, %s)\n", FN_NAME, TRP_CU(a), TRP_CMBMODE(a_mode), TRP_CU(b), TRP_CMBMODE(b_mode), TRP_CU(c), TRP_BOOL(c_invert), TRP_CU(d), TRP_BOOL(d_invert), shift, TRP_BOOL(invert));
+ assert(real_grAlphaCombineExt);
+ (*real_grAlphaCombineExt)(a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexColorCombineExt (GrChipID_t tmu,
+ GrTCCUColor_t a,
+ GrCombineMode_t a_mode,
+ GrTCCUColor_t b,
+ GrCombineMode_t b_mode,
+ GrTCCUColor_t c,
+ FxBool c_invert,
+ GrTCCUColor_t d,
+ FxBool d_invert,
+ FxU32 shift,
+ FxBool invert)
+{
+#define FN_NAME "grTexColorCombineExt"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s, %s, %s, %s, %lu, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_CU(a), TRP_CMBMODE(a_mode), TRP_CU(b), TRP_CMBMODE(b_mode), TRP_CU(c), TRP_BOOL(c_invert), TRP_CU(d), TRP_BOOL(d_invert), shift, TRP_BOOL(invert));
+ assert(real_grTexColorCombineExt);
+ (*real_grTexColorCombineExt)(tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTexAlphaCombineExt (GrChipID_t tmu,
+ GrTACUColor_t a,
+ GrCombineMode_t a_mode,
+ GrTACUColor_t b,
+ GrCombineMode_t b_mode,
+ GrTACUColor_t c,
+ FxBool c_invert,
+ GrTACUColor_t d,
+ FxBool d_invert,
+ FxU32 shift,
+ FxBool invert)
+{
+#define FN_NAME "grTexAlphaCombineExt"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s, %s, %s, %s, %lu, %s)\n", FN_NAME, TRP_TMU(tmu), TRP_CU(a), TRP_CMBMODE(a_mode), TRP_CU(b), TRP_CMBMODE(b_mode), TRP_CU(c), TRP_BOOL(c_invert), TRP_CU(d), TRP_BOOL(d_invert), shift, TRP_BOOL(invert));
+ assert(real_grTexAlphaCombineExt);
+ (*real_grTexAlphaCombineExt)(tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grConstantColorValueExt (GrChipID_t tmu,
+ GrColor_t value)
+{
+#define FN_NAME "grConstantColorValueExt"
+ TRAP_LOG("%s(%s, %08lx)\n", FN_NAME, TRP_TMU(tmu), value);
+ assert(real_grConstantColorValueExt);
+ (*real_grConstantColorValueExt)(tmu, value);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grColorMaskExt (FxBool r,
+ FxBool g,
+ FxBool b,
+ FxBool a)
+{
+#define FN_NAME "grColorMaskExt"
+ TRAP_LOG("%s(%s, %s, %s, %s)\n", FN_NAME, TRP_BOOL(r), TRP_BOOL(g), TRP_BOOL(b), TRP_BOOL(a));
+ assert(real_grColorMaskExt);
+ (*real_grColorMaskExt)(r, g, b, a);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grAlphaBlendFunctionExt (GrAlphaBlendFnc_t rgb_sf,
+ GrAlphaBlendFnc_t rgb_df,
+ GrAlphaBlendOp_t rgb_op,
+ GrAlphaBlendFnc_t alpha_sf,
+ GrAlphaBlendFnc_t alpha_df,
+ GrAlphaBlendOp_t alpha_op)
+{
+#define FN_NAME "grAlphaBlendFunctionExt"
+ TRAP_LOG("%s(%s, %s, %s, %s, %s, %s)\n", FN_NAME, TRP_BLEND(rgb_sf), TRP_BLEND(rgb_df), TRP_BLENDOP(rgb_op), TRP_BLEND(alpha_sf), TRP_BLEND(alpha_df), TRP_BLENDOP(alpha_op));
+ assert(real_grAlphaBlendFunctionExt);
+ (*real_grAlphaBlendFunctionExt)(rgb_sf, rgb_df, rgb_op, alpha_sf, alpha_df, alpha_op);
+#undef FN_NAME
+}
+
+void FX_CALL trap_grTBufferWriteMaskExt (FxU32 tmask)
+{
+#define FN_NAME "grTBufferWriteMaskExt"
+ TRAP_LOG("%s(%08lx)\n", FN_NAME, tmask);
+ assert(real_grTBufferWriteMaskExt);
+ (*real_grTBufferWriteMaskExt)(tmask);
+#undef FN_NAME
+}
+
+/*
+** texus functions
+*/
+void FX_CALL trap_txImgQuantize (char *dst,
+ char *src,
+ int w,
+ int h,
+ FxU32 format,
+ FxU32 dither)
+{
+#define FN_NAME "txImgQuantize"
+ TRAP_LOG("%s(%p, %p, %d, %d, %s, %s)\n", FN_NAME, dst, src, w, h, TRP_TEXFMT(format), TRP_TXDITHER(dither));
+ assert(real_txImgQuantize);
+ (*real_txImgQuantize)(dst, src, w, h, format, dither);
+#undef FN_NAME
+}
+
+void FX_CALL trap_txMipQuantize (TxMip *pxMip,
+ TxMip *txMip,
+ int fmt,
+ FxU32 d,
+ FxU32 comp)
+{
+#define FN_NAME "txMipQuantize"
+ TRAP_LOG("%s(%p, %p, %s, %s, %s)\n", FN_NAME, (void *)pxMip, (void *)txMip, TRP_TEXFMT(fmt), TRP_TXDITHER(d), TRP_TXCOMPRESS(comp));
+ assert(real_txMipQuantize);
+ (*real_txMipQuantize)(pxMip, txMip, fmt, d, comp);
+#undef FN_NAME
+}
+
+void FX_CALL trap_txPalToNcc (GuNccTable *ncc_table,
+ const FxU32 *pal)
+{
+#define FN_NAME "txPalToNcc"
+ TRAP_LOG("%s(%p, %p)\n", FN_NAME, (void *)ncc_table, (void *)pal);
+ assert(real_txPalToNcc);
+ (*real_txPalToNcc)(ncc_table, pal);
+#undef FN_NAME
+}
+#endif
+
+
+
+/****************************************************************************\
+* housekeeping (fake pointers) *
+\****************************************************************************/
+char *FX_CALL fake_grGetRegistryOrEnvironmentStringExt (char *theEntry)
+{
+ return getenv(theEntry);
+}
+
+void FX_CALL fake_grTexDownloadTableExt (GrChipID_t tmu,
+ GrTexTable_t type,
+ void *data)
+{
+ (void)tmu;
+ grTexDownloadTable(type, data);
+}
+
+void FX_CALL fake_grTexDownloadTablePartialExt (GrChipID_t tmu,
+ GrTexTable_t type,
+ void *data,
+ int start,
+ int end)
+{
+ (void)tmu;
+ grTexDownloadTablePartial(type, data, start, end);
+}
+
+void FX_CALL fake_grTexNCCTableExt (GrChipID_t tmu,
+ GrNCCTable_t table)
+{
+ (void)tmu;
+ grTexNCCTable(table);
+}
+
+
+
+/****************************************************************************\
+* interface *
+\****************************************************************************/
+void tdfx_hook_glide (struct tdfx_glide *Glide, int pointcast)
+{
+/* GET_EXT_ADDR: get function pointer
+ * GET_EXT_FAKE: get function pointer if possible, else use a fake function
+ * GET_EXT_NULL: get function pointer if possible, else leave NULL pointer
+ */
+#if FX_TRAP_GLIDE
+#define GET_EXT_ADDR(name) *(GrProc *)&real_##name = grGetProcAddress(#name), Glide->name = trap_##name
+#define GET_EXT_FAKE(name) GET_EXT_ADDR(name); if (real_##name == NULL) real_##name = fake_##name
+#define GET_EXT_NULL(name) GET_EXT_ADDR(name); if (real_##name == NULL) Glide->name = NULL
+#else /* FX_TRAP_GLIDE */
+#define GET_EXT_ADDR(name) *(GrProc *)&Glide->name = grGetProcAddress(#name)
+#define GET_EXT_FAKE(name) GET_EXT_ADDR(name); if (Glide->name == NULL) Glide->name = fake_##name
+#define GET_EXT_NULL(name) GET_EXT_ADDR(name)
+#endif /* FX_TRAP_GLIDE */
+
+ /*
+ ** glide extensions
+ */
+ GET_EXT_NULL(grSetNumPendingBuffers);
+ GET_EXT_FAKE(grGetRegistryOrEnvironmentStringExt);
+ GET_EXT_ADDR(grGetGammaTableExt);
+ GET_EXT_ADDR(grChromaRangeModeExt);
+ GET_EXT_ADDR(grChromaRangeExt);
+ GET_EXT_ADDR(grTexChromaModeExt);
+ GET_EXT_ADDR(grTexChromaRangeExt);
+ /* pointcast */
+ if (pointcast) {
+ GET_EXT_FAKE(grTexDownloadTableExt);
+ GET_EXT_FAKE(grTexDownloadTablePartialExt);
+ GET_EXT_FAKE(grTexNCCTableExt);
+ } else {
+ Glide->grTexDownloadTableExt = fake_grTexDownloadTableExt;
+ Glide->grTexDownloadTablePartialExt = fake_grTexDownloadTablePartialExt;
+ Glide->grTexNCCTableExt = fake_grTexNCCTableExt;
+ }
+ /* tbext */
+ GET_EXT_ADDR(grTextureBufferExt);
+ GET_EXT_ADDR(grTextureAuxBufferExt);
+ GET_EXT_ADDR(grAuxBufferExt);
+ /* napalm */
+ GET_EXT_ADDR(grSstWinOpenExt);
+ GET_EXT_ADDR(grStencilFuncExt);
+ GET_EXT_ADDR(grStencilMaskExt);
+ GET_EXT_ADDR(grStencilOpExt);
+ GET_EXT_ADDR(grLfbConstantStencilExt);
+ GET_EXT_ADDR(grBufferClearExt);
+ GET_EXT_ADDR(grColorCombineExt);
+ GET_EXT_ADDR(grAlphaCombineExt);
+ GET_EXT_ADDR(grTexColorCombineExt);
+ GET_EXT_ADDR(grTexAlphaCombineExt);
+ GET_EXT_ADDR(grConstantColorValueExt);
+ GET_EXT_ADDR(grColorMaskExt);
+ GET_EXT_ADDR(grAlphaBlendFunctionExt);
+ GET_EXT_ADDR(grTBufferWriteMaskExt);
+
+ /*
+ ** texus
+ */
+ GET_EXT_NULL(txImgQuantize);
+ GET_EXT_NULL(txMipQuantize);
+ GET_EXT_NULL(txPalToNcc);
+
+#undef GET_EXT_ADDR
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxg.h b/src/mesa/drivers/glide/fxg.h
new file mode 100644
index 0000000..e712011
--- /dev/null
+++ b/src/mesa/drivers/glide/fxg.h
@@ -0,0 +1,382 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0.1
+ *
+ * Copyright (C) 1999-2003 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.
+ */
+
+/*
+ * Mesa/FX device driver. Interface to Glide3.
+ *
+ * Copyright (c) 2003 - Daniel Borca
+ * Email : dborca@users.sourceforge.net
+ * Web : http://www.geocities.com/dborca
+ */
+
+
+#ifndef TDFX_GLIDE_H_included
+#define TDFX_GLIDE_H_included
+
+#include <glide.h>
+#include <g3ext.h>
+
+#ifndef FX_TRAP_GLIDE
+#define FX_TRAP_GLIDE 0
+#endif
+
+#if FX_TRAP_GLIDE
+/*
+** rendering functions
+*/
+void FX_CALL trap_grDrawPoint (const void *pt);
+void FX_CALL trap_grDrawLine (const void *v1, const void *v2);
+void FX_CALL trap_grDrawTriangle (const void *a, const void *b, const void *c);
+void FX_CALL trap_grVertexLayout (FxU32 param, FxI32 offset, FxU32 mode);
+void FX_CALL trap_grDrawVertexArray (FxU32 mode, FxU32 Count, void *pointers);
+void FX_CALL trap_grDrawVertexArrayContiguous (FxU32 mode, FxU32 Count, void *pointers, FxU32 stride);
+
+/*
+** Antialiasing Functions
+*/
+void FX_CALL trap_grAADrawTriangle (const void *a, const void *b, const void *c, FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias);
+
+/*
+** buffer management
+*/
+void FX_CALL trap_grBufferClear (GrColor_t color, GrAlpha_t alpha, FxU32 depth);
+void FX_CALL trap_grBufferSwap (FxU32 swap_interval);
+void FX_CALL trap_grRenderBuffer (GrBuffer_t buffer);
+
+/*
+** error management
+*/
+void FX_CALL trap_grErrorSetCallback (GrErrorCallbackFnc_t fnc);
+
+/*
+** SST routines
+*/
+void FX_CALL trap_grFinish (void);
+void FX_CALL trap_grFlush (void);
+GrContext_t FX_CALL trap_grSstWinOpen (FxU32 hWnd, GrScreenResolution_t screen_resolution, GrScreenRefresh_t refresh_rate, GrColorFormat_t color_format, GrOriginLocation_t origin_location, int nColBuffers, int nAuxBuffers);
+FxBool FX_CALL trap_grSstWinClose (GrContext_t context);
+FxBool FX_CALL trap_grSelectContext (GrContext_t context);
+void FX_CALL trap_grSstOrigin (GrOriginLocation_t origin);
+void FX_CALL trap_grSstSelect (int which_sst);
+
+/*
+** Glide configuration and special effect maintenance functions
+*/
+void FX_CALL trap_grAlphaBlendFunction (GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df);
+void FX_CALL trap_grAlphaCombine (GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert);
+void FX_CALL trap_grAlphaControlsITRGBLighting (FxBool enable);
+void FX_CALL trap_grAlphaTestFunction (GrCmpFnc_t function);
+void FX_CALL trap_grAlphaTestReferenceValue (GrAlpha_t value);
+void FX_CALL trap_grChromakeyMode (GrChromakeyMode_t mode);
+void FX_CALL trap_grChromakeyValue (GrColor_t value);
+void FX_CALL trap_grClipWindow (FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy);
+void FX_CALL trap_grColorCombine (GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert);
+void FX_CALL trap_grColorMask (FxBool rgb, FxBool a);
+void FX_CALL trap_grCullMode (GrCullMode_t mode);
+void FX_CALL trap_grConstantColorValue (GrColor_t value);
+void FX_CALL trap_grDepthBiasLevel (FxI32 level);
+void FX_CALL trap_grDepthBufferFunction (GrCmpFnc_t function);
+void FX_CALL trap_grDepthBufferMode (GrDepthBufferMode_t mode);
+void FX_CALL trap_grDepthMask (FxBool mask);
+void FX_CALL trap_grDisableAllEffects (void);
+void FX_CALL trap_grDitherMode (GrDitherMode_t mode);
+void FX_CALL trap_grFogColorValue (GrColor_t fogcolor);
+void FX_CALL trap_grFogMode (GrFogMode_t mode);
+void FX_CALL trap_grFogTable (const GrFog_t ft[]);
+void FX_CALL trap_grLoadGammaTable (FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue);
+void FX_CALL trap_grSplash (float x, float y, float width, float height, FxU32 frame);
+FxU32 FX_CALL trap_grGet (FxU32 pname, FxU32 plength, FxI32 *params);
+const char * FX_CALL trap_grGetString (FxU32 pname);
+FxI32 FX_CALL trap_grQueryResolutions (const GrResolution *resTemplate, GrResolution *output);
+FxBool FX_CALL trap_grReset (FxU32 what);
+GrProc FX_CALL trap_grGetProcAddress (char *procName);
+void FX_CALL trap_grEnable (GrEnableMode_t mode);
+void FX_CALL trap_grDisable (GrEnableMode_t mode);
+void FX_CALL trap_grCoordinateSpace (GrCoordinateSpaceMode_t mode);
+void FX_CALL trap_grDepthRange (FxFloat n, FxFloat f);
+void FX_CALL trap_grStippleMode (GrStippleMode_t mode);
+void FX_CALL trap_grStipplePattern (GrStipplePattern_t mode);
+void FX_CALL trap_grViewport (FxI32 x, FxI32 y, FxI32 width, FxI32 height);
+
+/*
+** texture mapping control functions
+*/
+FxU32 FX_CALL trap_grTexCalcMemRequired (GrLOD_t lodmin, GrLOD_t lodmax, GrAspectRatio_t aspect, GrTextureFormat_t fmt);
+FxU32 FX_CALL trap_grTexTextureMemRequired (FxU32 evenOdd, GrTexInfo *info);
+FxU32 FX_CALL trap_grTexMinAddress (GrChipID_t tmu);
+FxU32 FX_CALL trap_grTexMaxAddress (GrChipID_t tmu);
+void FX_CALL trap_grTexNCCTable (GrNCCTable_t table);
+void FX_CALL trap_grTexSource (GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info);
+void FX_CALL trap_grTexClampMode (GrChipID_t tmu, GrTextureClampMode_t s_clampmode, GrTextureClampMode_t t_clampmode);
+void FX_CALL trap_grTexCombine (GrChipID_t tmu, GrCombineFunction_t rgb_function, GrCombineFactor_t rgb_factor, GrCombineFunction_t alpha_function, GrCombineFactor_t alpha_factor, FxBool rgb_invert, FxBool alpha_invert);
+void FX_CALL trap_grTexDetailControl (GrChipID_t tmu, int lod_bias, FxU8 detail_scale, float detail_max);
+void FX_CALL trap_grTexFilterMode (GrChipID_t tmu, GrTextureFilterMode_t minfilter_mode, GrTextureFilterMode_t magfilter_mode);
+void FX_CALL trap_grTexLodBiasValue (GrChipID_t tmu, float bias);
+void FX_CALL trap_grTexDownloadMipMap (GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info);
+void FX_CALL trap_grTexDownloadMipMapLevel (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data);
+FxBool FX_CALL trap_grTexDownloadMipMapLevelPartial (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data, int start, int end);
+void FX_CALL trap_grTexDownloadTable (GrTexTable_t type, void *data);
+void FX_CALL trap_grTexDownloadTablePartial (GrTexTable_t type, void *data, int start, int end);
+void FX_CALL trap_grTexMipMapMode (GrChipID_t tmu, GrMipMapMode_t mode, FxBool lodBlend);
+void FX_CALL trap_grTexMultibase (GrChipID_t tmu, FxBool enable);
+void FX_CALL trap_grTexMultibaseAddress (GrChipID_t tmu, GrTexBaseRange_t range, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info);
+
+/*
+** linear frame buffer functions
+*/
+FxBool FX_CALL trap_grLfbLock (GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, FxBool pixelPipeline, GrLfbInfo_t *info);
+FxBool FX_CALL trap_grLfbUnlock (GrLock_t type, GrBuffer_t buffer);
+void FX_CALL trap_grLfbConstantAlpha (GrAlpha_t alpha);
+void FX_CALL trap_grLfbConstantDepth (FxU32 depth);
+void FX_CALL trap_grLfbWriteColorSwizzle (FxBool swizzleBytes, FxBool swapWords);
+void FX_CALL trap_grLfbWriteColorFormat (GrColorFormat_t colorFormat);
+FxBool FX_CALL trap_grLfbWriteRegion (GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format, FxU32 src_width, FxU32 src_height, FxBool pixelPipeline, FxI32 src_stride, void *src_data);
+FxBool FX_CALL trap_grLfbReadRegion (GrBuffer_t src_buffer, FxU32 src_x, FxU32 src_y, FxU32 src_width, FxU32 src_height, FxU32 dst_stride, void *dst_data);
+
+/*
+** glide management functions
+*/
+void FX_CALL trap_grGlideInit (void);
+void FX_CALL trap_grGlideShutdown (void);
+void FX_CALL trap_grGlideGetState (void *state);
+void FX_CALL trap_grGlideSetState (const void *state);
+void FX_CALL trap_grGlideGetVertexLayout (void *layout);
+void FX_CALL trap_grGlideSetVertexLayout (const void *layout);
+
+/*
+** glide utility functions
+*/
+void FX_CALL trap_guGammaCorrectionRGB (FxFloat red, FxFloat green, FxFloat blue);
+float FX_CALL trap_guFogTableIndexToW (int i);
+void FX_CALL trap_guFogGenerateExp (GrFog_t *fogtable, float density);
+void FX_CALL trap_guFogGenerateExp2 (GrFog_t *fogtable, float density);
+void FX_CALL trap_guFogGenerateLinear (GrFog_t *fogtable, float nearZ, float farZ);
+
+#ifndef FX_TRAP_GLIDE_internal
+/*
+** rendering functions
+*/
+#define grDrawPoint trap_grDrawPoint
+#define grDrawLine trap_grDrawLine
+#define grDrawTriangle trap_grDrawTriangle
+#define grVertexLayout trap_grVertexLayout
+#define grDrawVertexArray trap_grDrawVertexArray
+#define grDrawVertexArrayContiguous trap_grDrawVertexArrayContiguous
+
+/*
+** Antialiasing Functions
+*/
+#define grAADrawTriangle trap_grAADrawTriangle
+
+/*
+** buffer management
+*/
+#define grBufferClear trap_grBufferClear
+#define grBufferSwap trap_grBufferSwap
+#define grRenderBuffer trap_grRenderBuffer
+
+/*
+** error management
+*/
+#define grErrorSetCallback trap_grErrorSetCallback
+
+/*
+** SST routines
+*/
+#define grFinish trap_grFinish
+#define grFlush trap_grFlush
+#define grSstWinOpen trap_grSstWinOpen
+#define grSstWinClose trap_grSstWinClose
+#define grSelectContext trap_grSelectContext
+#define grSstOrigin trap_grSstOrigin
+#define grSstSelect trap_grSstSelect
+
+/*
+** Glide configuration and special effect maintenance functions
+*/
+#define grAlphaBlendFunction trap_grAlphaBlendFunction
+#define grAlphaCombine trap_grAlphaCombine
+#define grAlphaControlsITRGBLighting trap_grAlphaControlsITRGBLighting
+#define grAlphaTestFunction trap_grAlphaTestFunction
+#define grAlphaTestReferenceValue trap_grAlphaTestReferenceValue
+#define grChromakeyMode trap_grChromakeyMode
+#define grChromakeyValue trap_grChromakeyValue
+#define grClipWindow trap_grClipWindow
+#define grColorCombine trap_grColorCombine
+#define grColorMask trap_grColorMask
+#define grCullMode trap_grCullMode
+#define grConstantColorValue trap_grConstantColorValue
+#define grDepthBiasLevel trap_grDepthBiasLevel
+#define grDepthBufferFunction trap_grDepthBufferFunction
+#define grDepthBufferMode trap_grDepthBufferMode
+#define grDepthMask trap_grDepthMask
+#define grDisableAllEffects trap_grDisableAllEffects
+#define grDitherMode trap_grDitherMode
+#define grFogColorValue trap_grFogColorValue
+#define grFogMode trap_grFogMode
+#define grFogTable trap_grFogTable
+#define grLoadGammaTable trap_grLoadGammaTable
+#define grSplash trap_grSplash
+#define grGet trap_grGet
+#define grGetString trap_grGetString
+#define grQueryResolutions trap_grQueryResolutions
+#define grReset trap_grReset
+#define grGetProcAddress trap_grGetProcAddress
+#define grEnable trap_grEnable
+#define grDisable trap_grDisable
+#define grCoordinateSpace trap_grCoordinateSpace
+#define grDepthRange trap_grDepthRange
+#define grStippleMode trap_grStippleMode
+#define grStipplePattern trap_grStipplePattern
+#define grViewport trap_grViewport
+
+/*
+** texture mapping control functions
+*/
+#define grTexCalcMemRequired trap_grTexCalcMemRequired
+#define grTexTextureMemRequired trap_grTexTextureMemRequired
+#define grTexMinAddress trap_grTexMinAddress
+#define grTexMaxAddress trap_grTexMaxAddress
+#define grTexNCCTable trap_grTexNCCTable
+#define grTexSource trap_grTexSource
+#define grTexClampMode trap_grTexClampMode
+#define grTexCombine trap_grTexCombine
+#define grTexDetailControl trap_grTexDetailControl
+#define grTexFilterMode trap_grTexFilterMode
+#define grTexLodBiasValue trap_grTexLodBiasValue
+#define grTexDownloadMipMap trap_grTexDownloadMipMap
+#define grTexDownloadMipMapLevel trap_grTexDownloadMipMapLevel
+#define grTexDownloadMipMapLevelPartial trap_grTexDownloadMipMapLevelPartial
+#define grTexDownloadTable trap_grTexDownloadTable
+#define grTexDownloadTablePartial trap_grTexDownloadTablePartial
+#define grTexMipMapMode trap_grTexMipMapMode
+#define grTexMultibase trap_grTexMultibase
+#define grTexMultibaseAddress trap_grTexMultibaseAddress
+
+/*
+** linear frame buffer functions
+*/
+#define grLfbLock trap_grLfbLock
+#define grLfbUnlock trap_grLfbUnlock
+#define grLfbConstantAlpha trap_grLfbConstantAlpha
+#define grLfbConstantDepth trap_grLfbConstantDepth
+#define grLfbWriteColorSwizzle trap_grLfbWriteColorSwizzle
+#define grLfbWriteColorFormat trap_grLfbWriteColorFormat
+#define grLfbWriteRegion trap_grLfbWriteRegion
+#define grLfbReadRegion trap_grLfbReadRegion
+
+/*
+** glide management functions
+*/
+#define grGlideInit trap_grGlideInit
+#define grGlideShutdown trap_grGlideShutdown
+#define grGlideGetState trap_grGlideGetState
+#define grGlideSetState trap_grGlideSetState
+#define grGlideGetVertexLayout trap_grGlideGetVertexLayout
+#define grGlideSetVertexLayout trap_grGlideSetVertexLayout
+
+/*
+** glide utility functions
+*/
+#define guGammaCorrectionRGB trap_guGammaCorrectionRGB
+#define guFogTableIndexToW trap_guFogTableIndexToW
+#define guFogGenerateExp trap_guFogGenerateExp
+#define guFogGenerateExp2 trap_guFogGenerateExp2
+#define guFogGenerateLinear trap_guFogGenerateLinear
+#endif /* FX_TRAP_GLIDE_internal */
+#endif /* FX_TRAP_GLIDE */
+
+
+
+/* <texus.h> */
+#define TX_MAX_LEVEL 16
+typedef struct _TxMip {
+ int format;
+ int width;
+ int height;
+ int depth;
+ int size;
+ void *data[TX_MAX_LEVEL];
+ FxU32 pal[256];
+} TxMip;
+
+#define TX_DITHER_NONE 0x00000000
+#define TX_DITHER_4x4 0x00000001
+#define TX_DITHER_ERR 0x00000002
+
+#define TX_COMPRESSION_STATISTICAL 0x00000000
+#define TX_COMPRESSION_HEURISTIC 0x00000010
+/* <texus.h> */
+
+
+
+struct tdfx_glide {
+ /*
+ ** glide extensions
+ */
+ void (FX_CALL *grSetNumPendingBuffers) (FxI32 NumPendingBuffers);
+ char * (FX_CALL *grGetRegistryOrEnvironmentStringExt) (char *theEntry);
+ void (FX_CALL *grGetGammaTableExt) (FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue);
+ void (FX_CALL *grChromaRangeModeExt) (GrChromakeyMode_t mode);
+ void (FX_CALL *grChromaRangeExt) (GrColor_t color, GrColor_t range, GrChromaRangeMode_t match_mode);
+ void (FX_CALL *grTexChromaModeExt) (GrChipID_t tmu, GrChromakeyMode_t mode);
+ void (FX_CALL *grTexChromaRangeExt) (GrChipID_t tmu, GrColor_t min, GrColor_t max, GrTexChromakeyMode_t mode);
+
+ /* pointcast */
+ void (FX_CALL *grTexDownloadTableExt) (GrChipID_t tmu, GrTexTable_t type, void *data);
+ void (FX_CALL *grTexDownloadTablePartialExt) (GrChipID_t tmu, GrTexTable_t type, void *data, int start, int end);
+ void (FX_CALL *grTexNCCTableExt) (GrChipID_t tmu, GrNCCTable_t table);
+
+ /* tbext */
+ void (FX_CALL *grTextureBufferExt) (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLOD, GrLOD_t largeLOD, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 odd_even_mask);
+ void (FX_CALL *grTextureAuxBufferExt) (GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLOD, GrLOD_t largeLOD, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 odd_even_mask);
+ void (FX_CALL *grAuxBufferExt) (GrBuffer_t buffer);
+
+ /* napalm */
+ GrContext_t (FX_CALL *grSstWinOpenExt) (FxU32 hWnd, GrScreenResolution_t resolution, GrScreenRefresh_t refresh, GrColorFormat_t format, GrOriginLocation_t origin, GrPixelFormat_t pixelformat, int nColBuffers, int nAuxBuffers);
+ void (FX_CALL *grStencilFuncExt) (GrCmpFnc_t fnc, GrStencil_t ref, GrStencil_t mask);
+ void (FX_CALL *grStencilMaskExt) (GrStencil_t value);
+ void (FX_CALL *grStencilOpExt) (GrStencilOp_t stencil_fail, GrStencilOp_t depth_fail, GrStencilOp_t depth_pass);
+ void (FX_CALL *grLfbConstantStencilExt) (GrStencil_t value);
+ void (FX_CALL *grBufferClearExt) (GrColor_t color, GrAlpha_t alpha, FxU32 depth, GrStencil_t stencil);
+ void (FX_CALL *grColorCombineExt) (GrCCUColor_t a, GrCombineMode_t a_mode, GrCCUColor_t b, GrCombineMode_t b_mode, GrCCUColor_t c, FxBool c_invert, GrCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+ void (FX_CALL *grAlphaCombineExt) (GrACUColor_t a, GrCombineMode_t a_mode, GrACUColor_t b, GrCombineMode_t b_mode, GrACUColor_t c, FxBool c_invert, GrACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+ void (FX_CALL *grTexColorCombineExt) (GrChipID_t tmu, GrTCCUColor_t a, GrCombineMode_t a_mode, GrTCCUColor_t b, GrCombineMode_t b_mode, GrTCCUColor_t c, FxBool c_invert, GrTCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+ void (FX_CALL *grTexAlphaCombineExt) (GrChipID_t tmu, GrTACUColor_t a, GrCombineMode_t a_mode, GrTACUColor_t b, GrCombineMode_t b_mode, GrTACUColor_t c, FxBool c_invert, GrTACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert);
+ void (FX_CALL *grConstantColorValueExt) (GrChipID_t tmu, GrColor_t value);
+ void (FX_CALL *grColorMaskExt) (FxBool r, FxBool g, FxBool b, FxBool a);
+ void (FX_CALL *grAlphaBlendFunctionExt) (GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendOp_t rgb_op, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df, GrAlphaBlendOp_t alpha_op);
+ void (FX_CALL *grTBufferWriteMaskExt) (FxU32 tmask);
+
+ /*
+ ** Texus2 functions
+ */
+ void (FX_CALL *txImgQuantize) (char *dst, char *src, int w, int h, FxU32 format, FxU32 dither);
+ void (FX_CALL *txMipQuantize) (TxMip *pxMip, TxMip *txMip, int fmt, FxU32 d, FxU32 comp);
+ void (FX_CALL *txPalToNcc) (GuNccTable *ncc_table, const FxU32 *pal);
+};
+
+void tdfx_hook_glide (struct tdfx_glide *Glide, int pointcast);
+
+#endif
diff --git a/src/mesa/drivers/glide/fxglidew.c b/src/mesa/drivers/glide/fxglidew.c
new file mode 100644
index 0000000..1fedf2a
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.c
@@ -0,0 +1,269 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "fxglidew.h"
+#include "fxdrv.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+FxI32
+FX_grGetInteger_NoLock(FxU32 pname)
+{
+ FxI32 result;
+
+ if (grGet(pname, 4, &result)) {
+ return result;
+ }
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "FX_grGetInteger_NoLock: wrong parameter (%lx)\n", pname);
+ }
+ return -1;
+}
+
+FxBool
+FX_grSstControl(FxU32 code)
+{
+ /* The glide 3 sources call for grEnable/grDisable to be called in exchange
+ * for grSstControl. */
+ switch (code) {
+ case GR_CONTROL_ACTIVATE:
+ grEnable(GR_PASSTHRU);
+ break;
+ case GR_CONTROL_DEACTIVATE:
+ grDisable(GR_PASSTHRU);
+ break;
+ }
+ /* Appearently GR_CONTROL_RESIZE can be ignored. */
+ return 1; /* OK? */
+}
+
+
+int
+FX_grSstScreenWidth()
+{
+ FxI32 result[4];
+
+ BEGIN_BOARD_LOCK();
+ grGet(GR_VIEWPORT, sizeof(FxI32) * 4, result);
+ END_BOARD_LOCK();
+
+ return result[2];
+}
+
+int
+FX_grSstScreenHeight()
+{
+ FxI32 result[4];
+
+ BEGIN_BOARD_LOCK();
+ grGet(GR_VIEWPORT, sizeof(FxI32) * 4, result);
+ END_BOARD_LOCK();
+
+ return result[3];
+}
+
+void
+FX_grSstPerfStats(GrSstPerfStats_t * st)
+{
+ FxI32 n;
+ grGet(GR_STATS_PIXELS_IN, 4, &n);
+ st->pixelsIn = n;
+ grGet(GR_STATS_PIXELS_CHROMA_FAIL, 4, &n);
+ st->chromaFail = n;
+ grGet(GR_STATS_PIXELS_DEPTHFUNC_FAIL, 4, &n);
+ st->zFuncFail = n;
+ grGet(GR_STATS_PIXELS_AFUNC_FAIL, 4, &n);
+ st->aFuncFail = n;
+ grGet(GR_STATS_PIXELS_OUT, 4, &n);
+ st->pixelsOut = n;
+}
+
+void
+FX_setupGrVertexLayout(void)
+{
+ BEGIN_BOARD_LOCK();
+ grReset(GR_VERTEX_PARAMETER);
+
+ grCoordinateSpace(GR_WINDOW_COORDS);
+ grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE);
+#if FX_PACKEDCOLOR
+ grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PARGB_OFFSET << 2, GR_PARAM_ENABLE);
+#else /* !FX_PACKEDCOLOR */
+ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_RGB_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_A, GR_VERTEX_A_OFFSET << 2, GR_PARAM_ENABLE);
+#endif /* !FX_PACKEDCOLOR */
+ grVertexLayout(GR_PARAM_Q, GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2,
+ GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2,
+ GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2,
+ GR_PARAM_DISABLE);
+ END_BOARD_LOCK();
+}
+
+void
+FX_grHints_NoLock(GrHint_t hintType, FxU32 hintMask)
+{
+ switch (hintType) {
+ case GR_HINT_STWHINT:
+ {
+ if (hintMask & GR_STWHINT_W_DIFF_TMU0)
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2,
+ GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_ST_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2,
+ GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_W_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2,
+ GR_PARAM_DISABLE);
+
+ }
+ }
+}
+
+/*
+ * Glide3 doesn't have the grSstQueryHardware function anymore.
+ * Instead, we call grGet() and fill in the data structures ourselves.
+ */
+int
+FX_grSstQueryHardware(GrHwConfiguration * config)
+{
+ int i, j;
+ int numFB;
+
+ BEGIN_BOARD_LOCK();
+
+ grGet(GR_NUM_BOARDS, 4, (void *) &(config->num_sst));
+ if (config->num_sst == 0)
+ return 0;
+
+ for (i = 0; i < config->num_sst; i++) {
+ FxI32 result;
+ const char *extension;
+
+ grSstSelect(i);
+
+ extension = grGetString(GR_HARDWARE);
+ if (strstr(extension, "Rush")) {
+ config->SSTs[i].type = GR_SSTTYPE_SST96;
+ } else if (strstr(extension, "Voodoo2")) {
+ config->SSTs[i].type = GR_SSTTYPE_Voodoo2;
+ } else if (strstr(extension, "Voodoo Banshee")) {
+ config->SSTs[i].type = GR_SSTTYPE_Banshee;
+ } else if (strstr(extension, "Voodoo3")) {
+ config->SSTs[i].type = GR_SSTTYPE_Voodoo3;
+ } else if (strstr(extension, "Voodoo4")) {
+ config->SSTs[i].type = GR_SSTTYPE_Voodoo4;
+ } else if (strstr(extension, "Voodoo5")) {
+ config->SSTs[i].type = GR_SSTTYPE_Voodoo5;
+ } else {
+ config->SSTs[i].type = GR_SSTTYPE_VOODOO;
+ }
+
+ grGet(GR_MEMORY_FB, 4, &result);
+ config->SSTs[i].fbRam = result / (1024 * 1024);
+
+ grGet(GR_NUM_TMU, 4, &result);
+ config->SSTs[i].nTexelfx = result;
+
+ grGet(GR_REVISION_FB, 4, &result);
+ config->SSTs[i].fbiRev = result;
+
+ for (j = 0; j < config->SSTs[i].nTexelfx; j++) {
+ grGet(GR_MEMORY_TMU, 4, &result);
+ config->SSTs[i].tmuConfig[j].tmuRam = result / (1024 * 1024);
+ grGet(GR_REVISION_TMU, 4, &result);
+ config->SSTs[i].tmuConfig[j].tmuRev = result;
+ }
+
+ extension = grGetString(GR_EXTENSION);
+ config->SSTs[i].HavePalExt = (strstr(extension, " PALETTE6666 ") != NULL);
+ config->SSTs[i].HavePixExt = (strstr(extension, " PIXEXT ") != NULL);
+ config->SSTs[i].HaveTexFmt = (strstr(extension, " TEXFMT ") != NULL);
+ config->SSTs[i].HaveCmbExt = (strstr(extension, " COMBINE ") != NULL);
+ config->SSTs[i].HaveMirExt = (strstr(extension, " TEXMIRROR ") != NULL);
+ config->SSTs[i].HaveTexUma = (strstr(extension, " TEXUMA ") != NULL);
+
+ /* number of Voodoo chips */
+ grGet(GR_NUM_FB, 4, (void *) &numFB);
+ config->SSTs[i].numChips = numFB;
+
+ }
+
+ tdfx_hook_glide(&config->Glide, getenv("MESA_FX_POINTCAST") != NULL);
+
+ END_BOARD_LOCK();
+ return 1;
+}
+
+
+
+#else
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_glidew(void);
+int
+gl_fx_dummy_function_glidew(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxglidew.h b/src/mesa/drivers/glide/fxglidew.h
new file mode 100644
index 0000000..a19d0b5
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.h
@@ -0,0 +1,228 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+
+#ifndef __FX_GLIDE_WARPER__
+#define __FX_GLIDE_WARPER__
+
+
+#include "fxg.h"
+
+#ifndef FX_PACKEDCOLOR
+#define FX_PACKEDCOLOR 1
+#endif
+
+#define MAX_NUM_SST 4
+
+enum {
+ GR_SSTTYPE_VOODOO = 0,
+ GR_SSTTYPE_SST96 = 1,
+ GR_SSTTYPE_AT3D = 2,
+ GR_SSTTYPE_Voodoo2 = 3,
+ GR_SSTTYPE_Banshee = 4,
+ GR_SSTTYPE_Voodoo3 = 5,
+ GR_SSTTYPE_Voodoo4 = 6,
+ GR_SSTTYPE_Voodoo5 = 7
+};
+
+#define GrState void
+
+typedef int GrSstType;
+
+typedef struct GrTMUConfig_St {
+ int tmuRev; /* Rev of Texelfx chip */
+ int tmuRam; /* 1, 2, or 4 MB */
+} GrTMUConfig_t;
+
+typedef struct {
+ int num_sst; /* # of HW units in the system */
+ struct SstCard_St {
+ GrSstType type; /* Which hardware is it? */
+ int fbRam; /* 1, 2, or 4 MB */
+ int fbiRev; /* Rev of Pixelfx chip */
+ int nTexelfx; /* How many texelFX chips are there? */
+ int numChips; /* Number of Voodoo chips */
+ GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */
+ /* Glide3 extensions */
+ FxBool HavePalExt; /* PALETTE6666 */
+ FxBool HavePixExt; /* PIXEXT */
+ FxBool HaveTexFmt; /* TEXFMT */
+ FxBool HaveCmbExt; /* COMBINE */
+ FxBool HaveMirExt; /* TEXMIRROR */
+ FxBool HaveTexUma; /* TEXUMA */
+ }
+ SSTs[MAX_NUM_SST]; /* configuration for each board */
+ struct tdfx_glide Glide;
+} GrHwConfiguration;
+
+
+
+typedef FxU32 GrHint_t;
+#define GR_HINTTYPE_MIN 0
+#define GR_HINT_STWHINT 0
+
+typedef FxU32 GrSTWHint_t;
+#define GR_STWHINT_W_DIFF_FBI FXBIT(0)
+#define GR_STWHINT_W_DIFF_TMU0 FXBIT(1)
+#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2)
+#define GR_STWHINT_W_DIFF_TMU1 FXBIT(3)
+#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4)
+#define GR_STWHINT_W_DIFF_TMU2 FXBIT(5)
+#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6)
+
+#define GR_CONTROL_ACTIVATE 1
+#define GR_CONTROL_DEACTIVATE 0
+
+
+
+/*
+** move the vertex layout defintion to application
+*/
+typedef struct {
+ float sow; /* s texture ordinate (s over w) */
+ float tow; /* t texture ordinate (t over w) */
+ float oow; /* 1/w (used mipmapping - really 0xfff/w) */
+} GrTmuVertex;
+
+#if FX_PACKEDCOLOR
+typedef struct {
+ float x, y; /* X and Y in screen space */
+ float ooz; /* 65535/Z (used for Z-buffering) */
+ float oow; /* 1/W (used for W-buffering, texturing) */
+ unsigned char pargb[4]; /* B, G, R, A [0..255] */
+ GrTmuVertex tmuvtx[GLIDE_NUM_TMU];
+ float fog; /* fog coordinate */
+ unsigned char pspec[4]; /* B, G, R, A [0..255] */
+ float psize; /* point size */
+ long pad[16 - 14]; /* ensure 64b structure */
+} GrVertex;
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 1
+#define GR_VERTEX_OOZ_OFFSET 2
+#define GR_VERTEX_OOW_OFFSET 3
+#define GR_VERTEX_PARGB_OFFSET 4
+#define GR_VERTEX_SOW_TMU0_OFFSET 5
+#define GR_VERTEX_TOW_TMU0_OFFSET 6
+#define GR_VERTEX_OOW_TMU0_OFFSET 7
+#define GR_VERTEX_SOW_TMU1_OFFSET 8
+#define GR_VERTEX_TOW_TMU1_OFFSET 9
+#define GR_VERTEX_OOW_TMU1_OFFSET 10
+#define GR_VERTEX_FOG_OFFSET 11
+#define GR_VERTEX_PSPEC_OFFSET 12
+#else /* !FX_PACKEDCOLOR */
+typedef struct {
+ float x, y; /* X and Y in screen space */
+ float ooz; /* 65535/Z (used for Z-buffering) */
+ float oow; /* 1/W (used for W-buffering, texturing) */
+ float r, g, b, a; /* R, G, B, A [0..255] */
+ GrTmuVertex tmuvtx[GLIDE_NUM_TMU];
+ float fog; /* fog coordinate */
+ float r1, g1, b1; /* R, G, B [0..255] */
+ float psize; /* point size */
+ long pad[20 - 19]; /* ensure multiple of 16 */
+} GrVertex;
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 1
+#define GR_VERTEX_OOZ_OFFSET 2
+#define GR_VERTEX_OOW_OFFSET 3
+#define GR_VERTEX_RGB_OFFSET 4
+#define GR_VERTEX_A_OFFSET 7
+#define GR_VERTEX_SOW_TMU0_OFFSET 8
+#define GR_VERTEX_TOW_TMU0_OFFSET 9
+#define GR_VERTEX_OOW_TMU0_OFFSET 10
+#define GR_VERTEX_SOW_TMU1_OFFSET 11
+#define GR_VERTEX_TOW_TMU1_OFFSET 12
+#define GR_VERTEX_OOW_TMU1_OFFSET 13
+#define GR_VERTEX_FOG_OFFSET 14
+#define GR_VERTEX_SPEC_OFFSET 15
+#endif /* !FX_PACKEDCOLOR */
+
+
+
+/*
+ * For Lod/LodLog2 conversion.
+ */
+#define FX_largeLodLog2(info) (info).largeLodLog2
+#define FX_aspectRatioLog2(info) (info).aspectRatioLog2
+#define FX_smallLodLog2(info) (info).smallLodLog2
+#define FX_lodToValue(val) ((int)(GR_LOD_LOG2_256-val))
+#define FX_largeLodValue(info) ((int)(GR_LOD_LOG2_256-(info).largeLodLog2))
+#define FX_smallLodValue(info) ((int)(GR_LOD_LOG2_256-(info).smallLodLog2))
+#define FX_valueToLod(val) ((GrLOD_t)(GR_LOD_LOG2_256-val))
+
+
+
+/*
+ * Query
+ */
+extern int FX_grSstScreenWidth(void);
+extern int FX_grSstScreenHeight(void);
+extern void FX_grSstPerfStats(GrSstPerfStats_t *st);
+extern int FX_grSstQueryHardware(GrHwConfiguration *config);
+#define FX_grGetInteger FX_grGetInteger_NoLock
+extern FxI32 FX_grGetInteger_NoLock(FxU32 pname);
+
+
+
+/*
+ * GrHints
+ */
+#define FX_grHints FX_grHints_NoLock
+extern void FX_grHints_NoLock(GrHint_t hintType, FxU32 hintMask);
+
+
+
+/*
+ * Needed for Glide3 only, to set up Glide2 compatible vertex layout.
+ */
+extern void FX_setupGrVertexLayout(void);
+
+
+
+/*
+ * grSstControl stuff
+ */
+extern FxBool FX_grSstControl(FxU32 code);
+
+#define FX_grBufferClear(c, a, d) \
+ do { \
+ BEGIN_CLIP_LOOP(); \
+ grBufferClear(c, a, d); \
+ END_CLIP_LOOP(); \
+ } while (0)
+
+
+
+#endif /* __FX_GLIDE_WARPER__ */
diff --git a/src/mesa/drivers/glide/fxopengl.def b/src/mesa/drivers/glide/fxopengl.def
new file mode 100644
index 0000000..fecbb25
--- /dev/null
+++ b/src/mesa/drivers/glide/fxopengl.def
@@ -0,0 +1,938 @@
+LIBRARY OpenGL32
+DESCRIPTION "Mesa 5.1"
+EXPORTS
+ glAccum
+ glActiveStencilFaceEXT
+ glActiveTexture
+ glActiveTextureARB
+ glAlphaFunc
+ glAreProgramsResidentNV
+ glAreTexturesResident
+ glAreTexturesResidentEXT
+ glArrayElement
+ glArrayElementEXT
+ glBegin
+ glBeginQueryARB
+ glBindBufferARB
+ glBindProgramARB
+ glBindProgramNV
+ glBindTexture
+ glBindTextureEXT
+ glBitmap
+;glBlendColor
+;glBlendColorEXT
+ glBlendEquation
+ glBlendEquationEXT
+ glBlendFunc
+ glBlendFuncSeparate
+ glBlendFuncSeparateEXT
+ glBlendFuncSeparateINGR
+ glBufferDataARB
+ glBufferSubDataARB
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClientActiveTexture
+ glClientActiveTextureARB
+ glClipPlane
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorPointerEXT
+ glColorSubTable
+ glColorSubTableEXT
+ glColorTable
+ glColorTableEXT
+ glColorTableParameterfv
+ glColorTableParameterfvSGI
+ glColorTableParameteriv
+ glColorTableParameterivSGI
+ glColorTableSGI
+ 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
+ glCombinerInputNV
+ glCombinerOutputNV
+ glCombinerParameterfNV
+ glCombinerParameterfvNV
+ glCombinerParameteriNV
+ glCombinerParameterivNV
+ glCompressedTexImage1D
+ glCompressedTexImage1DARB
+ glCompressedTexImage2D
+ glCompressedTexImage2DARB
+ glCompressedTexImage3D
+ glCompressedTexImage3DARB
+ glCompressedTexSubImage1D
+ glCompressedTexSubImage1DARB
+ glCompressedTexSubImage2D
+ glCompressedTexSubImage2DARB
+ glCompressedTexSubImage3D
+ glCompressedTexSubImage3DARB
+ glConvolutionFilter1D
+ glConvolutionFilter1DEXT
+ glConvolutionFilter2D
+ glConvolutionFilter2DEXT
+ glConvolutionParameterf
+ glConvolutionParameterfEXT
+ glConvolutionParameterfv
+ glConvolutionParameterfvEXT
+ glConvolutionParameteri
+ glConvolutionParameteriEXT
+ glConvolutionParameteriv
+ glConvolutionParameterivEXT
+ glCopyColorSubTable
+ glCopyColorSubTableEXT
+ glCopyColorTable
+ glCopyColorTableSGI
+ glCopyConvolutionFilter1D
+ glCopyConvolutionFilter1DEXT
+ glCopyConvolutionFilter2D
+ glCopyConvolutionFilter2DEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage1DEXT
+ glCopyTexImage2D
+ glCopyTexImage2DEXT
+ glCopyTexSubImage1D
+ glCopyTexSubImage1DEXT
+ glCopyTexSubImage2D
+ glCopyTexSubImage2DEXT
+ glCopyTexSubImage3D
+ glCopyTexSubImage3DEXT
+ glCullFace
+ glCullParameterdvEXT
+ glCullParameterfvEXT
+ glDeleteBuffersARB
+ glDeleteFencesNV
+ glDeleteLists
+ glDeleteProgramsARB
+ glDeleteProgramsNV
+ glDeleteQueriesARB
+ glDeleteTextures
+ glDeleteTexturesEXT
+ glDepthBoundsEXT
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDetailTexFuncSGIS
+ glDisable
+ glDisableClientState
+ glDisableVertexAttribArrayARB
+ glDrawArrays
+ glDrawArraysEXT
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glDrawRangeElements
+ glDrawRangeElementsEXT
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagPointerEXT
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnableVertexAttribArrayARB
+ glEnd
+ glEndList
+ glEndQueryARB
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glExecuteProgramNV
+ glFeedbackBuffer
+ glFinalCombinerInputNV
+ glFinish
+ glFinishFenceNV
+ glFlush
+ glFlushRasterSGIX
+ glFlushVertexArrayRangeNV
+ glFogCoordd
+ glFogCoorddEXT
+ glFogCoorddv
+ glFogCoorddvEXT
+ glFogCoordf
+ glFogCoordfEXT
+ glFogCoordfv
+ glFogCoordfvEXT
+ glFogCoordPointer
+ glFogCoordPointerEXT
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFragmentColorMaterialSGIX
+ glFragmentLightfSGIX
+ glFragmentLightfvSGIX
+ glFragmentLightiSGIX
+ glFragmentLightivSGIX
+ glFragmentLightModelfSGIX
+ glFragmentLightModelfvSGIX
+ glFragmentLightModeliSGIX
+ glFragmentLightModelivSGIX
+ glFragmentMaterialfSGIX
+ glFragmentMaterialfvSGIX
+ glFragmentMaterialiSGIX
+ glFragmentMaterialivSGIX
+ glFrameZoomSGIX
+ glFrontFace
+ glFrustum
+ glGenBuffersARB
+ glGenFencesNV
+ glGenLists
+ glGenProgramsARB
+ glGenProgramsNV
+ glGenQueriesARB
+ glGenTextures
+ glGenTexturesEXT
+ glGetBooleanv
+ glGetBufferParameterivARB
+ glGetBufferPointervARB
+ glGetBufferSubDataARB
+ glGetClipPlane
+ glGetColorTable
+ glGetColorTableEXT
+ glGetColorTableParameterfv
+ glGetColorTableParameterfvEXT
+ glGetColorTableParameterfvSGI
+ glGetColorTableParameteriv
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterivSGI
+ glGetColorTableSGI
+ glGetCombinerInputParameterfvNV
+ glGetCombinerInputParameterivNV
+ glGetCombinerOutputParameterfvNV
+ glGetCombinerOutputParameterivNV
+ glGetCompressedTexImage
+ glGetCompressedTexImageARB
+ glGetConvolutionFilter
+ glGetConvolutionFilterEXT
+ glGetConvolutionParameterfv
+ glGetConvolutionParameterfvEXT
+ glGetConvolutionParameteriv
+ glGetConvolutionParameterivEXT
+ glGetDetailTexFuncSGIS
+ glGetDoublev
+ glGetError
+ glGetFenceivNV
+ glGetFinalCombinerInputParameterfvNV
+ glGetFinalCombinerInputParameterivNV
+ glGetFloatv
+ glGetFragmentLightfvSGIX
+ glGetFragmentLightivSGIX
+ glGetFragmentMaterialfvSGIX
+ glGetFragmentMaterialivSGIX
+ glGetHistogram
+ glGetHistogramEXT
+ glGetHistogramParameterfv
+ glGetHistogramParameterfvEXT
+ glGetHistogramParameteriv
+ glGetHistogramParameterivEXT
+ glGetInstrumentsSGIX
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetListParameterfvSGIX
+ glGetListParameterivSGIX
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetMinmax
+ glGetMinmaxEXT
+ glGetMinmaxParameterfv
+ glGetMinmaxParameterfvEXT
+ glGetMinmaxParameteriv
+ glGetMinmaxParameterivEXT
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPixelTexGenParameterfvSGIS
+ glGetPixelTexGenParameterivSGIS
+ glGetPointerv
+ glGetPointervEXT
+ glGetPolygonStipple
+ glGetProgramEnvParameterdvARB
+ glGetProgramEnvParameterfvARB
+ glGetProgramivARB
+ glGetProgramivNV
+ glGetProgramLocalParameterdvARB
+ glGetProgramLocalParameterfvARB
+ glGetProgramNamedParameterdvNV
+ glGetProgramNamedParameterfvNV
+ glGetProgramParameterdvNV
+ glGetProgramParameterfvNV
+ glGetProgramStringARB
+ glGetProgramStringNV
+ glGetQueryivARB
+ glGetQueryObjectivARB
+ glGetQueryObjectuivARB
+ glGetSeparableFilter
+ glGetSeparableFilterEXT
+ glGetSharpenTexFuncSGIS
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexFilterFuncSGIS
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glGetTrackMatrixivNV
+ glGetVertexAttribdvARB
+ glGetVertexAttribdvNV
+ glGetVertexAttribfvARB
+ glGetVertexAttribfvNV
+ glGetVertexAttribivARB
+ glGetVertexAttribivNV
+ glGetVertexAttribPointervARB
+ glGetVertexAttribPointervNV
+ glHint
+ glHintPGI
+ glHistogram
+ glHistogramEXT
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexFuncEXT
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexMask
+ glIndexMaterialEXT
+ glIndexPointer
+ glIndexPointerEXT
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInstrumentsBufferSGIX
+ glInterleavedArrays
+ glIsBufferARB
+ glIsEnabled
+ glIsFenceNV
+ glIsList
+ glIsProgramARB
+ glIsProgramNV
+ glIsQueryARB
+ glIsTexture
+ glIsTextureEXT
+ glLightEnviSGIX
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glListParameterfSGIX
+ glListParameterfvSGIX
+ glListParameteriSGIX
+ glListParameterivSGIX
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLoadProgramNV
+ glLoadTransposeMatrixd
+ glLoadTransposeMatrixdARB
+ glLoadTransposeMatrixf
+ glLoadTransposeMatrixfARB
+ glLockArraysEXT
+ glLogicOp
+ glMapBufferARB
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMinmax
+ glMinmaxEXT
+ glMultiDrawArrays
+ glMultiDrawArraysEXT
+ glMultiDrawElements
+ glMultiDrawElementsEXT
+ glMultiModeDrawArraysIBM
+ glMultiModeDrawElementsIBM
+ glMultiTexCoord1d
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dv
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1f
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fv
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1i
+ glMultiTexCoord1iARB
+ glMultiTexCoord1iv
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1s
+ glMultiTexCoord1sARB
+ glMultiTexCoord1sv
+ glMultiTexCoord1svARB
+ glMultiTexCoord2d
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dv
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2f
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fv
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2i
+ glMultiTexCoord2iARB
+ glMultiTexCoord2iv
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2s
+ glMultiTexCoord2sARB
+ glMultiTexCoord2sv
+ glMultiTexCoord2svARB
+ glMultiTexCoord3d
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dv
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3f
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fv
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3i
+ glMultiTexCoord3iARB
+ glMultiTexCoord3iv
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3s
+ glMultiTexCoord3sARB
+ glMultiTexCoord3sv
+ glMultiTexCoord3svARB
+ glMultiTexCoord4d
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dv
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4f
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fv
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4i
+ glMultiTexCoord4iARB
+ glMultiTexCoord4iv
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4s
+ glMultiTexCoord4sARB
+ glMultiTexCoord4sv
+ glMultiTexCoord4svARB
+ glMultMatrixd
+ glMultMatrixf
+ glMultTransposeMatrixd
+ glMultTransposeMatrixdARB
+ glMultTransposeMatrixf
+ glMultTransposeMatrixfARB
+ glNewList
+ glNormalPointer
+ glNormalPointerEXT
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTexGenParameterfSGIS
+ glPixelTexGenParameterfvSGIS
+ glPixelTexGenParameteriSGIS
+ glPixelTexGenParameterivSGIS
+ glPixelTexGenSGIX
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointParameterf
+ glPointParameterfARB
+ glPointParameterfEXT
+ glPointParameterfSGIS
+ glPointParameterfv
+ glPointParameterfvARB
+ glPointParameterfvEXT
+ glPointParameterfvSGIS
+ glPointParameteri
+ glPointParameteriNV
+ glPointParameteriv
+ glPointParameterivNV
+ glPointSize
+ glPollInstrumentsSGIX
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPrioritizeTexturesEXT
+ glProgramEnvParameter4dARB
+ glProgramEnvParameter4dvARB
+ glProgramEnvParameter4fARB
+ glProgramEnvParameter4fvARB
+ glProgramLocalParameter4dARB
+ glProgramLocalParameter4dvARB
+ glProgramLocalParameter4fARB
+ glProgramLocalParameter4fvARB
+ glProgramNamedParameter4dNV
+ glProgramNamedParameter4dvNV
+ glProgramNamedParameter4fNV
+ glProgramNamedParameter4fvNV
+ glProgramParameters4dvNV
+ glProgramParameters4fvNV
+ glProgramParameter4dNV
+ glProgramParameter4dvNV
+ glProgramParameter4fNV
+ glProgramParameter4fvNV
+ glProgramStringARB
+ 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
+ glReadInstrumentsSGIX
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glReferencePlaneSGIX
+ glRenderMode
+ glRequestResidentProgramsNV
+ glResetHistogram
+ glResetHistogramEXT
+ glResetMinmax
+ glResetMinmaxEXT
+ glResizeBuffersMESA
+ glRotated
+ glRotatef
+ glSampleCoverage
+ glSampleCoverageARB
+ glSampleMaskEXT
+ glSampleMaskSGIS
+ glSamplePatternEXT
+ glSamplePatternSGIS
+ glScaled
+ glScalef
+ glScissor
+ glSecondaryColorPointer
+ glSecondaryColorPointerEXT
+ glSecondaryColor3b
+ glSecondaryColor3bEXT
+ glSecondaryColor3bv
+ glSecondaryColor3bvEXT
+ glSecondaryColor3d
+ glSecondaryColor3dEXT
+ glSecondaryColor3dv
+ glSecondaryColor3dvEXT
+ glSecondaryColor3f
+ glSecondaryColor3fEXT
+ glSecondaryColor3fv
+ glSecondaryColor3fvEXT
+ glSecondaryColor3i
+ glSecondaryColor3iEXT
+ glSecondaryColor3iv
+ glSecondaryColor3ivEXT
+ glSecondaryColor3s
+ glSecondaryColor3sEXT
+ glSecondaryColor3sv
+ glSecondaryColor3svEXT
+ glSecondaryColor3ub
+ glSecondaryColor3ubEXT
+ glSecondaryColor3ubv
+ glSecondaryColor3ubvEXT
+ glSecondaryColor3ui
+ glSecondaryColor3uiEXT
+ glSecondaryColor3uiv
+ glSecondaryColor3uivEXT
+ glSecondaryColor3us
+ glSecondaryColor3usEXT
+ glSecondaryColor3usv
+ glSecondaryColor3usvEXT
+ glSelectBuffer
+ glSeparableFilter2D
+ glSeparableFilter2DEXT
+ glSetFenceNV
+ glShadeModel
+ glSharpenTexFuncSGIS
+ glSpriteParameterfSGIX
+ glSpriteParameterfvSGIX
+ glSpriteParameteriSGIX
+ glSpriteParameterivSGIX
+ glStartInstrumentsSGIX
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glStopInstrumentsSGIX
+ glTagSampleBufferSGIX
+ glTbufferMask3DFX
+ glTestFenceNV
+ glTexCoordPointer
+ glTexCoordPointerEXT
+ 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
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexFilterFuncSGIS
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexImage3D
+ glTexImage3DEXT
+ glTexImage4DSGIS
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage1DEXT
+ glTexSubImage2D
+ glTexSubImage2DEXT
+ glTexSubImage3D
+ glTexSubImage3DEXT
+ glTexSubImage4DSGIS
+ glTrackMatrixNV
+ glTranslated
+ glTranslatef
+ glUnlockArraysEXT
+ glUnmapBufferARB
+ glVertexArrayRangeNV
+ glVertexAttribPointerARB
+ glVertexAttribPointerNV
+ glVertexAttribs1dvNV
+ glVertexAttribs1fvNV
+ glVertexAttribs1svNV
+ glVertexAttribs2dvNV
+ glVertexAttribs2fvNV
+ glVertexAttribs2svNV
+ glVertexAttribs3dvNV
+ glVertexAttribs3fvNV
+ glVertexAttribs3svNV
+ glVertexAttribs4dvNV
+ glVertexAttribs4fvNV
+ glVertexAttribs4svNV
+ glVertexAttribs4ubvNV
+ glVertexAttrib1dARB
+ glVertexAttrib1dNV
+ glVertexAttrib1dvARB
+ glVertexAttrib1dvNV
+ glVertexAttrib1fARB
+ glVertexAttrib1fNV
+ glVertexAttrib1fvARB
+ glVertexAttrib1fvNV
+ glVertexAttrib1sARB
+ glVertexAttrib1sNV
+ glVertexAttrib1svARB
+ glVertexAttrib1svNV
+ glVertexAttrib2dARB
+ glVertexAttrib2dNV
+ glVertexAttrib2dvARB
+ glVertexAttrib2dvNV
+ glVertexAttrib2fARB
+ glVertexAttrib2fNV
+ glVertexAttrib2fvARB
+ glVertexAttrib2fvNV
+ glVertexAttrib2sARB
+ glVertexAttrib2sNV
+ glVertexAttrib2svARB
+ glVertexAttrib2svNV
+ glVertexAttrib3dARB
+ glVertexAttrib3dNV
+ glVertexAttrib3dvARB
+ glVertexAttrib3dvNV
+ glVertexAttrib3fARB
+ glVertexAttrib3fNV
+ glVertexAttrib3fvARB
+ glVertexAttrib3fvNV
+ glVertexAttrib3sARB
+ glVertexAttrib3sNV
+ glVertexAttrib3svARB
+ glVertexAttrib3svNV
+ glVertexAttrib4bvARB
+ glVertexAttrib4dARB
+ glVertexAttrib4dNV
+ glVertexAttrib4dvARB
+ glVertexAttrib4dvNV
+ glVertexAttrib4fARB
+ glVertexAttrib4fNV
+ glVertexAttrib4fvARB
+ glVertexAttrib4fvNV
+ glVertexAttrib4ivARB
+ glVertexAttrib4NbvARB
+ glVertexAttrib4NivARB
+ glVertexAttrib4NsvARB
+ glVertexAttrib4NubARB
+ glVertexAttrib4NubvARB
+ glVertexAttrib4NuivARB
+ glVertexAttrib4NusvARB
+ glVertexAttrib4sARB
+ glVertexAttrib4sNV
+ glVertexAttrib4svARB
+ glVertexAttrib4svNV
+ glVertexAttrib4ubNV
+ glVertexAttrib4ubvARB
+ glVertexAttrib4ubvNV
+ glVertexAttrib4uivARB
+ glVertexAttrib4usvARB
+ glVertexPointer
+ glVertexPointerEXT
+ glVertexWeightfEXT
+ glVertexWeightfvEXT
+ glVertexWeightPointerEXT
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glViewport
+ glWindowPos2d
+ glWindowPos2dARB
+ glWindowPos2dMESA
+ glWindowPos2dv
+ glWindowPos2dvARB
+ glWindowPos2dvMESA
+ glWindowPos2f
+ glWindowPos2fARB
+ glWindowPos2fMESA
+ glWindowPos2fv
+ glWindowPos2fvARB
+ glWindowPos2fvMESA
+ glWindowPos2i
+ glWindowPos2iARB
+ glWindowPos2iMESA
+ glWindowPos2iv
+ glWindowPos2ivARB
+ glWindowPos2ivMESA
+ glWindowPos2s
+ glWindowPos2sARB
+ glWindowPos2sMESA
+ glWindowPos2sv
+ glWindowPos2svARB
+ glWindowPos2svMESA
+ glWindowPos3d
+ glWindowPos3dARB
+ glWindowPos3dMESA
+ glWindowPos3dv
+ glWindowPos3dvARB
+ glWindowPos3dvMESA
+ glWindowPos3f
+ glWindowPos3fARB
+ glWindowPos3fMESA
+ glWindowPos3fv
+ glWindowPos3fvARB
+ glWindowPos3fvMESA
+ glWindowPos3i
+ glWindowPos3iARB
+ glWindowPos3iMESA
+ glWindowPos3iv
+ glWindowPos3ivARB
+ glWindowPos3ivMESA
+ glWindowPos3s
+ glWindowPos3sARB
+ glWindowPos3sMESA
+ glWindowPos3sv
+ glWindowPos3svARB
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+ fxCloseHardware
+;fxGetScreenGeometry
+ fxMesaCreateBestContext
+ fxMesaCreateContext
+ fxMesaDestroyContext
+ fxMesaGetCurrentContext
+ fxMesaMakeCurrent
+ fxMesaSelectCurrentBoard
+;fxMesaSetNearFar
+ fxMesaSwapBuffers
+ fxMesaUpdateScreenSize
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetDefaultProcAddress
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ ChoosePixelFormat
+ DescribePixelFormat
+ GetPixelFormat
+ SetPixelFormat
+ SwapBuffers
diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c
new file mode 100644
index 0000000..12654bd
--- /dev/null
+++ b/src/mesa/drivers/glide/fxsetup.c
@@ -0,0 +1,2176 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+#include "tnl.h"
+#include "tnl/t_context.h"
+#include "swrast.h"
+#include "texstore.h"
+
+
+static void
+fxTexValidate(GLcontext * ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GLint minl, maxl;
+
+ if (ti->validated) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTexValidate(NOP)\n");
+ }
+ return;
+ }
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTexValidate(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ ti->tObj = tObj;
+ minl = ti->minLevel = tObj->BaseLevel;
+ maxl = ti->maxLevel = MIN2(tObj->MaxLevel, tObj->Image[0][0]->MaxLog2);
+
+#if FX_RESCALE_BIG_TEXURES_HACK
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ /* [dBorca]
+ * Fake textures larger than HW supports:
+ * 1) we have mipmaps. Then we just push up to the first supported
+ * LOD. A possible drawback is that Mesa will ignore the skipped
+ * LODs on further texture handling.
+ * Will this interfere with GL_TEXTURE_[MIN|BASE]_LEVEL? How?
+ * 2) we don't have mipmaps. We need to rescale the big LOD in place.
+ * The above approach is somehow dumb! we might have rescaled
+ * once in TexImage2D to accomodate aspect ratio, and now we
+ * are rescaling again. The thing is, in TexImage2D we don't
+ * know whether we'll hit 1) or 2) by the time of validation.
+ */
+ if ((tObj->MinFilter == GL_NEAREST) || (tObj->MinFilter == GL_LINEAR)) {
+ /* no mipmaps! */
+ struct gl_texture_image *texImage = tObj->Image[0][minl];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ GLint _w, _h, maxSize = 1 << fxMesa->textureMaxLod;
+ if ((mml->width > maxSize) || (mml->height > maxSize)) {
+ /* need to rescale */
+ GLint texelBytes = texImage->TexFormat->TexelBytes;
+ GLvoid *texImage_Data = texImage->Data;
+ _w = MIN2(texImage->Width, maxSize);
+ _h = MIN2(texImage->Height, maxSize);
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTexValidate: rescaling %d x %d -> %d x %d\n",
+ texImage->Width, texImage->Height, _w, _h);
+ }
+ /* we should leave these as is and... (!) */
+ texImage->Width = _w;
+ texImage->Height = _h;
+ fxTexGetInfo(_w, _h, NULL, NULL, NULL, NULL,
+ &(mml->wScale), &(mml->hScale));
+ _w *= mml->wScale;
+ _h *= mml->hScale;
+ texImage->Data = MESA_PBUFFER_ALLOC(_w * _h * texelBytes);
+ _mesa_rescale_teximage2d(texelBytes,
+ _w * texelBytes, /* dst stride */
+ mml->width, mml->height, /* src */
+ _w, _h, /* dst */
+ texImage_Data /*src*/, texImage->Data /*dst*/ );
+ MESA_PBUFFER_FREE(texImage_Data);
+ mml->width = _w;
+ mml->height = _h;
+ /* (!) ... and set mml->wScale = _w / texImage->Width */
+ }
+ } else {
+ /* mipmapping */
+ if (maxl - minl > fxMesa->textureMaxLod) {
+ /* skip a certain number of LODs */
+ minl += maxl - fxMesa->textureMaxLod;
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTexValidate: skipping %d LODs\n", minl - ti->minLevel);
+ }
+ ti->minLevel = tObj->BaseLevel = minl;
+ }
+ }
+}
+#endif
+
+ fxTexGetInfo(tObj->Image[0][minl]->Width, tObj->Image[0][minl]->Height,
+ &(FX_largeLodLog2(ti->info)), &(FX_aspectRatioLog2(ti->info)),
+ &(ti->sScale), &(ti->tScale),
+ NULL, NULL);
+
+ if ((tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR))
+ fxTexGetInfo(tObj->Image[0][maxl]->Width, tObj->Image[0][maxl]->Height,
+ &(FX_smallLodLog2(ti->info)), NULL,
+ NULL, NULL, NULL, NULL);
+ else
+ FX_smallLodLog2(ti->info) = FX_largeLodLog2(ti->info);
+
+ /* [dBorca] this is necessary because of fxDDCompressedTexImage2D */
+ if (ti->padded) {
+ struct gl_texture_image *texImage = tObj->Image[0][minl];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+ if (mml->wScale != 1 || mml->hScale != 1) {
+ ti->sScale /= mml->wScale;
+ ti->tScale /= mml->hScale;
+ }
+ }
+
+ ti->baseLevelInternalFormat = tObj->Image[0][minl]->Format;
+
+ ti->validated = GL_TRUE;
+
+ ti->info.data = NULL;
+}
+
+#if FX_DEBUG
+static void
+fxPrintUnitsMode(const char *msg, GLuint mode)
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ mode,
+ (mode & FX_UM_E0_REPLACE) ? "E0_REPLACE, " : "",
+ (mode & FX_UM_E0_MODULATE) ? "E0_MODULATE, " : "",
+ (mode & FX_UM_E0_DECAL) ? "E0_DECAL, " : "",
+ (mode & FX_UM_E0_BLEND) ? "E0_BLEND, " : "",
+ (mode & FX_UM_E1_REPLACE) ? "E1_REPLACE, " : "",
+ (mode & FX_UM_E1_MODULATE) ? "E1_MODULATE, " : "",
+ (mode & FX_UM_E1_DECAL) ? "E1_DECAL, " : "",
+ (mode & FX_UM_E1_BLEND) ? "E1_BLEND, " : "",
+ (mode & FX_UM_E0_ALPHA) ? "E0_ALPHA, " : "",
+ (mode & FX_UM_E0_LUMINANCE) ? "E0_LUMINANCE, " : "",
+ (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E0_INTENSITY) ? "E0_INTENSITY, " : "",
+ (mode & FX_UM_E0_RGB) ? "E0_RGB, " : "",
+ (mode & FX_UM_E0_RGBA) ? "E0_RGBA, " : "",
+ (mode & FX_UM_E1_ALPHA) ? "E1_ALPHA, " : "",
+ (mode & FX_UM_E1_LUMINANCE) ? "E1_LUMINANCE, " : "",
+ (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E1_INTENSITY) ? "E1_INTENSITY, " : "",
+ (mode & FX_UM_E1_RGB) ? "E1_RGB, " : "",
+ (mode & FX_UM_E1_RGBA) ? "E1_RGBA, " : "",
+ (mode & FX_UM_COLOR_ITERATED) ? "COLOR_ITERATED, " : "",
+ (mode & FX_UM_COLOR_CONSTANT) ? "COLOR_CONSTANT, " : "",
+ (mode & FX_UM_ALPHA_ITERATED) ? "ALPHA_ITERATED, " : "",
+ (mode & FX_UM_ALPHA_CONSTANT) ? "ALPHA_CONSTANT, " : "");
+}
+#endif
+
+static GLuint
+fxGetTexSetConfiguration(GLcontext * ctx,
+ struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+ GLuint unitsmode = 0;
+ GLuint envmode = 0;
+ GLuint ifmt = 0;
+
+ if ((ctx->Light.ShadeModel == GL_SMOOTH) || 1 ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag)) unitsmode |= FX_UM_ALPHA_ITERATED;
+ else
+ unitsmode |= FX_UM_ALPHA_CONSTANT;
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH || 1)
+ unitsmode |= FX_UM_COLOR_ITERATED;
+ else
+ unitsmode |= FX_UM_COLOR_CONSTANT;
+
+
+
+ /*
+ OpenGL Feeds Texture 0 into Texture 1
+ Glide Feeds Texture 1 into Texture 0
+ */
+ if (tObj0) {
+ tfxTexInfo *ti0 = fxTMGetTexInfo(tObj0);
+
+ switch (ti0->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt |= FX_UM_E0_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt |= FX_UM_E0_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt |= FX_UM_E0_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt |= FX_UM_E0_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt |= FX_UM_E0_RGB;
+ break;
+ case GL_RGBA:
+ ifmt |= FX_UM_E0_RGBA;
+ break;
+ }
+
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ envmode |= FX_UM_E0_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode |= FX_UM_E0_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode |= FX_UM_E0_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode |= FX_UM_E0_BLEND;
+ break;
+ case GL_ADD:
+ envmode |= FX_UM_E0_ADD;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ if (tObj1) {
+ tfxTexInfo *ti1 = fxTMGetTexInfo(tObj1);
+
+ switch (ti1->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt |= FX_UM_E1_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt |= FX_UM_E1_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt |= FX_UM_E1_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt |= FX_UM_E1_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt |= FX_UM_E1_RGB;
+ break;
+ case GL_RGBA:
+ ifmt |= FX_UM_E1_RGBA;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ switch (ctx->Texture.Unit[1].EnvMode) {
+ case GL_DECAL:
+ envmode |= FX_UM_E1_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode |= FX_UM_E1_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode |= FX_UM_E1_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode |= FX_UM_E1_BLEND;
+ break;
+ case GL_ADD:
+ envmode |= FX_UM_E1_ADD;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ unitsmode |= (ifmt | envmode);
+
+#if FX_DEBUG
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fxPrintUnitsMode("fxGetTexSetConfiguration", unitsmode);
+#endif
+
+ return unitsmode;
+}
+
+/************************************************************************/
+/************************* Rendering Mode SetUp *************************/
+/************************************************************************/
+
+/************************* Single Texture Set ***************************/
+
+static void
+fxSetupSingleTMU_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ int tmu;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ ti->lastTimeUsed = fxMesa->texBindNumber;
+
+ /* Make sure we're not loaded incorrectly */
+ if (ti->isInTM) {
+ if (ti->LODblend) {
+ if (ti->whichTMU != FX_TMU_SPLIT)
+ fxTMMoveOutTM(fxMesa, tObj);
+ }
+ else {
+ if (ti->whichTMU == FX_TMU_SPLIT)
+ fxTMMoveOutTM(fxMesa, tObj);
+ }
+ }
+
+ /* Make sure we're loaded correctly */
+ if (!ti->isInTM) {
+ if (ti->LODblend)
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU_SPLIT);
+ else {
+ if (fxMesa->haveTwoTMUs) {
+ if (fxTMCheckStartAddr(fxMesa, FX_TMU0, ti)) {
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU0);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU1);
+ }
+ }
+ else
+ fxTMMoveInTM_NoLock(fxMesa, tObj, FX_TMU0);
+ }
+ }
+
+ if (ti->LODblend && ti->whichTMU == FX_TMU_SPLIT) {
+ /* broadcast */
+ if ((ti->info.format == GR_TEXFMT_P_8)
+ && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading texture palette\n");
+ }
+ grTexDownloadTable(ti->paltype, &(ti->palette));
+ }
+
+ grTexClampMode(GR_TMU0, ti->sClamp, ti->tClamp);
+ grTexClampMode(GR_TMU1, ti->sClamp, ti->tClamp);
+ grTexFilterMode(GR_TMU0, ti->minFilt, ti->maxFilt);
+ grTexFilterMode(GR_TMU1, ti->minFilt, ti->maxFilt);
+ grTexMipMapMode(GR_TMU0, ti->mmMode, ti->LODblend);
+ grTexMipMapMode(GR_TMU1, ti->mmMode, ti->LODblend);
+
+ grTexSource(GR_TMU0, ti->tm[FX_TMU0]->startAddr,
+ GR_MIPMAPLEVELMASK_ODD, &(ti->info));
+ grTexSource(GR_TMU1, ti->tm[FX_TMU1]->startAddr,
+ GR_MIPMAPLEVELMASK_EVEN, &(ti->info));
+ }
+ else {
+ if (ti->whichTMU == FX_TMU_BOTH)
+ tmu = FX_TMU0;
+ else
+ tmu = ti->whichTMU;
+
+ /* pointcast */
+ if ((ti->info.format == GR_TEXFMT_P_8)
+ && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: uploading texture palette\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(tmu, ti->paltype, &(ti->palette));
+ }
+
+ /* KW: The alternative is to do the download to the other tmu. If
+ * we get to this point, I think it means we are thrashing the
+ * texture memory, so perhaps it's not a good idea.
+ */
+ if (ti->LODblend && (TDFX_DEBUG & VERBOSE_DRIVER)) {
+ fprintf(stderr, "fxSetupSingleTMU_NoLock: not blending texture - only one tmu\n");
+ }
+
+ grTexClampMode(tmu, ti->sClamp, ti->tClamp);
+ grTexFilterMode(tmu, ti->minFilt, ti->maxFilt);
+ grTexMipMapMode(tmu, ti->mmMode, FXFALSE);
+
+ grTexSource(tmu, ti->tm[tmu]->startAddr, GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+ }
+}
+
+static void
+fxSelectSingleTMUSrc_NoLock(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+{
+ struct tdfx_texcombine tex0, tex1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSelectSingleTMUSrc_NoLock(%d, %d)\n", tmu, LODblend);
+ }
+
+ tex0.InvertRGB = FXFALSE;
+ tex0.InvertAlpha = FXFALSE;
+ tex1.InvertRGB = FXFALSE;
+ tex1.InvertAlpha = FXFALSE;
+
+ if (LODblend) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
+
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ fxMesa->tmuSrc = FX_TMU_SPLIT;
+ }
+ else {
+ if (tmu != FX_TMU1) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ fxMesa->tmuSrc = FX_TMU0;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ /* correct values to set TMU0 in passthrough mode */
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+
+ fxMesa->tmuSrc = FX_TMU1;
+ }
+ }
+
+ grTexCombine(GR_TMU0,
+ tex0.FunctionRGB,
+ tex0.FactorRGB,
+ tex0.FunctionAlpha,
+ tex0.FactorAlpha,
+ tex0.InvertRGB,
+ tex0.InvertAlpha);
+ if (fxMesa->haveTwoTMUs) {
+ grTexCombine(GR_TMU1,
+ tex1.FunctionRGB,
+ tex1.FactorRGB,
+ tex1.FunctionAlpha,
+ tex1.FactorAlpha,
+ tex1.InvertRGB,
+ tex1.InvertAlpha);
+ }
+}
+
+static void
+fxSetupTextureSingleTMU_NoLock(GLcontext * ctx, GLuint textureset)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ struct tdfx_combine alphaComb, colorComb;
+ GrCombineLocal_t localc, locala;
+ GLuint unitsmode;
+ GLint ifmt;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj = ctx->Texture.Unit[textureset]._Current;
+ int tmu;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock(%d)\n", textureset);
+ }
+
+ ti = fxTMGetTexInfo(tObj);
+
+ fxTexValidate(ctx, tObj);
+
+ fxSetupSingleTMU_NoLock(fxMesa, tObj);
+
+ if (ti->whichTMU == FX_TMU_BOTH)
+ tmu = FX_TMU0;
+ else
+ tmu = ti->whichTMU;
+ if (fxMesa->tmuSrc != tmu)
+ fxSelectSingleTMUSrc_NoLock(fxMesa, tmu, ti->LODblend);
+
+ if (textureset == 0 || !fxMesa->haveTwoTMUs)
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj, NULL);
+ else
+ unitsmode = fxGetTexSetConfiguration(ctx, NULL, tObj);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state = 0;
+ FX_grHints_NoLock(GR_HINT_STWHINT, 0);
+
+ ifmt = ti->baseLevelInternalFormat;
+
+ if (unitsmode & FX_UM_ALPHA_ITERATED)
+ locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (unitsmode & FX_UM_COLOR_ITERATED)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock: envmode is %s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
+
+ alphaComb.Local = locala;
+ alphaComb.Invert = FXFALSE;
+ colorComb.Local = localc;
+ colorComb.Invert = FXFALSE;
+
+ switch (ctx->Texture.Unit[textureset].EnvMode) {
+ case GL_DECAL:
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ case GL_MODULATE:
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ case GL_BLEND:
+ if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ /* Av = Af */
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else if (ifmt == GL_INTENSITY) {
+ /* Av = Af * (1 - It) + Ac * It */
+ alphaComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ alphaComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ alphaComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ }
+ else {
+ /* Av = Af * At */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ if (fxMesa->type >= GR_SSTTYPE_Voodoo2) {
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_RGB;
+ colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ } else if (ifmt == GL_INTENSITY) {
+ /* just a hack: RGB == ALPHA */
+ colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
+ colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
+ colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
+ } else {
+ /* Only Voodoo^2 can GL_BLEND (GR_COMBINE_FACTOR_TEXTURE_RGB)
+ * These settings assume that the TexEnv color is black and
+ * incoming fragment color is white.
+ */
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ colorComb.Invert = FXTRUE;
+ _mesa_problem(NULL, "can't GL_BLEND with SST1");
+ }
+ }
+
+ grConstantColorValue(
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[0] * 255.0f)) ) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[1] * 255.0f)) << 8) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[2] * 255.0f)) << 16) |
+ (((GLuint)(ctx->Texture.Unit[textureset].EnvColor[3] * 255.0f)) << 24));
+ break;
+ case GL_REPLACE:
+ if ((ifmt == GL_RGB) || (ifmt == GL_LUMINANCE)) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ case GL_ADD:
+ if (ifmt == GL_ALPHA ||
+ ifmt == GL_LUMINANCE_ALPHA ||
+ ifmt == GL_RGBA) {
+ /* product of texel and fragment alpha */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ else if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ /* fragment alpha is unchanged */
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else {
+ /* sum of texel and fragment alpha */
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ /* rgb unchanged */
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+ else {
+ /* sum of texel and fragment rgb */
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ default:
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureSingleTMU_NoLock: %x Texture.EnvMode not yet supported\n",
+ ctx->Texture.Unit[textureset].EnvMode);
+ }
+ return;
+ }
+
+ grAlphaCombine(alphaComb.Function,
+ alphaComb.Factor,
+ alphaComb.Local,
+ alphaComb.Other,
+ alphaComb.Invert);
+ grColorCombine(colorComb.Function,
+ colorComb.Factor,
+ colorComb.Local,
+ colorComb.Other,
+ colorComb.Invert);
+}
+
+#if 00
+static void
+fxSetupTextureSingleTMU(GLcontext * ctx, GLuint textureset)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetupTextureSingleTMU_NoLock(ctx, textureset);
+ END_BOARD_LOCK();
+}
+#endif
+
+
+/************************* Double Texture Set ***************************/
+
+static void
+fxSetupDoubleTMU_NoLock(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+#define T0_NOT_IN_TMU 0x01
+#define T1_NOT_IN_TMU 0x02
+#define T0_IN_TMU0 0x04
+#define T1_IN_TMU0 0x08
+#define T0_IN_TMU1 0x10
+#define T1_IN_TMU1 0x20
+
+ tfxTexInfo *ti0 = fxTMGetTexInfo(tObj0);
+ tfxTexInfo *ti1 = fxTMGetTexInfo(tObj1);
+ GLuint tstate = 0;
+ int tmu0 = 0, tmu1 = 1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock(...)\n");
+ }
+
+ /* We shouldn't need to do this. There is something wrong with
+ mutlitexturing when the TMUs are swapped. So, we're forcing
+ them to always be loaded correctly. !!! */
+ if (ti0->whichTMU == FX_TMU1)
+ fxTMMoveOutTM_NoLock(fxMesa, tObj0);
+ if (ti1->whichTMU == FX_TMU0)
+ fxTMMoveOutTM_NoLock(fxMesa, tObj1);
+
+ if (ti0->isInTM) {
+ switch (ti0->whichTMU) {
+ case FX_TMU0:
+ tstate |= T0_IN_TMU0;
+ break;
+ case FX_TMU1:
+ tstate |= T0_IN_TMU1;
+ break;
+ case FX_TMU_BOTH:
+ tstate |= T0_IN_TMU0 | T0_IN_TMU1;
+ break;
+ case FX_TMU_SPLIT:
+ tstate |= T0_NOT_IN_TMU;
+ break;
+ }
+ }
+ else
+ tstate |= T0_NOT_IN_TMU;
+
+ if (ti1->isInTM) {
+ switch (ti1->whichTMU) {
+ case FX_TMU0:
+ tstate |= T1_IN_TMU0;
+ break;
+ case FX_TMU1:
+ tstate |= T1_IN_TMU1;
+ break;
+ case FX_TMU_BOTH:
+ tstate |= T1_IN_TMU0 | T1_IN_TMU1;
+ break;
+ case FX_TMU_SPLIT:
+ tstate |= T1_NOT_IN_TMU;
+ break;
+ }
+ }
+ else
+ tstate |= T1_NOT_IN_TMU;
+
+ ti0->lastTimeUsed = fxMesa->texBindNumber;
+ ti1->lastTimeUsed = fxMesa->texBindNumber;
+
+ /* Move texture maps into TMUs */
+
+ if (!(((tstate & T0_IN_TMU0) && (tstate & T1_IN_TMU1)) ||
+ ((tstate & T0_IN_TMU1) && (tstate & T1_IN_TMU0)))) {
+ if (tObj0 == tObj1)
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU_BOTH);
+ else {
+ /* Find the minimal way to correct the situation */
+ if ((tstate & T0_IN_TMU0) || (tstate & T1_IN_TMU1)) {
+ /* We have one in the standard order, setup the other */
+ if (tstate & T0_IN_TMU0) { /* T0 is in TMU0, put T1 in TMU1 */
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU0);
+ }
+ /* tmu0 and tmu1 are setup */
+ }
+ else if ((tstate & T0_IN_TMU1) || (tstate & T1_IN_TMU0)) {
+ /* we have one in the reverse order, setup the other */
+ if (tstate & T1_IN_TMU0) { /* T1 is in TMU0, put T0 in TMU1 */
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU1);
+ }
+ else {
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU0);
+ }
+ tmu0 = 1;
+ tmu1 = 0;
+ }
+ else { /* Nothing is loaded */
+ fxTMMoveInTM_NoLock(fxMesa, tObj0, FX_TMU0);
+ fxTMMoveInTM_NoLock(fxMesa, tObj1, FX_TMU1);
+ /* tmu0 and tmu1 are setup */
+ }
+ }
+ }
+
+ /* [dBorca] Hack alert:
+ * we put these in reverse order, so that if we can't
+ * do _REAL_ pointcast, the TMU0 table gets broadcasted
+ */
+ if (!fxMesa->haveGlobalPaletteTexture) {
+ /* pointcast */
+ if (ti1->info.format == GR_TEXFMT_P_8) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading texture palette for TMU1\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(ti1->whichTMU, ti1->paltype, &(ti1->palette));
+ }
+ if (ti0->info.format == GR_TEXFMT_P_8) {
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupDoubleTMU_NoLock: uploading texture palette for TMU0\n");
+ }
+ fxMesa->Glide.grTexDownloadTableExt(ti0->whichTMU, ti0->paltype, &(ti0->palette));
+ }
+ }
+
+ grTexSource(tmu0, ti0->tm[tmu0]->startAddr,
+ GR_MIPMAPLEVELMASK_BOTH, &(ti0->info));
+ grTexClampMode(tmu0, ti0->sClamp, ti0->tClamp);
+ grTexFilterMode(tmu0, ti0->minFilt, ti0->maxFilt);
+ grTexMipMapMode(tmu0, ti0->mmMode, FXFALSE);
+
+ grTexSource(tmu1, ti1->tm[tmu1]->startAddr,
+ GR_MIPMAPLEVELMASK_BOTH, &(ti1->info));
+ grTexClampMode(tmu1, ti1->sClamp, ti1->tClamp);
+ grTexFilterMode(tmu1, ti1->minFilt, ti1->maxFilt);
+ grTexMipMapMode(tmu1, ti1->mmMode, FXFALSE);
+
+#undef T0_NOT_IN_TMU
+#undef T1_NOT_IN_TMU
+#undef T0_IN_TMU0
+#undef T1_IN_TMU0
+#undef T0_IN_TMU1
+#undef T1_IN_TMU1
+}
+
+static void
+fxSetupTextureDoubleTMU_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ struct tdfx_combine alphaComb, colorComb;
+ struct tdfx_texcombine tex0, tex1;
+ GrCombineLocal_t localc, locala;
+ tfxTexInfo *ti0, *ti1;
+ struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current;
+ struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current;
+ GLuint envmode, ifmt, unitsmode;
+ int tmu0 = 0, tmu1 = 1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock(...)\n");
+ }
+
+ ti0 = fxTMGetTexInfo(tObj0);
+ fxTexValidate(ctx, tObj0);
+
+ ti1 = fxTMGetTexInfo(tObj1);
+ fxTexValidate(ctx, tObj1);
+
+ fxSetupDoubleTMU_NoLock(fxMesa, tObj0, tObj1);
+
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj0, tObj1);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1;
+ FX_grHints_NoLock(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ envmode = unitsmode & FX_UM_E_ENVMODE;
+ ifmt = unitsmode & FX_UM_E_IFMT;
+
+ if (unitsmode & FX_UM_ALPHA_ITERATED)
+ locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (unitsmode & FX_UM_COLOR_ITERATED)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock: envmode is %s/%s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+
+ if ((ti0->whichTMU == FX_TMU1) || (ti1->whichTMU == FX_TMU0)) {
+ tmu0 = 1;
+ tmu1 = 0;
+ }
+ fxMesa->tmuSrc = FX_TMU_BOTH;
+
+ tex0.InvertRGB = FXFALSE;
+ tex0.InvertAlpha = FXFALSE;
+ tex1.InvertRGB = FXFALSE;
+ tex1.InvertAlpha = FXFALSE;
+ alphaComb.Local = locala;
+ alphaComb.Invert = FXFALSE;
+ colorComb.Local = localc;
+ colorComb.Invert = FXFALSE;
+
+ switch (envmode) {
+ case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE):
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+ case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
+ if (tmu0 == FX_TMU1) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
+ }
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
+ if (tmu1 == FX_TMU1) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertAlpha = FXTRUE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
+ }
+ else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_LOCAL;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ if (ti0->baseLevelInternalFormat == GL_RGB) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+
+
+ case (FX_UM_E0_MODULATE | FX_UM_E1_ADD): /* Quake 3 Sky */
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+
+ case (FX_UM_E0_REPLACE | FX_UM_E1_ADD): /* Vulpine Sky */
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ isalpha[tmu0] = (ti0->baseLevelInternalFormat == GL_ALPHA);
+ isalpha[tmu1] = (ti1->baseLevelInternalFormat == GL_ALPHA);
+
+ if (isalpha[FX_TMU1]) {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ tex1.InvertRGB = FXTRUE;
+ } else {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+ }
+
+ if (isalpha[FX_TMU0]) {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ } else {
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_ONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_ONE;
+ }
+
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ break;
+ }
+
+ case (FX_UM_E0_MODULATE | FX_UM_E1_REPLACE): /* Homeworld2 */
+ {
+ tex1.FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex1.FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
+ tex1.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ tex0.FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorRGB = GR_COMBINE_FACTOR_NONE;
+ tex0.FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
+ tex0.FactorAlpha = GR_COMBINE_FACTOR_NONE;
+
+ if (ifmt & (FX_UM_E0_RGB | FX_UM_E0_LUMINANCE)) {
+ alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
+ alphaComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
+ alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+
+ if (ifmt & FX_UM_E0_ALPHA) {
+ colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
+ colorComb.Factor = GR_COMBINE_FACTOR_NONE;
+ colorComb.Other = GR_COMBINE_OTHER_NONE;
+ } else {
+ colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
+ colorComb.Factor = GR_COMBINE_FACTOR_ONE;
+ colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "fxSetupTextureDoubleTMU_NoLock: Unexpected dual texture mode encountered\n");
+ return;
+ }
+
+ grAlphaCombine(alphaComb.Function,
+ alphaComb.Factor,
+ alphaComb.Local,
+ alphaComb.Other,
+ alphaComb.Invert);
+ grColorCombine(colorComb.Function,
+ colorComb.Factor,
+ colorComb.Local,
+ colorComb.Other,
+ colorComb.Invert);
+ grTexCombine(GR_TMU0,
+ tex0.FunctionRGB,
+ tex0.FactorRGB,
+ tex0.FunctionAlpha,
+ tex0.FactorAlpha,
+ tex0.InvertRGB,
+ tex0.InvertAlpha);
+ grTexCombine(GR_TMU1,
+ tex1.FunctionRGB,
+ tex1.FactorRGB,
+ tex1.FunctionAlpha,
+ tex1.FactorAlpha,
+ tex1.InvertRGB,
+ tex1.InvertAlpha);
+}
+
+/************************* No Texture ***************************/
+
+static void
+fxSetupTextureNone_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrCombineLocal_t localc, locala;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureNone_NoLock(...)\n");
+ }
+
+ if ((ctx->Light.ShadeModel == GL_SMOOTH) || 1 ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag)) locala = GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala = GR_COMBINE_LOCAL_CONSTANT;
+
+ if (ctx->Light.ShadeModel == GL_SMOOTH || 1)
+ localc = GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc = GR_COMBINE_LOCAL_CONSTANT;
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ fxMesa->lastUnitsMode = FX_UM_NONE;
+}
+
+#include "fxsetup.h"
+
+/************************************************************************/
+/************************** Texture Mode SetUp **************************/
+/************************************************************************/
+
+static void
+fxSetupTexture_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTexture_NoLock(...)\n");
+ }
+
+ if (fxMesa->HaveCmbExt) {
+ /* Texture Combine, Color Combine and Alpha Combine. */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ fxMesa->haveTwoTMUs) {
+ fxSetupTextureDoubleTMUNapalm_NoLock(ctx);
+ }
+ else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMUNapalm_NoLock(ctx, 0);
+ }
+ else if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMUNapalm_NoLock(ctx, 1);
+ }
+ else {
+ fxSetupTextureNoneNapalm_NoLock(ctx);
+ }
+ } else {
+ /* Texture Combine, Color Combine and Alpha Combine. */
+ if ((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) &&
+ fxMesa->haveTwoTMUs) {
+ fxSetupTextureDoubleTMU_NoLock(ctx);
+ }
+ else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMU_NoLock(ctx, 0);
+ }
+ else if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+ fxSetupTextureSingleTMU_NoLock(ctx, 1);
+ }
+ else {
+ fxSetupTextureNone_NoLock(ctx);
+ }
+ }
+}
+
+void
+fxSetupTexture(GLcontext * ctx)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetupTexture_NoLock(ctx);
+ END_BOARD_LOCK();
+}
+
+/************************************************************************/
+/**************************** Blend SetUp *******************************/
+/************************************************************************/
+
+void
+fxDDBlendFuncSeparate(GLcontext * ctx, GLenum sfactor, GLenum dfactor, GLenum asfactor, GLenum adfactor)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+ GLboolean isNapalm = (fxMesa->type >= GR_SSTTYPE_Voodoo4);
+ GLboolean have32bpp = (fxMesa->colDepth == 32);
+ GLboolean haveAlpha = fxMesa->haveHwAlpha;
+ GrAlphaBlendFnc_t sfact, dfact, asfact, adfact;
+
+ /*
+ * 15/16 BPP alpha channel alpha blending modes
+ * 0x0 AZERO Zero
+ * 0x4 AONE One
+ *
+ * 32 BPP alpha channel alpha blending modes
+ * 0x0 AZERO Zero
+ * 0x1 ASRC_ALPHA Source alpha
+ * 0x3 ADST_ALPHA Destination alpha
+ * 0x4 AONE One
+ * 0x5 AOMSRC_ALPHA 1 - Source alpha
+ * 0x7 AOMDST_ALPHA 1 - Destination alpha
+ *
+ * If we don't have HW alpha buffer:
+ * DST_ALPHA == 1
+ * ONE_MINUS_DST_ALPHA == 0
+ * Unsupported modes are:
+ * 1 if used as src blending factor
+ * 0 if used as dst blending factor
+ */
+
+ switch (sfactor) {
+ case GL_ZERO:
+ sfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ sfact = GR_BLEND_ONE;
+ break;
+ case GL_DST_COLOR:
+ sfact = GR_BLEND_DST_COLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sfact = GR_BLEND_ONE_MINUS_DST_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ sfact = GR_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sfact = GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ sfact = haveAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sfact = haveAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sfact = GR_BLEND_ALPHA_SATURATE;
+ break;
+ case GL_SRC_COLOR:
+ if (isNapalm) {
+ sfact = GR_BLEND_SAME_COLOR_EXT;
+ break;
+ }
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (isNapalm) {
+ sfact = GR_BLEND_ONE_MINUS_SAME_COLOR_EXT;
+ break;
+ }
+ default:
+ sfact = GR_BLEND_ONE;
+ break;
+ }
+
+ switch (asfactor) {
+ case GL_ZERO:
+ asfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ asfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ asfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ asfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ case GL_DST_ALPHA:
+ asfact = (have32bpp && haveAlpha) ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_ONE_MINUS_DST_ALPHA:
+ asfact = (have32bpp && haveAlpha) ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ asfact = GR_BLEND_ONE;
+ break;
+ default:
+ asfact = GR_BLEND_ONE;
+ break;
+ }
+
+ switch (dfactor) {
+ case GL_ZERO:
+ dfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ dfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ dfact = GR_BLEND_SRC_COLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dfact = GR_BLEND_ONE_MINUS_SRC_COLOR;
+ break;
+ case GL_SRC_ALPHA:
+ dfact = GR_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dfact = GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ dfact = haveAlpha ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dfact = haveAlpha ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ if (isNapalm) {
+ dfact = GR_BLEND_SAME_COLOR_EXT;
+ break;
+ }
+ case GL_ONE_MINUS_DST_COLOR:
+ if (isNapalm) {
+ dfact = GR_BLEND_ONE_MINUS_SAME_COLOR_EXT;
+ break;
+ }
+ default:
+ dfact = GR_BLEND_ZERO;
+ break;
+ }
+
+ switch (adfactor) {
+ case GL_ZERO:
+ adfact = GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ adfact = GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ adfact = have32bpp ? GR_BLEND_SRC_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ adfact = have32bpp ? GR_BLEND_ONE_MINUS_SRC_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ case GL_DST_COLOR:
+ case GL_DST_ALPHA:
+ adfact = (have32bpp && haveAlpha) ? GR_BLEND_DST_ALPHA : GR_BLEND_ONE/*bad*/;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_ONE_MINUS_DST_ALPHA:
+ adfact = (have32bpp && haveAlpha) ? GR_BLEND_ONE_MINUS_DST_ALPHA : GR_BLEND_ZERO/*bad*/;
+ break;
+ default:
+ adfact = GR_BLEND_ZERO;
+ break;
+ }
+
+ if ((sfact != us->blendSrcFuncRGB) || (asfact != us->blendSrcFuncAlpha)) {
+ us->blendSrcFuncRGB = sfact;
+ us->blendSrcFuncAlpha = asfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+
+ if ((dfact != us->blendDstFuncRGB) || (adfact != us->blendDstFuncAlpha)) {
+ us->blendDstFuncRGB = dfact;
+ us->blendDstFuncAlpha = adfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+}
+
+void
+fxDDBlendEquationSeparate(GLcontext * ctx, GLenum modeRGB, GLenum modeA)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+ GrAlphaBlendOp_t q;
+
+ switch (modeRGB) {
+ case GL_FUNC_ADD:
+ q = GR_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ q = GR_BLEND_OP_SUB;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ q = GR_BLEND_OP_REVSUB;
+ break;
+ default:
+ q = us->blendEqRGB;
+ }
+ if (q != us->blendEqRGB) {
+ us->blendEqRGB = q;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+
+ switch (modeA) {
+ case GL_FUNC_ADD:
+ q = GR_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ q = GR_BLEND_OP_SUB;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ q = GR_BLEND_OP_REVSUB;
+ break;
+ default:
+ q = us->blendEqAlpha;
+ }
+ if (q != us->blendEqAlpha) {
+ us->blendEqAlpha = q;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+}
+
+void
+fxSetupBlend(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (fxMesa->HavePixExt) {
+ if (us->blendEnabled) {
+ fxMesa->Glide.grAlphaBlendFunctionExt(us->blendSrcFuncRGB, us->blendDstFuncRGB,
+ us->blendEqRGB,
+ us->blendSrcFuncAlpha, us->blendDstFuncAlpha,
+ us->blendEqAlpha);
+ } else {
+ fxMesa->Glide.grAlphaBlendFunctionExt(GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_OP_ADD,
+ GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_OP_ADD);
+ }
+ } else {
+ if (us->blendEnabled) {
+ grAlphaBlendFunction(us->blendSrcFuncRGB, us->blendDstFuncRGB,
+ us->blendSrcFuncAlpha, us->blendDstFuncAlpha);
+ } else {
+ grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO,
+ GR_BLEND_ONE, GR_BLEND_ZERO);
+ }
+ }
+}
+
+/************************************************************************/
+/************************** Alpha Test SetUp ****************************/
+/************************************************************************/
+
+void
+fxDDAlphaFunc(GLcontext * ctx, GLenum func, GLfloat ref)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (
+ (us->alphaTestFunc != func)
+ ||
+ (us->alphaTestRefValue != ref)
+ ) {
+ us->alphaTestFunc = func;
+ us->alphaTestRefValue = ref;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ }
+}
+
+static void
+fxSetupAlphaTest(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->alphaTestEnabled) {
+ GrAlpha_t ref = (GLint) (us->alphaTestRefValue * 255.0);
+ grAlphaTestFunction(us->alphaTestFunc - GL_NEVER + GR_CMP_NEVER);
+ grAlphaTestReferenceValue(ref);
+ }
+ else
+ grAlphaTestFunction(GR_CMP_ALWAYS);
+}
+
+/************************************************************************/
+/************************** Depth Test SetUp ****************************/
+/************************************************************************/
+
+void
+fxDDDepthFunc(GLcontext * ctx, GLenum func)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->depthTestFunc != func) {
+ us->depthTestFunc = func;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+}
+
+void
+fxDDDepthMask(GLcontext * ctx, GLboolean flag)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (flag != us->depthMask) {
+ us->depthMask = flag;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+}
+
+void
+fxSetupDepthTest(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->depthTestEnabled) {
+ grDepthBufferFunction(us->depthTestFunc - GL_NEVER + GR_CMP_NEVER);
+ grDepthMask(us->depthMask);
+ }
+ else {
+ grDepthBufferFunction(GR_CMP_ALWAYS);
+ grDepthMask(FXFALSE);
+ }
+}
+
+/************************************************************************/
+/************************** Stencil SetUp *******************************/
+/************************************************************************/
+
+static GrStencil_t convertGLStencilOp( GLenum op )
+{
+ switch ( op ) {
+ case GL_KEEP:
+ return GR_STENCILOP_KEEP;
+ case GL_ZERO:
+ return GR_STENCILOP_ZERO;
+ case GL_REPLACE:
+ return GR_STENCILOP_REPLACE;
+ case GL_INCR:
+ return GR_STENCILOP_INCR_CLAMP;
+ case GL_DECR:
+ return GR_STENCILOP_DECR_CLAMP;
+ case GL_INVERT:
+ return GR_STENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT:
+ return GR_STENCILOP_INCR_WRAP;
+ case GL_DECR_WRAP_EXT:
+ return GR_STENCILOP_DECR_WRAP;
+ default:
+ _mesa_problem( NULL, "bad stencil op in convertGLStencilOp" );
+ }
+ return GR_STENCILOP_KEEP; /* never get, silence compiler warning */
+}
+
+void
+fxDDStencilFunc (GLcontext *ctx, GLenum func, GLint ref, GLuint mask)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (
+ (us->stencilFunction != func)
+ ||
+ (us->stencilRefValue != ref)
+ ||
+ (us->stencilValueMask != mask)
+ ) {
+ us->stencilFunction = func;
+ us->stencilRefValue = ref;
+ us->stencilValueMask = mask;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxDDStencilMask (GLcontext *ctx, GLuint mask)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->stencilWriteMask != mask) {
+ us->stencilWriteMask = mask;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxDDStencilOp (GLcontext *ctx, GLenum sfail, GLenum zfail, GLenum zpass)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (
+ (us->stencilFailFunc != sfail)
+ ||
+ (us->stencilZFailFunc != zfail)
+ ||
+ (us->stencilZPassFunc != zpass)
+ ) {
+ us->stencilFailFunc = sfail;
+ us->stencilZFailFunc = zfail;
+ us->stencilZPassFunc = zpass;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+}
+
+void
+fxSetupStencil (GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (us->stencilEnabled) {
+ grEnable(GR_STENCIL_MODE_EXT);
+ fxMesa->Glide.grStencilOpExt(convertGLStencilOp(us->stencilFailFunc),
+ convertGLStencilOp(us->stencilZFailFunc),
+ convertGLStencilOp(us->stencilZPassFunc));
+ fxMesa->Glide.grStencilFuncExt(us->stencilFunction - GL_NEVER + GR_CMP_NEVER,
+ us->stencilRefValue,
+ us->stencilValueMask);
+ fxMesa->Glide.grStencilMaskExt(us->stencilWriteMask);
+ } else {
+ grDisable(GR_STENCIL_MODE_EXT);
+ }
+}
+
+/************************************************************************/
+/**************************** Color Mask SetUp **************************/
+/************************************************************************/
+
+void
+fxDDColorMask(GLcontext * ctx,
+ GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ fxMesa->new_state |= FX_NEW_COLOR_MASK;
+ (void) r;
+ (void) g;
+ (void) b;
+ (void) a;
+}
+
+void
+fxSetupColorMask(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (fxMesa->colDepth == 32) {
+ /* 32bpp mode */
+ fxMesa->Glide.grColorMaskExt(ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveHwAlpha);
+ }
+ else {
+ /* 15/16 bpp mode */
+ grColorMask(ctx->Color.ColorMask[RCOMP] |
+ ctx->Color.ColorMask[GCOMP] |
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveHwAlpha);
+ }
+}
+
+
+
+
+/************************************************************************/
+/**************************** Fog Mode SetUp ****************************/
+/************************************************************************/
+
+/*
+ * This is called during state update in order to update the Glide fog state.
+ */
+static void
+fxSetupFog(GLcontext * ctx)
+{
+ if (ctx->Fog.Enabled /*&& ctx->FogMode==FOG_FRAGMENT */ ) {
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ /* update fog color */
+ GLubyte col[4];
+ col[0] = (unsigned int) (255 * ctx->Fog.Color[0]);
+ col[1] = (unsigned int) (255 * ctx->Fog.Color[1]);
+ col[2] = (unsigned int) (255 * ctx->Fog.Color[2]);
+ col[3] = (unsigned int) (255 * ctx->Fog.Color[3]);
+ grFogColorValue(FXCOLOR4(col));
+
+ if (fxMesa->fogTableMode != ctx->Fog.Mode ||
+ fxMesa->fogDensity != ctx->Fog.Density ||
+ fxMesa->fogStart != ctx->Fog.Start ||
+ fxMesa->fogEnd != ctx->Fog.End) {
+ /* reload the fog table */
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ guFogGenerateLinear(fxMesa->fogTable, ctx->Fog.Start,
+ ctx->Fog.End);
+ if (fxMesa->fogTable[0] > 63) {
+ /* [dBorca] Hack alert:
+ * As per Glide3 Programming Guide:
+ * The difference between consecutive fog values
+ * must be less than 64.
+ */
+ fxMesa->fogTable[0] = 63;
+ }
+ break;
+ case GL_EXP:
+ guFogGenerateExp(fxMesa->fogTable, ctx->Fog.Density);
+ break;
+ case GL_EXP2:
+ guFogGenerateExp2(fxMesa->fogTable, ctx->Fog.Density);
+ break;
+ default:
+ ;
+ }
+ fxMesa->fogTableMode = ctx->Fog.Mode;
+ fxMesa->fogDensity = ctx->Fog.Density;
+ fxMesa->fogStart = ctx->Fog.Start;
+ fxMesa->fogEnd = ctx->Fog.End;
+ }
+
+ grFogTable(fxMesa->fogTable);
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) {
+ grVertexLayout(GR_PARAM_FOG_EXT, GR_VERTEX_FOG_OFFSET << 2,
+ GR_PARAM_ENABLE);
+ grFogMode(GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+ } else {
+ grVertexLayout(GR_PARAM_FOG_EXT, GR_VERTEX_FOG_OFFSET << 2,
+ GR_PARAM_DISABLE);
+ grFogMode(GR_FOG_WITH_TABLE_ON_Q);
+ }
+ }
+ else {
+ grFogMode(GR_FOG_DISABLE);
+ }
+}
+
+void
+fxDDFogfv(GLcontext * ctx, GLenum pname, const GLfloat * params)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ switch (pname) {
+ case GL_FOG_COORDINATE_SOURCE_EXT: {
+ GLenum p = (GLenum)*params;
+ if (p == GL_FOG_COORDINATE_EXT) {
+ _swrast_allow_vertex_fog(ctx, GL_TRUE);
+ _swrast_allow_pixel_fog(ctx, GL_FALSE);
+ _tnl_allow_vertex_fog( ctx, GL_TRUE);
+ _tnl_allow_pixel_fog( ctx, GL_FALSE);
+ } else {
+ _swrast_allow_vertex_fog(ctx, GL_FALSE);
+ _swrast_allow_pixel_fog(ctx, GL_TRUE);
+ _tnl_allow_vertex_fog( ctx, GL_FALSE);
+ _tnl_allow_pixel_fog( ctx, GL_TRUE);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+}
+
+/************************************************************************/
+/************************** Scissor Test SetUp **************************/
+/************************************************************************/
+
+/* This routine is used in managing the lock state, and therefore can't lock */
+void
+fxSetScissorValues(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ int xmin, xmax;
+ int ymin, ymax;
+
+ if (ctx->Scissor.Enabled) {
+ xmin = ctx->Scissor.X;
+ xmax = ctx->Scissor.X + ctx->Scissor.Width;
+ ymin = ctx->Scissor.Y;
+ ymax = ctx->Scissor.Y + ctx->Scissor.Height;
+
+ if (xmin < 0)
+ xmin = 0;
+ if (xmax > fxMesa->width)
+ xmax = fxMesa->width;
+ if (ymin < fxMesa->screen_height - fxMesa->height)
+ ymin = fxMesa->screen_height - fxMesa->height;
+ if (ymax > fxMesa->screen_height - 0)
+ ymax = fxMesa->screen_height - 0;
+ }
+ else {
+ xmin = 0;
+ ymin = 0;
+ xmax = fxMesa->width;
+ ymax = fxMesa->height;
+ }
+
+ fxMesa->clipMinX = xmin;
+ fxMesa->clipMinY = ymin;
+ fxMesa->clipMaxX = xmax;
+ fxMesa->clipMaxY = ymax;
+ grClipWindow(xmin, ymin, xmax, ymax);
+}
+
+void
+fxSetupScissor(GLcontext * ctx)
+{
+ BEGIN_BOARD_LOCK();
+ fxSetScissorValues(ctx);
+ END_BOARD_LOCK();
+}
+
+void
+fxDDScissor(GLcontext * ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR;
+}
+
+/************************************************************************/
+/*************************** Cull mode setup ****************************/
+/************************************************************************/
+
+
+void
+fxDDCullFace(GLcontext * ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+}
+
+void
+fxDDFrontFace(GLcontext * ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+}
+
+
+void
+fxSetupCull(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrCullMode_t mode = GR_CULL_DISABLE;
+
+ if (ctx->Polygon.CullFlag && (fxMesa->raster_primitive == GL_TRIANGLES)) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ mode = GR_CULL_NEGATIVE;
+ else
+ mode = GR_CULL_POSITIVE;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ mode = GR_CULL_POSITIVE;
+ else
+ mode = GR_CULL_NEGATIVE;
+ break;
+ case GL_FRONT_AND_BACK:
+ /* Handled as a fallback on triangles in tdfx_tris.c */
+ return;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+
+ if (fxMesa->cullMode != mode) {
+ fxMesa->cullMode = mode;
+ grCullMode(mode);
+ }
+}
+
+
+/************************************************************************/
+/****************************** DD Enable ******************************/
+/************************************************************************/
+
+void
+fxDDEnable(GLcontext * ctx, GLenum cap, GLboolean state)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxUnitsState *us = &fxMesa->unitsState;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "%s(%s)\n", state ? "fxDDEnable" : "fxDDDisable",
+ _mesa_lookup_enum_by_nr(cap));
+ }
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (state != us->alphaTestEnabled) {
+ us->alphaTestEnabled = state;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ }
+ break;
+ case GL_BLEND:
+ if (state != us->blendEnabled) {
+ us->blendEnabled = state;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ }
+ break;
+ case GL_DEPTH_TEST:
+ if (state != us->depthTestEnabled) {
+ us->depthTestEnabled = state;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ }
+ break;
+ case GL_STENCIL_TEST:
+ if (fxMesa->haveHwStencil && state != us->stencilEnabled) {
+ us->stencilEnabled = state;
+ fxMesa->new_state |= FX_NEW_STENCIL;
+ }
+ break;
+ case GL_DITHER:
+ if (state) {
+ grDitherMode(GR_DITHER_4x4);
+ }
+ else {
+ grDitherMode(GR_DITHER_DISABLE);
+ }
+ break;
+ case GL_SCISSOR_TEST:
+ fxMesa->new_state |= FX_NEW_SCISSOR;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ fxDDTexUseGlbPalette(ctx, state);
+ break;
+ case GL_FOG:
+ fxMesa->new_state |= FX_NEW_FOG;
+ break;
+ case GL_CULL_FACE:
+ fxMesa->new_state |= FX_NEW_CULL;
+ break;
+ case GL_LINE_SMOOTH:
+ case GL_LINE_STIPPLE:
+ case GL_POINT_SMOOTH:
+ case GL_POLYGON_SMOOTH:
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ break;
+ default:
+ ; /* XXX no-op? */
+ }
+}
+
+
+
+
+/************************************************************************/
+/************************** Changes to units state **********************/
+/************************************************************************/
+
+
+/* All units setup is handled under texture setup.
+ */
+void
+fxDDShadeModel(GLcontext * ctx, GLenum mode)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING;
+}
+
+
+
+/************************************************************************/
+/****************************** Units SetUp *****************************/
+/************************************************************************/
+#if FX_DEBUG
+static void
+fx_print_state_flags(const char *msg, GLuint flags)
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & FX_NEW_TEXTURING) ? "texture, " : "",
+ (flags & FX_NEW_BLEND) ? "blend, " : "",
+ (flags & FX_NEW_ALPHA) ? "alpha, " : "",
+ (flags & FX_NEW_FOG) ? "fog, " : "",
+ (flags & FX_NEW_SCISSOR) ? "scissor, " : "",
+ (flags & FX_NEW_COLOR_MASK) ? "colormask, " : "",
+ (flags & FX_NEW_CULL) ? "cull, " : "",
+ (flags & FX_NEW_STENCIL) ? "stencil, " : "");
+}
+#endif
+
+void
+fxSetupFXUnits(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint newstate = fxMesa->new_state;
+
+#if FX_DEBUG
+ if (TDFX_DEBUG & VERBOSE_DRIVER)
+ fx_print_state_flags("fxSetupFXUnits", newstate);
+#endif
+
+ if (newstate) {
+ if (newstate & FX_NEW_TEXTURING)
+ fxSetupTexture(ctx);
+
+ if (newstate & FX_NEW_BLEND)
+ fxSetupBlend(ctx);
+
+ if (newstate & FX_NEW_ALPHA)
+ fxSetupAlphaTest(ctx);
+
+ if (newstate & FX_NEW_DEPTH)
+ fxSetupDepthTest(ctx);
+
+ if (newstate & FX_NEW_STENCIL)
+ fxSetupStencil(ctx);
+
+ if (newstate & FX_NEW_FOG)
+ fxSetupFog(ctx);
+
+ if (newstate & FX_NEW_SCISSOR)
+ fxSetupScissor(ctx);
+
+ if (newstate & FX_NEW_COLOR_MASK)
+ fxSetupColorMask(ctx);
+
+ if (newstate & FX_NEW_CULL)
+ fxSetupCull(ctx);
+
+ fxMesa->new_state = 0;
+ }
+}
+
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_setup(void);
+int
+gl_fx_dummy_function_setup(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxsetup.h b/src/mesa/drivers/glide/fxsetup.h
new file mode 100644
index 0000000..9d337d4
--- /dev/null
+++ b/src/mesa/drivers/glide/fxsetup.h
@@ -0,0 +1,850 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxsetup.c - 3Dfx VooDoo rendering mode setup functions */
+/* This code belongs to fxsetup.c, but I didn't want to clutter
+ * the original code with Napalm specifics, in order to keep things
+ * clear -- especially for backward compatibility. I should have
+ * put it into another .c file, but I didn't want to export so many
+ * things...
+ * The point is, Napalm uses a different technique for texture env.
+ * SST1 Single texturing:
+ * setup standard grTexCombine
+ * fiddle with grColorCombine/grAlphaCombine
+ * SST1 Multi texturing:
+ * fiddle with grTexCombine/grColorCombine/grAlphaCombine
+ * Napalm Single texturing:
+ * setup standard grColorCombineExt/grAlphaCombineExt
+ * fiddle with grTexColorCombine/grTexAlphaCombine
+ * Napalm Multi texturing:
+ * setup standard grColorCombineExt/grAlphaCombineExt
+ * fiddle with grTexColorCombine/grTexAlphaCombine
+ */
+
+/*
+ * These macros are used below when handling COMBINE_EXT.
+ */
+#define TEXENV_OPERAND_INVERTED(operand) \
+ (((operand) == GL_ONE_MINUS_SRC_ALPHA) \
+ || ((operand) == GL_ONE_MINUS_SRC_COLOR))
+#define TEXENV_OPERAND_ALPHA(operand) \
+ (((operand) == GL_SRC_ALPHA) || ((operand) == GL_ONE_MINUS_SRC_ALPHA))
+#define TEXENV_SETUP_ARG_A(param, source, operand, iteratedAlpha) \
+ switch (source) { \
+ case GL_TEXTURE: \
+ param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \
+ break; \
+ case GL_CONSTANT_EXT: \
+ param = GR_CMBX_TMU_CALPHA; \
+ break; \
+ case GL_PRIMARY_COLOR_EXT: \
+ param = GR_CMBX_ITALPHA; \
+ break; \
+ case GL_PREVIOUS_EXT: \
+ param = iteratedAlpha; \
+ break; \
+ default: \
+ /* \
+ * This is here just to keep from getting \
+ * compiler warnings. \
+ */ \
+ param = GR_CMBX_ZERO; \
+ break; \
+ }
+
+#define TEXENV_SETUP_ARG_RGB(param, source, operand, iteratedColor, iteratedAlpha) \
+ if (!TEXENV_OPERAND_ALPHA(operand)) { \
+ switch (source) { \
+ case GL_TEXTURE: \
+ param = GR_CMBX_LOCAL_TEXTURE_RGB; \
+ break; \
+ case GL_CONSTANT_EXT: \
+ param = GR_CMBX_TMU_CCOLOR; \
+ break; \
+ case GL_PRIMARY_COLOR_EXT: \
+ param = GR_CMBX_ITRGB; \
+ break; \
+ case GL_PREVIOUS_EXT: \
+ param = iteratedColor; \
+ break; \
+ default: \
+ /* \
+ * This is here just to keep from getting \
+ * compiler warnings. \
+ */ \
+ param = GR_CMBX_ZERO; \
+ break; \
+ } \
+ } else { \
+ switch (source) { \
+ case GL_TEXTURE: \
+ param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \
+ break; \
+ case GL_CONSTANT_EXT: \
+ param = GR_CMBX_TMU_CALPHA; \
+ break; \
+ case GL_PRIMARY_COLOR_EXT: \
+ param = GR_CMBX_ITALPHA; \
+ break; \
+ case GL_PREVIOUS_EXT: \
+ param = iteratedAlpha; \
+ break; \
+ default: \
+ /* \
+ * This is here just to keep from getting \
+ * compiler warnings. \
+ */ \
+ param = GR_CMBX_ZERO; \
+ break; \
+ } \
+ }
+
+#define TEXENV_SETUP_MODE_RGB(param, operand) \
+ switch (operand) { \
+ case GL_SRC_COLOR: \
+ case GL_SRC_ALPHA: \
+ param = GR_FUNC_MODE_X; \
+ break; \
+ case GL_ONE_MINUS_SRC_ALPHA: \
+ case GL_ONE_MINUS_SRC_COLOR: \
+ param = GR_FUNC_MODE_ONE_MINUS_X; \
+ break; \
+ default: \
+ param = GR_FUNC_MODE_ZERO; \
+ break; \
+ }
+
+#define TEXENV_SETUP_MODE_A(param, operand) \
+ switch (operand) { \
+ case GL_SRC_ALPHA: \
+ param = GR_FUNC_MODE_X; \
+ break; \
+ case GL_ONE_MINUS_SRC_ALPHA: \
+ param = GR_FUNC_MODE_ONE_MINUS_X; \
+ break; \
+ default: \
+ param = GR_FUNC_MODE_ZERO; \
+ break; \
+ }
+
+static void
+fxSetupTextureEnvNapalm_NoLock(GLcontext * ctx, GLuint textureset, GLuint tmu, GLboolean iterated)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[textureset];
+ struct tdfx_combine_alpha_ext alphaComb;
+ struct tdfx_combine_color_ext colorComb;
+ const GLfloat *envColor = texUnit->EnvColor;
+ GrCombineLocal_t localc, locala; /* fragmentColor/Alpha */
+ GLint ifmt;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj = texUnit->_Current;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureEnvNapalm_NoLock(unit %u, TMU %u, iterated %d)\n",
+ textureset, tmu, iterated);
+ }
+
+ ti = fxTMGetTexInfo(tObj);
+
+ ifmt = ti->baseLevelInternalFormat;
+
+ if (iterated) {
+ /* we don't have upstream TMU */
+ locala = GR_CMBX_ITALPHA;
+ localc = GR_CMBX_ITRGB;
+ } else {
+ /* we have upstream TMU */
+ locala = GR_CMBX_OTHER_TEXTURE_ALPHA;
+ localc = GR_CMBX_OTHER_TEXTURE_RGB;
+ }
+
+ alphaComb.InvertD = FXFALSE;
+ alphaComb.Shift = 0;
+ alphaComb.Invert = FXFALSE;
+ colorComb.InvertD = FXFALSE;
+ colorComb.Shift = 0;
+ colorComb.Invert = FXFALSE;
+
+ switch (texUnit->EnvMode) {
+ case GL_DECAL:
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+
+ colorComb.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = localc;
+ colorComb.ModeB = GR_FUNC_MODE_NEGATIVE_X;
+ colorComb.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ colorComb.InvertC = FXFALSE;
+ colorComb.SourceD = GR_CMBX_B;
+ break;
+ case GL_MODULATE:
+ if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.InvertC = FXFALSE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
+ colorComb.InvertC = FXFALSE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ }
+ break;
+ case GL_BLEND:
+ if (ifmt == GL_INTENSITY) {
+ alphaComb.SourceA = GR_CMBX_TMU_CALPHA;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = locala;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.InvertC = FXFALSE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.InvertC = FXFALSE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ colorComb.SourceA = GR_CMBX_TMU_CCOLOR;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = localc;
+ colorComb.ModeB = GR_FUNC_MODE_NEGATIVE_X;
+ colorComb.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
+ colorComb.InvertC = FXFALSE;
+ colorComb.SourceD = GR_CMBX_B;
+ }
+
+ fxMesa->Glide.grConstantColorValueExt(tmu,
+ (((GLuint)(envColor[0] * 255.0f)) ) |
+ (((GLuint)(envColor[1] * 255.0f)) << 8) |
+ (((GLuint)(envColor[2] * 255.0f)) << 16) |
+ (((GLuint)(envColor[3] * 255.0f)) << 24));
+ break;
+ case GL_REPLACE:
+ if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ alphaComb.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ colorComb.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ }
+ break;
+ case GL_ADD:
+ if (ifmt == GL_LUMINANCE || ifmt == GL_RGB) {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ } else if (ifmt == GL_INTENSITY) {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ alphaComb.SourceA = locala;
+ alphaComb.ModeA = GR_FUNC_MODE_X;
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_X;
+ alphaComb.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+ alphaComb.InvertC = FXFALSE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ }
+
+ if (ifmt == GL_ALPHA) {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ } else {
+ colorComb.SourceA = localc;
+ colorComb.ModeA = GR_FUNC_MODE_X;
+ colorComb.SourceB = GR_CMBX_LOCAL_TEXTURE_RGB;
+ colorComb.ModeB = GR_FUNC_MODE_X;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ }
+ break;
+ /* COMBINE_EXT */
+ case GL_COMBINE_EXT:
+ /* XXX todo - INCOMPLETE!!! */
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE)) {
+#if 1
+ fprintf(stderr, "COMBINE_EXT: %s + %s\n",
+ _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB),
+ _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+#else
+ fprintf(stderr, "Texture Unit %d\n", textureset);
+ fprintf(stderr, " GL_TEXTURE_ENV_MODE = %s\n", _mesa_lookup_enum_by_nr(texUnit->EnvMode));
+ fprintf(stderr, " GL_COMBINE_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+ fprintf(stderr, " GL_COMBINE_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+ fprintf(stderr, " GL_SOURCE0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[0]));
+ fprintf(stderr, " GL_SOURCE1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[1]));
+ fprintf(stderr, " GL_SOURCE2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceRGB[2]));
+ fprintf(stderr, " GL_SOURCE0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[0]));
+ fprintf(stderr, " GL_SOURCE1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[1]));
+ fprintf(stderr, " GL_SOURCE2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.SourceA[2]));
+ fprintf(stderr, " GL_OPERAND0_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[0]));
+ fprintf(stderr, " GL_OPERAND1_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[1]));
+ fprintf(stderr, " GL_OPERAND2_RGB = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandRGB[2]));
+ fprintf(stderr, " GL_OPERAND0_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[0]));
+ fprintf(stderr, " GL_OPERAND1_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[1]));
+ fprintf(stderr, " GL_OPERAND2_ALPHA = %s\n", _mesa_lookup_enum_by_nr(texUnit->Combine.OperandA[2]));
+ fprintf(stderr, " GL_RGB_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftRGB);
+ fprintf(stderr, " GL_ALPHA_SCALE = %d\n", 1 << texUnit->Combine.ScaleShiftA);
+ fprintf(stderr, " GL_TEXTURE_ENV_COLOR = (%f, %f, %f, %f)\n", envColor[0], envColor[1], envColor[2], envColor[3]);
+#endif
+ }
+
+ alphaComb.Shift = texUnit->Combine.ScaleShiftA;
+ colorComb.Shift = texUnit->Combine.ScaleShiftRGB;
+
+ switch (texUnit->Combine.ModeRGB) {
+ case GL_MODULATE:
+ /* Arg0 * Arg1 == (A + 0) * C + 0 */
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceA,
+ texUnit->Combine.SourceRGB[0],
+ texUnit->Combine.OperandRGB[0],
+ localc, locala);
+ TEXENV_SETUP_MODE_RGB(colorComb.ModeA,
+ texUnit->Combine.OperandRGB[0]);
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_ZERO;
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceC,
+ texUnit->Combine.SourceRGB[1],
+ texUnit->Combine.OperandRGB[1],
+ localc, locala);
+ colorComb.InvertC = TEXENV_OPERAND_INVERTED(
+ texUnit->Combine.OperandRGB[1]);
+ colorComb.SourceD = GR_CMBX_ZERO;
+ break;
+ case GL_REPLACE:
+ /* Arg0 == (A + 0) * 1 + 0 */
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceA,
+ texUnit->Combine.SourceRGB[0],
+ texUnit->Combine.OperandRGB[0],
+ localc, locala);
+ TEXENV_SETUP_MODE_RGB(colorComb.ModeA,
+ texUnit->Combine.OperandRGB[0]);
+ colorComb.SourceB = GR_CMBX_ZERO;
+ colorComb.ModeB = GR_FUNC_MODE_ZERO;
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ break;
+ case GL_ADD:
+ /* Arg0 + Arg1 = (A + B) * 1 + 0 */
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceA,
+ texUnit->Combine.SourceRGB[0],
+ texUnit->Combine.OperandRGB[0],
+ localc, locala);
+ TEXENV_SETUP_MODE_RGB(colorComb.ModeA,
+ texUnit->Combine.OperandRGB[0]);
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceB,
+ texUnit->Combine.SourceRGB[1],
+ texUnit->Combine.OperandRGB[1],
+ localc, locala);
+ TEXENV_SETUP_MODE_RGB(colorComb.ModeB,
+ texUnit->Combine.OperandRGB[1]);
+ colorComb.SourceC = GR_CMBX_ZERO;
+ colorComb.InvertC = FXTRUE;
+ colorComb.SourceD = GR_CMBX_ZERO;
+ break;
+ case GL_INTERPOLATE_EXT:
+ /* Arg0 * Arg2 + Arg1 * (1 - Arg2) ==
+ * (Arg0 - Arg1) * Arg2 + Arg1 == (A - B) * C + D
+ */
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceA,
+ texUnit->Combine.SourceRGB[0],
+ texUnit->Combine.OperandRGB[0],
+ localc, locala);
+ TEXENV_SETUP_MODE_RGB(colorComb.ModeA,
+ texUnit->Combine.OperandRGB[0]);
+ TEXENV_SETUP_ARG_RGB(colorComb.SourceB,
+ texUnit->Combine.SourceRGB[1],
+ texUnit->Combine.OperandRGB[1],
+ localc, locala);
+ if (TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[1])) {
+ /* Hack alert!!! This case is wrong!!! */
+ fprintf(stderr, "COMBINE_EXT_color: WRONG!!!\n");
+ colorComb.ModeB = GR_FUNC_MODE_NEGATIVE_X;
+ } else {
+ colorComb.ModeB = GR_FUNC_MODE_NEGATIVE_X;
+ }
+ /*
+ * The Source/Operand for the C value must
+ * specify some kind of alpha value.
+ */
+ TEXENV_SETUP_ARG_A(colorComb.SourceC,
+ texUnit->Combine.SourceRGB[2],
+ texUnit->Combine.OperandRGB[2],
+ locala);
+ colorComb.InvertC = FXFALSE;
+ colorComb.SourceD = GR_CMBX_B;
+ break;
+ default:
+ fprintf(stderr, "COMBINE_EXT_color: %s\n",
+ _mesa_lookup_enum_by_nr(texUnit->Combine.ModeRGB));
+ }
+
+ switch (texUnit->Combine.ModeA) {
+ case GL_MODULATE:
+ /* Arg0 * Arg1 == (A + 0) * C + 0 */
+ TEXENV_SETUP_ARG_A(alphaComb.SourceA,
+ texUnit->Combine.SourceA[0],
+ texUnit->Combine.OperandA[0],
+ locala);
+ TEXENV_SETUP_MODE_A(alphaComb.ModeA,
+ texUnit->Combine.OperandA[0]);
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_ZERO;
+ TEXENV_SETUP_ARG_A(alphaComb.SourceC,
+ texUnit->Combine.SourceA[1],
+ texUnit->Combine.OperandA[1],
+ locala);
+ alphaComb.InvertC = TEXENV_OPERAND_INVERTED(
+ texUnit->Combine.OperandA[1]);
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ break;
+ case GL_REPLACE:
+ /* Arg0 == (A + 0) * 1 + 0 */
+ TEXENV_SETUP_ARG_A(alphaComb.SourceA,
+ texUnit->Combine.SourceA[0],
+ texUnit->Combine.OperandA[0],
+ locala);
+ TEXENV_SETUP_MODE_A(alphaComb.ModeA,
+ texUnit->Combine.OperandA[0]);
+ alphaComb.SourceB = GR_CMBX_ZERO;
+ alphaComb.ModeB = GR_FUNC_MODE_ZERO;
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ break;
+ case GL_ADD:
+ /* Arg0 + Arg1 = (A + B) * 1 + 0 */
+ TEXENV_SETUP_ARG_A(alphaComb.SourceA,
+ texUnit->Combine.SourceA[0],
+ texUnit->Combine.OperandA[0],
+ locala);
+ TEXENV_SETUP_MODE_A(alphaComb.ModeA,
+ texUnit->Combine.OperandA[0]);
+ TEXENV_SETUP_ARG_A(alphaComb.SourceB,
+ texUnit->Combine.SourceA[1],
+ texUnit->Combine.OperandA[1],
+ locala);
+ TEXENV_SETUP_MODE_A(alphaComb.ModeB,
+ texUnit->Combine.OperandA[1]);
+ alphaComb.SourceC = GR_CMBX_ZERO;
+ alphaComb.InvertC = FXTRUE;
+ alphaComb.SourceD = GR_CMBX_ZERO;
+ break;
+ default:
+ fprintf(stderr, "COMBINE_EXT_alpha: %s\n",
+ _mesa_lookup_enum_by_nr(texUnit->Combine.ModeA));
+ }
+
+ fxMesa->Glide.grConstantColorValueExt(tmu,
+ (((GLuint)(envColor[0] * 255.0f)) ) |
+ (((GLuint)(envColor[1] * 255.0f)) << 8) |
+ (((GLuint)(envColor[2] * 255.0f)) << 16) |
+ (((GLuint)(envColor[3] * 255.0f)) << 24));
+ break;
+
+ default:
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureEnvNapalm_NoLock: %x Texture.EnvMode not yet supported\n",
+ texUnit->EnvMode);
+ }
+ return;
+ }
+
+ /* On Napalm we simply put the color combine unit into passthrough mode
+ * and do everything we need with the texture combine units. */
+ fxMesa->Glide.grColorCombineExt(GR_CMBX_TEXTURE_RGB,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+ fxMesa->Glide.grAlphaCombineExt(GR_CMBX_TEXTURE_ALPHA,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+
+ fxMesa->Glide.grTexAlphaCombineExt(tmu,
+ alphaComb.SourceA,
+ alphaComb.ModeA,
+ alphaComb.SourceB,
+ alphaComb.ModeB,
+ alphaComb.SourceC,
+ alphaComb.InvertC,
+ alphaComb.SourceD,
+ alphaComb.InvertD,
+ alphaComb.Shift,
+ alphaComb.Invert);
+ fxMesa->Glide.grTexColorCombineExt(tmu,
+ colorComb.SourceA,
+ colorComb.ModeA,
+ colorComb.SourceB,
+ colorComb.ModeB,
+ colorComb.SourceC,
+ colorComb.InvertC,
+ colorComb.SourceD,
+ colorComb.InvertD,
+ colorComb.Shift,
+ colorComb.Invert);
+}
+
+
+/************************* Single Texture Set ***************************/
+
+static void
+fxSelectSingleTMUSrcNapalm_NoLock(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+{
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSelectSingleTMUSrcNapalm_NoLock(%d, %d)\n", tmu, LODblend);
+ }
+
+ if (LODblend) {
+ /* XXX todo - GR_CMBX_LOD_FRAC? */
+ fxMesa->tmuSrc = FX_TMU_SPLIT;
+ }
+ else {
+ if (tmu != FX_TMU1) {
+ /* disable tex1 */
+ if (fxMesa->haveTwoTMUs) {
+ fxMesa->Glide.grTexAlphaCombineExt(FX_TMU1,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+ fxMesa->Glide.grTexColorCombineExt(FX_TMU1,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+ }
+
+ fxMesa->tmuSrc = FX_TMU0;
+ }
+ else {
+#if 1
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE,
+ FXFALSE,
+ FXFALSE);
+#else
+ /* [dBorca] why, oh why? doesn't work! stupid Glide? */
+ fxMesa->Glide.grTexAlphaCombineExt(FX_TMU0,
+ GR_CMBX_OTHER_TEXTURE_ALPHA,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+ fxMesa->Glide.grTexColorCombineExt(FX_TMU0,
+ GR_CMBX_OTHER_TEXTURE_RGB,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+#endif
+
+ fxMesa->tmuSrc = FX_TMU1;
+ }
+ }
+}
+
+static void
+fxSetupTextureSingleTMUNapalm_NoLock(GLcontext * ctx, GLuint textureset)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint unitsmode;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj = ctx->Texture.Unit[textureset]._Current;
+ int tmu;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureSingleTMUNapalm_NoLock(%d)\n", textureset);
+ }
+
+ ti = fxTMGetTexInfo(tObj);
+
+ fxTexValidate(ctx, tObj);
+
+ fxSetupSingleTMU_NoLock(fxMesa, tObj);
+
+ if (ti->whichTMU == FX_TMU_BOTH)
+ tmu = FX_TMU0;
+ else
+ tmu = ti->whichTMU;
+ if (fxMesa->tmuSrc != tmu)
+ fxSelectSingleTMUSrcNapalm_NoLock(fxMesa, tmu, ti->LODblend);
+
+ if (textureset == 0 || !fxMesa->haveTwoTMUs)
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj, NULL);
+ else
+ unitsmode = fxGetTexSetConfiguration(ctx, NULL, tObj);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state = 0;
+ FX_grHints_NoLock(GR_HINT_STWHINT, 0);
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureSingleTMUNapalm_NoLock: envmode is %s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
+
+ /* [dBorca] Hack alert:
+ * what if we're in split mode? (LODBlend)
+ * also should we update BOTH TMUs in FX_TMU_BOTH mode?
+ */
+ fxSetupTextureEnvNapalm_NoLock(ctx, textureset, tmu, GL_TRUE);
+}
+
+
+/************************* Double Texture Set ***************************/
+
+static void
+fxSetupTextureDoubleTMUNapalm_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ tfxTexInfo *ti0, *ti1;
+ struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current;
+ struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current;
+ GLuint unitsmode;
+ int tmu0 = 0, tmu1 = 1;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureDoubleTMUNapalm_NoLock(...)\n");
+ }
+
+ ti0 = fxTMGetTexInfo(tObj0);
+ fxTexValidate(ctx, tObj0);
+
+ ti1 = fxTMGetTexInfo(tObj1);
+ fxTexValidate(ctx, tObj1);
+
+ fxSetupDoubleTMU_NoLock(fxMesa, tObj0, tObj1);
+
+ unitsmode = fxGetTexSetConfiguration(ctx, tObj0, tObj1);
+
+/* if(fxMesa->lastUnitsMode==unitsmode) */
+/* return; */
+
+ fxMesa->lastUnitsMode = unitsmode;
+
+ fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1;
+ FX_grHints_NoLock(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE))
+ fprintf(stderr, "fxSetupTextureDoubleTMUNapalm_NoLock: envmode is %s/%s\n",
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ _mesa_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+
+ if ((ti0->whichTMU == FX_TMU1) || (ti1->whichTMU == FX_TMU0)) {
+ tmu0 = 1;
+ tmu1 = 0;
+ }
+ fxMesa->tmuSrc = FX_TMU_BOTH;
+
+ /* OpenGL vs Glide texture pipeline */
+ fxSetupTextureEnvNapalm_NoLock(ctx, 0, 1, GL_TRUE);
+ fxSetupTextureEnvNapalm_NoLock(ctx, 1, 0, GL_FALSE);
+}
+
+/************************* No Texture ***************************/
+
+static void
+fxSetupTextureNoneNapalm_NoLock(GLcontext * ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxSetupTextureNoneNapalm_NoLock(...)\n");
+ }
+
+ /* the combiner formula is: (A + B) * C + D
+ **
+ ** a = tc_otherselect
+ ** a_mode = tc_invert_other
+ ** b = tc_localselect
+ ** b_mode = tc_invert_local
+ ** c = (tc_mselect, tc_mselect_7)
+ ** d = (tc_add_clocal, tc_add_alocal)
+ ** shift = tc_outshift
+ ** invert = tc_invert_output
+ */
+
+ fxMesa->Glide.grColorCombineExt(GR_CMBX_ITRGB,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+ fxMesa->Glide.grAlphaCombineExt(GR_CMBX_ITALPHA,
+ GR_FUNC_MODE_X,
+ GR_CMBX_ZERO,
+ GR_FUNC_MODE_ZERO,
+ GR_CMBX_ZERO,
+ FXTRUE,
+ GR_CMBX_ZERO,
+ FXFALSE,
+ 0,
+ FXFALSE);
+
+ fxMesa->lastUnitsMode = FX_UM_NONE;
+}
diff --git a/src/mesa/drivers/glide/fxtexman.c b/src/mesa/drivers/glide/fxtexman.c
new file mode 100644
index 0000000..d0480de
--- /dev/null
+++ b/src/mesa/drivers/glide/fxtexman.c
@@ -0,0 +1,866 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Daryll Strauss
+ * Keith Whitwell
+ * Daniel Borca
+ * Hiroshi Morii
+ */
+
+/* fxtexman.c - 3Dfx VooDoo texture memory functions */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+int texSwaps = 0;
+static FxU32 texBoundMask;
+
+#define FX_2MB_SPLIT 0x200000
+
+static struct gl_texture_object *fxTMFindOldestObject(fxMesaContext fxMesa,
+ int tmu);
+
+
+#ifdef TEXSANITY
+static void
+fubar()
+{
+}
+
+ /* Sanity Check */
+static void
+sanity(fxMesaContext fxMesa)
+{
+ MemRange *tmp, *prev, *pos;
+
+ prev = 0;
+ tmp = fxMesa->tmFree[0];
+ while (tmp) {
+ if (!tmp->startAddr && !tmp->endAddr) {
+ fprintf(stderr, "Textures fubar\n");
+ fubar();
+ }
+ if (tmp->startAddr >= tmp->endAddr) {
+ fprintf(stderr, "Node fubar\n");
+ fubar();
+ }
+ if (prev && (prev->startAddr >= tmp->startAddr ||
+ prev->endAddr > tmp->startAddr)) {
+ fprintf(stderr, "Sorting fubar\n");
+ fubar();
+ }
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ prev = 0;
+ tmp = fxMesa->tmFree[1];
+ while (tmp) {
+ if (!tmp->startAddr && !tmp->endAddr) {
+ fprintf(stderr, "Textures fubar\n");
+ fubar();
+ }
+ if (tmp->startAddr >= tmp->endAddr) {
+ fprintf(stderr, "Node fubar\n");
+ fubar();
+ }
+ if (prev && (prev->startAddr >= tmp->startAddr ||
+ prev->endAddr > tmp->startAddr)) {
+ fprintf(stderr, "Sorting fubar\n");
+ fubar();
+ }
+ prev = tmp;
+ tmp = tmp->next;
+ }
+}
+#endif
+
+static MemRange *
+fxTMNewRangeNode(fxMesaContext fxMesa, FxU32 start, FxU32 end)
+{
+ MemRange *result = 0;
+
+ if (fxMesa->tmPool) {
+ result = fxMesa->tmPool;
+ fxMesa->tmPool = fxMesa->tmPool->next;
+ }
+ else {
+ if (!(result = MALLOC(sizeof(MemRange)))) {
+ fprintf(stderr, "fxTMNewRangeNode: ERROR: out of memory!\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ }
+ result->startAddr = start;
+ result->endAddr = end;
+ return result;
+}
+
+#if 1
+#define fxTMDeleteRangeNode(fxMesa, range) \
+ do { \
+ range->next = fxMesa->tmPool; \
+ fxMesa->tmPool = range; \
+ } while (0);
+#else
+static void
+fxTMDeleteRangeNode(fxMesaContext fxMesa, MemRange * range)
+{
+ range->next = fxMesa->tmPool;
+ fxMesa->tmPool = range;
+}
+#endif
+
+static void
+fxTMUInit(fxMesaContext fxMesa, int tmu)
+{
+ MemRange *tmn, *last;
+ FxU32 start, end, blockstart, blockend, chunk;
+
+ start = grTexMinAddress(tmu);
+ end = grTexMaxAddress(tmu);
+
+ chunk = (fxMesa->type >= GR_SSTTYPE_Banshee) ? (end - start) : FX_2MB_SPLIT;
+
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Voodoo TMU%d configuration:\n", tmu);
+ }
+
+ fxMesa->freeTexMem[tmu] = end - start;
+ fxMesa->tmFree[tmu] = NULL;
+
+ last = 0;
+ blockstart = start;
+ while (blockstart < end) {
+ if (blockstart + chunk > end)
+ blockend = end;
+ else
+ blockend = blockstart + chunk;
+
+ if (fxMesa->verbose)
+ fprintf(stderr, "Voodoo %08u-%08u\n",
+ (unsigned int) blockstart, (unsigned int) blockend);
+
+ tmn = fxTMNewRangeNode(fxMesa, blockstart, blockend);
+ tmn->next = NULL;
+
+
+ if (last)
+ last->next = tmn;
+ else
+ fxMesa->tmFree[tmu] = tmn;
+ last = tmn;
+
+ blockstart += chunk;
+ }
+}
+
+static int
+fxTMFindStartAddr(fxMesaContext fxMesa, GLint tmu, int size)
+{
+ MemRange *prev, *tmp;
+ int result;
+ struct gl_texture_object *obj;
+
+ if (fxMesa->HaveTexUma) {
+ tmu = FX_TMU0;
+ }
+
+ while (1) {
+ prev = 0;
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
+ result = tmp->startAddr;
+ tmp->startAddr += size;
+ if (tmp->startAddr == tmp->endAddr) { /* Empty */
+ if (prev) {
+ prev->next = tmp->next;
+ }
+ else {
+ fxMesa->tmFree[tmu] = tmp->next;
+ }
+ fxTMDeleteRangeNode(fxMesa, tmp);
+ }
+ fxMesa->freeTexMem[tmu] -= size;
+ return result;
+ }
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ /* No free space. Discard oldest */
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTMFindStartAddr: No free space. Discard oldest\n");
+ }
+ obj = fxTMFindOldestObject(fxMesa, tmu);
+ if (!obj) {
+ fprintf(stderr, "fxTMFindStartAddr: ERROR: No space for texture\n");
+ return -1;
+ }
+ fxTMMoveOutTM(fxMesa, obj);
+ texSwaps++;
+ }
+}
+
+int fxTMCheckStartAddr (fxMesaContext fxMesa, GLint tmu, tfxTexInfo *ti)
+{
+ MemRange /* *prev,*/ *tmp;
+ int size;
+/*struct gl_texture_object *obj;*/
+
+ if (fxMesa->HaveTexUma) {
+ return FXTRUE;
+ }
+
+ size = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (tmp->endAddr - tmp->startAddr >= size) { /* Fits here */
+ return FXTRUE;
+ }
+ tmp = tmp->next;
+ }
+
+ return FXFALSE;
+}
+
+static void
+fxTMRemoveRange(fxMesaContext fxMesa, GLint tmu, MemRange * range)
+{
+ MemRange *tmp, *prev;
+
+ if (fxMesa->HaveTexUma) {
+ tmu = FX_TMU0;
+ }
+
+ if (range->startAddr == range->endAddr) {
+ fxTMDeleteRangeNode(fxMesa, range);
+ return;
+ }
+ fxMesa->freeTexMem[tmu] += range->endAddr - range->startAddr;
+ prev = 0;
+ tmp = fxMesa->tmFree[tmu];
+ while (tmp) {
+ if (range->startAddr > tmp->startAddr) {
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ else
+ break;
+ }
+ /* When we create the regions, we make a split at the 2MB boundary.
+ Now we have to make sure we don't join those 2MB boundary regions
+ back together again. */
+ range->next = tmp;
+ if (tmp) {
+ if (range->endAddr == tmp->startAddr
+ && tmp->startAddr & texBoundMask) {
+ /* Combine */
+ tmp->startAddr = range->startAddr;
+ fxTMDeleteRangeNode(fxMesa, range);
+ range = tmp;
+ }
+ }
+ if (prev) {
+ if (prev->endAddr == range->startAddr
+ && range->startAddr & texBoundMask) {
+ /* Combine */
+ prev->endAddr = range->endAddr;
+ prev->next = range->next;
+ fxTMDeleteRangeNode(fxMesa, range);
+ }
+ else
+ prev->next = range;
+ }
+ else {
+ fxMesa->tmFree[tmu] = range;
+ }
+}
+
+static struct gl_texture_object *
+fxTMFindOldestObject(fxMesaContext fxMesa, int tmu)
+{
+ GLuint age, old, lasttime, bindnumber;
+ GLfloat lowestPriority;
+ tfxTexInfo *info;
+ struct gl_texture_object *obj, *tmp, *lowestPriorityObj;
+
+ tmp = fxMesa->glCtx->Shared->TexObjectList;
+ if (!tmp)
+ return 0;
+ obj = NULL;
+ old = 0;
+
+ lowestPriorityObj = NULL;
+ lowestPriority = 1.0F;
+
+ bindnumber = fxMesa->texBindNumber;
+ while (tmp) {
+ info = fxTMGetTexInfo(tmp);
+
+ if (info && info->isInTM &&
+ ((info->whichTMU == tmu) ||
+ (info->whichTMU == FX_TMU_BOTH) ||
+ (info->whichTMU == FX_TMU_SPLIT) ||
+ fxMesa->HaveTexUma
+ )
+ ) {
+ lasttime = info->lastTimeUsed;
+
+ if (lasttime > bindnumber)
+ age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */
+ else
+ age = bindnumber - lasttime;
+
+ if (age >= old) {
+ old = age;
+ obj = tmp;
+ }
+
+ /* examine priority */
+ if (tmp->Priority < lowestPriority) {
+ lowestPriority = tmp->Priority;
+ lowestPriorityObj = tmp;
+ }
+ }
+ tmp = tmp->Next;
+ }
+
+ if (lowestPriorityObj != NULL) {
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTMFindOldestObject: %d pri=%f\n", lowestPriorityObj->Name, lowestPriority);
+ }
+ return lowestPriorityObj;
+ }
+ else {
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ if (obj != NULL) {
+ fprintf(stderr, "fxTMFindOldestObject: %d age=%d\n", obj->Name, old);
+ }
+ }
+ return obj;
+ }
+}
+
+static MemRange *
+fxTMAddObj(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj, GLint tmu, int texmemsize)
+{
+ FxI32 startAddr;
+ MemRange *range;
+
+ startAddr = fxTMFindStartAddr(fxMesa, tmu, texmemsize);
+ if (startAddr < 0)
+ return 0;
+ range = fxTMNewRangeNode(fxMesa, startAddr, startAddr + texmemsize);
+ return range;
+}
+
+/* External Functions */
+
+void
+fxTMMoveInTM_NoLock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint where)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ int i, l;
+ int texmemsize;
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTMMoveInTM_NoLock(%d)\n", tObj->Name);
+ }
+
+ fxMesa->stats.reqTexUpload++;
+
+ if (!ti->validated) {
+ fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ if (ti->isInTM) {
+ if (ti->whichTMU == where)
+ return;
+ if (where == FX_TMU_SPLIT || ti->whichTMU == FX_TMU_SPLIT)
+ fxTMMoveOutTM_NoLock(fxMesa, tObj);
+ else {
+ if (ti->whichTMU == FX_TMU_BOTH)
+ return;
+ where = FX_TMU_BOTH;
+ }
+ }
+
+ if (TDFX_DEBUG & (VERBOSE_DRIVER | VERBOSE_TEXTURE)) {
+ fprintf(stderr, "fxTMMoveInTM_NoLock: downloading %p (%d) in texture memory in %d\n",
+ (void *)tObj, tObj->Name, where);
+ }
+
+ ti->whichTMU = (FxU32) where;
+
+ switch (where) {
+ case FX_TMU0:
+ case FX_TMU1:
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+ ti->tm[where] = fxTMAddObj(fxMesa, tObj, where, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
+ i <= FX_smallLodValue(ti->info); i++, l++) {
+ struct gl_texture_image *texImage = tObj->Image[0][l];
+ grTexDownloadMipMapLevel(where,
+ ti->tm[where]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+ }
+ break;
+ case FX_TMU_SPLIT:
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD, &(ti->info));
+ ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN, &(ti->info));
+ ti->tm[FX_TMU1] = fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
+ i <= FX_smallLodValue(ti->info); i++, l++) {
+ struct gl_texture_image *texImage = tObj->Image[0][l];
+
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_ODD,
+ texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_EVEN,
+ texImage->Data);
+ }
+ break;
+ case FX_TMU_BOTH:
+ texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
+ ti->tm[FX_TMU0] = fxTMAddObj(fxMesa, tObj, FX_TMU0, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ /*texmemsize = (int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &(ti->info));*/
+ ti->tm[FX_TMU1] = fxTMAddObj(fxMesa, tObj, FX_TMU1, texmemsize);
+ fxMesa->stats.memTexUpload += texmemsize;
+
+ for (i = FX_largeLodValue(ti->info), l = ti->minLevel;
+ i <= FX_smallLodValue(ti->info); i++, l++) {
+ struct gl_texture_image *texImage = tObj->Image[0][l];
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH,
+ texImage->Data);
+ }
+ break;
+ default:
+ fprintf(stderr, "fxTMMoveInTM_NoLock: INTERNAL ERROR: wrong tmu (%d)\n", where);
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ fxMesa->stats.texUpload++;
+
+ ti->isInTM = GL_TRUE;
+}
+
+
+void
+fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint where)
+{
+ BEGIN_BOARD_LOCK();
+ fxTMMoveInTM_NoLock(fxMesa, tObj, where);
+ END_BOARD_LOCK();
+}
+
+
+void
+fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint level)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GrLOD_t lodlevel;
+ GLint tmu;
+ struct gl_texture_image *texImage = tObj->Image[0][level];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTMReloadMipMapLevel(%p (%d), %d)\n", (void *)tObj, tObj->Name, level);
+ }
+
+ assert(mml);
+ assert(mml->width > 0);
+ assert(mml->height > 0);
+ assert(mml->glideFormat > 0);
+ assert(ti->isInTM);
+
+ if (!ti->validated) {
+ fprintf(stderr, "fxTMReloadMipMapLevel: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu = (int) ti->whichTMU;
+ fxMesa->stats.reqTexUpload++;
+ fxMesa->stats.texUpload++;
+
+ lodlevel = ti->info.largeLodLog2 - (level - ti->minLevel);
+
+ switch (tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevel(tmu,
+ ti->tm[tmu]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+ break;
+ case FX_TMU_SPLIT:
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[GR_TMU0]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_ODD, texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[GR_TMU1]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_EVEN, texImage->Data);
+ break;
+ case FX_TMU_BOTH:
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tm[GR_TMU0]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tm[GR_TMU1]->startAddr,
+ lodlevel,
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, texImage->Data);
+ break;
+
+ default:
+ fprintf(stderr, "fxTMReloadMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+void
+fxTMReloadSubMipMapLevel(fxMesaContext fxMesa,
+ struct gl_texture_object *tObj,
+ GLint level, GLint yoffset, GLint height)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ GrLOD_t lodlevel;
+ unsigned short *data;
+ GLint tmu;
+ struct gl_texture_image *texImage = tObj->Image[0][level];
+ tfxMipMapLevel *mml = FX_MIPMAP_DATA(texImage);
+
+ assert(mml);
+
+ if (!ti->validated) {
+ fprintf(stderr, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu = (int) ti->whichTMU;
+ fxTMMoveInTM(fxMesa, tObj, tmu);
+
+ fxTexGetInfo(mml->width, mml->height,
+ &lodlevel, NULL, NULL, NULL, NULL, NULL);
+
+ if ((ti->info.format == GR_TEXFMT_INTENSITY_8) ||
+ (ti->info.format == GR_TEXFMT_P_8) ||
+ (ti->info.format == GR_TEXFMT_ALPHA_8))
+ data = (GLushort *) texImage->Data + ((yoffset * mml->width) >> 1);
+ else
+ data = (GLushort *) texImage->Data + yoffset * mml->width;
+
+ switch (tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevelPartial(tmu,
+ ti->tm[tmu]->startAddr,
+ FX_valueToLod(FX_lodToValue(lodlevel)
+ + level),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, data,
+ yoffset, yoffset + height - 1);
+ break;
+ case FX_TMU_SPLIT:
+ grTexDownloadMipMapLevelPartial(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(FX_lodToValue(lodlevel)
+ + level),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_ODD, data,
+ yoffset, yoffset + height - 1);
+
+ grTexDownloadMipMapLevelPartial(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(FX_lodToValue(lodlevel)
+ + level),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_EVEN, data,
+ yoffset, yoffset + height - 1);
+ break;
+ case FX_TMU_BOTH:
+ grTexDownloadMipMapLevelPartial(GR_TMU0,
+ ti->tm[FX_TMU0]->startAddr,
+ FX_valueToLod(FX_lodToValue(lodlevel)
+ + level),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, data,
+ yoffset, yoffset + height - 1);
+
+ grTexDownloadMipMapLevelPartial(GR_TMU1,
+ ti->tm[FX_TMU1]->startAddr,
+ FX_valueToLod(FX_lodToValue(lodlevel)
+ + level),
+ FX_largeLodLog2(ti->info),
+ FX_aspectRatioLog2(ti->info),
+ ti->info.format,
+ GR_MIPMAPLEVELMASK_BOTH, data,
+ yoffset, yoffset + height - 1);
+ break;
+ default:
+ fprintf(stderr, "fxTMReloadSubMipMapLevel: INTERNAL ERROR: wrong tmu (%d)\n", tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+void
+fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+
+ if (TDFX_DEBUG & VERBOSE_DRIVER) {
+ fprintf(stderr, "fxTMMoveOutTM(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ if (!ti->isInTM)
+ return;
+
+ switch (ti->whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ fxTMRemoveRange(fxMesa, (int) ti->whichTMU, ti->tm[ti->whichTMU]);
+ break;
+ case FX_TMU_SPLIT:
+ case FX_TMU_BOTH:
+ fxTMRemoveRange(fxMesa, FX_TMU0, ti->tm[FX_TMU0]);
+ fxTMRemoveRange(fxMesa, FX_TMU1, ti->tm[FX_TMU1]);
+ break;
+ default:
+ fprintf(stderr, "fxTMMoveOutTM: INTERNAL ERROR: bad TMU (%ld)\n", ti->whichTMU);
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->isInTM = GL_FALSE;
+ ti->whichTMU = FX_TMU_NONE;
+}
+
+void
+fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti = fxTMGetTexInfo(tObj);
+ int i;
+
+ if (TDFX_DEBUG & VERBOSE_TEXTURE) {
+ fprintf(stderr, "fxTMFreeTexture(%p (%d))\n", (void *)tObj, tObj->Name);
+ }
+
+ fxTMMoveOutTM(fxMesa, tObj);
+
+ for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+ struct gl_texture_image *texImage = tObj->Image[0][i];
+ if (texImage) {
+ if (texImage->DriverData) {
+ FREE(texImage->DriverData);
+ texImage->DriverData = NULL;
+ }
+ }
+ }
+ switch (ti->whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ fxTMDeleteRangeNode(fxMesa, ti->tm[ti->whichTMU]);
+ break;
+ case FX_TMU_SPLIT:
+ case FX_TMU_BOTH:
+ fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU0]);
+ fxTMDeleteRangeNode(fxMesa, ti->tm[FX_TMU1]);
+ break;
+ }
+}
+
+void
+fxTMInit(fxMesaContext fxMesa)
+{
+ fxMesa->texBindNumber = 0;
+ fxMesa->tmPool = 0;
+
+ if (fxMesa->HaveTexUma) {
+ grEnable(GR_TEXTURE_UMA_EXT);
+ }
+
+ fxTMUInit(fxMesa, FX_TMU0);
+
+ if (!fxMesa->HaveTexUma && fxMesa->haveTwoTMUs)
+ fxTMUInit(fxMesa, FX_TMU1);
+
+ texBoundMask = (fxMesa->type >= GR_SSTTYPE_Banshee) ? -1 : (FX_2MB_SPLIT - 1);
+}
+
+void
+fxTMClose(fxMesaContext fxMesa)
+{
+ MemRange *tmp, *next;
+
+ tmp = fxMesa->tmPool;
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ tmp = fxMesa->tmFree[FX_TMU0];
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ if (fxMesa->haveTwoTMUs) {
+ tmp = fxMesa->tmFree[FX_TMU1];
+ while (tmp) {
+ next = tmp->next;
+ FREE(tmp);
+ tmp = next;
+ }
+ }
+}
+
+void
+fxTMRestoreTextures_NoLock(fxMesaContext ctx)
+{
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj;
+ int i, where;
+
+ tObj = ctx->glCtx->Shared->TexObjectList;
+ while (tObj) {
+ ti = fxTMGetTexInfo(tObj);
+ if (ti && ti->isInTM) {
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++)
+ if (ctx->glCtx->Texture.Unit[i]._Current == tObj) {
+ /* Force the texture onto the board, as it could be in use */
+ where = ti->whichTMU;
+ fxTMMoveOutTM_NoLock(ctx, tObj);
+ fxTMMoveInTM_NoLock(ctx, tObj, where);
+ break;
+ }
+ if (i == MAX_TEXTURE_UNITS) /* Mark the texture as off the board */
+ fxTMMoveOutTM_NoLock(ctx, tObj);
+ }
+ tObj = tObj->Next;
+ }
+}
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_texman(void);
+int
+gl_fx_dummy_function_texman(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxtris.c b/src/mesa/drivers/glide/fxtris.c
new file mode 100644
index 0000000..532ad63
--- /dev/null
+++ b/src/mesa/drivers/glide/fxtris.c
@@ -0,0 +1,1647 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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 <keith@tungstengraphics.com>
+ * Daniel Borca <dborca@users.sourceforge.net>
+ */
+
+#include "glheader.h"
+
+#ifdef FX
+
+#include "imports.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+#include "nvfragprog.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "fxdrv.h"
+
+
+GLboolean fxMultipass_ColorSum (GLcontext *ctx, GLuint pass);
+
+
+/*
+ * Subpixel offsets to adjust Mesa's (true) window coordinates to
+ * Glide coordinates. We need these to ensure precise rasterization.
+ * Otherwise, we'll fail a bunch of conformance tests.
+ */
+#define TRI_X_OFFSET ( 0.0F)
+#define TRI_Y_OFFSET ( 0.0F)
+#define LINE_X_OFFSET ( 0.0F)
+#define LINE_Y_OFFSET ( 0.125F)
+#define PNT_X_OFFSET ( 0.375F)
+#define PNT_Y_OFFSET ( 0.375F)
+
+static void fxRasterPrimitive( GLcontext *ctx, GLenum prim );
+static void fxRenderPrimitive( GLcontext *ctx, GLenum prim );
+
+static const GLenum reduced_prim[GL_POLYGON+1] = {
+ GL_POINTS,
+ GL_LINES,
+ GL_LINES,
+ GL_LINES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES,
+ GL_TRIANGLES
+};
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define TRI( a, b, c ) \
+do { \
+ if (DO_FALLBACK) \
+ fxMesa->draw_tri( fxMesa, a, b, c ); \
+ else \
+ grDrawTriangle( a, b, c ); \
+} while (0) \
+
+#define QUAD( a, b, c, d ) \
+do { \
+ if (DO_FALLBACK) { \
+ fxMesa->draw_tri( fxMesa, a, b, d ); \
+ fxMesa->draw_tri( fxMesa, b, c, d ); \
+ } else { \
+ GrVertex *_v_[4]; \
+ _v_[0] = d; \
+ _v_[1] = a; \
+ _v_[2] = b; \
+ _v_[3] = c; \
+ grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
+ /*grDrawTriangle( a, b, d );*/ \
+ /*grDrawTriangle( b, c, d );*/ \
+ } \
+} while (0)
+
+#define LINE( v0, v1 ) \
+do { \
+ if (DO_FALLBACK) \
+ fxMesa->draw_line( fxMesa, v0, v1 ); \
+ else { \
+ v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
+ v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
+ v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
+ v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
+ grDrawLine( v0, v1 ); \
+ v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
+ v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
+ v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
+ v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
+ } \
+} while (0)
+
+#define POINT( v0 ) \
+do { \
+ if (DO_FALLBACK) \
+ fxMesa->draw_point( fxMesa, v0 ); \
+ else { \
+ v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
+ v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
+ grDrawPoint( v0 ); \
+ v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
+ v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
+ } \
+} while (0)
+
+
+/***********************************************************************
+ * Fallback to swrast for basic primitives *
+ ***********************************************************************/
+
+/* Build an SWvertex from a hardware vertex.
+ *
+ * This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+static void
+fx_translate_vertex( GLcontext *ctx, const GrVertex *src, SWvertex *dst)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint ts0 = fxMesa->tmu_source[0];
+ GLuint ts1 = fxMesa->tmu_source[1];
+ GLfloat w = 1.0F / src->oow;
+
+ dst->win[0] = src->x;
+ dst->win[1] = src->y;
+ dst->win[2] = src->ooz;
+ dst->win[3] = src->oow;
+
+#if FX_PACKEDCOLOR
+ dst->color[0] = src->pargb[2];
+ dst->color[1] = src->pargb[1];
+ dst->color[2] = src->pargb[0];
+ dst->color[3] = src->pargb[3];
+
+ dst->specular[0] = src->pspec[2];
+ dst->specular[1] = src->pspec[1];
+ dst->specular[2] = src->pspec[0];
+#else /* !FX_PACKEDCOLOR */
+ dst->color[0] = src->r;
+ dst->color[1] = src->g;
+ dst->color[2] = src->b;
+ dst->color[3] = src->a;
+
+ dst->specular[0] = src->r1;
+ dst->specular[1] = src->g1;
+ dst->specular[2] = src->g1;
+#endif /* !FX_PACKEDCOLOR */
+
+ dst->texcoord[ts0][0] = fxMesa->inv_s0scale * src->tmuvtx[0].sow * w;
+ dst->texcoord[ts0][1] = fxMesa->inv_t0scale * src->tmuvtx[0].tow * w;
+
+ if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU0)
+ dst->texcoord[ts0][3] = src->tmuvtx[0].oow * w;
+ else
+ dst->texcoord[ts0][3] = 1.0F;
+
+ if (fxMesa->SetupIndex & SETUP_TMU1) {
+ dst->texcoord[ts1][0] = fxMesa->inv_s1scale * src->tmuvtx[1].sow * w;
+ dst->texcoord[ts1][1] = fxMesa->inv_t1scale * src->tmuvtx[1].tow * w;
+
+ if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU1)
+ dst->texcoord[ts1][3] = src->tmuvtx[1].oow * w;
+ else
+ dst->texcoord[ts1][3] = 1.0F;
+ }
+
+ dst->pointSize = src->psize;
+}
+
+
+static void
+fx_fallback_tri( fxMesaContext fxMesa,
+ GrVertex *v0,
+ GrVertex *v1,
+ GrVertex *v2 )
+{
+ GLcontext *ctx = fxMesa->glCtx;
+ SWvertex v[3];
+
+ fx_translate_vertex( ctx, v0, &v[0] );
+ fx_translate_vertex( ctx, v1, &v[1] );
+ fx_translate_vertex( ctx, v2, &v[2] );
+ _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+}
+
+
+static void
+fx_fallback_line( fxMesaContext fxMesa,
+ GrVertex *v0,
+ GrVertex *v1 )
+{
+ GLcontext *ctx = fxMesa->glCtx;
+ SWvertex v[2];
+ fx_translate_vertex( ctx, v0, &v[0] );
+ fx_translate_vertex( ctx, v1, &v[1] );
+ _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+
+static void
+fx_fallback_point( fxMesaContext fxMesa,
+ GrVertex *v0 )
+{
+ GLcontext *ctx = fxMesa->glCtx;
+ SWvertex v[1];
+ fx_translate_vertex( ctx, v0, &v[0] );
+ _swrast_Point( ctx, &v[0] );
+}
+
+/***********************************************************************
+ * Functions to draw basic primitives *
+ ***********************************************************************/
+#if 0 /**/
+static void fx_print_vertex( GLcontext *ctx, const GrVertex *v )
+{
+ fprintf(stderr, "fx_print_vertex:\n");
+
+ fprintf(stderr, "\tvertex at %p\n", (void *) v);
+
+ fprintf(stderr, "\tx %f y %f z %f oow %f\n", v->x, v->y, v->ooz, v->oow);
+#if FX_PACKEDCOLOR
+ fprintf(stderr, "\tr %d g %d b %d a %d\n", v->pargb[2], v->pargb[1], v->pargb[0], v->pargb[3]);
+#else /* !FX_PACKEDCOLOR */
+ fprintf(stderr, "\tr %f g %f b %f a %f\n", v->r, v->g, v->b, v->a);
+#endif /* !FX_PACKEDCOLOR */
+
+ fprintf(stderr, "\n");
+}
+#endif /**/
+
+#define DO_FALLBACK 0
+
+/* Need to do clip loop at each triangle when mixing swrast and hw
+ * rendering. These functions are only used when mixed-mode rendering
+ * is occurring.
+ */
+static void fx_draw_triangle( fxMesaContext fxMesa,
+ GrVertex *v0,
+ GrVertex *v1,
+ GrVertex *v2 )
+{
+ BEGIN_CLIP_LOOP();
+ TRI( v0, v1, v2 );
+ END_CLIP_LOOP();
+}
+
+static void fx_draw_line( fxMesaContext fxMesa,
+ GrVertex *v0,
+ GrVertex *v1 )
+{
+ /* No support for wide lines (avoid wide/aa line fallback).
+ */
+ BEGIN_CLIP_LOOP();
+ LINE(v0, v1);
+ END_CLIP_LOOP();
+}
+
+static void fx_draw_point( fxMesaContext fxMesa,
+ GrVertex *v0 )
+{
+ /* No support for wide points.
+ */
+ BEGIN_CLIP_LOOP();
+ POINT( v0 );
+ END_CLIP_LOOP();
+}
+
+#ifndef M_2PI
+#define M_2PI 6.28318530717958647692528676655901
+#endif
+#define __GL_COSF cos
+#define __GL_SINF sin
+static void fx_draw_point_sprite ( fxMesaContext fxMesa,
+ GrVertex *v0, GLfloat psize )
+{
+ const GLcontext *ctx = fxMesa->glCtx;
+
+ GLfloat radius;
+ GrVertex _v_[4];
+ GLuint ts0 = fxMesa->tmu_source[0];
+ GLuint ts1 = fxMesa->tmu_source[1];
+ GLfloat w = v0->oow;
+ GLfloat u0scale = fxMesa->s0scale * w;
+ GLfloat v0scale = fxMesa->t0scale * w;
+ GLfloat u1scale = fxMesa->s1scale * w;
+ GLfloat v1scale = fxMesa->t1scale * w;
+
+ radius = psize / 2.0F;
+ _v_[0] = *v0;
+ _v_[1] = *v0;
+ _v_[2] = *v0;
+ _v_[3] = *v0;
+ /* CLIP_LOOP ?!? */
+ /* point coverage? */
+ /* we don't care about culling here (see fxSetupCull) */
+
+ if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) {
+ _v_[0].x -= radius;
+ _v_[0].y += radius;
+ _v_[1].x += radius;
+ _v_[1].y += radius;
+ _v_[2].x += radius;
+ _v_[2].y -= radius;
+ _v_[3].x -= radius;
+ _v_[3].y -= radius;
+ } else {
+ _v_[0].x -= radius;
+ _v_[0].y -= radius;
+ _v_[1].x += radius;
+ _v_[1].y -= radius;
+ _v_[2].x += radius;
+ _v_[2].y += radius;
+ _v_[3].x -= radius;
+ _v_[3].y += radius;
+ }
+
+ if (ctx->Point.CoordReplace[ts0]) {
+ _v_[0].tmuvtx[0].sow = 0;
+ _v_[0].tmuvtx[0].tow = 0;
+ _v_[1].tmuvtx[0].sow = u0scale;
+ _v_[1].tmuvtx[0].tow = 0;
+ _v_[2].tmuvtx[0].sow = u0scale;
+ _v_[2].tmuvtx[0].tow = v0scale;
+ _v_[3].tmuvtx[0].sow = 0;
+ _v_[3].tmuvtx[0].tow = v0scale;
+ }
+ if (ctx->Point.CoordReplace[ts1]) {
+ _v_[0].tmuvtx[1].sow = 0;
+ _v_[0].tmuvtx[1].tow = 0;
+ _v_[1].tmuvtx[1].sow = u1scale;
+ _v_[1].tmuvtx[1].tow = 0;
+ _v_[2].tmuvtx[1].sow = u1scale;
+ _v_[2].tmuvtx[1].tow = v1scale;
+ _v_[3].tmuvtx[1].sow = 0;
+ _v_[3].tmuvtx[1].tow = v1scale;
+ }
+
+ grDrawVertexArrayContiguous(GR_TRIANGLE_FAN, 4, _v_, sizeof(GrVertex));
+}
+
+static void fx_draw_point_wide ( fxMesaContext fxMesa,
+ GrVertex *v0 )
+{
+ GLint i, n;
+ GLfloat ang, radius, oon;
+ GrVertex vtxB, vtxC;
+ GrVertex *_v_[3];
+
+ const GLcontext *ctx = fxMesa->glCtx;
+ const GLfloat psize = (ctx->_TriangleCaps & DD_POINT_ATTEN)
+ ? CLAMP(v0->psize, ctx->Point.MinSize, ctx->Point.MaxSize)
+ : ctx->Point._Size; /* clamped */
+
+ if (ctx->Point.PointSprite) {
+ fx_draw_point_sprite(fxMesa, v0, psize);
+ return;
+ }
+
+ _v_[0] = v0;
+ _v_[1] = &vtxB;
+ _v_[2] = &vtxC;
+
+ radius = psize / 2.0F;
+ n = IROUND(psize * 2); /* radius x 4 */
+ if (n < 4) n = 4;
+ oon = 1.0F / (GLfloat)n;
+
+ /* CLIP_LOOP ?!? */
+ /* point coverage? */
+ /* we don't care about culling here (see fxSetupCull) */
+
+ vtxB = *v0;
+ vtxC = *v0;
+
+ vtxB.x += radius;
+ ang = M_2PI * oon;
+ vtxC.x += radius * __GL_COSF(ang);
+ vtxC.y += radius * __GL_SINF(ang);
+ grDrawVertexArray(GR_TRIANGLE_FAN, 3, _v_);
+ for (i = 2; i <= n; i++) {
+ ang = M_2PI * i * oon;
+ vtxC.x = v0->x + radius * __GL_COSF(ang);
+ vtxC.y = v0->y + radius * __GL_SINF(ang);
+ grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE, 1, &_v_[2]);
+ }
+}
+
+static void fx_render_pw_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ (void) flags;
+
+ fxRenderPrimitive( ctx, GL_POINTS );
+
+ for ( ; start < count ; start++)
+ fx_draw_point_wide(fxMesa, fxVB + start);
+}
+
+static void fx_render_pw_elts ( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
+ (void) flags;
+
+ fxRenderPrimitive( ctx, GL_POINTS );
+
+ for ( ; start < count ; start++)
+ fx_draw_point_wide(fxMesa, fxVB + elt[start]);
+}
+
+static void fx_draw_point_wide_aa ( fxMesaContext fxMesa,
+ GrVertex *v0 )
+{
+ GLint i, n;
+ GLfloat ang, radius, oon;
+ GrVertex vtxB, vtxC;
+
+ const GLcontext *ctx = fxMesa->glCtx;
+ const GLfloat psize = (ctx->_TriangleCaps & DD_POINT_ATTEN)
+ ? CLAMP(v0->psize, ctx->Point.MinSize, ctx->Point.MaxSize)
+ : ctx->Point._Size; /* clamped */
+
+ if (ctx->Point.PointSprite) {
+ fx_draw_point_sprite(fxMesa, v0, psize);
+ return;
+ }
+
+ radius = psize / 2.0F;
+ n = IROUND(psize * 2); /* radius x 4 */
+ if (n < 4) n = 4;
+ oon = 1.0F / (GLfloat)n;
+
+ /* CLIP_LOOP ?!? */
+ /* point coverage? */
+ /* we don't care about culling here (see fxSetupCull) */
+
+ vtxB = *v0;
+ vtxC = *v0;
+
+ vtxB.x += radius;
+ for (i = 1; i <= n; i++) {
+ ang = M_2PI * i * oon;
+ vtxC.x = v0->x + radius * __GL_COSF(ang);
+ vtxC.y = v0->y + radius * __GL_SINF(ang);
+ grAADrawTriangle( v0, &vtxB, &vtxC, FXFALSE, FXTRUE, FXFALSE);
+ /*grDrawTriangle( v0, &vtxB, &vtxC);*/
+ vtxB.x = vtxC.x;
+ vtxB.y = vtxC.y;
+ }
+}
+#undef __GLCOSF
+#undef __GLSINF
+#undef M_2PI
+
+#undef DO_FALLBACK
+
+
+#define FX_UNFILLED_BIT 0x1
+#define FX_OFFSET_BIT 0x2
+#define FX_TWOSIDE_BIT 0x4
+#define FX_FLAT_BIT 0x8
+#define FX_FALLBACK_BIT 0x10
+#define FX_MAX_TRIFUNC 0x20
+
+static struct {
+ tnl_points_func points;
+ tnl_line_func line;
+ tnl_triangle_func triangle;
+ tnl_quad_func quad;
+} rast_tab[FX_MAX_TRIFUNC];
+
+#define DO_FALLBACK (IND & FX_FALLBACK_BIT)
+#define DO_OFFSET (IND & FX_OFFSET_BIT)
+#define DO_UNFILLED (IND & FX_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
+#define DO_FLAT (IND & FX_FLAT_BIT)
+#define DO_TRI 1
+#define DO_QUAD 1
+#define DO_LINE 1
+#define DO_POINTS 1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA 1
+#define HAVE_SPEC 1
+#define HAVE_HW_FLATSHADE 0
+#define HAVE_BACK_COLORS 0
+#define VERTEX GrVertex
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->x
+#define VERT_Y(_v) _v->y
+#define VERT_Z(_v) _v->ooz
+#define GET_VERTEX(e) (fxMesa->verts + e)
+
+#ifdef USE_IEEE
+#define AREA_IS_CCW( a ) (((fi_type *)&(a))->i < 0)
+#else
+#define AREA_IS_CCW( a ) (a < 0)
+#endif
+
+
+#if FX_PACKEDCOLOR
+#define VERT_SET_RGBA( dst, f ) \
+do { \
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
+} while (0)
+
+#define VERT_COPY_RGBA( v0, v1 ) \
+ *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
+
+#define VERT_SAVE_RGBA( idx ) \
+ *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
+
+#define VERT_RESTORE_RGBA( idx ) \
+ *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
+
+
+#define VERT_SET_SPEC( dst, f ) \
+do { \
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
+ UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
+} while (0)
+
+#define VERT_COPY_SPEC( v0, v1 ) \
+ *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
+
+#define VERT_SAVE_SPEC( idx ) \
+ *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
+
+#define VERT_RESTORE_SPEC( idx ) \
+ *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
+
+
+#define LOCAL_VARS(n) \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GLubyte color[n][4], spec[n][4]; \
+ (void) color; (void) spec;
+#else /* !FX_PACKEDCOLOR */
+#define VERT_SET_RGBA( dst, f ) \
+do { \
+ CNORM(dst->r, f[0]); \
+ CNORM(dst->g, f[1]); \
+ CNORM(dst->b, f[2]); \
+ CNORM(dst->a, f[3]); \
+} while (0)
+
+#define VERT_COPY_RGBA( v0, v1 ) \
+do { \
+ *(GLuint *)&v0->r = *(GLuint *)&v1->r; \
+ *(GLuint *)&v0->g = *(GLuint *)&v1->g; \
+ *(GLuint *)&v0->b = *(GLuint *)&v1->b; \
+ *(GLuint *)&v0->a = *(GLuint *)&v1->a; \
+} while (0)
+
+#define VERT_SAVE_RGBA( idx ) \
+do { \
+ *(GLuint *)&color[idx][0] = *(GLuint *)&v[idx]->r;\
+ *(GLuint *)&color[idx][1] = *(GLuint *)&v[idx]->g;\
+ *(GLuint *)&color[idx][2] = *(GLuint *)&v[idx]->b;\
+ *(GLuint *)&color[idx][3] = *(GLuint *)&v[idx]->a;\
+} while (0)
+
+#define VERT_RESTORE_RGBA( idx ) \
+do { \
+ *(GLuint *)&v[idx]->r = *(GLuint *)&color[idx][0];\
+ *(GLuint *)&v[idx]->g = *(GLuint *)&color[idx][1];\
+ *(GLuint *)&v[idx]->b = *(GLuint *)&color[idx][2];\
+ *(GLuint *)&v[idx]->a = *(GLuint *)&color[idx][3];\
+} while (0)
+
+
+#define VERT_SET_SPEC( dst, f ) \
+do { \
+ CNORM(dst->r1, f[0]); \
+ CNORM(dst->g1, f[1]); \
+ CNORM(dst->b1, f[2]); \
+} while (0)
+
+#define VERT_COPY_SPEC( v0, v1 ) \
+do { \
+ *(GLuint *)&v0->r1 = *(GLuint *)&v1->r1; \
+ *(GLuint *)&v0->g1 = *(GLuint *)&v1->g1; \
+ *(GLuint *)&v0->b1 = *(GLuint *)&v1->b1; \
+} while (0)
+
+#define VERT_SAVE_SPEC( idx ) \
+do { \
+ *(GLuint *)&spec[idx][0] = *(GLuint *)&v[idx]->r1;\
+ *(GLuint *)&spec[idx][1] = *(GLuint *)&v[idx]->g1;\
+ *(GLuint *)&spec[idx][2] = *(GLuint *)&v[idx]->b1;\
+} while (0)
+
+#define VERT_RESTORE_SPEC( idx ) \
+do { \
+ *(GLuint *)&v[idx]->r1 = *(GLuint *)&spec[idx][0];\
+ *(GLuint *)&v[idx]->g1 = *(GLuint *)&spec[idx][1];\
+ *(GLuint *)&v[idx]->b1 = *(GLuint *)&spec[idx][2];\
+} while (0)
+
+
+#define LOCAL_VARS(n) \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GLuint color[n][4], spec[n][4]; \
+ (void) color; (void) spec;
+#endif /* !FX_PACKEDCOLOR */
+
+
+
+/***********************************************************************
+ * Functions to draw basic unfilled primitives *
+ ***********************************************************************/
+
+#define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
+ fxRasterPrimitive( ctx, reduced_prim[x] )
+#define RENDER_PRIMITIVE fxMesa->render_primitive
+#define IND FX_FALLBACK_BIT
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+/***********************************************************************
+ * Functions to draw GL primitives *
+ ***********************************************************************/
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
+ FX_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+/* Fx doesn't support provoking-vertex flat-shading?
+ */
+#define IND (FX_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_offset_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_offset_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_offset_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_offset_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
+ FX_FALLBACK_BIT|FX_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_rast_tab( void )
+{
+ init();
+ init_offset();
+ init_twoside();
+ init_twoside_offset();
+ init_unfilled();
+ init_offset_unfilled();
+ init_twoside_unfilled();
+ init_twoside_offset_unfilled();
+ init_fallback();
+ init_offset_fallback();
+ init_twoside_fallback();
+ init_twoside_offset_fallback();
+ init_unfilled_fallback();
+ init_offset_unfilled_fallback();
+ init_twoside_unfilled_fallback();
+ init_twoside_offset_unfilled_fallback();
+
+ init_flat();
+ init_offset_flat();
+ init_twoside_flat();
+ init_twoside_offset_flat();
+ init_unfilled_flat();
+ init_offset_unfilled_flat();
+ init_twoside_unfilled_flat();
+ init_twoside_offset_unfilled_flat();
+ init_fallback_flat();
+ init_offset_fallback_flat();
+ init_twoside_fallback_flat();
+ init_twoside_offset_fallback_flat();
+ init_unfilled_fallback_flat();
+ init_offset_unfilled_fallback_flat();
+ init_twoside_unfilled_fallback_flat();
+ init_twoside_offset_unfilled_fallback_flat();
+}
+
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+
+/* Accelerate vertex buffer rendering when renderindex == 0 and
+ * there is no clipping.
+ */
+#define INIT(x) fxRenderPrimitive( ctx, x )
+
+static void fx_render_vb_points( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLint i;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_points\n");
+ }
+
+ INIT(GL_POINTS);
+
+ /* Adjust point coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x += PNT_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y += PNT_Y_OFFSET - TRI_Y_OFFSET;
+ }
+
+ grDrawVertexArrayContiguous( GR_POINTS, count-start,
+ fxVB + start, sizeof(GrVertex));
+ /* restore point coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x -= PNT_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y -= PNT_Y_OFFSET - TRI_Y_OFFSET;
+ }
+}
+
+static void fx_render_vb_line_strip( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLint i;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_line_strip\n");
+ }
+
+ INIT(GL_LINE_STRIP);
+
+ /* adjust line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+
+ grDrawVertexArrayContiguous( GR_LINE_STRIP, count-start,
+ fxVB + start, sizeof(GrVertex));
+
+ /* restore line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+}
+
+static void fx_render_vb_line_loop( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLint i;
+ GLint j = start;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_line_loop\n");
+ }
+
+ INIT(GL_LINE_LOOP);
+
+ if (!(flags & PRIM_BEGIN)) {
+ j++;
+ }
+
+ /* adjust line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+
+ grDrawVertexArrayContiguous( GR_LINE_STRIP, count-j,
+ fxVB + j, sizeof(GrVertex));
+
+ if (flags & PRIM_END)
+ grDrawLine( fxVB + (count - 1),
+ fxVB + start );
+
+ /* restore line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+}
+
+static void fx_render_vb_lines( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLint i;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_lines\n");
+ }
+
+ INIT(GL_LINES);
+
+ /* adjust line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+
+ grDrawVertexArrayContiguous( GR_LINES, count-start,
+ fxVB + start, sizeof(GrVertex));
+
+ /* restore line coords */
+ for (i = start; i < count; i++) {
+ fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
+ fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
+ }
+}
+
+static void fx_render_vb_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLuint j;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_triangles\n");
+ }
+
+ INIT(GL_TRIANGLES);
+
+ for (j=start+2; j<count; j+=3) {
+ grDrawTriangle(fxVB + (j-2), fxVB + (j-1), fxVB + j);
+ }
+}
+
+
+static void fx_render_vb_tri_strip( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_tri_strip\n");
+ }
+
+ INIT(GL_TRIANGLE_STRIP);
+
+ /* no GR_TRIANGLE_STRIP_CONTINUE?!? */
+
+ grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP, count-start,
+ fxVB + start, sizeof(GrVertex));
+}
+
+
+static void fx_render_vb_tri_fan( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_tri_fan\n");
+ }
+
+ INIT(GL_TRIANGLE_FAN);
+
+ grDrawVertexArrayContiguous( GR_TRIANGLE_FAN, count-start,
+ fxVB + start, sizeof(GrVertex) );
+}
+
+static void fx_render_vb_quads( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ GLuint i;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_quads\n");
+ }
+
+ INIT(GL_QUADS);
+
+ for (i = start + 3 ; i < count ; i += 4 ) {
+#define VERT(x) (fxVB + (x))
+ GrVertex *_v_[4];
+ _v_[0] = VERT(i);
+ _v_[1] = VERT(i-3);
+ _v_[2] = VERT(i-2);
+ _v_[3] = VERT(i-1);
+ grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);
+ /*grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
+ /*grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
+#undef VERT
+ }
+}
+
+static void fx_render_vb_quad_strip( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_quad_strip\n");
+ }
+
+ INIT(GL_QUAD_STRIP);
+
+ count -= (count-start)&1;
+
+ grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP,
+ count-start, fxVB + start, sizeof(GrVertex));
+}
+
+static void fx_render_vb_poly( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GrVertex *fxVB = fxMesa->verts;
+ (void) flags;
+
+ if (TDFX_DEBUG & VERBOSE_VARRAY) {
+ fprintf(stderr, "fx_render_vb_poly\n");
+ }
+
+ INIT(GL_POLYGON);
+
+ grDrawVertexArrayContiguous( GR_POLYGON, count-start,
+ fxVB + start, sizeof(GrVertex));
+}
+
+static void fx_render_vb_noop( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ (void) (ctx && start && count && flags);
+}
+
+static void (*fx_render_tab_verts[GL_POLYGON+2])(GLcontext *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ fx_render_vb_points,
+ fx_render_vb_lines,
+ fx_render_vb_line_loop,
+ fx_render_vb_line_strip,
+ fx_render_vb_triangles,
+ fx_render_vb_tri_strip,
+ fx_render_vb_tri_fan,
+ fx_render_vb_quads,
+ fx_render_vb_quad_strip,
+ fx_render_vb_poly,
+ fx_render_vb_noop,
+};
+#undef INIT
+
+
+/**********************************************************************/
+/* Render whole (indexed) begin/end objects */
+/**********************************************************************/
+
+
+#define VERT(x) (vertptr + x)
+
+#define RENDER_POINTS( start, count ) \
+ for ( ; start < count ; start++) \
+ grDrawPoint( VERT(ELT(start)) );
+
+#define RENDER_LINE( v0, v1 ) \
+ grDrawLine( VERT(v0), VERT(v1) )
+
+#define RENDER_TRI( v0, v1, v2 ) \
+ grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
+
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ do { \
+ GrVertex *_v_[4]; \
+ _v_[0] = VERT(v3);\
+ _v_[1] = VERT(v0);\
+ _v_[2] = VERT(v1);\
+ _v_[3] = VERT(v2);\
+ grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
+ /*grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
+ /*grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
+ } while (0)
+
+#define INIT(x) fxRenderPrimitive( ctx, x )
+
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ fxMesaContext fxMesa = FX_CONTEXT(ctx); \
+ GrVertex *vertptr = fxMesa->verts; \
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
+ (void) elt;
+
+#define RESET_STIPPLE
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#undef TAG
+#define TAG(x) fx_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl_dd/t_dd_rendertmp.h"
+
+/* Verts, no clipping.
+ */
+#undef ELT
+#undef TAG
+#define TAG(x) fx_##x##_verts
+#define ELT(x) x
+/*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
+
+
+
+/**********************************************************************/
+/* Render clipped primitives */
+/**********************************************************************/
+
+
+
+static void fxRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint prim = fxMesa->render_primitive;
+
+ /* Render the new vertices as an unclipped polygon.
+ */
+ {
+ GLuint *tmp = VB->Elts;
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
+ PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+ }
+
+ /* Restore the render primitive
+ */
+ if (prim != GL_POLYGON)
+ tnl->Driver.Render.PrimitiveNotify( ctx, prim );
+}
+
+
+static void fxFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ int i;
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ GrVertex *vertptr = fxMesa->verts;
+ if (n == 3) {
+ grDrawTriangle( VERT(elts[0]), VERT(elts[1]), VERT(elts[2]) );
+ } else if (n <= 32) {
+ GrVertex *newvptr[32];
+ for (i = 0 ; i < n ; i++) {
+ newvptr[i] = VERT(elts[i]);
+ }
+ grDrawVertexArray(GR_TRIANGLE_FAN, n, newvptr);
+ } else {
+ const GrVertex *start = VERT(elts[0]);
+ for (i = 2 ; i < n ; i++) {
+ grDrawTriangle( start, VERT(elts[i-1]), VERT(elts[i]) );
+ }
+ }
+}
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+
+#define POINT_FALLBACK (DD_POINT_SMOOTH)
+#define LINE_FALLBACK (DD_LINE_STIPPLE)
+#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
+ | DD_TRI_UNFILLED)
+
+
+
+void fxDDChooseRenderState(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint index = 0;
+
+ if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
+ if (flags & ANY_RASTER_FLAGS) {
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= FX_TWOSIDE_BIT;
+ if (flags & DD_TRI_OFFSET) index |= FX_OFFSET_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= FX_UNFILLED_BIT;
+ if (flags & DD_FLATSHADE) index |= FX_FLAT_BIT;
+ }
+
+ fxMesa->draw_point = fx_draw_point;
+ fxMesa->draw_line = fx_draw_line;
+ fxMesa->draw_tri = fx_draw_triangle;
+
+ /* Hook in fallbacks for specific primitives. */
+ if (flags & (POINT_FALLBACK|
+ LINE_FALLBACK|
+ TRI_FALLBACK))
+ {
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Voodoo ! fallback (%x), raster (%x)\n",
+ flags & ANY_FALLBACK_FLAGS, flags & ANY_RASTER_FLAGS);
+ }
+
+ if (flags & POINT_FALLBACK)
+ fxMesa->draw_point = fx_fallback_point;
+
+ if (flags & LINE_FALLBACK)
+ fxMesa->draw_line = fx_fallback_line;
+
+ if (flags & TRI_FALLBACK)
+ fxMesa->draw_tri = fx_fallback_tri;
+
+ index |= FX_FALLBACK_BIT;
+ }
+ }
+
+ tnl->Driver.Render.Points = rast_tab[index].points;
+ tnl->Driver.Render.Line = rast_tab[index].line;
+ tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+ tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+ tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+ if (index == 0) {
+ tnl->Driver.Render.PrimTabVerts = fx_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = fx_render_tab_elts;
+ tnl->Driver.Render.ClippedPolygon = fxFastRenderClippedPoly;
+ } else {
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedPolygon = fxRenderClippedPoly;
+ }
+
+ fxMesa->render_index = index;
+
+ /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
+ if (flags & (DD_POINT_SIZE | DD_POINT_ATTEN)) {
+ /* We need to set the point primitive to go through "rast_tab",
+ * to make sure "POINT" calls "fxMesa->draw_point" instead of
+ * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
+ * (not really a total rasterization fallback, so we don't alter
+ * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
+ * we're done, cos we've already set _tnl_render_tab_{verts|elts}
+ * above. Otherwise, the T&L engine can optimize point rendering
+ * by using fx_render_tab_{verts|elts} hence the extra work.
+ */
+ if (flags & DD_POINT_SMOOTH) {
+ fxMesa->draw_point = fx_draw_point_wide_aa;
+ } else {
+ fxMesa->draw_point = fx_draw_point_wide;
+ fx_render_tab_verts[0] = fx_render_pw_verts;
+ fx_render_tab_elts[0] = fx_render_pw_elts;
+ }
+ tnl->Driver.Render.Points = rast_tab[index|FX_FALLBACK_BIT].points;
+ } else {
+ fx_render_tab_verts[0] = fx_render_vb_points;
+ fx_render_tab_elts[0] = fx_render_points_elts;
+ }
+}
+
+
+/**********************************************************************/
+/* Runtime render state and callbacks */
+/**********************************************************************/
+
+static void fxRunPipeline( GLcontext *ctx )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint new_gl_state = fxMesa->new_gl_state;
+
+ if (TDFX_DEBUG & VERBOSE_PIPELINE) {
+ fprintf(stderr, "fxRunPipeline()\n");
+ }
+
+#if 0
+ /* Recalculate fog table on projection matrix changes. This used to
+ * be triggered by the NearFar callback.
+ */
+ if (new_gl_state & _NEW_PROJECTION)
+ fxMesa->new_state |= FX_NEW_FOG;
+#endif
+
+ if (new_gl_state & _FX_NEW_IS_IN_HARDWARE)
+ fxCheckIsInHardware(ctx);
+
+ if (fxMesa->new_state)
+ fxSetupFXUnits(ctx);
+
+ if (!fxMesa->fallback) {
+ if (new_gl_state & _FX_NEW_RENDERSTATE)
+ fxDDChooseRenderState(ctx);
+
+ if (new_gl_state & _FX_NEW_SETUP_FUNCTION)
+ fxChooseVertexState(ctx);
+ }
+
+ if (new_gl_state & _NEW_TEXTURE) {
+ struct gl_texture_unit *t0 = &ctx->Texture.Unit[fxMesa->tmu_source[0]];
+ struct gl_texture_unit *t1 = &ctx->Texture.Unit[fxMesa->tmu_source[1]];
+
+ if (t0->_Current && FX_TEXTURE_DATA(t0)) {
+ fxMesa->s0scale = FX_TEXTURE_DATA(t0)->sScale;
+ fxMesa->t0scale = FX_TEXTURE_DATA(t0)->tScale;
+ fxMesa->inv_s0scale = 1.0F / fxMesa->s0scale;
+ fxMesa->inv_t0scale = 1.0F / fxMesa->t0scale;
+ }
+
+ if (t1->_Current && FX_TEXTURE_DATA(t1)) {
+ fxMesa->s1scale = FX_TEXTURE_DATA(t1)->sScale;
+ fxMesa->t1scale = FX_TEXTURE_DATA(t1)->tScale;
+ fxMesa->inv_s1scale = 1.0F / fxMesa->s1scale;
+ fxMesa->inv_t1scale = 1.0F / fxMesa->t1scale;
+ }
+ }
+
+ fxMesa->new_gl_state = 0;
+
+ _tnl_run_pipeline( ctx );
+}
+
+
+
+/* Always called between RenderStart and RenderFinish --> We already
+ * hold the lock.
+ */
+static void fxRasterPrimitive( GLcontext *ctx, GLenum prim )
+{
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+
+ fxMesa->raster_primitive = prim;
+
+ fxSetupCull(ctx);
+}
+
+
+
+/* Determine the rasterized primitive when not drawing unfilled
+ * polygons.
+ */
+static void fxRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint rprim = reduced_prim[prim];
+
+ fxMesa->render_primitive = prim;
+
+ if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ return;
+
+ if (fxMesa->raster_primitive != rprim) {
+ fxRasterPrimitive( ctx, rprim );
+ }
+}
+
+static void fxRenderFinish( GLcontext *ctx )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ if (fxMesa->render_index & FX_FALLBACK_BIT)
+ _swrast_flush( ctx );
+}
+
+
+
+/**********************************************************************/
+/* Manage total rasterization fallbacks */
+/**********************************************************************/
+
+static const char *fallbackStrings[] = {
+ "3D/Rect/Cube Texture map",
+ "glDrawBuffer(GL_FRONT_AND_BACK)",
+ "Separate specular color",
+ "glEnable/Disable(GL_STENCIL_TEST)",
+ "glRenderMode(selection or feedback)",
+ "glLogicOp()",
+ "Texture env mode",
+ "Texture border",
+ "glColorMask",
+ "blend mode",
+ "multitex"
+};
+
+
+static const char *getFallbackString(GLuint bit)
+{
+ int i = 0;
+ while (bit > 1) {
+ i++;
+ bit >>= 1;
+ }
+ return fallbackStrings[i];
+}
+
+
+void fxCheckIsInHardware( GLcontext *ctx )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint oldfallback = fxMesa->fallback;
+ GLuint newfallback = fxMesa->fallback = fx_check_IsInHardware( ctx );
+
+ if (newfallback) {
+ if (oldfallback == 0) {
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Voodoo ! enter SW 0x%08x %s\n", newfallback, getFallbackString(newfallback));
+ }
+ _swsetup_Wakeup( ctx );
+ }
+ }
+ else {
+ if (oldfallback) {
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = fxCheckTexSizes;
+ tnl->Driver.Render.Finish = fxRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = fxBuildVertices;
+ fxChooseVertexState(ctx);
+ fxDDChooseRenderState(ctx);
+ if (fxMesa->verbose) {
+ fprintf(stderr, "Voodoo ! leave SW 0x%08x %s\n", oldfallback, getFallbackString(oldfallback));
+ }
+ }
+ tnl->Driver.Render.Multipass = (HAVE_SPEC && NEED_SECONDARY_COLOR(ctx)) ? fxMultipass_ColorSum : NULL;
+ }
+}
+
+void fxDDInitTriFuncs( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_rast_tab();
+ firsttime = 0;
+ }
+
+ tnl->Driver.RunPipeline = fxRunPipeline;
+ tnl->Driver.Render.Start = fxCheckTexSizes;
+ tnl->Driver.Render.Finish = fxRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = fxBuildVertices;
+ tnl->Driver.Render.Multipass = NULL;
+#if 0 /**/
+ (void) fx_print_vertex;
+#endif /**/
+}
+
+
+/* [dBorca] Hack alert:
+ * doesn't work with blending.
+ * XXX todo - need to take care of stencil.
+ */
+GLboolean fxMultipass_ColorSum (GLcontext *ctx, GLuint pass)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ static int t0 = 0;
+ static int t1 = 0;
+
+ switch (pass) {
+ case 1: /* first pass: the TEXTURED triangles are drawn */
+ /* save per-pass data */
+ fxMesa->restoreUnitsState = fxMesa->unitsState;
+ /* turn off texturing */
+ t0 = ctx->Texture.Unit[0]._ReallyEnabled;
+ t1 = ctx->Texture.Unit[1]._ReallyEnabled;
+ ctx->Texture.Unit[0]._ReallyEnabled = 0;
+ ctx->Texture.Unit[1]._ReallyEnabled = 0;
+ /* SUM the colors */
+ fxDDBlendEquationSeparate(ctx, GL_FUNC_ADD, GL_FUNC_ADD);
+ fxDDBlendFuncSeparate(ctx, GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
+ fxDDEnable(ctx, GL_BLEND, GL_TRUE);
+ /* make sure we draw only where we want to */
+ if (ctx->Depth.Mask) {
+ switch (ctx->Depth.Func) {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ break;
+ default:
+ fxDDDepthFunc( ctx, GL_EQUAL );
+ break;
+ }
+ fxDDDepthMask( ctx, GL_FALSE );
+ }
+ /* switch to secondary colors */
+#if FX_PACKEDCOLOR
+ grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PSPEC_OFFSET << 2, GR_PARAM_ENABLE);
+#else /* !FX_PACKEDCOLOR */
+ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_SPEC_OFFSET << 2, GR_PARAM_ENABLE);
+#endif /* !FX_PACKEDCOLOR */
+ /* don't advertise new state */
+ fxMesa->new_state = 0;
+ break;
+ case 2: /* 2nd pass (last): the secondary color is summed over texture */
+ /* restore original state */
+ fxMesa->unitsState = fxMesa->restoreUnitsState;
+ /* restore texturing */
+ ctx->Texture.Unit[0]._ReallyEnabled = t0;
+ ctx->Texture.Unit[1]._ReallyEnabled = t1;
+ /* revert to primary colors */
+#if FX_PACKEDCOLOR
+ grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PARGB_OFFSET << 2, GR_PARAM_ENABLE);
+#else /* !FX_PACKEDCOLOR */
+ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_RGB_OFFSET << 2, GR_PARAM_ENABLE);
+#endif /* !FX_PACKEDCOLOR */
+ break;
+ default:
+ assert(0); /* NOTREACHED */
+ }
+
+ /* update HW state */
+ fxSetupBlend(ctx);
+ fxSetupDepthTest(ctx);
+ fxSetupTexture(ctx);
+
+ return (pass == 1);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_tris(void);
+int
+gl_fx_dummy_function_tris(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxvb.c b/src/mesa/drivers/glide/fxvb.c
new file mode 100644
index 0000000..d535a98
--- /dev/null
+++ b/src/mesa/drivers/glide/fxvb.c
@@ -0,0 +1,834 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2003 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
+ * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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 <keith@tungstengraphics.com>
+ * Daniel Borca <dborca@users.sourceforge.net>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef FX
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "math/m_translate.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#include "fxdrv.h"
+
+
+static void copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ GrVertex *dst = fxMesa->verts + edst;
+ GrVertex *src = fxMesa->verts + esrc;
+
+#if FX_PACKEDCOLOR
+ *(GLuint *)&dst->pargb = *(GLuint *)&src->pargb;
+#else /* !FX_PACKEDCOLOR */
+ *(GLuint *)&dst->r = *(GLuint *)&src->r;
+ *(GLuint *)&dst->g = *(GLuint *)&src->g;
+ *(GLuint *)&dst->b = *(GLuint *)&src->b;
+ *(GLuint *)&dst->a = *(GLuint *)&src->a;
+#endif /* !FX_PACKEDCOLOR */
+}
+
+static void copy_pv2( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ GrVertex *dst = fxMesa->verts + edst;
+ GrVertex *src = fxMesa->verts + esrc;
+
+#if FX_PACKEDCOLOR
+ *(GLuint *)&dst->pargb = *(GLuint *)&src->pargb;
+ *(GLuint *)&dst->pspec = *(GLuint *)&src->pspec;
+#else /* !FX_PACKEDCOLOR */
+ *(GLuint *)&dst->r = *(GLuint *)&src->r;
+ *(GLuint *)&dst->g = *(GLuint *)&src->g;
+ *(GLuint *)&dst->b = *(GLuint *)&src->b;
+ *(GLuint *)&dst->a = *(GLuint *)&src->a;
+ *(GLuint *)&dst->r1 = *(GLuint *)&src->r1;
+ *(GLuint *)&dst->g1 = *(GLuint *)&src->g1;
+ *(GLuint *)&dst->b1 = *(GLuint *)&src->b1;
+#endif /* !FX_PACKEDCOLOR */
+}
+
+static struct {
+ tnl_emit_func emit;
+ tnl_copy_pv_func copy_pv;
+ tnl_interp_func interp;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_format;
+} setup_tab[MAX_SETUP];
+
+
+#define GET_COLOR(ptr, idx) ((ptr)->data[idx])
+
+
+static void interp_extras( GLcontext *ctx,
+ GLfloat t,
+ GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ if (VB->ColorPtr[1]) {
+ assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
+
+ INTERP_4F( t,
+ GET_COLOR(VB->ColorPtr[1], dst),
+ GET_COLOR(VB->ColorPtr[1], out),
+ GET_COLOR(VB->ColorPtr[1], in) );
+
+ if (VB->SecondaryColorPtr[1]) {
+ INTERP_3F( t,
+ GET_COLOR(VB->SecondaryColorPtr[1], dst),
+ GET_COLOR(VB->SecondaryColorPtr[1], out),
+ GET_COLOR(VB->SecondaryColorPtr[1], in) );
+ }
+ }
+
+ if (VB->EdgeFlag) {
+ VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
+ }
+
+ setup_tab[FX_CONTEXT(ctx)->SetupIndex].interp(ctx, t, dst, out, in,
+ force_boundary);
+}
+
+static void copy_pv_extras( GLcontext *ctx, GLuint dst, GLuint src )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ if (VB->ColorPtr[1]) {
+ COPY_4FV( GET_COLOR(VB->ColorPtr[1], dst),
+ GET_COLOR(VB->ColorPtr[1], src) );
+
+ if (VB->SecondaryColorPtr[1]) {
+ COPY_3FV( GET_COLOR(VB->SecondaryColorPtr[1], dst),
+ GET_COLOR(VB->SecondaryColorPtr[1], src) );
+ }
+ }
+
+ setup_tab[FX_CONTEXT(ctx)->SetupIndex].copy_pv(ctx, dst, src);
+}
+
+
+#define IND (SETUP_XYZW|SETUP_RGBA)
+#define TAG(x) x##_wg
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0)
+#define TAG(x) x##_wgt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_wgt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PTEX)
+#define TAG(x) x##_wgpt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX)
+#define TAG(x) x##_wgpt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_PSIZ)
+#define TAG(x) x##_wga
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PSIZ)
+#define TAG(x) x##_wgt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|SETUP_PSIZ)
+#define TAG(x) x##_wgt0t1a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_wgpt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_wgpt0t1a
+#include "fxvbtmp.h"
+
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC)
+#define TAG(x) x##_2wg
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0)
+#define TAG(x) x##_2wgt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_2wgt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PTEX)
+#define TAG(x) x##_2wgpt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX)
+#define TAG(x) x##_2wgpt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_PSIZ)
+#define TAG(x) x##_2wga
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PSIZ)
+#define TAG(x) x##_2wgt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|SETUP_PSIZ)
+#define TAG(x) x##_2wgt0t1a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_2wgpt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_2wgpt0t1a
+#include "fxvbtmp.h"
+
+/* fog { */
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_FOGC)
+#define TAG(x) x##_wgf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_FOGC)
+#define TAG(x) x##_wgt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|SETUP_FOGC)
+#define TAG(x) x##_wgt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_wgpt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_wgpt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wgaf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wgt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wgt0t1af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wgpt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wgpt0t1af
+#include "fxvbtmp.h"
+
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_FOGC)
+#define TAG(x) x##_2wgf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_FOGC)
+#define TAG(x) x##_2wgt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|SETUP_FOGC)
+#define TAG(x) x##_2wgt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_2wgpt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_2wgpt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wgaf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wgt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wgt0t1af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wgpt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1|\
+ SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wgpt0t1af
+#include "fxvbtmp.h"
+/* fog } */
+
+
+/* Snapping for voodoo-1
+ */
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA)
+#define TAG(x) x##_wsg
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0)
+#define TAG(x) x##_wsgt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1)
+#define TAG(x) x##_wsgt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_PTEX)
+#define TAG(x) x##_wsgpt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX)
+#define TAG(x) x##_wsgpt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_PSIZ)
+#define TAG(x) x##_wsga
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|SETUP_PSIZ)
+#define TAG(x) x##_wsgt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PSIZ)
+#define TAG(x) x##_wsgt0t1a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_wsgpt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_wsgpt0t1a
+#include "fxvbtmp.h"
+
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC)
+#define TAG(x) x##_2wsg
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0)
+#define TAG(x) x##_2wsgt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1)
+#define TAG(x) x##_2wsgt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_PTEX)
+#define TAG(x) x##_2wsgpt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX)
+#define TAG(x) x##_2wsgpt0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_PSIZ)
+#define TAG(x) x##_2wsga
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PSIZ)
+#define TAG(x) x##_2wsgt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PSIZ)
+#define TAG(x) x##_2wsgt0t1a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_2wsgpt0a
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_PSIZ)
+#define TAG(x) x##_2wsgpt0t1a
+#include "fxvbtmp.h"
+
+/* fog { */
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_FOGC)
+#define TAG(x) x##_wsgf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|SETUP_FOGC)
+#define TAG(x) x##_wsgt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_FOGC)
+#define TAG(x) x##_wsgt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_wsgpt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_wsgpt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wsgaf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wsgt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wsgt0t1af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wsgpt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_wsgpt0t1af
+#include "fxvbtmp.h"
+
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_FOGC)
+#define TAG(x) x##_2wsgf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_FOGC)
+#define TAG(x) x##_2wsgt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_FOGC)
+#define TAG(x) x##_2wsgt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_2wsgpt0f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_FOGC)
+#define TAG(x) x##_2wsgpt0t1f
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wsgaf
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wsgt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wsgt0t1af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wsgpt0af
+#include "fxvbtmp.h"
+
+#define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|\
+ SETUP_TMU1|SETUP_PTEX|SETUP_PSIZ|SETUP_FOGC)
+#define TAG(x) x##_2wsgpt0t1af
+#include "fxvbtmp.h"
+/* fog } */
+
+
+/* Vertex repair (multipass rendering)
+ */
+#define IND (SETUP_RGBA)
+#define TAG(x) x##_g
+#include "fxvbtmp.h"
+
+#define IND (SETUP_TMU0)
+#define TAG(x) x##_t0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_t0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_RGBA|SETUP_TMU0)
+#define TAG(x) x##_gt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_gt0t1
+#include "fxvbtmp.h"
+
+
+#define IND (SETUP_RGBA|SETUP_SPEC)
+#define TAG(x) x##_2g
+#include "fxvbtmp.h"
+
+#define IND (SETUP_TMU0|SETUP_SPEC)
+#define TAG(x) x##_2t0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_TMU0|SETUP_SPEC|SETUP_TMU1)
+#define TAG(x) x##_2t0t1
+#include "fxvbtmp.h"
+
+#define IND (SETUP_RGBA|SETUP_SPEC|SETUP_TMU0)
+#define TAG(x) x##_2gt0
+#include "fxvbtmp.h"
+
+#define IND (SETUP_RGBA|SETUP_SPEC|SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_2gt0t1
+#include "fxvbtmp.h"
+
+
+
+static void init_setup_tab( void )
+{
+ init_wg();
+ init_wgt0();
+ init_wgt0t1();
+ init_wgpt0();
+ init_wgpt0t1();
+ init_wga();
+ init_wgt0a();
+ init_wgt0t1a();
+ init_wgpt0a();
+ init_wgpt0t1a();
+ init_2wg();
+ init_2wgt0();
+ init_2wgt0t1();
+ init_2wgpt0();
+ init_2wgpt0t1();
+ init_2wga();
+ init_2wgt0a();
+ init_2wgt0t1a();
+ init_2wgpt0a();
+ init_2wgpt0t1a();
+ init_wgf();
+ init_wgt0f();
+ init_wgt0t1f();
+ init_wgpt0f();
+ init_wgpt0t1f();
+ init_wgaf();
+ init_wgt0af();
+ init_wgt0t1af();
+ init_wgpt0af();
+ init_wgpt0t1af();
+ init_2wgf();
+ init_2wgt0f();
+ init_2wgt0t1f();
+ init_2wgpt0f();
+ init_2wgpt0t1f();
+ init_2wgaf();
+ init_2wgt0af();
+ init_2wgt0t1af();
+ init_2wgpt0af();
+ init_2wgpt0t1af();
+
+ init_wsg();
+ init_wsgt0();
+ init_wsgt0t1();
+ init_wsgpt0();
+ init_wsgpt0t1();
+ init_wsga();
+ init_wsgt0a();
+ init_wsgt0t1a();
+ init_wsgpt0a();
+ init_wsgpt0t1a();
+ init_2wsg();
+ init_2wsgt0();
+ init_2wsgt0t1();
+ init_2wsgpt0();
+ init_2wsgpt0t1();
+ init_2wsga();
+ init_2wsgt0a();
+ init_2wsgt0t1a();
+ init_2wsgpt0a();
+ init_2wsgpt0t1a();
+ init_wsgf();
+ init_wsgt0f();
+ init_wsgt0t1f();
+ init_wsgpt0f();
+ init_wsgpt0t1f();
+ init_wsgaf();
+ init_wsgt0af();
+ init_wsgt0t1af();
+ init_wsgpt0af();
+ init_wsgpt0t1af();
+ init_2wsgf();
+ init_2wsgt0f();
+ init_2wsgt0t1f();
+ init_2wsgpt0f();
+ init_2wsgpt0t1f();
+ init_2wsgaf();
+ init_2wsgt0af();
+ init_2wsgt0t1af();
+ init_2wsgpt0af();
+ init_2wsgpt0t1af();
+
+ init_g();
+ init_t0();
+ init_t0t1();
+ init_gt0();
+ init_gt0t1();
+ init_2g();
+ init_2t0();
+ init_2t0t1();
+ init_2gt0();
+ init_2gt0t1();
+}
+
+
+#if 0
+void fxPrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s(%x): %s%s%s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & SETUP_XYZW) ? " xyzw," : "",
+ (flags & SETUP_SNAP) ? " snap," : "",
+ (flags & SETUP_RGBA) ? " rgba," : "",
+ (flags & SETUP_TMU0) ? " tex-0," : "",
+ (flags & SETUP_TMU1) ? " tex-1," : "",
+ (flags & SETUP_PSIZ) ? " psiz," : "",
+ (flags & SETUP_SPEC) ? " spec," : "",
+ (flags & SETUP_FOGC) ? " fog," : "");
+}
+#endif
+
+
+void fxCheckTexSizes( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+
+ if (!setup_tab[fxMesa->SetupIndex].check_tex_sizes(ctx)) {
+ GLuint ind = fxMesa->SetupIndex |= (SETUP_PTEX|SETUP_RGBA);
+
+ /* Tdfx handles projective textures nicely; just have to change
+ * up to the new vertex format.
+ */
+ if (setup_tab[ind].vertex_format != fxMesa->stw_hint_state) {
+
+ fxMesa->stw_hint_state = setup_tab[ind].vertex_format;
+ FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ /* This is required as we have just changed the vertex
+ * format, so the interp routines must also change.
+ * In the unfilled and twosided cases we are using the
+ * Extras ones anyway, so leave them in place.
+ */
+ if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[fxMesa->SetupIndex].interp;
+ }
+ }
+ }
+}
+
+
+void fxBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+ GLuint newinputs )
+{
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ GrVertex *v = (fxMesa->verts + start);
+
+ if (!newinputs)
+ return;
+
+ if (newinputs & VERT_BIT_POS) {
+ setup_tab[fxMesa->SetupIndex].emit( ctx, start, count, v );
+ } else {
+ GLuint ind = 0;
+
+ if (newinputs & VERT_BIT_COLOR0)
+ ind |= SETUP_RGBA;
+
+ if (newinputs & VERT_BIT_COLOR1)
+ ind |= SETUP_SPEC;
+
+ if (newinputs & VERT_BIT_FOG)
+ ind |= SETUP_FOGC;
+
+ if (newinputs & VERT_BIT_TEX0)
+ ind |= SETUP_TMU0;
+
+ if (newinputs & VERT_BIT_TEX1)
+ ind |= SETUP_TMU0|SETUP_TMU1;
+
+ if (fxMesa->SetupIndex & SETUP_PTEX)
+ ind = ~0;
+
+ ind &= fxMesa->SetupIndex;
+
+ if (ind) {
+ setup_tab[ind].emit( ctx, start, count, v );
+ }
+ }
+}
+
+
+void fxChooseVertexState( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ GLuint ind = SETUP_XYZW|SETUP_RGBA;
+
+ if (fxMesa->snapVertices)
+ ind |= SETUP_SNAP;
+
+ fxMesa->tmu_source[0] = 0;
+ fxMesa->tmu_source[1] = 1;
+
+ if (ctx->Texture._EnabledUnits & 0x2) {
+ if (ctx->Texture._EnabledUnits & 0x1) {
+ ind |= SETUP_TMU1;
+ }
+ ind |= SETUP_TMU0;
+ fxMesa->tmu_source[0] = 1;
+ fxMesa->tmu_source[1] = 0;
+ }
+ else if (ctx->Texture._EnabledUnits & 0x1) {
+ ind |= SETUP_TMU0;
+ }
+
+ if (ctx->_TriangleCaps & DD_POINT_ATTEN) {
+ ind |= SETUP_PSIZ;
+ }
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+ ind |= SETUP_SPEC;
+ }
+
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) {
+ ind |= SETUP_FOGC;
+ }
+
+ fxMesa->SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = interp_extras;
+ tnl->Driver.Render.CopyPV = copy_pv_extras;
+ } else {
+ tnl->Driver.Render.Interp = setup_tab[ind].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+ }
+
+ if (setup_tab[ind].vertex_format != fxMesa->stw_hint_state) {
+ fxMesa->stw_hint_state = setup_tab[ind].vertex_format;
+ FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+ }
+}
+
+
+
+void fxAllocVB( GLcontext *ctx )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+ static int firsttime = 1;
+ if (firsttime) {
+ init_setup_tab();
+ firsttime = 0;
+ }
+
+ fxMesa->verts = (GrVertex *)ALIGN_MALLOC(size * sizeof(GrVertex), 32);
+ fxMesa->SetupIndex = SETUP_XYZW|SETUP_RGBA;
+}
+
+
+void fxFreeVB( GLcontext *ctx )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ if (fxMesa->verts) {
+ ALIGN_FREE(fxMesa->verts);
+ fxMesa->verts = 0;
+ }
+}
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+extern int gl_fx_dummy_function_vb(void);
+int
+gl_fx_dummy_function_vb(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxvbtmp.h b/src/mesa/drivers/glide/fxvbtmp.h
new file mode 100644
index 0000000..8ca46dd
--- /dev/null
+++ b/src/mesa/drivers/glide/fxvbtmp.h
@@ -0,0 +1,369 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 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 <keith@tungstengraphics.com>
+ * Daniel Borca <dborca@users.sourceforge.net>
+ */
+
+
+#define VIEWPORT_X(dst,x) dst = s[0] * x + s[12]
+#define VIEWPORT_Y(dst,y) dst = s[5] * y + s[13]
+#define VIEWPORT_Z(dst,z) dst = s[10] * z + s[14]
+
+static void TAG(emit)( GLcontext *ctx,
+ GLuint start, GLuint end,
+ void *dest )
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLuint tmu0_source = fxMesa->tmu_source[0];
+ GLuint tmu1_source = fxMesa->tmu_source[1];
+ GLfloat (*tc0)[4], (*tc1)[4];
+ GLfloat (*col)[4], (*spec)[4];
+ GLuint tc0_stride, tc1_stride, col_stride, spec_stride;
+ GLuint tc0_size, tc1_size, col_size;
+ GLfloat (*proj)[4] = VB->NdcPtr->data;
+ GLuint proj_stride = VB->NdcPtr->stride;
+ GLfloat (*psize)[4];
+ GLuint psize_stride;
+ GLfloat (*fog)[4];
+ GLuint fog_stride;
+ GrVertex *v = (GrVertex *)dest;
+ GLfloat u0scale,v0scale,u1scale,v1scale;
+ const GLubyte *mask = VB->ClipMask;
+ const GLfloat *const s = ctx->Viewport._WindowMap.m;
+ int i;
+
+ if (IND & SETUP_PSIZ) {
+ psize = VB->PointSizePtr->data;
+ psize_stride = VB->PointSizePtr->stride;
+ }
+
+ if (IND & SETUP_TMU0) {
+ tc0 = VB->TexCoordPtr[tmu0_source]->data;
+ tc0_stride = VB->TexCoordPtr[tmu0_source]->stride;
+ u0scale = fxMesa->s0scale;
+ v0scale = fxMesa->t0scale;
+ if (IND & SETUP_PTEX)
+ tc0_size = VB->TexCoordPtr[tmu0_source]->size;
+ }
+
+ if (IND & SETUP_TMU1) {
+ tc1 = VB->TexCoordPtr[tmu1_source]->data;
+ tc1_stride = VB->TexCoordPtr[tmu1_source]->stride;
+ u1scale = fxMesa->s1scale; /* wrong if tmu1_source == 0, possible? */
+ v1scale = fxMesa->t1scale;
+ if (IND & SETUP_PTEX)
+ tc1_size = VB->TexCoordPtr[tmu1_source]->size;
+ }
+
+ if (IND & SETUP_RGBA) {
+ col = VB->ColorPtr[0]->data;
+ col_stride = VB->ColorPtr[0]->stride;
+ col_size = VB->ColorPtr[0]->size;
+ }
+
+ if (IND & SETUP_SPEC) {
+ spec = VB->SecondaryColorPtr[0]->data;
+ spec_stride = VB->SecondaryColorPtr[0]->stride;
+ }
+
+ if (IND & SETUP_FOGC) {
+ fog = VB->FogCoordPtr->data;
+ fog_stride = VB->FogCoordPtr->stride;
+ }
+
+ if (start) {
+ proj = (GLfloat (*)[4])((GLubyte *)proj + start * proj_stride);
+ if (IND & SETUP_PSIZ)
+ psize = (GLfloat (*)[4])((GLubyte *)psize + start * psize_stride);
+ if (IND & SETUP_TMU0)
+ tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
+ if (IND & SETUP_TMU1)
+ tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride);
+ if (IND & SETUP_RGBA)
+ STRIDE_4F(col, start * col_stride);
+ if (IND & SETUP_SPEC)
+ STRIDE_4F(spec, start * spec_stride);
+ if (IND & SETUP_FOGC)
+ fog = (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
+ }
+
+ for (i=start; i < end; i++, v++) {
+ if (IND & SETUP_PSIZ) {
+ v->psize = psize[0][0];
+ psize = (GLfloat (*)[4])((GLubyte *)psize + psize_stride);
+ }
+
+ if (IND & SETUP_XYZW) {
+ if (mask[i] == 0) {
+ /* unclipped */
+ VIEWPORT_X(v->x, proj[0][0]);
+ VIEWPORT_Y(v->y, proj[0][1]);
+ VIEWPORT_Z(v->ooz, proj[0][2]);
+ v->oow = proj[0][3];
+ } else {
+ /* clipped */
+ v->oow = 1.0;
+ }
+
+ if (IND & SETUP_SNAP) {
+#if defined(USE_IEEE)
+ const float snapper = (3L << 18);
+ v->x += snapper;
+ v->x -= snapper;
+ v->y += snapper;
+ v->y -= snapper;
+#else
+ v->x = ((int) (v->x * 16.0f)) * (1.0f / 16.0f);
+ v->y = ((int) (v->y * 16.0f)) * (1.0f / 16.0f);
+#endif
+ }
+
+ proj = (GLfloat (*)[4])((GLubyte *)proj + proj_stride);
+ }
+ if (IND & SETUP_RGBA) {
+#if FX_PACKEDCOLOR
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pargb[2], col[0][0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pargb[1], col[0][1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pargb[0], col[0][2]);
+ if (col_size == 4) {
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pargb[3], col[0][3]);
+ } else {
+ v->pargb[3] = 255;
+ }
+#else /* !FX_PACKEDCOLOR */
+ CNORM(v->r, col[0][0]);
+ CNORM(v->g, col[0][1]);
+ CNORM(v->b, col[0][2]);
+ if (col_size == 4) {
+ CNORM(v->a, col[0][3]);
+ } else {
+ v->a = 255.0f;
+ }
+#endif /* !FX_PACKEDCOLOR */
+ STRIDE_4F(col, col_stride);
+ }
+ if (IND & SETUP_SPEC) {
+#if FX_PACKEDCOLOR
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pspec[2], spec[0][0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pspec[1], spec[0][1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v->pspec[0], spec[0][2]);
+#else /* !FX_PACKEDCOLOR */
+ CNORM(v->r1, spec[0][0]);
+ CNORM(v->g1, spec[0][1]);
+ CNORM(v->b1, spec[0][2]);
+#endif /* !FX_PACKEDCOLOR */
+ STRIDE_4F(spec, spec_stride);
+ }
+ if (IND & SETUP_FOGC) {
+ v->fog = CLAMP(fog[0][0], 0.0f, 1.0f);
+ fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
+ }
+ if (IND & SETUP_TMU0) {
+ GLfloat w = v->oow;
+ v->tmuvtx[0].sow = tc0[0][0] * u0scale * w;
+ v->tmuvtx[0].tow = tc0[0][1] * v0scale * w;
+ if (IND & SETUP_PTEX) {
+ v->tmuvtx[0].oow = w;
+ if (tc0_size == 4)
+ v->tmuvtx[0].oow *= tc0[0][3];
+ }
+ tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + tc0_stride);
+ }
+ if (IND & SETUP_TMU1) {
+ GLfloat w = v->oow;
+ v->tmuvtx[1].sow = tc1[0][0] * u1scale * w;
+ v->tmuvtx[1].tow = tc1[0][1] * v1scale * w;
+ if (IND & SETUP_PTEX) {
+ v->tmuvtx[1].oow = w;
+ if (tc1_size == 4)
+ v->tmuvtx[1].oow *= tc1[0][3];
+ }
+ tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + tc1_stride);
+ }
+ }
+}
+
+#if (IND & SETUP_XYZW) && (IND & SETUP_RGBA)
+
+static GLboolean TAG(check_tex_sizes)( GLcontext *ctx )
+{
+/* fprintf(stderr, "%s\n", __FUNCTION__); */
+
+ if (IND & SETUP_PTEX)
+ return GL_TRUE;
+
+ if (IND & SETUP_TMU0) {
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ if (IND & SETUP_TMU1) {
+ if (VB->TexCoordPtr[0] == 0)
+ VB->TexCoordPtr[0] = VB->TexCoordPtr[1];
+
+ if (VB->TexCoordPtr[1]->size == 4)
+ return GL_FALSE;
+ }
+
+ if (VB->TexCoordPtr[0] && VB->TexCoordPtr[0]->size == 4)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static void TAG(interp)( GLcontext *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ fxMesaContext fxMesa = FX_CONTEXT( ctx );
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *dstclip = VB->ClipPtr->data[edst];
+ const GLfloat oow = (dstclip[3] == 0.0F) ? 1.0F : (1.0F / dstclip[3]);
+ const GLfloat *const s = ctx->Viewport._WindowMap.m;
+ GrVertex *fxverts = fxMesa->verts;
+ GrVertex *dst = (GrVertex *) (fxverts + edst);
+ const GrVertex *out = (const GrVertex *) (fxverts + eout);
+ const GrVertex *in = (const GrVertex *) (fxverts + ein);
+ const GLfloat wout = oow / out->oow;
+ const GLfloat win = oow / in->oow;
+
+ VIEWPORT_X(dst->x, dstclip[0] * oow);
+ VIEWPORT_Y(dst->y, dstclip[1] * oow);
+ VIEWPORT_Z(dst->ooz, dstclip[2] * oow);
+ dst->oow = oow;
+
+ if (IND & SETUP_SNAP) {
+#if defined(USE_IEEE)
+ const float snapper = (3L << 18);
+ dst->x += snapper;
+ dst->x -= snapper;
+ dst->y += snapper;
+ dst->y -= snapper;
+#else
+ dst->x = ((int) (dst->x * 16.0f)) * (1.0f / 16.0f);
+ dst->y = ((int) (dst->y * 16.0f)) * (1.0f / 16.0f);
+#endif
+ }
+
+
+#if FX_PACKEDCOLOR
+ INTERP_UB( t, dst->pargb[0], out->pargb[0], in->pargb[0] );
+ INTERP_UB( t, dst->pargb[1], out->pargb[1], in->pargb[1] );
+ INTERP_UB( t, dst->pargb[2], out->pargb[2], in->pargb[2] );
+ INTERP_UB( t, dst->pargb[3], out->pargb[3], in->pargb[3] );
+#else /* !FX_PACKEDCOLOR */
+ INTERP_F( t, dst->r, out->r, in->r );
+ INTERP_F( t, dst->g, out->g, in->g );
+ INTERP_F( t, dst->b, out->b, in->b );
+ INTERP_F( t, dst->a, out->a, in->a );
+#endif /* !FX_PACKEDCOLOR */
+
+ if (IND & SETUP_SPEC) {
+#if FX_PACKEDCOLOR
+ INTERP_UB( t, dst->pspec[0], out->pspec[0], in->pspec[0] );
+ INTERP_UB( t, dst->pspec[1], out->pspec[1], in->pspec[1] );
+ INTERP_UB( t, dst->pspec[2], out->pspec[2], in->pspec[2] );
+#else /* !FX_PACKEDCOLOR */
+ INTERP_F( t, dst->r1, out->r1, in->r1 );
+ INTERP_F( t, dst->g1, out->g1, in->g1 );
+ INTERP_F( t, dst->b1, out->b1, in->b1 );
+#endif /* !FX_PACKEDCOLOR */
+ }
+
+ if (IND & SETUP_FOGC) {
+ INTERP_F( t, dst->fog, out->fog, in->fog );
+ }
+
+ if (IND & SETUP_TMU0) {
+ INTERP_F( t,
+ dst->tmuvtx[0].sow,
+ out->tmuvtx[0].sow * wout,
+ in->tmuvtx[0].sow * win );
+ INTERP_F( t,
+ dst->tmuvtx[0].tow,
+ out->tmuvtx[0].tow * wout,
+ in->tmuvtx[0].tow * win );
+ if (IND & SETUP_PTEX) {
+ INTERP_F( t,
+ dst->tmuvtx[0].oow,
+ out->tmuvtx[0].oow * wout,
+ in->tmuvtx[0].oow * win );
+ }
+ }
+
+ if (IND & SETUP_TMU1) {
+ INTERP_F( t,
+ dst->tmuvtx[1].sow,
+ out->tmuvtx[1].sow * wout,
+ in->tmuvtx[1].sow * win );
+ INTERP_F( t,
+ dst->tmuvtx[1].tow,
+ out->tmuvtx[1].tow * wout,
+ in->tmuvtx[1].tow * win );
+ if (IND & SETUP_PTEX) {
+ INTERP_F( t,
+ dst->tmuvtx[1].oow,
+ out->tmuvtx[1].oow * wout,
+ in->tmuvtx[1].oow * win );
+ }
+ }
+}
+#endif
+
+
+static void TAG(init)( void )
+{
+ setup_tab[IND].emit = TAG(emit);
+
+ if (IND & SETUP_SPEC) {
+ setup_tab[IND].copy_pv = copy_pv2;
+ } else {
+ setup_tab[IND].copy_pv = copy_pv;
+ }
+
+#if ((IND & SETUP_XYZW) && (IND & SETUP_RGBA))
+ setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes);
+ setup_tab[IND].interp = TAG(interp);
+
+ setup_tab[IND].vertex_format = 0;
+ if (IND & SETUP_PTEX) {
+ setup_tab[IND].vertex_format |= GR_STWHINT_W_DIFF_TMU0;
+ }
+
+#if (IND & SETUP_TMU1)
+ setup_tab[IND].vertex_format |= GR_STWHINT_ST_DIFF_TMU1;
+ if (IND & SETUP_PTEX) {
+ setup_tab[IND].vertex_format |= GR_STWHINT_W_DIFF_TMU1;
+ }
+#endif
+
+#endif
+}
+
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/glide/fxwgl.c b/src/mesa/drivers/glide/fxwgl.c
new file mode 100644
index 0000000..354a67f
--- /dev/null
+++ b/src/mesa/drivers/glide/fxwgl.c
@@ -0,0 +1,1123 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.0
+ *
+ * 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:
+ * David Bucciarelli
+ * Brian Paul
+ * Keith Whitwell
+ * Hiroshi Morii
+ * Daniel Borca
+ */
+
+/* fxwgl.c - Microsoft wgl functions emulation for
+ * 3Dfx VooDoo/Mesa interface
+ */
+
+
+#ifdef _WIN32
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "GL/fxmesa.h"
+#include "glheader.h"
+#include "glapi.h"
+#include "imports.h"
+#include "fxdrv.h"
+
+#define MAX_MESA_ATTRS 20
+
+#if (_MSC_VER >= 1200)
+#pragma warning( push )
+#pragma warning( disable : 4273 )
+#endif
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLint mesaAttr[MAX_MESA_ATTRS];
+};
+
+static GLushort gammaTable[3*256];
+
+static struct __pixelformat__ pix[] = {
+ /* 16bit RGB565 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 6, 5, 5, 11, 0, 0,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 16,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit RGB565 double buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER | PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 6, 5, 5, 11, 0, 0,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 16,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit ARGB1555 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 5, 5, 5, 10, 1, 15,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 15,
+ FXMESA_ALPHA_SIZE, 1,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 16bit ARGB1555 double buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER | PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 16,
+ 5, 0, 5, 5, 5, 10, 1, 15,
+ 0, 0, 0, 0, 0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 15,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 1,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 32bit ARGB8888 single buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL,
+ PFD_TYPE_RGBA,
+ 32,
+ 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0,
+ 24,
+ 8,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 32,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 24,
+ FXMESA_STENCIL_SIZE, 8,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+ ,
+ /* 32bit ARGB8888 double buffer with depth */
+ {
+ {sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
+ PFD_DOUBLEBUFFER | PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0,
+ 24,
+ 8,
+ 0,
+ PFD_MAIN_PLANE,
+ 0, 0, 0, 0}
+ ,
+ {FXMESA_COLORDEPTH, 32,
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 24,
+ FXMESA_STENCIL_SIZE, 8,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE}
+ }
+};
+
+static fxMesaContext ctx = NULL;
+static WNDPROC hWNDOldProc;
+static int curPFD = 0;
+static HDC hDC;
+static HWND hWND;
+
+
+static int env_check (const char *var, int val)
+{
+ const char *env = getenv(var);
+ return (env && (env[0] == val));
+}
+
+static LRESULT WINAPI
+__wglMonitor(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT ret; /* Now gives the resized window at the end to hWNDOldProc */
+
+ if (ctx && hwnd == hWND) {
+ switch (message) {
+ case WM_PAINT:
+ case WM_MOVE:
+ break;
+ case WM_DISPLAYCHANGE:
+ case WM_SIZE:
+ break;
+ case WM_ACTIVATE:
+ break;
+ case WM_SHOWWINDOW:
+ break;
+ case WM_SYSKEYDOWN:
+ case WM_SYSCHAR:
+ break;
+ }
+ }
+
+ /* Finaly call the hWNDOldProc, which handles the resize witch the
+ now changed window sizes */
+ ret = CallWindowProc(hWNDOldProc, hwnd, message, wParam, lParam);
+
+ return (ret);
+}
+
+static void wgl_error (long error)
+{
+#define WGL_INVALID_PIXELFORMAT ERROR_INVALID_PIXEL_FORMAT
+ SetLastError(0xC0000000 /* error severity */
+ |0x00070000 /* error facility (who we are) */
+ |error);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
+{
+ return (FALSE);
+}
+
+GLAPI HGLRC GLAPIENTRY
+wglCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ WNDPROC oldProc;
+ int error;
+
+ if (ctx) {
+ SetLastError(0);
+ return (NULL);
+ }
+
+ if (!(hWnd = WindowFromDC(hdc))) {
+ SetLastError(0);
+ return (NULL);
+ }
+
+ if (curPFD == 0) {
+ wgl_error(WGL_INVALID_PIXELFORMAT);
+ return (NULL);
+ }
+
+ if ((oldProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC)) != __wglMonitor) {
+ hWNDOldProc = oldProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG) __wglMonitor);
+ }
+
+ /* always log when debugging, or if user demands */
+ if (TDFX_DEBUG || env_check("MESA_FX_INFO", 'r')) {
+ freopen("MESA.LOG", "w", stderr);
+ }
+
+ {
+ RECT cliRect;
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hWnd);
+ Sleep(100); /* a hack for win95 */
+ if (env_check("MESA_GLX_FX", 'w') && !(GetWindowLong (hWnd, GWL_STYLE) & WS_POPUP)) {
+ /* XXX todo - windowed modes */
+ error = !(ctx = fxMesaCreateContext((GLuint) hWnd, GR_RESOLUTION_NONE, GR_REFRESH_NONE, pix[curPFD - 1].mesaAttr));
+ } else {
+ GetClientRect(hWnd, &cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint) hWnd, cliRect.right, cliRect.bottom, pix[curPFD - 1].mesaAttr));
+ }
+ }
+
+ if (error) {
+ SetLastError(0);
+ return (NULL);
+ }
+
+ hDC = hdc;
+ hWND = hWnd;
+
+ /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */
+ wglMakeCurrent(hdc, (HGLRC) 1);
+
+ return ((HGLRC) 1);
+}
+
+GLAPI HGLRC GLAPIENTRY
+wglCreateLayerContext(HDC hdc, int iLayerPlane)
+{
+ SetLastError(0);
+ return (NULL);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDeleteContext(HGLRC hglrc)
+{
+ if (ctx && hglrc == (HGLRC) 1) {
+
+ fxMesaDestroyContext(ctx);
+
+ SetWindowLong(WindowFromDC(hDC), GWL_WNDPROC, (LONG) hWNDOldProc);
+
+ ctx = NULL;
+ hDC = 0;
+ return (TRUE);
+ }
+
+ SetLastError(0);
+
+ return (FALSE);
+}
+
+GLAPI HGLRC GLAPIENTRY
+wglGetCurrentContext(VOID)
+{
+ if (ctx)
+ return ((HGLRC) 1);
+
+ SetLastError(0);
+ return (NULL);
+}
+
+GLAPI HDC GLAPIENTRY
+wglGetCurrentDC(VOID)
+{
+ if (ctx)
+ return (hDC);
+
+ SetLastError(0);
+ return (NULL);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSwapIntervalEXT (int interval)
+{
+ if (ctx == NULL) {
+ return FALSE;
+ }
+ if (interval < 0) {
+ interval = 0;
+ } else if (interval > 3) {
+ interval = 3;
+ }
+ ctx->swapInterval = interval;
+ return TRUE;
+}
+
+GLAPI int GLAPIENTRY
+wglGetSwapIntervalEXT (void)
+{
+ return (ctx == NULL) ? -1 : ctx->swapInterval;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglGetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays)
+{
+ /* gammaTable should be per-context */
+ memcpy(arrays, gammaTable, 3*256*sizeof(GLushort));
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetDeviceGammaRamp3DFX (HDC hdc, LPVOID arrays)
+{
+ GLint i, tableSize, inc, index;
+ GLushort *red, *green, *blue;
+ FxU32 gammaTableR[256], gammaTableG[256], gammaTableB[256];
+
+ /* gammaTable should be per-context */
+ memcpy(gammaTable, arrays, 3*256*sizeof(GLushort));
+
+ tableSize = FX_grGetInteger(GR_GAMMA_TABLE_ENTRIES);
+ inc = 256 / tableSize;
+ red = (GLushort *)arrays;
+ green = (GLushort *)arrays + 256;
+ blue = (GLushort *)arrays + 512;
+ for (i = 0, index = 0; i < tableSize; i++, index += inc) {
+ gammaTableR[i] = red[index] >> 8;
+ gammaTableG[i] = green[index] >> 8;
+ gammaTableB[i] = blue[index] >> 8;
+ }
+
+ grLoadGammaTable(tableSize, gammaTableR, gammaTableG, gammaTableB);
+
+ return TRUE;
+}
+
+typedef void *HPBUFFERARB;
+
+/* WGL_ARB_pixel_format */
+GLAPI BOOL GLAPIENTRY
+wglGetPixelFormatAttribivARB (HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ int *piValues)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglGetPixelFormatAttribfvARB (HDC hdc,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ FLOAT *pfValues)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglChoosePixelFormatARB (HDC hdc,
+ const int *piAttribIList,
+ const FLOAT *pfAttribFList,
+ UINT nMaxFormats,
+ int *piFormats,
+ UINT *nNumFormats)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+/* WGL_ARB_render_texture */
+GLAPI BOOL GLAPIENTRY
+wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetPbufferAttribARB (HPBUFFERARB hPbuffer,
+ const int *piAttribList)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+/* WGL_ARB_pbuffer */
+GLAPI HPBUFFERARB GLAPIENTRY
+wglCreatePbufferARB (HDC hDC,
+ int iPixelFormat,
+ int iWidth,
+ int iHeight,
+ const int *piAttribList)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI HDC GLAPIENTRY
+wglGetPbufferDCARB (HPBUFFERARB hPbuffer)
+{
+ SetLastError(0);
+ return NULL;
+}
+
+GLAPI int GLAPIENTRY
+wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC)
+{
+ SetLastError(0);
+ return -1;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDestroyPbufferARB (HPBUFFERARB hPbuffer)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglQueryPbufferARB (HPBUFFERARB hPbuffer,
+ int iAttribute,
+ int *piValue)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI const char * GLAPIENTRY
+wglGetExtensionsStringEXT (void)
+{
+ return "WGL_3DFX_gamma_control "
+ "WGL_EXT_swap_control "
+ "WGL_EXT_extensions_string WGL_ARB_extensions_string"
+ /*WGL_ARB_pixel_format WGL_ARB_render_texture WGL_ARB_pbuffer*/;
+}
+
+GLAPI const char * GLAPIENTRY
+wglGetExtensionsStringARB (HDC hdc)
+{
+ return wglGetExtensionsStringEXT();
+}
+
+static struct {
+ const char *name;
+ PROC func;
+} wgl_ext[] = {
+ {"wglGetExtensionsStringARB", (PROC)wglGetExtensionsStringARB},
+ {"wglGetExtensionsStringEXT", (PROC)wglGetExtensionsStringEXT},
+ {"wglSwapIntervalEXT", (PROC)wglSwapIntervalEXT},
+ {"wglGetSwapIntervalEXT", (PROC)wglGetSwapIntervalEXT},
+ {"wglGetDeviceGammaRamp3DFX", (PROC)wglGetDeviceGammaRamp3DFX},
+ {"wglSetDeviceGammaRamp3DFX", (PROC)wglSetDeviceGammaRamp3DFX},
+ /* WGL_ARB_pixel_format */
+ {"wglGetPixelFormatAttribivARB", (PROC)wglGetPixelFormatAttribivARB},
+ {"wglGetPixelFormatAttribfvARB", (PROC)wglGetPixelFormatAttribfvARB},
+ {"wglChoosePixelFormatARB", (PROC)wglChoosePixelFormatARB},
+ /* WGL_ARB_render_texture */
+ {"wglBindTexImageARB", (PROC)wglBindTexImageARB},
+ {"wglReleaseTexImageARB", (PROC)wglReleaseTexImageARB},
+ {"wglSetPbufferAttribARB", (PROC)wglSetPbufferAttribARB},
+ /* WGL_ARB_pbuffer */
+ {"wglCreatePbufferARB", (PROC)wglCreatePbufferARB},
+ {"wglGetPbufferDCARB", (PROC)wglGetPbufferDCARB},
+ {"wglReleasePbufferDCARB", (PROC)wglReleasePbufferDCARB},
+ {"wglDestroyPbufferARB", (PROC)wglDestroyPbufferARB},
+ {"wglQueryPbufferARB", (PROC)wglQueryPbufferARB},
+ {NULL, NULL}
+};
+
+GLAPI PROC GLAPIENTRY
+wglGetProcAddress(LPCSTR lpszProc)
+{
+ int i;
+ PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc);
+
+ /* we can't BlendColor. work around buggy applications */
+ if (p && strcmp(lpszProc, "glBlendColor") && strcmp(lpszProc, "glBlendColorEXT"))
+ return p;
+
+ for (i = 0; wgl_ext[i].name; i++) {
+ if (!strcmp(lpszProc, wgl_ext[i].name)) {
+ return wgl_ext[i].func;
+ }
+ }
+
+ SetLastError(0);
+ return (NULL);
+}
+
+GLAPI PROC GLAPIENTRY
+wglGetDefaultProcAddress(LPCSTR lpszProc)
+{
+ SetLastError(0);
+ return (NULL);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglMakeCurrent(HDC hdc, HGLRC hglrc)
+{
+ if ((hdc == NULL) && (hglrc == NULL))
+ return (TRUE);
+
+ if (!ctx || hglrc != (HGLRC) 1 || WindowFromDC(hdc) != hWND) {
+ SetLastError(0);
+ return (FALSE);
+ }
+
+ hDC = hdc;
+
+ fxMesaMakeCurrent(ctx);
+
+ return (TRUE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
+{
+ if (!ctx || hglrc1 != (HGLRC) 1 || hglrc1 != hglrc2) {
+ SetLastError(0);
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+static BOOL
+wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, DWORD numChars,
+ DWORD listBase)
+{
+ TEXTMETRIC metric;
+ BITMAPINFO *dibInfo;
+ HDC bitDevice;
+ COLORREF tempColor;
+ int i;
+
+ GetTextMetrics(fontDevice, &metric);
+
+ dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1);
+ dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibInfo->bmiHeader.biPlanes = 1;
+ dibInfo->bmiHeader.biBitCount = 1;
+ dibInfo->bmiHeader.biCompression = BI_RGB;
+
+ bitDevice = CreateCompatibleDC(fontDevice);
+
+ /* Swap fore and back colors so the bitmap has the right polarity */
+ tempColor = GetBkColor(bitDevice);
+ SetBkColor(bitDevice, GetTextColor(bitDevice));
+ SetTextColor(bitDevice, tempColor);
+
+ /* Place chars based on base line */
+ SetTextAlign(bitDevice, TA_BASELINE);
+
+ for (i = 0; i < (int)numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth, charHeight, bmapWidth, bmapHeight, numBytes, res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = (char)(i + firstChar); /* [koolsmoky] explicit cast */
+
+ /* Find how high/wide this character is */
+ GetTextExtentPoint32(bitDevice, &curChar, 1, &size);
+
+ /* Create the output bitmap */
+ charWidth = size.cx;
+ charHeight = size.cy;
+ bmapWidth = ((charWidth + 31) / 32) * 32; /* Round up to the next multiple of 32 bits */
+ bmapHeight = charHeight;
+ bitObject = CreateCompatibleBitmap(bitDevice, bmapWidth, bmapHeight);
+ /*VERIFY(bitObject);*/
+
+ /* Assign the output bitmap to the device */
+ origBmap = SelectObject(bitDevice, bitObject);
+
+ PatBlt(bitDevice, 0, 0, bmapWidth, bmapHeight, BLACKNESS);
+
+ /* Use our source font on the device */
+ SelectObject(bitDevice, GetCurrentObject(fontDevice, OBJ_FONT));
+
+ /* Draw the character */
+ TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1);
+
+ /* Unselect our bmap object */
+ SelectObject(bitDevice, origBmap);
+
+ /* Convert the display dependant representation to a 1 bit deep DIB */
+ numBytes = (bmapWidth * bmapHeight) / 8;
+ bmap = MALLOC(numBytes);
+ dibInfo->bmiHeader.biWidth = bmapWidth;
+ dibInfo->bmiHeader.biHeight = bmapHeight;
+ res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap,
+ dibInfo, DIB_RGB_COLORS);
+
+ /* Create the GL object */
+ glNewList(i + listBase, GL_COMPILE);
+ glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent,
+ charWidth, 0.0, bmap);
+ glEndList();
+ /* CheckGL(); */
+
+ /* Destroy the bmap object */
+ DeleteObject(bitObject);
+
+ /* Deallocate the bitmap data */
+ FREE(bmap);
+ }
+
+ /* Destroy the DC */
+ DeleteDC(bitDevice);
+
+ FREE(dibInfo);
+
+ return TRUE;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ return (FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontOutlinesA(HDC hdc, DWORD first, DWORD count,
+ DWORD listBase, FLOAT deviation,
+ FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return (FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglUseFontOutlinesW(HDC hdc, DWORD first, DWORD count,
+ DWORD listBase, FLOAT deviation,
+ FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return (FALSE);
+}
+
+
+GLAPI BOOL GLAPIENTRY
+wglSwapLayerBuffers(HDC hdc, UINT fuPlanes)
+{
+ if (ctx && WindowFromDC(hdc) == hWND) {
+ fxMesaSwapBuffers();
+
+ return (TRUE);
+ }
+
+ SetLastError(0);
+ return (FALSE);
+}
+
+static int pfd_tablen (void)
+{
+ /* we should take an envvar for `fxMesaSelectCurrentBoard' */
+ return (fxMesaSelectCurrentBoard(0) < GR_SSTTYPE_Voodoo4)
+ ? 2 /* only 16bit entries */
+ : sizeof(pix) / sizeof(pix[0]); /* full table */
+}
+
+GLAPI int GLAPIENTRY
+wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd)
+{
+ int i, best = -1, qt_valid_pix;
+ PIXELFORMATDESCRIPTOR pfd = *ppfd;
+
+ qt_valid_pix = pfd_tablen();
+
+#if 1 || QUAKE2 || GORE
+ /* QUAKE2: 24+32 */
+ /* GORE : 24+16 */
+ if ((pfd.cColorBits == 24) || (pfd.cColorBits == 32)) {
+ /* the first 2 entries are 16bit */
+ pfd.cColorBits = (qt_valid_pix > 2) ? 32 : 16;
+ }
+ if (pfd.cColorBits == 32) {
+ pfd.cDepthBits = 24;
+ } else if (pfd.cColorBits == 16) {
+ pfd.cDepthBits = 16;
+ }
+#endif
+
+ if (pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR) || pfd.nVersion != 1) {
+ SetLastError(0);
+ return (0);
+ }
+
+ for (i = 0; i < qt_valid_pix; i++) {
+ if (pfd.cColorBits > 0 && pix[i].pfd.cColorBits != pfd.cColorBits)
+ continue;
+
+ if ((pfd.dwFlags & PFD_DRAW_TO_WINDOW)
+ && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue;
+ if ((pfd.dwFlags & PFD_DRAW_TO_BITMAP)
+ && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) continue;
+ if ((pfd.dwFlags & PFD_SUPPORT_GDI)
+ && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI)) continue;
+ if ((pfd.dwFlags & PFD_SUPPORT_OPENGL)
+ && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue;
+ if (!(pfd.dwFlags & PFD_DOUBLEBUFFER_DONTCARE)
+ && ((pfd.dwFlags & PFD_DOUBLEBUFFER) !=
+ (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) continue;
+#if 1 /* Doom3 fails here! */
+ if (!(pfd.dwFlags & PFD_STEREO_DONTCARE)
+ && ((pfd.dwFlags & PFD_STEREO) !=
+ (pix[i].pfd.dwFlags & PFD_STEREO))) continue;
+#endif
+
+ if (pfd.cDepthBits > 0 && pix[i].pfd.cDepthBits == 0)
+ continue; /* need depth buffer */
+
+ if (pfd.cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0)
+ continue; /* need alpha buffer */
+
+#if 0 /* regression bug? */
+ if (pfd.cStencilBits > 0 && pix[i].pfd.cStencilBits == 0)
+ continue; /* need stencil buffer */
+#endif
+
+ if (pfd.iPixelType == pix[i].pfd.iPixelType) {
+ best = i + 1;
+ break;
+ }
+ }
+
+ if (best == -1) {
+ FILE *err = fopen("MESA.LOG", "w");
+ if (err != NULL) {
+ fprintf(err, "wglChoosePixelFormat failed\n");
+ fprintf(err, "\tnSize = %d\n", ppfd->nSize);
+ fprintf(err, "\tnVersion = %d\n", ppfd->nVersion);
+ fprintf(err, "\tdwFlags = %lu\n", ppfd->dwFlags);
+ fprintf(err, "\tiPixelType = %d\n", ppfd->iPixelType);
+ fprintf(err, "\tcColorBits = %d\n", ppfd->cColorBits);
+ fprintf(err, "\tcRedBits = %d\n", ppfd->cRedBits);
+ fprintf(err, "\tcRedShift = %d\n", ppfd->cRedShift);
+ fprintf(err, "\tcGreenBits = %d\n", ppfd->cGreenBits);
+ fprintf(err, "\tcGreenShift = %d\n", ppfd->cGreenShift);
+ fprintf(err, "\tcBlueBits = %d\n", ppfd->cBlueBits);
+ fprintf(err, "\tcBlueShift = %d\n", ppfd->cBlueShift);
+ fprintf(err, "\tcAlphaBits = %d\n", ppfd->cAlphaBits);
+ fprintf(err, "\tcAlphaShift = %d\n", ppfd->cAlphaShift);
+ fprintf(err, "\tcAccumBits = %d\n", ppfd->cAccumBits);
+ fprintf(err, "\tcAccumRedBits = %d\n", ppfd->cAccumRedBits);
+ fprintf(err, "\tcAccumGreenBits = %d\n", ppfd->cAccumGreenBits);
+ fprintf(err, "\tcAccumBlueBits = %d\n", ppfd->cAccumBlueBits);
+ fprintf(err, "\tcAccumAlphaBits = %d\n", ppfd->cAccumAlphaBits);
+ fprintf(err, "\tcDepthBits = %d\n", ppfd->cDepthBits);
+ fprintf(err, "\tcStencilBits = %d\n", ppfd->cStencilBits);
+ fprintf(err, "\tcAuxBuffers = %d\n", ppfd->cAuxBuffers);
+ fprintf(err, "\tiLayerType = %d\n", ppfd->iLayerType);
+ fprintf(err, "\tbReserved = %d\n", ppfd->bReserved);
+ fprintf(err, "\tdwLayerMask = %lu\n", ppfd->dwLayerMask);
+ fprintf(err, "\tdwVisibleMask = %lu\n", ppfd->dwVisibleMask);
+ fprintf(err, "\tdwDamageMask = %lu\n", ppfd->dwDamageMask);
+ fclose(err);
+ }
+
+ SetLastError(0);
+ return (0);
+ }
+
+ return (best);
+}
+
+GLAPI int GLAPIENTRY
+ChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd)
+{
+
+ return wglChoosePixelFormat(hdc, ppfd);
+}
+
+GLAPI int GLAPIENTRY
+wglDescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = pfd_tablen();
+
+ if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix ||
+ ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) {
+ SetLastError(0);
+ return (qt_valid_pix);
+ }
+
+ if (nBytes != 0)
+ *ppfd = pix[iPixelFormat - 1].pfd;
+
+ return (qt_valid_pix);
+}
+
+GLAPI int GLAPIENTRY
+DescribePixelFormat(HDC hdc, int iPixelFormat, UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ return wglDescribePixelFormat(hdc, iPixelFormat, nBytes, ppfd);
+}
+
+GLAPI int GLAPIENTRY
+wglGetPixelFormat(HDC hdc)
+{
+ if (curPFD == 0) {
+ SetLastError(0);
+ return (0);
+ }
+
+ return (curPFD);
+}
+
+GLAPI int GLAPIENTRY
+GetPixelFormat(HDC hdc)
+{
+ return wglGetPixelFormat(hdc);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSetPixelFormat(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = pfd_tablen();
+
+ if (iPixelFormat < 1 || iPixelFormat > qt_valid_pix) {
+ if (ppfd == NULL) {
+ PIXELFORMATDESCRIPTOR my_pfd;
+ if (!wglDescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &my_pfd)) {
+ SetLastError(0);
+ return (FALSE);
+ }
+ } else if (ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ SetLastError(0);
+ return (FALSE);
+ }
+ }
+ curPFD = iPixelFormat;
+
+ return (TRUE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglSwapBuffers(HDC hdc)
+{
+ if (!ctx) {
+ SetLastError(0);
+ return (FALSE);
+ }
+
+ fxMesaSwapBuffers();
+
+ return (TRUE);
+}
+
+GLAPI BOOL GLAPIENTRY
+SetPixelFormat(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd)
+{
+ return wglSetPixelFormat(hdc, iPixelFormat, ppfd);
+}
+
+GLAPI BOOL GLAPIENTRY
+SwapBuffers(HDC hdc)
+{
+ return wglSwapBuffers(hdc);
+}
+
+static FIXED FixedFromDouble(double d)
+{
+ struct {
+ FIXED f;
+ long l;
+ } pun;
+ pun.l = (long)(d * 65536L);
+ return pun.f;
+}
+
+/*
+** This was yanked from windows/gdi/wgl.c
+*/
+GLAPI BOOL GLAPIENTRY
+wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ int i;
+ GLuint font_list;
+ DWORD size;
+ GLYPHMETRICS gm;
+ HANDLE hBits;
+ LPSTR lpBits;
+ MAT2 mat;
+ int success = TRUE;
+
+ if (first<0)
+ return FALSE;
+ if (count<0)
+ return FALSE;
+ if (listBase<0)
+ return FALSE;
+
+ font_list = listBase;
+
+ mat.eM11 = FixedFromDouble(1);
+ mat.eM12 = FixedFromDouble(0);
+ mat.eM21 = FixedFromDouble(0);
+ mat.eM22 = FixedFromDouble(-1);
+
+ memset(&gm,0,sizeof(gm));
+
+ /*
+ ** If we can't get the glyph outline, it may be because this is a fixed
+ ** font. Try processing it that way.
+ */
+ if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat)
+ == GDI_ERROR )
+ {
+ return wglUseFontBitmaps_FX( hdc, first, count, listBase );
+ }
+
+ /*
+ ** Otherwise process all desired characters.
+ */
+ for (i = 0; i < count; i++)
+ {
+ DWORD err;
+
+ glNewList( font_list+i, GL_COMPILE );
+
+ /* allocate space for the bitmap/outline */
+ size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, NULL, &mat);
+ if (size == GDI_ERROR)
+ {
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ hBits = GlobalAlloc(GHND, size+1);
+ lpBits = GlobalLock(hBits);
+
+ err = GetGlyphOutline(hdc, /* handle to device context */
+ first + i, /* character to query */
+ GGO_BITMAP, /* format of data to return */
+ &gm, /* pointer to structure for metrics*/
+ size, /* size of buffer for data */
+ lpBits, /* pointer to buffer for data */
+ &mat /* pointer to transformation */
+ /* matrix structure */
+ );
+
+ if (err == GDI_ERROR)
+ {
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
+ -gm.gmptGlyphOrigin.x,
+ gm.gmptGlyphOrigin.y,
+ gm.gmCellIncX,gm.gmCellIncY,
+ (const GLubyte * )lpBits);
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ }
+
+ return success;
+}
+
+GLAPI BOOL GLAPIENTRY
+wglDescribeLayerPlane(HDC hdc, int iPixelFormat, int iLayerPlane,
+ UINT nBytes, LPLAYERPLANEDESCRIPTOR ppfd)
+{
+ SetLastError(0);
+ return (FALSE);
+}
+
+GLAPI int GLAPIENTRY
+wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart,
+ int cEntries, COLORREF *pcr)
+{
+ SetLastError(0);
+ return (FALSE);
+}
+
+GLAPI BOOL GLAPIENTRY
+wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI int GLAPIENTRY
+wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane, int iStart,
+ int cEntries, CONST COLORREF *pcr)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+#if (_MSC_VER >= 1200)
+#pragma warning( pop )
+#endif
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/glide3x_dxe.c b/src/mesa/drivers/glide/glide3x_dxe.c
new file mode 100644
index 0000000..7dcf277
--- /dev/null
+++ b/src/mesa/drivers/glide/glide3x_dxe.c
@@ -0,0 +1,176 @@
+/* C source for generating a dummy glide3x.dxe to be used when
+ * generating an import library for a dxe depending on glide3x.
+ *
+ * gcc -Wall -c glide3x.c -o glide3x.o
+ * dxe3gen -o glide3x.dxe -E _gr -E _gu -U glide3x.o
+ */
+
+/* common gr and gu symbols exported by all
+ * sst1, sst96, cvg, h3 and h5 glide3x.dxe:
+ */
+void grAADrawTriangle () {}
+void grAlphaBlendFunction () {}
+void grAlphaCombine () {}
+void grAlphaControlsITRGBLighting () {}
+void grAlphaTestFunction () {}
+void grAlphaTestReferenceValue () {}
+void grBufferClear () {}
+void grBufferSwap () {}
+void grCheckForRoom () {}
+void grChromakeyMode () {}
+void grChromakeyValue () {}
+void grClipWindow () {}
+void grColorCombine () {}
+void grColorMask () {}
+void grConstantColorValue () {}
+void grCoordinateSpace () {}
+void grCullMode () {}
+void grDepthBiasLevel () {}
+void grDepthBufferFunction () {}
+void grDepthBufferMode () {}
+void grDepthMask () {}
+void grDepthRange () {}
+void grDisable () {}
+void grDisableAllEffects () {}
+void grDitherMode () {}
+void grDrawLine () {}
+void grDrawPoint () {}
+void grDrawTriangle () {}
+void grDrawVertexArray () {}
+void grDrawVertexArrayContiguous () {}
+void grEnable () {}
+void grErrorSetCallback () {}
+void grFinish () {}
+void grFlush () {}
+void grFogColorValue () {}
+void grFogMode () {}
+void grFogTable () {}
+void grGet () {}
+void grGetProcAddress () {}
+void grGetRegistryOrEnvironmentString () {}
+void grGetString () {}
+void grGlideGetState () {}
+void grGlideGetVersion () {}
+void grGlideGetVertexLayout () {}
+void grGlideInit () {}
+void grGlideSetState () {}
+void grGlideSetVertexLayout () {}
+void grGlideShutdown () {}
+void grLfbConstantAlpha () {}
+void grLfbConstantDepth () {}
+void grLfbLock () {}
+void grLfbReadRegion () {}
+void grLfbUnlock () {}
+void grLfbWriteColorFormat () {}
+void grLfbWriteColorSwizzle () {}
+void grLfbWriteRegion () {}
+void grLoadGammaTable () {}
+void grQueryResolutions () {}
+void grRenderBuffer () {}
+void grReset () {}
+void grSelectContext () {}
+void grSetNumPendingBuffers () {}
+void grSplash () {}
+void grSstOrigin () {}
+void grSstSelect () {}
+void grSstVidMode () {}
+void grSstWinClose () {}
+void grSstWinOpen () {}
+void grTexCalcMemRequired () {}
+void grTexClampMode () {}
+void grTexCombine () {}
+void grTexDetailControl () {}
+void grTexDownloadMipMap () {}
+void grTexDownloadMipMapLevel () {}
+void grTexDownloadMipMapLevelPartial () {}
+void grTexDownloadTable () {}
+void grTexDownloadTableExt () {}
+void grTexDownloadTablePartial () {}
+void grTexFilterMode () {}
+void grTexLodBiasValue () {}
+void grTexMaxAddress () {}
+void grTexMinAddress () {}
+void grTexMipMapMode () {}
+void grTexMultibase () {}
+void grTexMultibaseAddress () {}
+void grTexNCCTable () {}
+void grTexSource () {}
+void grTexTextureMemRequired () {}
+void grTriStats () {}
+void grVertexLayout () {}
+void grViewport () {}
+void gu3dfGetInfo () {}
+void gu3dfLoad () {}
+void guFogGenerateExp () {}
+void guFogGenerateExp2 () {}
+void guFogGenerateLinear () {}
+void guFogTableIndexToW () {}
+void guGammaCorrectionRGB () {}
+
+/* external libc symbols required by all of
+ * sst1, sst96, cvg, h3 and h5 glide3x.dxe:
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+#include <dos.h>
+#include <dpmi.h>
+#include <sys/nearptr.h>
+#include <setjmp.h>
+#include <crt0.h>
+long EXTSYM0000 = (long) &_crt0_startup_flags;
+long EXTSYM0001 = (long) &__dj_assert;
+long EXTSYM0002 = (long) &__djgpp_base_address;
+long EXTSYM0003 = (long) &__djgpp_nearptr_disable;
+long EXTSYM0004 = (long) &__djgpp_nearptr_enable;
+long EXTSYM0005 = (long) &__dj_stderr;
+long EXTSYM0006 = (long) &__dj_stdout;
+long EXTSYM0007 = (long) &__dpmi_free_physical_address_mapping;
+long EXTSYM0008 = (long) &__dpmi_physical_address_mapping;
+long EXTSYM0009 = (long) &atof;
+long EXTSYM0010 = (long) &atoi;
+long EXTSYM0011 = (long) &atol;
+long EXTSYM0012 = (long) &clock;
+long EXTSYM0013 = (long) &exit;
+long EXTSYM0014 = (long) &fclose;
+long EXTSYM0015 = (long) &fflush;
+long EXTSYM0016 = (long) &fgetc;
+long EXTSYM0017 = (long) &fgets;
+long EXTSYM0018 = (long) &fopen;
+long EXTSYM0019 = (long) &fprintf;
+long EXTSYM0020 = (long) &fread;
+long EXTSYM0021 = (long) &free;
+long EXTSYM0022 = (long) &fwrite;
+long EXTSYM0023 = (long) &getc;
+long EXTSYM0024 = (long) &getenv;
+long EXTSYM0025 = (long) &int86;
+long EXTSYM0026 = (long) &longjmp;
+long EXTSYM0027 = (long) &malloc;
+long EXTSYM0028 = (long) &memcpy;
+long EXTSYM0029 = (long) &memset;
+long EXTSYM0030 = (long) &pow;
+long EXTSYM0031 = (long) &printf;
+long EXTSYM0032 = (long) &putenv;
+long EXTSYM0033 = (long) &puts;
+long EXTSYM0034 = (long) &setjmp;
+long EXTSYM0035 = (long) &signal;
+long EXTSYM0036 = (long) &sprintf;
+long EXTSYM0037 = (long) &sscanf;
+long EXTSYM0038 = (long) &strcat;
+long EXTSYM0039 = (long) &strchr;
+long EXTSYM0040 = (long) &strcmp;
+long EXTSYM0041 = (long) &strcpy;
+long EXTSYM0042 = (long) &strncat;
+long EXTSYM0043 = (long) &strncpy;
+long EXTSYM0044 = (long) &strtok;
+long EXTSYM0045 = (long) &strtoul;
+long EXTSYM0046 = (long) &usleep;
+long EXTSYM0047 = (long) &vfprintf;
+long EXTSYM0048 = (long) &vsprintf;
+
diff --git a/src/mesa/drivers/osmesa/Makefile.win b/src/mesa/drivers/osmesa/Makefile.win
new file mode 100644
index 0000000..36d520e
--- /dev/null
+++ b/src/mesa/drivers/osmesa/Makefile.win
@@ -0,0 +1,39 @@
+# Makefile for Win32
+
+!include <win32.mak>
+
+TOP = ..\..
+
+OSMESA_SRCS = osmesa.c
+OSMESA_OBJS = osmesa.obj
+
+ASM_SRCS =
+CORE_SRCS =
+DRIVER_SRCS = $(OSMESA_SRCS)
+
+SRCS = $(OSMESA_SRCS)
+
+all : osmesadll
+
+!include "$(TOP)/mesawin32.mak"
+
+osmesadll: $(OSMESADLL)
+
+CFLAGS = $(cvarsdll) $(CFLAGS) -D_OPENGL32_ -DBUILD_GL32 -I$(TOP)/src
+LFLAGS = $(dlllflags) $(lcommon) $(LFLAGS)
+
+OBJS = $(ASM_SRCS:.S=.obj) $(CORE_SRCS:.c=.obj) $(DRIVER_SRCS:.c=.obj)
+LIBS = $(guilibsdll) $(TOP)/lib/$(MESALIB)
+
+$(OSMESADLL) : $(OBJS) osmesa.def
+ $(link) $(LFLAGS) -def:osmesa.def -out:$(OSMESADLL) $(OBJS) $(LIBS)
+ @echo "copying OSMesa library to library directory..."
+ -copy $(OSMESALIB) $(TOP)\lib
+ @echo "copying OSMesa dll to library directory..."
+ -copy $(OSMESADLL) $(TOP)\lib
+
+install : $(OSMESADLL)
+ @echo "copying OSMesa library to system library directory..."
+ -copy $(OSMESALIB) $(LIBINSTALL)
+ @echo "copying OSMesa dll to system library directory..."
+ -copy $(OSMESADLL) $(DLLINSTALL)
diff --git a/src/mesa/drivers/osmesa/descrip.mms b/src/mesa/drivers/osmesa/descrip.mms
new file mode 100644
index 0000000..64dc041
--- /dev/null
+++ b/src/mesa/drivers/osmesa/descrip.mms
@@ -0,0 +1,41 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
+# Last revision : 16 June 2003
+
+.first
+ define gl [----.include.gl]
+ define math [--.math]
+ define tnl [--.tnl]
+ define swrast [--.swrast]
+ define swrast_setup [--.swrast_setup]
+ define array_cache [--.array_cache]
+ define drivers [-]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)
+
+SOURCES = osmesa.c
+
+OBJECTS = osmesa.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+osmesa.obj : osmesa.c
diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c
new file mode 100644
index 0000000..366bb03
--- /dev/null
+++ b/src/mesa/drivers/osmesa/osmesa.c
@@ -0,0 +1,1307 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+/*
+ * Off-Screen Mesa rendering / Rendering into client memory space
+ *
+ * Note on thread safety: this driver is thread safe. All
+ * functions are reentrant. The notion of current context is
+ * managed by the core _mesa_make_current() and _mesa_get_current_context()
+ * functions. Those functions are thread-safe.
+ */
+
+
+#include "glheader.h"
+#include "GL/osmesa.h"
+#include "buffers.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "imports.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstore.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 "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+
+
+
+/*
+ * 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.
+ */
+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 rshift, gshift; /* bit shifts for RGBA formats */
+ GLint bshift, ashift;
+ 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 */
+};
+
+
+/* Just cast, since we're using structure containment */
+#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx))
+
+
+
+/**********************************************************************/
+/*** Private Device Driver Functions ***/
+/**********************************************************************/
+
+
+static const GLubyte *
+get_string( GLcontext *ctx, GLenum name )
+{
+ (void) ctx;
+ switch (name) {
+ case GL_RENDERER:
+#if CHAN_BITS == 32
+ return (const GLubyte *) "Mesa OffScreen32";
+#elif CHAN_BITS == 16
+ return (const GLubyte *) "Mesa OffScreen16";
+#else
+ return (const GLubyte *) "Mesa OffScreen";
+#endif
+ default:
+ return NULL;
+ }
+}
+
+
+static void
+osmesa_update_state( GLcontext *ctx, GLuint new_state )
+{
+ /* easy - just propogate */
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+
+static void
+set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
+{
+ /* separate read buffer not supported */
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(bufferBit == DD_FRONT_LEFT_BIT);
+}
+
+
+static void
+get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
+ GLcontext *ctx = (GLcontext *) _glapi_get_context();
+ (void) buffer;
+ if (ctx) {
+ OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ *width = osmesa->width;
+ *height = osmesa->height;
+ }
+}
+
+
+static void
+clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ /* sanity check - we only have a front-left buffer */
+ ASSERT((mask & (DD_FRONT_RIGHT_BIT |
+ DD_BACK_LEFT_BIT |
+ DD_BACK_RIGHT_BIT)) == 0);
+
+ /* use optimized clear for common cases (clear whole buffer to black) */
+ if (mask & DD_FRONT_LEFT_BIT) {
+ if (osmesa->format == OSMESA_COLOR_INDEX) {
+ if (ctx->Color.ClearIndex == 0 &&
+ ctx->Color.IndexMask == (GLuint) ~0 &&
+ osmesa->rowlength == osmesa->width &&
+ all) {
+ /* clear whole buffer to zeros */
+ _mesa_bzero(osmesa->buffer,
+ osmesa->width * osmesa->height * sizeof(GLchan));
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ }
+ else {
+ /* RGB[A] format */
+ if (*colorMask == 0xffffffff &&
+ ctx->Color.ClearColor[0] == 0.0F &&
+ ctx->Color.ClearColor[1] == 0.0F &&
+ ctx->Color.ClearColor[2] == 0.0F &&
+ ctx->Color.ClearColor[3] == 0.0F &&
+ osmesa->rowlength == osmesa->width &&
+ all) {
+ GLint bytesPerPixel;
+ /* clear whole buffer to black */
+ if (osmesa->format == OSMESA_RGBA ||
+ osmesa->format == OSMESA_BGRA ||
+ osmesa->format == OSMESA_ARGB)
+ bytesPerPixel = 4 * sizeof(GLchan);
+ else if (osmesa->format == OSMESA_RGB ||
+ osmesa->format == OSMESA_BGR)
+ bytesPerPixel = 3 * sizeof(GLchan);
+ else if (osmesa->format == OSMESA_RGB_565)
+ bytesPerPixel = sizeof(GLushort);
+ else {
+ _mesa_problem(ctx, "bad pixel format in osmesa_clear()");
+ return;
+ }
+ _mesa_bzero(osmesa->buffer,
+ bytesPerPixel * osmesa->width * osmesa->height);
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ }
+ }
+
+ if (mask) {
+ /* software fallback (spans) for everything else. */
+ _swrast_Clear(ctx, mask, all, x, y, width, height);
+ }
+}
+
+
+/**********************************************************************/
+/***** Read/write spans/arrays of pixels *****/
+/**********************************************************************/
+
+
+/* RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#if CHAN_TYPE == GL_FLOAT
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = MAX2((R), 0.0F); \
+ P[1] = MAX2((G), 0.0F); \
+ P[2] = MAX2((B), 0.0F); \
+ P[3] = CHAN_MAXF
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = MAX2((R), 0.0F); \
+ P[1] = MAX2((G), 0.0F); \
+ P[2] = MAX2((B), 0.0F); \
+ P[3] = CLAMP((A), 0.0F, CHAN_MAXF)
+#else
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = R; P[1] = G; P[2] = B; P[3] = A
+#endif
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[0]; G = P[1]; B = P[2]; A = P[3]
+#include "swrast/s_spantemp.h"
+
+/* BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[2] = R; P[1] = G; P[0] = B; P[3] = A
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[2]; G = P[1]; B = P[0]; A = P[3]
+#include "swrast/s_spantemp.h"
+
+/* ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[1] = R; P[2] = G; P[3] = B; P[0] = A
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[1]; G = P[2]; B = P[3]; A = P[0]
+#include "swrast/s_spantemp.h"
+
+/* RGB */
+#define NAME(PREFIX) PREFIX##_RGB
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = R; P[1] = G; P[2] = B
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = R; P[1] = G; P[2] = B
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = P[0]; G = P[1]; B = P[2]; A = CHAN_MAX
+#include "swrast/s_spantemp.h"
+
+/* BGR */
+#define NAME(PREFIX) PREFIX##_BGR
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ P[0] = B; P[1] = G; P[2] = R
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ P[0] = B; P[1] = G; P[2] = R
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ B = P[0]; G = P[1]; R = P[2]; A = CHAN_MAX
+#include "swrast/s_spantemp.h"
+
+/* 16-bit BGR */
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+#define NAME(PREFIX) PREFIX##_RGB_565
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
+ G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
+ B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
+ A = CHAN_MAX
+#include "swrast/s_spantemp.h"
+#endif
+
+/* color index */
+#define NAME(PREFIX) PREFIX##_CI
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLchan *P = osmesa->rowaddr[Y] + (X)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_CI_PIXEL(P, CI) \
+ P[0] = CI
+#define FETCH_CI_PIXEL(CI, P) \
+ CI = P[0]
+#include "swrast/s_spantemp.h"
+
+
+/**********************************************************************/
+/***** Optimized line rendering *****/
+/**********************************************************************/
+
+
+#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; \
+ (DST)[osmesa->gInd] = G; \
+ (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 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
+#define CLIP_HACK 1
+#define SETUP_CODE \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
+ const GLchan *color = vert1->color;
+
+#define PLOT(X, Y) \
+do { \
+ GLchan *p = PIXELADDR4(X, Y); \
+ PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
+} while (0)
+
+#ifdef WIN32
+#include "..\swrast\s_linetemp.h"
+#else
+#include "swrast/s_linetemp.h"
+#endif
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
+ */
+#define NAME flat_rgba_z_line
+#define CLIP_HACK 1
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
+ const GLchan *color = vert1->color;
+
+#define PLOT(X, Y) \
+do { \
+ if (Z < *zPtr) { \
+ GLchan *p = PIXELADDR4(X, Y); \
+ PACK_RGBA(p, color[RCOMP], color[GCOMP], \
+ color[BCOMP], color[ACOMP]); \
+ *zPtr = Z; \
+ } \
+} while (0)
+
+#ifdef WIN32
+#include "..\swrast\s_linetemp.h"
+#else
+#include "swrast/s_linetemp.h"
+#endif
+
+
+
+/*
+ * Analyze context state to see if we can provide a fast line drawing
+ * function, like those in lines.c. Otherwise, return NULL.
+ */
+static swrast_line_func
+osmesa_choose_line_function( GLcontext *ctx )
+{
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (CHAN_BITS != 8) return NULL;
+ if (ctx->RenderMode != GL_RENDER) return NULL;
+ if (ctx->Line.SmoothFlag) return NULL;
+ if (ctx->Texture._EnabledUnits) return NULL;
+ if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
+ if (ctx->Line.Width != 1.0F) return NULL;
+ if (ctx->Line.StippleFlag) return NULL;
+ if (ctx->Line.SmoothFlag) return NULL;
+ if (osmesa->format != OSMESA_RGBA &&
+ osmesa->format != OSMESA_BGRA &&
+ osmesa->format != OSMESA_ARGB) return NULL;
+
+ if (swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
+ return (swrast_line_func) flat_rgba_z_line;
+ }
+
+ if (swrast->_RasterMask == 0) {
+ return (swrast_line_func) flat_rgba_line;
+ }
+
+ return (swrast_line_func) NULL;
+}
+
+
+/**********************************************************************/
+/***** Optimized triangle rendering *****/
+/**********************************************************************/
+
+
+/*
+ * Smooth-shaded, z-less triangle, RGBA color.
+ */
+#define NAME smooth_rgba_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define SETUP_CODE \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLchan *img = PIXELADDR4(span.x, span.y); \
+ for (i = 0; i < span.end; i++, img += 4) { \
+ const GLdepth z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ PACK_RGBA(img, FixedToChan(span.red), \
+ FixedToChan(span.green), FixedToChan(span.blue), \
+ FixedToChan(span.alpha)); \
+ zRow[i] = z; \
+ } \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ span.alpha += span.alphaStep; \
+ span.z += span.zStep; \
+ }
+#ifdef WIN32
+#include "..\swrast\s_tritemp.h"
+#else
+#include "swrast/s_tritemp.h"
+#endif
+
+
+
+/*
+ * Flat-shaded, z-less triangle, RGBA color.
+ */
+#define NAME flat_rgba_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
+ GLuint pixel; \
+ PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \
+ v2->color[2], v2->color[3]);
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \
+ for (i = 0; i < span.end; i++) { \
+ const GLdepth z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ img[i] = pixel; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#ifdef WIN32
+#include "..\swrast\s_tritemp.h"
+#else
+#include "swrast/s_tritemp.h"
+#endif
+
+
+
+/*
+ * Return pointer to an accelerated triangle function if possible.
+ */
+static swrast_tri_func
+osmesa_choose_triangle_function( GLcontext *ctx )
+{
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (CHAN_BITS != 8) 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->Polygon.StippleFlag) return (swrast_tri_func) NULL;
+ if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL;
+ if (osmesa->format != OSMESA_RGBA &&
+ osmesa->format != OSMESA_BGRA &&
+ osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
+ if (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) {
+ if (ctx->Light.ShadeModel == GL_SMOOTH) {
+ return (swrast_tri_func) smooth_rgba_z_triangle;
+ }
+ else {
+ return (swrast_tri_func) flat_rgba_z_triangle;
+ }
+ }
+ 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
+osmesa_choose_triangle( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ swrast->Triangle = osmesa_choose_triangle_function( ctx );
+ if (!swrast->Triangle)
+ _swrast_choose_triangle( ctx );
+}
+
+static void
+osmesa_choose_line( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ swrast->Line = osmesa_choose_line_function( ctx );
+ if (!swrast->Line)
+ _swrast_choose_line( ctx );
+}
+
+
+#define OSMESA_NEW_LINE (_NEW_LINE | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+
+/* one-time, per-context initialization */
+static void
+hook_in_driver_functions( GLcontext *ctx )
+{
+ OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
+
+ /* use default TCL pipeline */
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ swdd->SetBuffer = set_buffer;
+
+ /* RGB(A) span/pixel functions */
+ if (osmesa->format == OSMESA_RGB) {
+ swdd->WriteRGBASpan = write_rgba_span_RGB;
+ swdd->WriteRGBSpan = write_rgb_span_RGB;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_RGB;
+ swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB;
+ swdd->ReadRGBASpan = read_rgba_span_RGB;
+ swdd->ReadRGBAPixels = read_rgba_pixels_RGB;
+ }
+ else if (osmesa->format == OSMESA_BGR) {
+ swdd->WriteRGBASpan = write_rgba_span_BGR;
+ swdd->WriteRGBSpan = write_rgb_span_BGR;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_BGR;
+ swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR;
+ swdd->ReadRGBASpan = read_rgba_span_BGR;
+ swdd->ReadRGBAPixels = read_rgba_pixels_BGR;
+ }
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ else if (osmesa->format == OSMESA_RGB_565) {
+ swdd->WriteRGBASpan = write_rgba_span_RGB_565;
+ swdd->WriteRGBSpan = write_rgb_span_RGB_565;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565;
+ swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565;
+ swdd->ReadRGBASpan = read_rgba_span_RGB_565;
+ swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565;
+ }
+#endif
+ else if (osmesa->format == OSMESA_RGBA) {
+ swdd->WriteRGBASpan = write_rgba_span_RGBA;
+ swdd->WriteRGBSpan = write_rgb_span_RGBA;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA;
+ swdd->WriteRGBAPixels = write_rgba_pixels_RGBA;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA;
+ swdd->ReadRGBASpan = read_rgba_span_RGBA;
+ swdd->ReadRGBAPixels = read_rgba_pixels_RGBA;
+ }
+ else if (osmesa->format == OSMESA_BGRA) {
+ swdd->WriteRGBASpan = write_rgba_span_BGRA;
+ swdd->WriteRGBSpan = write_rgb_span_BGRA;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA;
+ swdd->WriteRGBAPixels = write_rgba_pixels_BGRA;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA;
+ swdd->ReadRGBASpan = read_rgba_span_BGRA;
+ swdd->ReadRGBAPixels = read_rgba_pixels_BGRA;
+ }
+ else if (osmesa->format == OSMESA_ARGB) {
+ swdd->WriteRGBASpan = write_rgba_span_ARGB;
+ swdd->WriteRGBSpan = write_rgb_span_ARGB;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB;
+ swdd->WriteRGBAPixels = write_rgba_pixels_ARGB;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB;
+ swdd->ReadRGBASpan = read_rgba_span_ARGB;
+ swdd->ReadRGBAPixels = read_rgba_pixels_ARGB;
+ }
+ else if (osmesa->format == OSMESA_COLOR_INDEX) {
+ swdd->WriteCI32Span = write_index32_span_CI;
+ swdd->WriteCI8Span = write_index8_span_CI;
+ swdd->WriteMonoCISpan = write_monoindex_span_CI;
+ swdd->WriteCI32Pixels = write_index_pixels_CI;
+ swdd->WriteMonoCIPixels = write_monoindex_pixels_CI;
+ swdd->ReadCI32Span = read_index_span_CI;
+ swdd->ReadCI32Pixels = read_index_pixels_CI;
+ }
+ else {
+ _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n");
+ }
+
+ /* Extend the software rasterizer with our optimized line and triangle
+ * drawin functions.
+ */
+ swrast->choose_line = osmesa_choose_line;
+ swrast->choose_triangle = osmesa_choose_triangle;
+ swrast->invalidate_line |= OSMESA_NEW_LINE;
+ swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
+}
+
+
+
+
+/**********************************************************************/
+/***** Public Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Create an Off-Screen Mesa rendering context. The only attribute needed is
+ * an RGBA vs Color-Index mode flag.
+ *
+ * Input: format - either GL_RGBA or GL_COLOR_INDEX
+ * sharelist - specifies another OSMesaContext with which to share
+ * display lists. NULL indicates no sharing.
+ * Return: an OSMesaContext or 0 if error
+ */
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
+{
+ const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
+ return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
+ 8, accumBits, sharelist);
+}
+
+
+
+/*
+ * New in Mesa 3.5
+ *
+ * Create context and specify size of ancillary buffers.
+ */
+GLAPI OSMesaContext GLAPIENTRY
+OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
+ GLint accumBits, OSMesaContext sharelist )
+{
+ OSMesaContext osmesa;
+ struct dd_function_table functions;
+ GLint rshift, gshift, bshift, ashift;
+ GLint rind, gind, bind, aind;
+ GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
+ GLboolean rgbmode;
+ const GLuint i4 = 1;
+ const GLubyte *i1 = (GLubyte *) &i4;
+ const GLint little_endian = *i1;
+
+ rind = gind = bind = aind = 0;
+ if (format==OSMESA_COLOR_INDEX) {
+ indexBits = 8;
+ rshift = gshift = bshift = ashift = 0;
+ rgbmode = GL_FALSE;
+ }
+ else if (format==OSMESA_RGBA) {
+ indexBits = 0;
+ redBits = CHAN_BITS;
+ greenBits = CHAN_BITS;
+ blueBits = CHAN_BITS;
+ alphaBits = CHAN_BITS;
+ rind = 0;
+ gind = 1;
+ bind = 2;
+ aind = 3;
+ if (little_endian) {
+ rshift = 0;
+ gshift = 8;
+ bshift = 16;
+ ashift = 24;
+ }
+ else {
+ rshift = 24;
+ gshift = 16;
+ bshift = 8;
+ ashift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_BGRA) {
+ indexBits = 0;
+ redBits = CHAN_BITS;
+ greenBits = CHAN_BITS;
+ blueBits = CHAN_BITS;
+ alphaBits = CHAN_BITS;
+ bind = 0;
+ gind = 1;
+ rind = 2;
+ aind = 3;
+ if (little_endian) {
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ }
+ else {
+ bshift = 24;
+ gshift = 16;
+ rshift = 8;
+ ashift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_ARGB) {
+ indexBits = 0;
+ redBits = CHAN_BITS;
+ greenBits = CHAN_BITS;
+ blueBits = CHAN_BITS;
+ alphaBits = CHAN_BITS;
+ aind = 0;
+ rind = 1;
+ gind = 2;
+ bind = 3;
+ if (little_endian) {
+ ashift = 0;
+ rshift = 8;
+ gshift = 16;
+ bshift = 24;
+ }
+ else {
+ ashift = 24;
+ rshift = 16;
+ gshift = 8;
+ bshift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_RGB) {
+ indexBits = 0;
+ redBits = CHAN_BITS;
+ greenBits = CHAN_BITS;
+ blueBits = CHAN_BITS;
+ alphaBits = 0;
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ rind = 0;
+ gind = 1;
+ bind = 2;
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_BGR) {
+ indexBits = 0;
+ redBits = CHAN_BITS;
+ greenBits = CHAN_BITS;
+ blueBits = CHAN_BITS;
+ alphaBits = 0;
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ rind = 2;
+ gind = 1;
+ bind = 0;
+ rgbmode = GL_TRUE;
+ }
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ else if (format==OSMESA_RGB_565) {
+ indexBits = 0;
+ redBits = 5;
+ greenBits = 6;
+ blueBits = 5;
+ alphaBits = 0;
+ rshift = 11;
+ gshift = 5;
+ bshift = 0;
+ ashift = 0;
+ rind = 0; /* not used */
+ gind = 0;
+ bind = 0;
+ rgbmode = GL_TRUE;
+ }
+#endif
+ else {
+ return NULL;
+ }
+
+
+ osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
+ if (osmesa) {
+ osmesa->gl_visual = _mesa_create_visual( rgbmode,
+ GL_FALSE, /* double buffer */
+ GL_FALSE, /* stereo */
+ redBits,
+ greenBits,
+ blueBits,
+ alphaBits,
+ indexBits,
+ depthBits,
+ stencilBits,
+ accumBits,
+ accumBits,
+ accumBits,
+ alphaBits ? accumBits : 0,
+ 1 /* num samples */
+ );
+ if (!osmesa->gl_visual) {
+ FREE(osmesa);
+ return NULL;
+ }
+
+ /* Initialize device driver function table */
+ _mesa_init_driver_functions(&functions);
+ /* override with our functions */
+ functions.GetString = get_string;
+ functions.UpdateState = osmesa_update_state;
+ functions.GetBufferSize = get_buffer_size;
+ functions.Clear = clear;
+
+ if (!_mesa_initialize_context(&osmesa->mesa,
+ osmesa->gl_visual,
+ sharelist ? &sharelist->mesa
+ : (GLcontext *) NULL,
+ &functions, (void *) osmesa)) {
+ _mesa_destroy_visual( osmesa->gl_visual );
+ FREE(osmesa);
+ return NULL;
+ }
+
+ _mesa_enable_sw_extensions(&(osmesa->mesa));
+ _mesa_enable_1_3_extensions(&(osmesa->mesa));
+ _mesa_enable_1_4_extensions(&(osmesa->mesa));
+ _mesa_enable_1_5_extensions(&(osmesa->mesa));
+
+ osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
+ (GLboolean) ( osmesa->gl_visual->depthBits > 0 ),
+ (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ),
+ (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ),
+ GL_FALSE /* s/w alpha */ );
+
+ if (!osmesa->gl_buffer) {
+ _mesa_destroy_visual( osmesa->gl_visual );
+ _mesa_free_context_data( &osmesa->mesa );
+ FREE(osmesa);
+ return NULL;
+ }
+ osmesa->format = format;
+ osmesa->buffer = NULL;
+ osmesa->width = 0;
+ osmesa->height = 0;
+ osmesa->userRowLength = 0;
+ osmesa->rowlength = 0;
+ osmesa->yup = GL_TRUE;
+ osmesa->rshift = rshift;
+ osmesa->gshift = gshift;
+ osmesa->bshift = bshift;
+ osmesa->ashift = ashift;
+ osmesa->rInd = rind;
+ osmesa->gInd = gind;
+ osmesa->bInd = bind;
+ osmesa->aInd = aind;
+
+ /* Initialize the software rasterizer and helper modules. */
+ {
+ GLcontext *ctx = &osmesa->mesa;
+
+ if (!_swrast_CreateContext( ctx ) ||
+ !_ac_CreateContext( ctx ) ||
+ !_tnl_CreateContext( ctx ) ||
+ !_swsetup_CreateContext( ctx )) {
+ _mesa_destroy_visual(osmesa->gl_visual);
+ _mesa_free_context_data(ctx);
+ _mesa_free(osmesa);
+ return NULL;
+ }
+
+ _swsetup_Wakeup( ctx );
+ hook_in_driver_functions( ctx );
+ }
+ }
+ return osmesa;
+}
+
+
+/*
+ * Destroy an Off-Screen Mesa rendering context.
+ *
+ * Input: ctx - 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 )
+{
+ GLint bytesPerPixel, bytesPerRow, i;
+ GLubyte *origin = (GLubyte *) ctx->buffer;
+
+ if (ctx->format == OSMESA_COLOR_INDEX) {
+ /* CI mode */
+ bytesPerPixel = 1 * sizeof(GLchan);
+ }
+ 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);
+ }
+ }
+}
+
+
+/*
+ * 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
+ * of 4 if using RGBA mode.
+ *
+ * Image data is stored in the order of glDrawPixels: row-major order
+ * with the lower-left image pixel stored in the first array position
+ * (ie. bottom-to-top).
+ *
+ * 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
+ * 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.
+ * width, height - size of image buffer in pixels, at least 1
+ * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
+ * 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,
+ GLsizei width, GLsizei height )
+{
+ if (!ctx || !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;
+ }
+ else if (type != CHAN_TYPE) {
+ return GL_FALSE;
+ }
+
+ osmesa_update_state( &ctx->mesa, 0 );
+ _mesa_make_current( &ctx->mesa, ctx->gl_buffer );
+
+ ctx->buffer = buffer;
+ ctx->width = width;
+ ctx->height = height;
+ if (ctx->userRowLength)
+ ctx->rowlength = ctx->userRowLength;
+ else
+ ctx->rowlength = width;
+
+ compute_row_addresses( ctx );
+
+ /* init viewport */
+ if (ctx->mesa.Viewport.Width == 0) {
+ /* initialize viewport and scissor box to buffer size */
+ _mesa_Viewport( 0, 0, width, height );
+ ctx->mesa.Scissor.Width = width;
+ ctx->mesa.Scissor.Height = height;
+ }
+ else {
+ /* this will make ensure we recognize the new buffer size */
+ _mesa_ResizeBuffersMESA();
+ }
+
+ /* Added by Gerk Huisma: */
+ _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer,
+ ctx->mesa.ReadBuffer );
+
+ return GL_TRUE;
+}
+
+
+
+GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
+{
+ GLcontext *ctx = _mesa_get_current_context();
+ if (ctx)
+ return (OSMesaContext) ctx;
+ else
+ return NULL;
+}
+
+
+
+GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
+{
+ OSMesaContext osmesa = OSMesaGetCurrentContext();
+
+ switch (pname) {
+ case OSMESA_ROW_LENGTH:
+ if (value<0) {
+ _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
+ "OSMesaPixelStore(value)" );
+ return;
+ }
+ osmesa->userRowLength = value;
+ osmesa->rowlength = value ? value : osmesa->width;
+ break;
+ case OSMESA_Y_UP:
+ osmesa->yup = value ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
+ return;
+ }
+
+ compute_row_addresses( osmesa );
+}
+
+
+GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
+{
+ OSMesaContext osmesa = OSMesaGetCurrentContext();
+
+ switch (pname) {
+ case OSMESA_WIDTH:
+ *value = osmesa->width;
+ return;
+ case OSMESA_HEIGHT:
+ *value = osmesa->height;
+ return;
+ case OSMESA_FORMAT:
+ *value = osmesa->format;
+ return;
+ case OSMESA_TYPE:
+ *value = CHAN_TYPE;
+ return;
+ case OSMESA_ROW_LENGTH:
+ *value = osmesa->userRowLength;
+ return;
+ case OSMESA_Y_UP:
+ *value = osmesa->yup;
+ return;
+ case OSMESA_MAX_WIDTH:
+ *value = MAX_WIDTH;
+ return;
+ case OSMESA_MAX_HEIGHT:
+ *value = MAX_HEIGHT;
+ return;
+ default:
+ _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
+ return;
+ }
+}
+
+/*
+ * Return the depth buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLAPI GLboolean GLAPIENTRY
+OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
+ GLint *bytesPerValue, void **buffer )
+{
+ if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
+ *width = 0;
+ *height = 0;
+ *bytesPerValue = 0;
+ *buffer = 0;
+ return GL_FALSE;
+ }
+ else {
+ *width = c->gl_buffer->Width;
+ *height = c->gl_buffer->Height;
+ if (c->gl_visual->depthBits <= 16)
+ *bytesPerValue = sizeof(GLushort);
+ else
+ *bytesPerValue = sizeof(GLuint);
+ *buffer = c->gl_buffer->DepthBuffer;
+ return GL_TRUE;
+ }
+}
+
+/*
+ * Return the color buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * format - the pixel format (OSMESA_FORMAT)
+ * buffer - pointer to color buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLAPI GLboolean GLAPIENTRY
+OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
+ GLint *height, GLint *format, void **buffer )
+{
+ if (!c->buffer) {
+ *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;
+ }
+}
+
+
+typedef void (*OSMESAproc)(void);
+
+struct name_function
+{
+ const char *Name;
+ OSMESAproc Function;
+};
+
+static struct name_function functions[] = {
+ { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
+ { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
+ { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
+ { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
+ { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
+ { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
+ { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
+ { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
+ { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
+ { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
+ { NULL, NULL }
+};
+
+GLAPI void * GLAPIENTRY
+OSMesaGetProcAddress( const char *funcName )
+{
+ int i;
+ for (i = 0; functions[i].Name; i++) {
+ if (_mesa_strcmp(functions[i].Name, funcName) == 0)
+ return (void *) functions[i].Function;
+ }
+ return (void *) _glapi_get_proc_address(funcName);
+}
diff --git a/src/mesa/drivers/osmesa/osmesa.def b/src/mesa/drivers/osmesa/osmesa.def
new file mode 100644
index 0000000..a92a30f
--- /dev/null
+++ b/src/mesa/drivers/osmesa/osmesa.def
@@ -0,0 +1,13 @@
+DESCRIPTION 'Mesa OSMesa lib for Win32'
+VERSION 4.1
+
+EXPORTS
+ OSMesaCreateContext
+ OSMesaCreateContextExt
+ OSMesaDestroyContext
+ OSMesaMakeCurrent
+ OSMesaGetCurrentContext
+ OSMesaPixelStore
+ OSMesaGetIntegerv
+ OSMesaGetDepthBuffer
+ OSMesaGetColorBuffer
diff --git a/src/mesa/drivers/osmesa/osmesa.dsp b/src/mesa/drivers/osmesa/osmesa.dsp
new file mode 100644
index 0000000..c818185
--- /dev/null
+++ b/src/mesa/drivers/osmesa/osmesa.dsp
@@ -0,0 +1,119 @@
+# Microsoft Developer Studio Project File - Name="osmesa" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=osmesa - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "osmesa.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "osmesa.mak" CFG="osmesa - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "osmesa - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "osmesa - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "osmesa - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSMESA_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../../include" /I "../../" /I "../../main" /I "../../glapi" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSMESA_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 msvcrt.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib /out:"Release/OSMESA32.DLL"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy Release\OSMESA32.LIB ..\..\..\..\lib copy Release\OSMESA32.DLL ..\..\..\..\lib
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "osmesa - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSMESA_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../" /I "../../../../include" /I "../../main" /I "../../glapi" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OSMESA_EXPORTS" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 msvcrtd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /nodefaultlib /out:"Debug/OSMESA32.DLL" /pdbtype:sept
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Cmds=copy Debug\OSMESA32.LIB ..\..\..\..\lib copy Debug\OSMESA32.DLL ..\..\..\..\lib
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "osmesa - Win32 Release"
+# Name "osmesa - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\osmesa.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\osmesa.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c
new file mode 100644
index 0000000..5f636e1
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa.c
@@ -0,0 +1,513 @@
+/* $Id: svgamesa.c,v 1.23 2002/11/11 18:42:38 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vga.h>
+#include "GL/svgamesa.h"
+#include "context.h"
+#include "extensions.h"
+#include "imports.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "svgapix.h"
+#include "svgamesa8.h"
+#include "svgamesa15.h"
+#include "svgamesa16.h"
+#include "svgamesa24.h"
+#include "svgamesa32.h"
+
+struct svga_buffer SVGABuffer;
+vga_modeinfo * SVGAInfo;
+SVGAMesaContext SVGAMesa; /* the current context */
+
+#ifdef SVGA_DEBUG
+
+#include <sys/types.h>
+#include <signal.h>
+
+FILE * logfile;
+char cbuf[1024]={0};
+
+void SVGAlog(char * what)
+{
+ logfile=fopen("svgamesa.log","a");
+ if (!logfile) return;
+ fprintf(logfile,"%s\n",what);
+ fclose(logfile);
+}
+#endif
+
+/**********************************************************************/
+/***** Init stuff... *****/
+/**********************************************************************/
+
+int SVGAMesaInit( int GraphMode )
+{
+ vga_init();
+ if (!vga_hasmode(GraphMode))
+ {
+ fprintf(stderr,"GraphMode %d unavailable...",GraphMode);
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAMesaInit: invalid GraphMode (doesn't exist)");
+#endif
+ return(1);
+ }
+ SVGAInfo=vga_getmodeinfo(GraphMode);
+ if (SVGAInfo->flags & IS_MODEX)
+ {
+ fprintf(stderr,"ModeX not implemented...");
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAMesaInit: invalid GraphMode (ModeX)");
+#endif
+ return(2);
+ }
+ if (!SVGAInfo->bytesperpixel)
+ {
+ fprintf(stderr,"1 / 4 bit color not implemented...");
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAMesaInit: invalid GraphMode (1 or 4 bit)");
+#endif
+ return(3);
+ }
+ switch (SVGAInfo->colors) {
+ case 256: SVGABuffer.Depth = 8; break;
+ case 32768: SVGABuffer.Depth = 15; break;
+ case 65536: SVGABuffer.Depth = 16; break;
+ default: SVGABuffer.Depth = SVGAInfo->bytesperpixel<<3; break;
+ }
+ SVGABuffer.BufferSize=SVGAInfo->linewidth*SVGAInfo->height;
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaInit: double buffer info.\n" \
+ " depth : %d\n" \
+ " mode : %d\n" \
+ " width : %d\n" \
+ " height : %d\n" \
+ " bufsize: %d\n", \
+ SVGABuffer.Depth,GraphMode,SVGAInfo->linewidth, \
+ SVGAInfo->height,SVGABuffer.BufferSize);
+ SVGAlog(cbuf);
+#endif
+ SVGABuffer.FrontBuffer=(void*)malloc(SVGABuffer.BufferSize + 4);
+ if (!SVGABuffer.FrontBuffer) {
+ {
+ fprintf(stderr,"Not enough RAM for FRONT_LEFT_BUFFER...");
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAMesaInit: Not enough RAM (front buffer)");
+#endif
+ return(4);
+ }
+ }
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaInit: FrontBuffer - %p",SVGABuffer.FrontBuffer);
+ SVGAlog(cbuf);
+#endif
+ SVGABuffer.BackBuffer=(void*)malloc(SVGABuffer.BufferSize + 4);
+ if (!SVGABuffer.BackBuffer) {
+ {
+ free(SVGABuffer.FrontBuffer);
+ fprintf(stderr,"Not enough RAM for BACK_LEFT_BUFFER...");
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAMesaInit: Not enough RAM (back buffer)");
+#endif
+ return(5);
+ }
+ }
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaInit: BackBuffer - %p",SVGABuffer.BackBuffer);
+ SVGAlog(cbuf);
+#endif
+
+ vga_setmode(GraphMode);
+ SVGABuffer.VideoRam=vga_getgraphmem();
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaInit: VRAM - %p",SVGABuffer.VideoRam);
+ SVGAlog(cbuf);
+ sprintf(cbuf,"SVGAMesaInit: done. (Mode %d)",GraphMode);
+ SVGAlog(cbuf);
+#endif
+
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ SVGABuffer.ReadBuffer = SVGABuffer.BackBuffer;
+
+ return 0;
+}
+
+int SVGAMesaClose( void )
+{
+ vga_setmode(TEXT);
+ free(SVGABuffer.FrontBuffer);
+ free(SVGABuffer.BackBuffer);
+ return 0;
+}
+
+void SVGAMesaSetCI(int ndx, GLubyte red, GLubyte green, GLubyte blue)
+{
+ if (ndx<256)
+ vga_setpalette(ndx, red>>2, green>>2, blue>>2);
+}
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+static void copy_buffer( const GLubyte * buffer) {
+ int size = SVGABuffer.BufferSize, page = 0;
+
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"copy_buffer: copy %p to %p",buffer,SVGABuffer.VideoRam);
+ SVGAlog(cbuf);
+#endif
+
+ while(size>0) {
+ vga_setpage(page++);
+ if (size>>16) {
+ memcpy(SVGABuffer.VideoRam,buffer,0x10000);
+ buffer+=0x10000;
+ }else{
+ memcpy(SVGABuffer.VideoRam,buffer,size & 0xffff);
+ }
+ size-=0xffff;
+ }
+}
+
+static void get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ *width = SVGAMesa->width = vga_getxdim();
+ *height = SVGAMesa->height = vga_getydim();
+}
+
+
+static void set_buffer( GLcontext *ctx, GLframebuffer *colorBuffer,
+ GLenum buffer )
+{
+ /* We can ignore colorBuffer since we don't support a MakeCurrentRead()
+ * function.
+ */
+ (void) colorBuffer;
+
+ if (buffer == GL_FRONT_LEFT) {
+ SVGABuffer.ReadBuffer = SVGABuffer.FrontBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+#if 0
+ void * tmpptr;
+ /* vga_waitretrace(); */
+ copy_buffer(SVGABuffer.FrontBuffer);
+ tmpptr=SVGABuffer.BackBuffer;
+ SVGABuffer.BackBuffer=SVGABuffer.FrontBuffer;
+ SVGABuffer.FrontBuffer=tmpptr;
+#endif
+ }
+ else if (buffer == GL_BACK_LEFT) {
+ SVGABuffer.ReadBuffer = SVGABuffer.BackBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+#if 0
+ /* vga_waitretrace(); */
+ copy_buffer(SVGABuffer.BackBuffer);
+#endif
+ }
+}
+
+/**********************************************************************/
+/***** *****/
+/**********************************************************************/
+
+static void svgamesa_update_state( GLcontext *ctx, GLuint new_state )
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+
+ /* 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 = svgamesa_update_state;
+
+ ctx->Driver.GetBufferSize = get_buffer_size;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+
+ /* Software rasterizer pixel paths:
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+ ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
+
+ /* Fill in the swrast driver interface:
+ */
+ swdd->SetBuffer = set_buffer;
+
+ switch (SVGABuffer.Depth) {
+ case 8: ctx->Driver.ClearIndex = __clear_index8;
+ ctx->Driver.Clear = __clear8;
+
+ swdd->ReadCI32Span = __read_ci32_span8;
+ swdd->ReadCI32Pixels = __read_ci32_pixels8;
+ swdd->WriteCI8Span = __write_ci8_span8;
+ swdd->WriteCI32Span = __write_ci32_span8;
+ swdd->WriteCI32Pixels = __write_ci32_pixels8;
+ swdd->WriteMonoCISpan = __write_mono_ci_span8;
+ swdd->WriteMonoCIPixels = __write_mono_ci_pixels8;
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAUpdateState: 8 bit mode.");
+#endif
+
+ break;
+ case 15: ctx->Driver.ClearColor = __clear_color15;
+ ctx->Driver.Clear = __clear15;
+
+ swdd->ReadRGBASpan = __read_rgba_span15;
+ swdd->ReadRGBAPixels = __read_rgba_pixels15;
+ swdd->WriteRGBASpan = __write_rgba_span15;
+ swdd->WriteRGBAPixels = __write_rgba_pixels15;
+ swdd->WriteMonoRGBASpan = __write_mono_rgba_span15;
+ swdd->WriteMonoRGBAPixels = __write_mono_rgba_pixels15;
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAUpdateState: 15 bit mode.");
+#endif
+ break;
+ case 16: ctx->Driver.ClearColor = __clear_color16;
+ ctx->Driver.Clear = __clear16;
+
+ swdd->ReadRGBASpan = __read_rgba_span16;
+ swdd->ReadRGBAPixels = __read_rgba_pixels16;
+ swdd->WriteRGBASpan = __write_rgba_span16;
+ swdd->WriteRGBAPixels = __write_rgba_pixels16;
+ swdd->WriteMonoRGBASpan = __write_mono_rgba_span16;
+ swdd->WriteMonoRGBAPixels = __write_mono_rgba_pixels16;
+ break;
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAUpdateState: 16 bit mode.");
+#endif
+ case 24: ctx->Driver.ClearColor = __clear_color24;
+ ctx->Driver.Clear = __clear24;
+
+ swdd->ReadRGBASpan = __read_rgba_span24;
+ swdd->ReadRGBAPixels = __read_rgba_pixels24;
+ swdd->WriteRGBASpan = __write_rgba_span24;
+ swdd->WriteRGBAPixels = __write_rgba_pixels24;
+ swdd->WriteMonoRGBASpan = __write_mono_rgba_span24;
+ swdd->WriteMonoRGBAPixels = __write_mono_rgba_pixels24;
+ break;
+#ifdef SVGA_DEBUG
+ SVGAlog("SVGAUpdateState: 32 bit mode.");
+#endif
+ case 32: ctx->Driver.ClearColor = __clear_color32;
+ ctx->Driver.Clear = __clear32;
+
+ swdd->ReadRGBASpan = __read_rgba_span32;
+ swdd->ReadRGBAPixels = __read_rgba_pixels32;
+ swdd->WriteRGBASpan = __write_rgba_span32;
+ swdd->WriteRGBAPixels = __write_rgba_pixels32;
+ swdd->WriteMonoRGBASpan = __write_mono_rgba_span32;
+ swdd->WriteMonoRGBAPixels = __write_mono_rgba_pixels32;
+ }
+}
+
+/*
+ * Create a new VGA/Mesa context and return a handle to it.
+ */
+SVGAMesaContext SVGAMesaCreateContext( GLboolean doubleBuffer )
+{
+ SVGAMesaContext ctx;
+#ifndef DEV
+ GLboolean rgb_flag;
+ GLfloat redscale, greenscale, bluescale, alphascale;
+ GLint index_bits;
+ GLint redbits, greenbits, bluebits, alphabits;
+
+ /* determine if we're in RGB or color index mode */
+ if ((SVGABuffer.Depth==32) || (SVGABuffer.Depth==24)) {
+ rgb_flag = GL_TRUE;
+ redscale = greenscale = bluescale = alphascale = 255.0;
+ redbits = greenbits = bluebits = 8;
+ alphabits = 0;
+ index_bits = 0;
+ }
+ else if (SVGABuffer.Depth==8) {
+ rgb_flag = GL_FALSE;
+ redscale = greenscale = bluescale = alphascale = 0.0;
+ redbits = greenbits = bluebits = alphabits = 0;
+ index_bits = 8;
+ }
+ else if (SVGABuffer.Depth==15) {
+ rgb_flag = GL_TRUE;
+ redscale = greenscale = bluescale = alphascale = 31.0;
+ redbits = greenbits = bluebits = 5;
+ alphabits = 0;
+ index_bits = 0;
+ }
+ else if (SVGABuffer.Depth==16) {
+ rgb_flag = GL_TRUE;
+ redscale = bluescale = alphascale = 31.0;
+ greenscale = 63.0;
+ redbits = bluebits = 5;
+ greenbits = 6;
+ alphabits = 0;
+ index_bits = 0;
+ }
+
+ ctx = (SVGAMesaContext) calloc( 1, sizeof(struct svgamesa_context) );
+ if (!ctx) {
+ return NULL;
+ }
+
+ ctx->gl_vis = _mesa_create_visual( rgb_flag,
+ doubleBuffer,
+ GL_FALSE, /* stereo */
+ redbits, greenbits,
+ bluebits, alphabits,
+ index_bits,
+ 16, /* depth_size */
+ 8, /* stencil_size */
+ 16, 16, 16, 16, /* accum_size */
+ 1 /* samples */
+ );
+
+ ctx->gl_ctx = _mesa_create_context( ctx->gl_vis,
+ NULL, /* share list context */
+ (void *) ctx, GL_FALSE );
+
+ _mesa_enable_sw_extensions(ctx->gl_ctx);
+ _mesa_enable_1_3_extensions(ctx->gl_ctx);
+
+ ctx->gl_buffer = _mesa_create_framebuffer( ctx->gl_vis,
+ ctx->gl_vis->depthBits > 0,
+ ctx->gl_vis->stencilBits > 0,
+ ctx->gl_vis->accumRedBits > 0,
+ ctx->gl_vis->alphaBits > 0 );
+
+ ctx->width = ctx->height = 0; /* temporary until first "make-current" */
+#endif
+ return ctx;
+}
+
+/*
+ * Destroy the given VGA/Mesa context.
+ */
+void SVGAMesaDestroyContext( SVGAMesaContext ctx )
+{
+#ifndef DEV
+ if (ctx) {
+ _mesa_destroy_visual( ctx->gl_vis );
+ _mesa_destroy_context( ctx->gl_ctx );
+ _mesa_destroy_framebuffer( ctx->gl_buffer );
+ free( ctx );
+ if (ctx==SVGAMesa) {
+ SVGAMesa = NULL;
+ }
+ }
+#endif
+}
+
+/*
+ * Make the specified VGA/Mesa context the current one.
+ */
+void SVGAMesaMakeCurrent( SVGAMesaContext ctx )
+{
+#ifndef DEV
+ SVGAMesa = ctx;
+ svgamesa_update_state( ctx->gl_ctx, ~0 );
+ _mesa_make_current( ctx->gl_ctx, ctx->gl_buffer );
+
+ if (ctx->width==0 || ctx->height==0) {
+ /* setup initial viewport */
+ ctx->width = vga_getxdim();
+ ctx->height = vga_getydim();
+ _mesa_set_viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
+ }
+#endif
+}
+
+/*
+ * Return a handle to the current VGA/Mesa context.
+ */
+SVGAMesaContext SVGAMesaGetCurrentContext( void )
+{
+ return SVGAMesa;
+}
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void SVGAMesaSwapBuffers( void )
+{
+#if 000
+ void * tmpptr;
+#endif
+
+ /* vga_waitretrace(); */
+ copy_buffer(SVGABuffer.BackBuffer);
+
+#ifndef DEV
+ _mesa_notifySwapBuffers( SVGAMesa->gl_ctx );
+ if (SVGAMesa->gl_vis->doubleBufferMode)
+#endif /* DEV */
+ {
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaSwapBuffers : Swapping...");
+ SVGAlog(cbuf);
+#endif /* SVGA_DEBUG */
+#if 000
+ tmpptr=SVGABuffer.BackBuffer;
+ SVGABuffer.BackBuffer=SVGABuffer.FrontBuffer;
+ SVGABuffer.FrontBuffer=tmpptr;
+#endif
+#ifdef SVGA_DEBUG
+ sprintf(cbuf,"SVGAMesaSwapBuffers : WriteBuffer : %p\n"
+ " Readbuffer : %p", \
+ SVGABuffer.BackBuffer, SVGABuffer.FrontBuffer );
+ SVGAlog(cbuf);
+#endif /* SVGA_DEBUG */
+ }
+}
+
+#else /*SVGA*/
+
+/*
+ * Need this to provide at least one external definition when SVGA is
+ * not defined on the compiler command line.
+ */
+
+int gl_svga_dummy_function(void)
+{
+ return 0;
+}
+
+#endif /*SVGA*/
+
diff --git a/src/mesa/drivers/svga/svgamesa15.c b/src/mesa/drivers/svga/svgamesa15.c
new file mode 100644
index 0000000..54b6c97
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa15.c
@@ -0,0 +1,217 @@
+/* $Id: svgamesa15.c,v 1.11 2002/11/11 18:42:39 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+#include "svgapix.h"
+#include "svgamesa15.h"
+#include "swrast/swrast.h"
+
+
+static void __svga_drawpixel15(int x, int y, unsigned long c)
+{
+ unsigned long offset;
+ GLshort *shortBuffer=(void *)SVGABuffer.DrawBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ shortBuffer[offset]=c;
+}
+
+static unsigned long __svga_getpixel15(int x, int y)
+{
+ unsigned long offset;
+ GLshort *shortBuffer=(void *)SVGABuffer.ReadBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ return shortBuffer[offset];
+}
+
+void __clear_color15( GLcontext *ctx, const GLfloat color[4] )
+{
+ GLubyte col[3];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ SVGAMesa->clear_hicolor=(col[0]>>3)<<10 | (col[1]>>3)<<5 | (col[2]>>3);
+/* SVGAMesa->clear_hicolor=(red)<<10 | (green)<<5 | (blue);*/
+}
+
+void __clear15( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ int i, j;
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ GLshort *shortBuffer=(void *)SVGABuffer.FrontBuffer;
+ if (all) {
+ for (i=0;i<SVGABuffer.BufferSize / 2;i++)
+ shortBuffer[i]=SVGAMesa->clear_hicolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel15(i,j,SVGAMesa->clear_hicolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ GLshort *shortBuffer=(void *)SVGABuffer.BackBuffer;
+ if (all) {
+ for (i=0;i<SVGABuffer.BufferSize / 2;i++)
+ shortBuffer[i]=SVGAMesa->clear_hicolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel15(i,j,SVGAMesa->clear_hicolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+void __write_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel15( x, y, (rgba[i][RCOMP]>>3)<<10 | \
+ (rgba[i][GCOMP]>>3)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+ __svga_drawpixel15( x, y, (rgba[i][RCOMP]>>3)<<10 | \
+ (rgba[i][GCOMP]>>3)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+}
+
+void __write_mono_rgba_span15( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ GLushort hicolor = (color[RCOMP] >> 3) << 10 |
+ (color[GCOMP] >> 3) << 5 |
+ (color[BCOMP] >> 3);
+ int i;
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel15( x, y, hicolor);
+ }
+ }
+}
+
+void __read_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ int i,pix;
+ for (i=0; i<n; i++, x++) {
+ pix = __svga_getpixel15( x, y);
+ rgba[i][RCOMP] = ((pix>>10)<<3) & 0xff;
+ rgba[i][GCOMP] = ((pix>> 5)<<3) & 0xff;
+ rgba[i][BCOMP] = ((pix )<<3) & 0xff;
+ }
+}
+
+void __write_rgba_pixels15( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel15( x[i], y[i], (rgba[i][RCOMP]>>3)<<10 | \
+ (rgba[i][GCOMP]>>3)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+}
+
+
+void __write_mono_rgba_pixels15( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4], const GLubyte mask[] )
+{
+ GLushort hicolor = (color[RCOMP] >> 3) << 10 |
+ (color[GCOMP] >> 3) << 5 |
+ (color[BCOMP] >> 3);
+ int i;
+ /* use current rgb color */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel15( x[i], y[i], hicolor );
+ }
+ }
+}
+
+void __read_rgba_pixels15( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i,pix;
+ for (i=0; i<n; i++,x++) {
+ pix = __svga_getpixel15( x[i], y[i] );
+ rgba[i][RCOMP] = ((pix>>10)<<3) & 0xff;
+ rgba[i][GCOMP] = ((pix>> 5)<<3) & 0xff;
+ rgba[i][BCOMP] = ((pix )<<3) & 0xff;
+ }
+}
+
+#else
+
+
+/* silence compiler warning */
+extern void _mesa_svga15_dummy_function(void);
+void _mesa_svga15_dummy_function(void)
+{
+}
+
+
+#endif
diff --git a/src/mesa/drivers/svga/svgamesa15.h b/src/mesa/drivers/svga/svgamesa15.h
new file mode 100644
index 0000000..3ed7db8
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa15.h
@@ -0,0 +1,43 @@
+/* $Id: svgamesa15.h,v 1.7 2002/11/11 18:42:39 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGA_MESA_15_H
+#define SVGA_MESA_15_H
+
+extern void __clear_color15( GLcontext *ctx, const GLfloat color[4] );
+extern void __clear15( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+extern void __write_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]);
+extern void __read_rgba_span15( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+extern void __write_rgba_pixels15( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_pixels15( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[] );
+extern void __read_rgba_pixels15( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+#endif /* SVGA_MESA_15_H */
diff --git a/src/mesa/drivers/svga/svgamesa16.c b/src/mesa/drivers/svga/svgamesa16.c
new file mode 100644
index 0000000..72ac818
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa16.c
@@ -0,0 +1,215 @@
+/* $Id: svgamesa16.c,v 1.11 2002/11/11 18:42:40 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+#include "svgapix.h"
+#include "svgamesa16.h"
+#include "swrast/swrast.h"
+
+
+static void __svga_drawpixel16(int x, int y, unsigned long c)
+{
+ unsigned long offset;
+ GLshort *shortBuffer=(void *)SVGABuffer.DrawBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ shortBuffer[offset]=c;
+}
+
+static unsigned long __svga_getpixel16(int x, int y)
+{
+ unsigned long offset;
+
+ GLshort *shortBuffer=(void *)SVGABuffer.ReadBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ return shortBuffer[offset];
+}
+
+void __clear_color16( GLcontext *ctx, const GLfloat color[4] )
+{
+ GLubyte col[3];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ SVGAMesa->clear_hicolor = (col[0] >> 3) << 11 |
+ (col[1] >> 2) << 5 |
+ (col[2] >> 3);
+/* SVGAMesa->clear_hicolor=(red)<<11 | (green)<<5 | (blue); */
+}
+
+void __clear16( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ int i,j;
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ if (all) {
+ GLshort *shortBuffer=(void *)SVGABuffer.FrontBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 2;i++)
+ shortBuffer[i]=SVGAMesa->clear_hicolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel16(i,j,SVGAMesa->clear_hicolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ if (all) {
+ GLshort *shortBuffer=(void *)SVGABuffer.BackBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 2;i++)
+ shortBuffer[i]=SVGAMesa->clear_hicolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel16(i,j,SVGAMesa->clear_hicolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+void __write_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel16( x, y, (rgba[i][RCOMP]>>3)<<11 | \
+ (rgba[i][GCOMP]>>2)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+ __svga_drawpixel16( x, y, (rgba[i][RCOMP]>>3)<<11 | \
+ (rgba[i][GCOMP]>>2)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+}
+
+void __write_mono_rgba_span16( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ GLushort hicolor=(color[RCOMP]>>3)<<11 | (color[GCOMP]>>2)<<5 | (color[BCOMP]>>3);
+ int i;
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel16( x, y, hicolor);
+ }
+ }
+}
+
+void __read_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ int i,pix;
+ for (i=0; i<n; i++, x++) {
+ pix = __svga_getpixel16( x, y );
+ rgba[i][RCOMP] = ((pix>>11)<<3) & 0xff;
+ rgba[i][GCOMP] = ((pix>> 5)<<2) & 0xff;
+ rgba[i][BCOMP] = ((pix )<<3) & 0xff;
+ }
+}
+
+void __write_rgba_pixels16( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel16( x[i], y[i], (rgba[i][RCOMP]>>3)<<11 | \
+ (rgba[i][GCOMP]>>2)<<5 | \
+ (rgba[i][BCOMP]>>3));
+ }
+ }
+}
+
+
+void __write_mono_rgba_pixels16( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4], const GLubyte mask[] )
+{
+ GLushort hicolor=(color[RCOMP]>>3)<<11 | (color[GCOMP]>>2)<<5 | (color[BCOMP]>>3);
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel16( x[i], y[i], hicolor );
+ }
+ }
+}
+
+void __read_rgba_pixels16( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i,pix;
+ for (i=0; i<n; i++,x++) {
+ pix = __svga_getpixel16( x[i], y[i] );
+ rgba[i][RCOMP] = ((pix>>11)<<3) & 0xff;
+ rgba[i][GCOMP] = ((pix>> 5)<<2) & 0xff;
+ rgba[i][BCOMP] = ((pix )<<3) & 0xff;
+ }
+}
+
+#else
+
+
+/* silence compiler warning */
+extern void _mesa_svga16_dummy_function(void);
+void _mesa_svga16_dummy_function(void)
+{
+}
+
+
+#endif
diff --git a/src/mesa/drivers/svga/svgamesa16.h b/src/mesa/drivers/svga/svgamesa16.h
new file mode 100644
index 0000000..247c1f4
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa16.h
@@ -0,0 +1,44 @@
+/* $Id: svgamesa16.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGA_MESA_16_H
+#define SVGA_MESA_16_H
+
+extern void __clear_color16( GLcontext *ctx, const GLfloat color[4] );
+extern void __clear16( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+extern void __write_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]);
+extern void __read_rgba_span16( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+extern void __write_rgba_pixels16( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_pixels16( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[] );
+extern void __read_rgba_pixels16( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+#endif /* SVGA_MESA_16_H */
+
diff --git a/src/mesa/drivers/svga/svgamesa24.c b/src/mesa/drivers/svga/svgamesa24.c
new file mode 100644
index 0000000..07491cc
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa24.c
@@ -0,0 +1,239 @@
+/* $Id: svgamesa24.c,v 1.12 2002/11/11 18:42:41 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+#include "svgapix.h"
+#include "svgamesa24.h"
+#include "swrast/swrast.h"
+
+
+#if 0
+/* this doesn't compile with GCC on RedHat 6.1 */
+static inline int RGB2BGR24(int c)
+{
+ asm("rorw $8, %0\n"
+ "rorl $16, %0\n"
+ "rorw $8, %0\n"
+ "shrl $8, %0\n"
+ : "=q"(c):"0"(c));
+ return c;
+}
+#else
+static unsigned long RGB2BGR24(unsigned long color)
+{
+ return (color & 0xff00)|(color>>16)|((color & 0xff)<<16);
+}
+#endif
+
+static void __svga_drawpixel24(int x, int y, GLubyte r, GLubyte g, GLubyte b)
+{
+ unsigned long offset;
+
+ _RGB *rgbBuffer=(void *)SVGABuffer.DrawBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+
+ rgbBuffer[offset].r=r;
+ rgbBuffer[offset].g=g;
+ rgbBuffer[offset].b=b;
+}
+
+static unsigned long __svga_getpixel24(int x, int y)
+{
+ unsigned long offset;
+
+ _RGB *rgbBuffer=(void *)SVGABuffer.ReadBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ return rgbBuffer[offset].r<<16 | rgbBuffer[offset].g<<8 | rgbBuffer[offset].b;
+}
+
+void __clear_color24( GLcontext *ctx, const GLfloat color[4] )
+{
+ GLubyte col[3];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ SVGAMesa->clear_red = col[0];
+ SVGAMesa->clear_green = col[1];
+ SVGAMesa->clear_blue = col[2];
+/* SVGAMesa->clear_truecolor = red<<16 | green<<8 | blue; */
+}
+
+void __clear24( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ int i,j;
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ if (all) {
+ _RGB *rgbBuffer=(void *)SVGABuffer.FrontBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 3;i++) {
+ rgbBuffer[i].r=SVGAMesa->clear_red;
+ rgbBuffer[i].g=SVGAMesa->clear_green;
+ rgbBuffer[i].b=SVGAMesa->clear_blue;
+ }
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel24( i, j, SVGAMesa->clear_red,
+ SVGAMesa->clear_green,
+ SVGAMesa->clear_blue);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ if (all) {
+ _RGB *rgbBuffer=(void *)SVGABuffer.BackBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 3;i++) {
+ rgbBuffer[i].r=SVGAMesa->clear_red;
+ rgbBuffer[i].g=SVGAMesa->clear_green;
+ rgbBuffer[i].b=SVGAMesa->clear_blue;
+ }
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel24( i, j, SVGAMesa->clear_red,
+ SVGAMesa->clear_green,
+ SVGAMesa->clear_blue);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+void __write_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel24( x, y, rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+ __svga_drawpixel24( x, y, rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ }
+}
+
+void __write_mono_rgba_span24( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ int i;
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel24( x, y, color[RCOMP], color[GCOMP], color[BCOMP]);
+ }
+ }
+}
+
+void __read_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ int i;
+ for (i=0; i<n; i++, x++) {
+ *((GLint*)rgba[i]) = RGB2BGR24(__svga_getpixel24( x, y));
+ }
+}
+
+void __write_rgba_pixels24( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel24( x[i], y[i], rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]);
+ }
+ }
+}
+
+void __write_mono_rgba_pixels24( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel24( x[i], y[i],
+ color[RCOMP], color[GCOMP], color[BCOMP] );
+ }
+ }
+}
+
+void __read_rgba_pixels24( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++,x++) {
+ *((GLint*)rgba[i]) = RGB2BGR24(__svga_getpixel24( x[i], y[i]));
+ }
+}
+
+#else
+
+
+/* silence compiler warning */
+extern void _mesa_svga24_dummy_function(void);
+void _mesa_svga24_dummy_function(void)
+{
+}
+
+
+#endif
diff --git a/src/mesa/drivers/svga/svgamesa24.h b/src/mesa/drivers/svga/svgamesa24.h
new file mode 100644
index 0000000..54d1a82
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa24.h
@@ -0,0 +1,44 @@
+/* $Id: svgamesa24.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGA_MESA_24_H
+#define SVGA_MESA_24_H
+
+extern void __clear_color24( GLcontext *ctx, const GLfloat color[4] );
+extern void __clear24( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+extern void __write_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]);
+extern void __read_rgba_span24( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+extern void __write_rgba_pixels24( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_pixels24( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[] );
+extern void __read_rgba_pixels24( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+#endif /* SVGA_MESA_24_H */
+
diff --git a/src/mesa/drivers/svga/svgamesa32.c b/src/mesa/drivers/svga/svgamesa32.c
new file mode 100644
index 0000000..8a36699
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa32.c
@@ -0,0 +1,220 @@
+/* $Id: svgamesa32.c,v 1.12 2002/11/11 18:42:42 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+#include "svgapix.h"
+#include "svgamesa32.h"
+#include "swrast/swrast.h"
+
+
+#if 0
+/* this doesn't compile with GCC on RedHat 6.1 */
+static inline int RGB2BGR32(int c)
+{
+ asm("rorw $8, %0\n"
+ "rorl $16, %0\n"
+ "rorw $8, %0\n"
+ "shrl $8, %0\n"
+ : "=q"(c):"0"(c));
+ return c;
+}
+#else
+static unsigned long RGB2BGR32(unsigned long color)
+{
+ return (color & 0xff00)|(color>>16)|((color & 0xff)<<16);
+}
+#endif
+
+static void __svga_drawpixel32(int x, int y, unsigned long c)
+{
+ unsigned long offset;
+
+ GLint *intBuffer=(void *)SVGABuffer.DrawBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ intBuffer[offset]=c;
+}
+
+static unsigned long __svga_getpixel32(int x, int y)
+{
+ unsigned long offset;
+
+ const GLint *intBuffer=(void *)SVGABuffer.ReadBuffer;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->width + x;
+ return intBuffer[offset];
+}
+
+void __clear_color32( GLcontext *ctx, const GLfloat color[4] )
+{
+ GLubyte col[3];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ SVGAMesa->clear_truecolor = (col[0] << 16) | (col[1] << 8) | col[2];
+}
+
+void __clear32( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ int i,j;
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ if (all) {
+ GLint *intBuffer=(void *)SVGABuffer.FrontBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 4;i++)
+ intBuffer[i]=SVGAMesa->clear_truecolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel32(i,j,SVGAMesa->clear_truecolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ if (all) {
+ GLint *intBuffer=(void *)SVGABuffer.BackBuffer;
+ for (i=0;i<SVGABuffer.BufferSize / 4;i++)
+ intBuffer[i]=SVGAMesa->clear_truecolor;
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel32(i,j,SVGAMesa->clear_truecolor);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+void __write_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel32( x, y, RGB2BGR32(*((GLint*)rgba[i])));
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+ __svga_drawpixel32( x, y, RGB2BGR32(*((GLint*)rgba[i])));
+ }
+ }
+}
+
+void __write_mono_rgba_span32( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ int i;
+ GLuint truecolor = color[RCOMP]<<16 | color[GCOMP]<<8 | color[BCOMP];
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ __svga_drawpixel32( x, y, truecolor);
+ }
+ }
+}
+
+void __read_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ int i;
+ for (i=0; i<n; i++, x++) {
+ *((GLint*)rgba[i]) = RGB2BGR32(__svga_getpixel32( x, y ));
+ }
+}
+
+void __write_rgba_pixels32( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel32( x[i], y[i], RGB2BGR32(*((GLint*)rgba[i])));
+ }
+ }
+}
+
+void __write_mono_rgba_pixels32( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4], const GLubyte mask[] )
+{
+ GLuint truecolor = color[RCOMP]<<16 | color[GCOMP]<<8 | color[BCOMP];
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel32( x[i], y[i], truecolor );
+ }
+ }
+}
+
+void __read_rgba_pixels32( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++,x++) {
+ *((GLint*)rgba[i]) = RGB2BGR32(__svga_getpixel32( x[i], y[i] ));
+ }
+}
+
+
+#else
+
+
+/* silence compiler warning */
+extern void _mesa_svga32_dummy_function(void);
+void _mesa_svga32_dummy_function(void)
+{
+}
+
+
+#endif
+
diff --git a/src/mesa/drivers/svga/svgamesa32.h b/src/mesa/drivers/svga/svgamesa32.h
new file mode 100644
index 0000000..f518e11
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa32.h
@@ -0,0 +1,44 @@
+/* $Id: svgamesa32.h,v 1.6 2002/11/11 18:42:42 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGA_MESA_32_H
+#define SVGA_MESA_32_H
+
+extern void __clear_color32( GLcontext *ctx, const GLfloat color[4] );
+extern void __clear32( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+extern void __write_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLchan color[4], const GLubyte mask[]);
+extern void __read_rgba_span32( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+extern void __write_rgba_pixels32( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+extern void __write_mono_rgba_pixels32( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLchan color[4], const GLubyte mask[] );
+extern void __read_rgba_pixels32( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+#endif /* SVGA_MESA_32_H */
+
diff --git a/src/mesa/drivers/svga/svgamesa8.c b/src/mesa/drivers/svga/svgamesa8.c
new file mode 100644
index 0000000..29fd407
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa8.c
@@ -0,0 +1,191 @@
+/* $Id: svgamesa8.c,v 1.8 2001/02/06 00:03:48 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.3
+ * Copyright (C) 1995-2000 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+
+#include "svgapix.h"
+#include "svgamesa8.h"
+#include "swrast/swrast.h"
+
+
+static void __svga_drawpixel8(int x, int y, unsigned long c)
+{
+ unsigned long offset;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->linewidth + x;
+ SVGABuffer.DrawBuffer[offset]=c;
+}
+
+static unsigned long __svga_getpixel8(int x, int y)
+{
+ unsigned long offset;
+ y = SVGAInfo->height-y-1;
+ offset = y * SVGAInfo->linewidth + x;
+ return SVGABuffer.ReadBuffer[offset];
+}
+
+void __clear_index8( GLcontext *ctx, GLuint index )
+{
+ SVGAMesa->clear_index = index;
+}
+
+void __clear8( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ int i,j;
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ if (all) {
+ memset(SVGABuffer.FrontBuffer, SVGAMesa->clear_index, SVGABuffer.BufferSize);
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel8(i,j,SVGAMesa->clear_index);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ if (all) {
+ memset(SVGABuffer.BackBuffer, SVGAMesa->clear_index, SVGABuffer.BufferSize);
+ }
+ else {
+ GLubyte *tmp = SVGABuffer.DrawBuffer;
+ SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
+ for (i=x;i<width;i++)
+ for (j=y;j<height;j++)
+ __svga_drawpixel8(i,j,SVGAMesa->clear_index);
+ SVGABuffer.DrawBuffer = tmp;
+ }
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+void __write_ci32_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ __svga_drawpixel8( x, y, index[i]);
+ }
+ }
+}
+
+void __write_ci8_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ int i;
+
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ __svga_drawpixel8( x, y, index[i]);
+ }
+ }
+}
+
+void __write_mono_ci_span8( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ int i;
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ __svga_drawpixel8( x, y, colorIndex);
+ }
+ }
+}
+
+void __read_ci32_span8( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[])
+{
+ int i;
+ for (i=0; i<n; i++,x++) {
+ index[i] = __svga_getpixel8( x, y);
+ }
+}
+
+void __write_ci32_pixels8( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel8( x[i], y[i], index[i]);
+ }
+ }
+}
+
+
+void __write_mono_ci_pixels8( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ __svga_drawpixel8( x[i], y[i], colorIndex);
+ }
+ }
+}
+
+void __read_ci32_pixels8( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++,x++) {
+ index[i] = __svga_getpixel8( x[i], y[i]);
+ }
+}
+
+
+#else
+
+
+/* silence compiler warning */
+extern void _mesa_svga8_dummy_function(void);
+void _mesa_svga8_dummy_function(void)
+{
+}
+
+
+#endif
diff --git a/src/mesa/drivers/svga/svgamesa8.h b/src/mesa/drivers/svga/svgamesa8.h
new file mode 100644
index 0000000..1aa25f9
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa8.h
@@ -0,0 +1,44 @@
+/* $Id: svgamesa8.h,v 1.4 2001/02/06 00:03:48 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.2
+ * Copyright (C) 1995-2000 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGA_MESA_8_H
+#define SVGA_MESA_8_H
+
+extern void __clear_index8( GLcontext *ctx, GLuint index );
+extern void __clear8( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+extern void __write_ci32_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLuint index[], const GLubyte mask[] );
+extern void __write_ci8_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte index[], const GLubyte mask[] );
+extern void __write_mono_ci_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint colorIndex, const GLubyte mask[] );
+extern void __read_ci32_span8( const GLcontext *ctx, GLuint n, GLint x, GLint y, GLuint index[]);
+extern void __write_ci32_pixels8( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLuint index[], const GLubyte mask[] );
+extern void __write_mono_ci_pixels8( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLuint colorIndex, const GLubyte mask[] );
+extern void __read_ci32_pixels8( const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLuint index[], const GLubyte mask[] );
+
+#endif /* SVGA_MESA_15_H */
diff --git a/src/mesa/drivers/svga/svgapix.h b/src/mesa/drivers/svga/svgapix.h
new file mode 100644
index 0000000..0b19551
--- /dev/null
+++ b/src/mesa/drivers/svga/svgapix.h
@@ -0,0 +1,71 @@
+/* $Id: svgapix.h,v 1.5 2002/11/11 18:42:44 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.0
+ * Copyright (C) 1995-2002 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.
+ */
+
+
+/*
+ * SVGA driver for Mesa.
+ * Original author: Brian Paul
+ * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
+ */
+
+
+#ifndef SVGAPIX_H
+#define SVGAPIX_H
+
+#include "GL/gl.h"
+#include "GL/svgamesa.h"
+#include "context.h"
+#include "colormac.h"
+#include "vga.h"
+
+struct svgamesa_context {
+ GLcontext *gl_ctx; /* the core Mesa context */
+ GLvisual *gl_vis; /* describes the color buffer */
+ GLframebuffer *gl_buffer; /* the ancillary buffers */
+ GLuint clear_index; /* current clear index */
+ GLint clear_red,
+ clear_green,
+ clear_blue; /* current clear rgb color */
+ GLuint clear_truecolor; /* current clear rgb color */
+ GLushort hicolor; /* current hicolor */
+ GLushort clear_hicolor; /* current clear hicolor */
+ GLint width, height; /* size of color buffer */
+ GLint depth; /* bits per pixel (8,16,24 or 32) */
+};
+
+typedef struct { GLubyte b,g,r; } _RGB;
+
+struct svga_buffer {
+ GLint Depth;
+ GLint BufferSize;
+ GLubyte * FrontBuffer;
+ GLubyte * BackBuffer;
+ GLubyte * VideoRam;
+ GLubyte * DrawBuffer; /* == FrontBuffer or BackBuffer */
+ GLubyte * ReadBuffer; /* == FrontBuffer or BackBuffer */
+};
+
+extern struct svga_buffer SVGABuffer;
+extern vga_modeinfo * SVGAInfo;
+extern SVGAMesaContext SVGAMesa; /* the current context */
+
+#endif /* SVGAPIX_H */
diff --git a/src/mesa/drivers/verite/.gdbinit b/src/mesa/drivers/verite/.gdbinit
new file mode 100644
index 0000000..a735046
--- /dev/null
+++ b/src/mesa/drivers/verite/.gdbinit
@@ -0,0 +1,41 @@
+# veritemesa perf-counter inspection helpers
+#
+# Requires libGL.a built with VERITE_INSTRUMENT=1 !
+#
+# $ gdbserver :2345 ./glquake +timedemo demo1
+# $ gdb glquake
+# (gdb) target remote localhost:2345
+# (gdb) break vrMesaSwapBuffers
+# (gdb) run
+# (gdb) vrp
+# (gdb) vrpwatch
+
+define vrp
+ printf "VRPERF(live) frames=%llu\n", g_vrp.frames
+ printf " fallback: tex=%llu blend=%llu afunc=%llu zfunc=%llu\n", \
+ g_vrp.fb[0], g_vrp.fb[1], g_vrp.fb[2], g_vrp.fb[3]
+ printf " stipple=%llu smooth=%llu twoside=%llu spec=%llu\n", \
+ g_vrp.fb[4], g_vrp.fb[5], g_vrp.fb[6], g_vrp.fb[7]
+ printf " unfilled=%llu rmode=%llu texres=%llu alphagrad=%llu\n", \
+ g_vrp.fb[8], g_vrp.fb[9], g_vrp.fb[10], g_vrp.fb[11]
+ printf " texval: first=%llu evict=%llu dirty=%llu bindonly=%llu failv=%llu\n", \
+ g_vrp.tv_first, g_vrp.tv_evict, g_vrp.tv_dirty, g_vrp.tv_bindonly, g_vrp.tv_failv
+ printf " churn: fgcolor=%llu mipbind=%llu filt=%llu fences=%llu\n", \
+ g_vrp.fgcolor_writes, g_vrp.mip_binds, g_vrp.filt_changes, g_vrp.fences
+end
+document vrp
+Dump the veritemesa driver perf counters at the current stop.
+end
+
+# Break at each swap, print the counters, and keep going.
+define vrpwatch
+ break vrMesaSwapBuffers
+ commands
+ silent
+ vrp
+ continue
+ end
+end
+document vrpwatch
+Install a breakpoint at vrMesaSwapBuffers that prints g_vrp every frame.
+end
diff --git a/src/mesa/drivers/verite/README b/src/mesa/drivers/verite/README
new file mode 100644
index 0000000..38417fa
--- /dev/null
+++ b/src/mesa/drivers/verite/README
@@ -0,0 +1,5 @@
+veritemesa - Mesa 6.2 driver for the Rendition Verite V2200
+
+NetBSD, no X, /dev/verite3d kernel interface.
+
+Build: configs/netbsd-verite
diff --git a/src/mesa/drivers/verite/libv3d.c b/src/mesa/drivers/verite/libv3d.c
new file mode 100644
index 0000000..b09f960
--- /dev/null
+++ b/src/mesa/drivers/verite/libv3d.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* libv3d - thin userland layer over /dev/verite3d. */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "libv3d.h"
+
+uint64_t
+v3d_now_ns(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;
+}
+
+/* 0 when timing is off: the accumulators just stay zero */
+static uint64_t
+v3d_t0(const struct v3d *v)
+{
+
+ return v->opt_stats ? v3d_now_ns() : 0;
+}
+
+int
+v3d_open(struct v3d *v, const char *devpath, const char *ucpath)
+{
+ struct v3d_init vi;
+ struct v3d_mode vm;
+ static uint8_t uc[1024 * 1024];
+ FILE *f;
+ size_t sz;
+ uint32_t w;
+ int s;
+
+ memset(v, 0, sizeof(*v));
+ if (getenv("RLGL_STATS") != NULL)
+ v->opt_stats = atoi(getenv("RLGL_STATS"));
+ v->opt_nulldraw = getenv("RLGL_NULLDRAW") != NULL;
+ v->opt_nosync = getenv("RLGL_NOSYNC") != NULL;
+ v->opt_noflip = getenv("RLGL_NOFLIP") != NULL;
+ v->opt_tearflip = getenv("RLGL_TEARFLIP") != NULL;
+ if (v->opt_nulldraw || v->opt_nosync || v->opt_noflip ||
+ v->opt_tearflip)
+ fprintf(stderr, "libv3d: EXPERIMENT MODE nulldraw=%d "
+ "nosync=%d noflip=%d tearflip=%d\n", v->opt_nulldraw,
+ v->opt_nosync, v->opt_noflip, v->opt_tearflip);
+ v->fd = open(devpath, O_RDWR);
+ if (v->fd == -1) {
+ perror(devpath);
+ return -1;
+ }
+
+ f = fopen(ucpath, "rb");
+ if (f == NULL) {
+ perror(ucpath);
+ goto fail;
+ }
+ sz = fread(uc, 1, sizeof(uc), f);
+ fclose(f);
+
+ vi.vi_ucode = (uint64_t)(uintptr_t)uc;
+ vi.vi_size = (uint32_t)sz;
+ if (ioctl(v->fd, V3D_INIT, &vi) == -1) {
+ perror("V3D_INIT");
+ goto fail;
+ }
+ v->ctx_base = vi.vi_ctx_base;
+ v->memsize = vi.vi_memsize;
+ v->pool_base = vi.vi_pool_base;
+
+ for (s = 0; s < V3D_RING_SLOTS; s++) {
+ v->slot[s] = mmap(NULL, V3D_SLOT_SIZE,
+ PROT_READ | PROT_WRITE, MAP_SHARED, v->fd,
+ (off_t)s * V3D_SLOT_SIZE);
+ if (v->slot[s] == MAP_FAILED) {
+ perror("mmap slot");
+ goto fail;
+ }
+ }
+
+ /* GL context up; fence it */
+ usleep(10000);
+ v3d_emit1(v, V3D_GL_CTX_INIT);
+ if (v3d_sync(v) != 0)
+ goto fail;
+
+ /* mode query fills geometry */
+ memset(&vm, 0, sizeof(vm));
+ if (ioctl(v->fd, V3D_MODE, &vm) == -1)
+ goto fail;
+ v->width = vm.vm_width;
+ v->height = vm.vm_height;
+ v->stride = vm.vm_stride;
+ v->pe_stride = vm.vm_pe_stride;
+ (void)w;
+ return 0;
+fail:
+ close(v->fd);
+ v->fd = -1;
+ return -1;
+}
+
+void
+v3d_close(struct v3d *v)
+{
+
+ if (v->fd == -1)
+ return;
+ /* park politely */
+ v3d_emit1(v, V3D_GL_EXIT);
+ (void)v3d_flush(v);
+ if (v->vram != NULL) {
+ munmap(v->vram, v->memsize);
+ v->vram = NULL;
+ }
+ close(v->fd);
+ v->fd = -1;
+}
+
+const uint8_t *
+v3d_vram(struct v3d *v)
+{
+
+ if (v->vram == NULL) {
+ /* RW for span writes (Mesa swrast), RO fallback */
+ v->vram = mmap(NULL, v->memsize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, v->fd, V3D_VRAM_MMAP_OFF);
+ if (v->vram == MAP_FAILED)
+ v->vram = mmap(NULL, v->memsize, PROT_READ,
+ MAP_SHARED, v->fd, V3D_VRAM_MMAP_OFF);
+ if (v->vram == MAP_FAILED) {
+ perror("mmap vram");
+ v->vram = NULL;
+ }
+ }
+ return v->vram;
+}
+
+void
+v3d_emit(struct v3d *v, const uint32_t *w, uint32_t n)
+{
+
+ if (v->n + n > V3D_SLOT_SIZE / 4) {
+ if (v3d_flush(v) != 0)
+ return;
+ }
+ memcpy(v->slot[v->cur] + v->n, w, n * 4);
+ v->n += n;
+ v->st.words += n;
+}
+
+void
+v3d_emit1(struct v3d *v, uint32_t w)
+{
+
+ v3d_emit(v, &w, 1);
+}
+
+uint32_t *
+v3d_reserve(struct v3d *v, uint32_t nwords)
+{
+
+ if (nwords > V3D_SLOT_SIZE / 4)
+ return NULL;
+ if (v->n + nwords > V3D_SLOT_SIZE / 4) {
+ if (v3d_flush(v) != 0)
+ return NULL;
+ }
+ return v->slot[v->cur] + v->n;
+}
+
+void
+v3d_commit(struct v3d *v, uint32_t nwords)
+{
+
+ v->n += nwords;
+ v->st.words += nwords;
+}
+
+void
+v3d_emitf(struct v3d *v, float f)
+{
+ union { float f; uint32_t u; } u;
+
+ u.f = f;
+ v3d_emit1(v, u.u);
+}
+
+int
+v3d_flush(struct v3d *v)
+{
+ struct v3d_submit vs;
+ uint64_t t0;
+
+ if (v->n == 0)
+ return 0;
+ vs.vs_slot = (uint32_t)v->cur;
+ vs.vs_len = v->n * 4;
+ vs.vs_swap = 1; /* XXX: host-native words */
+ v->n = 0;
+ v->cur = (v->cur + 1) % V3D_RING_SLOTS;
+ v->st.submits++;
+ v->st.submit_bytes += vs.vs_len;
+ if (v->opt_nulldraw)
+ return 0;
+ t0 = v3d_t0(v);
+ if (ioctl(v->fd, V3D_SUBMIT, &vs) == -1) {
+ perror("V3D_SUBMIT");
+ return -1;
+ }
+ if (t0 != 0)
+ v->st.submit_ns += v3d_now_ns() - t0;
+ return 0;
+}
+
+int
+v3d_sync(struct v3d *v)
+{
+ uint32_t word = V3D_GL_SYNC;
+ uint64_t t0;
+
+ if (v3d_flush(v) != 0)
+ return -1;
+ v->st.syncs++;
+ if (v->opt_nulldraw)
+ return 0;
+ t0 = v3d_t0(v);
+ if (ioctl(v->fd, V3D_SYNC, &word) == -1) {
+ perror("V3D_SYNC");
+ return -1;
+ }
+ if (t0 != 0)
+ v->st.sync_ns += v3d_now_ns() - t0;
+ return 0;
+}
+
+int
+v3d_alloc(struct v3d *v, uint32_t size, uint32_t align, uint32_t *addr)
+{
+ struct v3d_alloc va;
+
+ va.va_size = size;
+ va.va_align = align;
+ if (ioctl(v->fd, V3D_ALLOC, &va) == -1)
+ return -1;
+ *addr = va.va_addr;
+ return 0;
+}
+
+int
+v3d_mode(struct v3d *v, uint32_t depth, uint32_t frame_base)
+{
+ struct v3d_mode vm;
+
+ memset(&vm, 0, sizeof(vm));
+ vm.vm_depth = depth;
+ vm.vm_frame_base = frame_base;
+ if (ioctl(v->fd, V3D_MODE, &vm) == -1)
+ return -1;
+ v->width = vm.vm_width;
+ v->height = vm.vm_height;
+ v->stride = vm.vm_stride;
+ v->pe_stride = vm.vm_pe_stride;
+ return 0;
+}
+
+int
+v3d_flip(struct v3d *v, uint32_t frame_base)
+{
+ uint64_t t0;
+ int r;
+
+ if (v3d_flush(v) != 0)
+ return -1;
+ v->st.flips++;
+ if (v->opt_nulldraw || v->opt_noflip)
+ return 0;
+ if (v->opt_tearflip)
+ frame_base |= V3D_FLIP_NOWAIT;
+ t0 = v3d_t0(v);
+ r = ioctl(v->fd, V3D_FLIP, &frame_base);
+ if (t0 != 0)
+ v->st.flip_ns += v3d_now_ns() - t0;
+ return r;
+}
+
+void
+v3d_st(struct v3d *v, uint32_t reg, uint32_t val)
+{
+ uint32_t w[2];
+
+ w[0] = (1 << 12) | reg;
+ w[1] = val;
+ v->st.st_calls++;
+ v3d_emit(v, w, 2);
+}
+
+void
+v3d_texbind(struct v3d *v, uint32_t addr, uint32_t srcstride,
+ uint32_t w, uint32_t h, uint32_t uscale, uint32_t vscale)
+{
+ uint32_t c[6];
+
+ c[0] = (4 << 12) | V3D_PE_SRCBASE;
+ c[1] = addr;
+ c[2] = srcstride;
+ c[3] = ((h - 1) << 16) | (w - 1);
+ c[4] = uscale;
+ c[5] = vscale;
+ v->st.texbinds++;
+ v3d_emit(v, c, 6);
+}
+
+/* below this many payload bytes of slot room, flush for a fresh slot */
+#define V3D_UPLOAD_MIN 4096
+
+int
+v3d_upload(struct v3d *v, uint32_t dst, const void *data, uint32_t bytes)
+{
+ const uint32_t *p = data;
+ uint32_t chunk, room, hdr[3];
+
+ v->st.uploads++;
+ v->st.upload_bytes += bytes;
+ while (bytes > 0) {
+ /*
+ * Batch into the current slot alongside whatever is
+ * already queued
+ */
+ room = (V3D_SLOT_SIZE / 4 - v->n) * 4;
+ if (room < V3D_UPLOAD_MIN + 3 * 4) {
+ if (v3d_flush(v) != 0)
+ return -1;
+ room = V3D_SLOT_SIZE;
+ }
+ chunk = bytes;
+ if (chunk > room - 3 * 4)
+ chunk = room - 3 * 4;
+ hdr[0] = V3D_GL_MEM_WRITE;
+ hdr[1] = dst;
+ hdr[2] = chunk;
+ v3d_emit(v, hdr, 3);
+ v3d_emit(v, p, chunk / 4);
+ p += chunk / 4;
+ dst += chunk;
+ bytes -= chunk;
+ }
+ return 0;
+}
+
+void
+v3d_clear(struct v3d *v, uint32_t addr, uint32_t stride, uint32_t wbytes,
+ uint32_t h, uint32_t val)
+{
+ uint32_t c[6];
+
+ c[0] = V3D_GL_CLEAR_RECT;
+ c[1] = addr;
+ c[2] = stride;
+ c[3] = wbytes;
+ c[4] = h;
+ c[5] = val;
+ v3d_emit(v, c, 6);
+}
diff --git a/src/mesa/drivers/verite/libv3d.h b/src/mesa/drivers/verite/libv3d.h
new file mode 100644
index 0000000..4ee44b1
--- /dev/null
+++ b/src/mesa/drivers/verite/libv3d.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * libv3d - thin userland layer over /dev/verite3d (verite3dio.h),
+ * shaped after the RRedline command-buffer model. Uses the v2000gl.uc
+ * command numbers (sync=8, context_init=2, exit=0) and the decoded
+ * state-class words.
+ */
+#ifndef LIBV3D_H
+#define LIBV3D_H
+
+#include <stdint.h>
+#include "verite3dio.h"
+
+/*
+ * Perf counters
+ */
+struct v3d_stats {
+ uint64_t words; /* words emitted into slots */
+ uint64_t submits, submit_bytes, submit_ns;
+ uint64_t syncs, sync_ns;
+ uint64_t flips, flip_ns;
+ uint64_t uploads, upload_bytes;
+ uint64_t st_calls, texbinds;
+};
+
+struct v3d {
+ int fd;
+ uint32_t *slot[V3D_RING_SLOTS];
+ uint8_t *vram; /* lazy full-VRAM read mapping */
+ int cur; /* slot being filled */
+ uint32_t n; /* words used in cur */
+ /* geometry from the kernel */
+ uint32_t ctx_base, memsize, pool_base;
+ uint32_t width, height, stride, pe_stride;
+ /* RLGL_STATS / RLGL_NULLDRAW / RLGL_NOSYNC / RLGL_NOFLIP /
+ * RLGL_TEARFLIP */
+ int opt_stats, opt_nulldraw, opt_nosync, opt_noflip;
+ int opt_tearflip;
+ struct v3d_stats st;
+};
+
+/* GL blob FIFO ABI */
+#define V3D_GL_EXIT 0
+#define V3D_GL_CTX_INIT 2
+#define V3D_GL_SYNC 8
+#define V3D_GL_MEM_WRITE 9
+#define V3D_GL_CLEAR_RECT 13
+#define V3D_GL_LINE 16 /* hw Bresenham line (rdraw2) */
+#define V3D_GL_AALINE 20 /* coverage-graded AA line */
+#define V3D_GL_TRIANGLE 24
+#define V3D_GL_TRISTRIP 26 /* hw tri-strip start (cont word 48) */
+#define V3D_GL_TRIFAN 27 /* hw tri-fan start (cont word 49) */
+#define V3D_GL_AAPOINT 50 /* coverage-graded AA point */
+#define V3D_GL_STRIP_CONT 48 /* tristrip_third_vertex continuation */
+#define V3D_GL_FAN_CONT 49 /* trifan continuation (single vtx) */
+
+/* PE register indices (state class 1 writes, value pre-shifted) */
+#define V3D_PE_SRCBASE 0
+#define V3D_PE_STRIDE 3
+#define V3D_PE_DSTBASE 4
+#define V3D_PE_DSTFMT 6
+#define V3D_PE_PMASK 7
+#define V3D_PE_SCISSORX 14
+#define V3D_PE_SCISSORY 15
+#define V3D_PE_ZBASE 16
+#define V3D_PE_FGCOLOR 19
+#define V3D_PE_FOGCOLOR 21 /* 0x00RRGGBB */
+#define V3D_PE_SRCFMT 48
+#define V3D_PE_SRCFUNC 49 /* value << 4 */
+#define V3D_PE_SRCFILTER 50 /* value << 7 */
+#define V3D_PE_ALUMODE 64 /* bits 3:0 */
+#define V3D_PE_BLENDSRCFUNC 65 /* value << 4 */
+#define V3D_PE_BLENDDSTFUNC 66 /* value << 8 */
+#define V3D_PE_ZBUFMODE 67 /* value << 12 */
+#define V3D_PE_ZBUFWRMODE 68 /* value << 16 */
+#define V3D_PE_BLENDENABLE 70 /* value << 19 */
+#define V3D_PE_DITHEREN 71 /* value << 20 */
+#define V3D_PE_FOGEN 72 /* value << 21 */
+#define V3D_PE_DSTRDDIS 74 /* value << 23 */
+
+uint64_t v3d_now_ns(void);
+int v3d_open(struct v3d *, const char *devpath, const char *ucpath);
+void v3d_close(struct v3d *);
+/*
+ * VRAM window
+ */
+const uint8_t *v3d_vram(struct v3d *);
+void v3d_emit(struct v3d *, const uint32_t *, uint32_t);
+void v3d_emit1(struct v3d *, uint32_t);
+void v3d_emitf(struct v3d *, float);
+
+uint32_t *v3d_reserve(struct v3d *, uint32_t nwords);
+void v3d_commit(struct v3d *, uint32_t nwords);
+int v3d_flush(struct v3d *);
+int v3d_sync(struct v3d *);
+int v3d_alloc(struct v3d *, uint32_t, uint32_t, uint32_t *);
+int v3d_mode(struct v3d *, uint32_t depth, uint32_t frame_base);
+int v3d_flip(struct v3d *, uint32_t frame_base);
+
+/* state class 1: single PE register write (pre-shifted value) */
+void v3d_st(struct v3d *, uint32_t reg, uint32_t val);
+/* state class 4: full texture bind */
+void v3d_texbind(struct v3d *, uint32_t addr, uint32_t srcstride,
+ uint32_t w, uint32_t h, uint32_t uscale, uint32_t vscale);
+/* mem_write upload (chunks as needed) and engine-side clear */
+int v3d_upload(struct v3d *, uint32_t dst, const void *, uint32_t);
+void v3d_clear(struct v3d *, uint32_t addr, uint32_t stride,
+ uint32_t wbytes, uint32_t h, uint32_t val);
+
+#endif /* LIBV3D_H */
diff --git a/src/mesa/drivers/verite/rlgl.c b/src/mesa/drivers/verite/rlgl.c
new file mode 100644
index 0000000..1da14f2
--- /dev/null
+++ b/src/mesa/drivers/verite/rlgl.c
@@ -0,0 +1,982 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rlgl.h"
+#include "rlvec.h"
+
+int rlgl_force_rebind = 0;
+
+/*
+ * Line-bytes -> encoded stride nibble pair
+ */
+static uint32_t
+stride_code(uint32_t linebytes)
+{
+ static const struct { uint32_t bytes, s0, s1; } tab[] = {
+ { 16, 0, 1 }, { 32, 0, 2 }, { 64, 0, 3 }, { 128, 0, 4 },
+ { 256, 1, 0 }, { 512, 2, 0 }, { 1024, 3, 0 },
+ { 2048, 0, 6 }, { 4096, 0, 7 },
+ };
+ unsigned i;
+
+ for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++)
+ if (tab[i].bytes == linebytes)
+ return (tab[i].s1 << 4) | tab[i].s0;
+ return (uint32_t)-1;
+}
+
+int
+rlgl_init(struct rlgl *rl, const char *ucpath)
+{
+ struct v3d *v = &rl->v;
+
+ memset(rl, 0, sizeof(*rl));
+ rlvec_init();
+ if (v3d_open(v, "/dev/verite3d", ucpath) != 0)
+ return -1;
+ if (v3d_mode(v, 16, 0) != 0)
+ return -1;
+ if (v3d_alloc(v, v->stride * v->height, 4096, &rl->fb[0]) != 0 ||
+ v3d_alloc(v, v->stride * v->height, 4096, &rl->fb[1]) != 0 ||
+ v3d_alloc(v, v->stride * v->height, 4096, &rl->zbuf) != 0)
+ return -1;
+ /* tiny throwaway surface for the glCopyPixels source-read seed
+ * (128px * 8 rows * 2B = 2KB, addressed at a 256B stride) */
+ if (v3d_alloc(v, 128 * 8 * 2, 4096, &rl->scratch) != 0)
+ return -1;
+
+ /* constant state */
+ v3d_st(v, V3D_PE_DSTFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SCISSORX, v->width);
+ v3d_st(v, V3D_PE_SCISSORY, v->height);
+ v3d_st(v, V3D_PE_ALUMODE, 0xC);
+ v3d_st(v, V3D_PE_DSTRDDIS, 0);
+ v3d_st(v, V3D_PE_ZBASE, rl->zbuf);
+ /*
+ * Zero every mode the GL microcode's context_init leaves
+ * undefined
+ */
+ v3d_st(v, 69, 0); /* YUV2RGB */
+ v3d_st(v, V3D_PE_DITHEREN, 0); /* DitherEnable */
+ v3d_st(v, 72, 0); /* FogEnable */
+ v3d_st(v, 73, 0); /* DstColorNoPad */
+ v3d_st(v, 75, 0); /* DstBGR */
+ v3d_st(v, 76, 0); /* TranspReject */
+ v3d_st(v, 55, 0); /* SrcBGR */
+ v3d_st(v, 81, 0); /* PatEnable */
+ v3d_st(v, 83, 0); /* SpecularEn */
+ v3d_st(v, 62, 0); /* UClamp (wrap) */
+ v3d_st(v, 63, 0); /* VClamp (wrap) */
+ v3d_st(v, V3D_PE_PMASK, 0xFFFFFFFF); /* all planes */
+ /* dst + Z stride identical, src patched by tex_bind */
+ v3d_st(v, V3D_PE_STRIDE, v->pe_stride |
+ ((v->pe_stride >> 8) << 16));
+ v3d_st(v, V3D_PE_DSTBASE, rl->fb[0]);
+ rl->cur_tex = (uint32_t)-1;
+ rl->cur_func = -1;
+ rl->env_mod = RLGL_ENV_REPLACE;
+ rl->fog_on = 0;
+ rlgl_depth_test(rl, 0);
+ rlgl_depth_mask(rl, 1);
+ rlgl_blend(rl, 0, 0, 0);
+ rlgl_alpha_test(rl, 0, 0);
+ rlgl_tex_bind(rl, NULL);
+
+ /*
+ * Claim the glass: clear both color buffers + Z, then point
+ * scanout at the FRONT buffer.
+ */
+ v3d_clear(v, rl->fb[0], v->stride, v->width * 2, v->height, 0);
+ v3d_clear(v, rl->fb[1], v->stride, v->width * 2, v->height, 0);
+ v3d_clear(v, rl->zbuf, v->stride, v->width * 2, v->height,
+ 0xFFFFFFFFU);
+ if (v3d_sync(v) != 0)
+ return -1;
+ return v3d_flip(v, rl->fb[rl->back ^ 1]);
+}
+
+void
+rlgl_shutdown(struct rlgl *rl)
+{
+
+ rlgl_stats_print(rl);
+ v3d_close(&rl->v);
+}
+
+int
+rlgl_tex_init(struct rlgl_tex *t, int w, int h, uint32_t fmt)
+{
+ uint32_t code = stride_code((uint32_t)w * 2);
+
+ if (code == (uint32_t)-1 || (w & (w - 1)) || (h & (h - 1)))
+ return -1;
+ t->w = (uint16_t)w;
+ t->h = (uint16_t)h;
+ t->fmt = fmt;
+ t->srcstride = code;
+ t->addr = 0;
+ return 0;
+}
+
+static uint32_t
+tex_align(uint32_t w)
+{
+ uint32_t a = w * 2;
+
+ return a < 64 ? 64 : a;
+}
+
+int
+rlgl_tex_alloc(struct rlgl *rl, struct rlgl_tex *t)
+{
+
+ return v3d_alloc(&rl->v, (uint32_t)t->w * t->h * 2,
+ tex_align(t->w), &t->addr);
+}
+
+/*
+ * Allocate a whole mip pyramid as ONE contiguous VRAM block,
+ * like 3dfx does.
+ */
+int
+rlgl_tex_pyramid(struct rlgl *rl, struct rlgl_tex *levs, int nlev)
+{
+ uint32_t total = 0, base;
+ int i;
+
+ for (i = 0; i < nlev; i++) {
+ uint32_t a = tex_align(levs[i].w);
+
+ total = (total + a - 1) & ~(a - 1);
+ total += (uint32_t)levs[i].w * (uint32_t)levs[i].h * 2;
+ }
+ if (v3d_alloc(&rl->v, total, tex_align(levs[0].w), &base) != 0)
+ return -1;
+ total = 0;
+ for (i = 0; i < nlev; i++) {
+ uint32_t a = tex_align(levs[i].w);
+
+ total = (total + a - 1) & ~(a - 1);
+ levs[i].addr = base + total;
+ total += (uint32_t)levs[i].w * (uint32_t)levs[i].h * 2;
+ }
+ return 0;
+}
+
+int
+rlgl_tex_create(struct rlgl *rl, struct rlgl_tex *t, int w, int h,
+ uint32_t fmt)
+{
+
+ if (rlgl_tex_init(t, w, h, fmt) != 0)
+ return -1;
+ return rlgl_tex_alloc(rl, t);
+}
+
+int
+rlgl_tex_upload_rows(struct rlgl *rl, struct rlgl_tex *t,
+ const uint16_t *texels, int y, int rows)
+{
+ static uint32_t buf[512 * 512 / 2];
+ uint32_t n = (uint32_t)t->w * (uint32_t)rows;
+ uint32_t base = (uint32_t)t->w * (uint32_t)y;
+ uint32_t i;
+
+ if (n / 2 > sizeof(buf) / 4)
+ return -1;
+ for (i = 0; i < n; i += 2)
+ buf[i / 2] = ((uint32_t)texels[base + i] << 16) |
+ (uint32_t)texels[base + i + 1];
+ return v3d_upload(&rl->v, t->addr + base * 2, buf, n * 2);
+}
+
+int
+rlgl_tex_upload(struct rlgl *rl, struct rlgl_tex *t, const uint16_t *texels)
+{
+
+ return rlgl_tex_upload_rows(rl, t, texels, 0, t->h);
+}
+
+static void
+set_srcfunc(struct rlgl *rl, int func)
+{
+
+ if (rlgl_force_rebind || rl->cur_func != func) {
+ v3d_st(&rl->v, V3D_PE_SRCFUNC, (uint32_t)func << 4);
+ rl->cur_func = func;
+ }
+}
+
+void
+rlgl_tex_bind(struct rlgl *rl, const struct rlgl_tex *t)
+{
+ struct v3d *v = &rl->v;
+
+ if (t == NULL) {
+ set_srcfunc(rl, 0); /* NOTEXTURE */
+ return;
+ }
+ if (rlgl_force_rebind || rl->cur_tex != t->addr) {
+ v3d_texbind(v, t->addr, t->srcstride, t->w, t->h,
+ 0x10000, 0x10000);
+ v3d_st(v, V3D_PE_SRCFMT, t->fmt);
+ rl->cur_tex = t->addr;
+ }
+ set_srcfunc(rl, rl->env_mod);
+}
+
+void
+rlgl_tex_env(struct rlgl *rl, int modulate)
+{
+
+ rlgl_tex_env_code(rl, modulate ? RLGL_ENV_MODULATE :
+ RLGL_ENV_REPLACE);
+}
+
+void
+rlgl_tex_env_code(struct rlgl *rl, int code)
+{
+
+ rl->env_mod = code;
+ if (rl->cur_func != 0) /* texturing active: apply now */
+ set_srcfunc(rl, code);
+}
+
+void
+rlgl_tex_wrap(struct rlgl *rl, int uclamp, int vclamp)
+{
+
+ v3d_st(&rl->v, 62, uclamp ? 1 << 15 : 0); /* UClamp */
+ v3d_st(&rl->v, 63, vclamp ? 1 << 16 : 0); /* VClamp */
+}
+
+void
+rlgl_tex_free(struct rlgl *rl, struct rlgl_tex *t)
+{
+ uint32_t addr = t->addr;
+
+ if (addr == 0)
+ return;
+ if (rl->cur_tex == addr)
+ rl->cur_tex = (uint32_t)-1;
+ (void)ioctl(rl->v.fd, V3D_FREE, &addr);
+ t->addr = 0;
+}
+
+void
+rlgl_tex_filter(struct rlgl *rl, int bilinear)
+{
+
+ v3d_st(&rl->v, V3D_PE_SRCFILTER, bilinear ? 1 << 7 : 0);
+}
+
+void
+rlgl_depth_test(struct rlgl *rl, int enable)
+{
+
+ /* LE keeps coplanar multi-pass (lightmaps) stable */
+ rlgl_depth_func(rl, enable, RLGL_Z_LE);
+}
+
+void
+rlgl_depth_func(struct rlgl *rl, int enable, int pe_code)
+{
+
+ v3d_st(&rl->v, V3D_PE_ZBUFMODE, enable ? pe_code << 12 : 0);
+}
+
+void
+rlgl_depth_mask(struct rlgl *rl, int write)
+{
+
+ v3d_st(&rl->v, V3D_PE_ZBUFWRMODE, write ? 1 << 16 : 0);
+}
+
+void
+rlgl_blend(struct rlgl *rl, int enable, uint32_t srcf, uint32_t dstf)
+{
+ struct v3d *v = &rl->v;
+
+ v3d_st(v, V3D_PE_BLENDENABLE, enable ? 1 << 19 : 0);
+ if (enable) {
+ v3d_st(v, V3D_PE_BLENDSRCFUNC, srcf << 4);
+ v3d_st(v, V3D_PE_BLENDDSTFUNC, dstf << 8);
+ }
+}
+
+void
+rlgl_alpha_test(struct rlgl *rl, int enable, uint32_t thresh8)
+{
+ struct v3d *v = &rl->v;
+
+ /* TranspReject: reject texel alpha <= AlphaThres */
+ v3d_st(v, 76, enable ? 1 << 25 : 0);
+ if (enable)
+ v3d_st(v, 29, thresh8); /* AlphaThres */
+}
+
+/*
+ * Hardware scissor.
+ */
+void
+rlgl_scissor(struct rlgl *rl, int x, int y, int w, int h)
+{
+ struct v3d *v = &rl->v;
+ int W = v->width, H = v->height;
+ int left = x, right = x + w;
+ int top = H - (y + h), bottom = H - y;
+
+ if (left < 0) left = 0; if (left > W) left = W;
+ if (right < 0) right = 0; if (right > W) right = W;
+ if (top < 0) top = 0; if (top > H) top = H;
+ if (bottom < 0) bottom = 0; if (bottom > H) bottom = H;
+ if (right < left) right = left; /* off-screen -> empty box */
+ if (bottom < top) bottom = top;
+ v3d_st(v, V3D_PE_SCISSORX, ((uint32_t)left << 16) | (uint32_t)right);
+ v3d_st(v, V3D_PE_SCISSORY, ((uint32_t)top << 16) | (uint32_t)bottom);
+}
+
+/*
+ * Hardware color mask
+ */
+void
+rlgl_color_mask(struct rlgl *rl, int r, int g, int b)
+{
+ uint32_t m = (r ? 0xF800u : 0) | (g ? 0x07E0u : 0) | (b ? 0x001Fu : 0);
+
+ v3d_st(&rl->v, V3D_PE_PMASK, m | (m << 16));
+}
+
+/*
+ * Hardware logic op (glLogicOp).
+ */
+void
+rlgl_logic_op(struct rlgl *rl, int enable, int code)
+{
+ v3d_st(&rl->v, V3D_PE_ALUMODE, enable ? (uint32_t)(code & 0xF) : 0xC);
+}
+
+/*
+ * Hardware dither (GL_DITHER).
+ */
+void
+rlgl_dither(struct rlgl *rl, int enable)
+{
+ v3d_st(&rl->v, V3D_PE_DITHEREN, enable ? (1u << 20) : 0);
+}
+
+/*
+ * Per-vertex fog (GL_FOG).
+ */
+void
+rlgl_fog(struct rlgl *rl, int enable, uint32_t rgb888)
+{
+ v3d_st(&rl->v, V3D_PE_FOGCOLOR, rgb888 & 0x00FFFFFFu);
+ v3d_st(&rl->v, V3D_PE_FOGEN, enable ? (1u << 21) : 0);
+ rl->fog_on = enable ? 1 : 0;
+}
+
+static int
+stride_codes(uint32_t bytes, uint32_t *s0code, uint32_t *s1code)
+{
+ static const struct { uint32_t code, bytes; } s0[] = {
+ { 0, 0 }, { 4, 4 }, { 1, 256 }, { 2, 512 }, { 3, 1024 },
+ };
+ static const struct { uint32_t code, bytes; } s1[] = {
+ { 0, 0 }, { 1, 16 }, { 2, 32 }, { 3, 64 }, { 4, 128 },
+ { 5, 1024 }, { 6, 2048 }, { 7, 4096 },
+ };
+ unsigned i, j;
+
+ for (i = 0; i < sizeof(s0) / sizeof(s0[0]); i++)
+ for (j = 0; j < sizeof(s1) / sizeof(s1[0]); j++)
+ if (s0[i].bytes + s1[j].bytes == bytes) {
+ *s0code = s0[i].code;
+ *s1code = s1[j].code;
+ return 0;
+ }
+ return -1;
+}
+
+int
+rlgl_copy_rect(struct rlgl *rl, uint32_t src_base, int src_w,
+ uint32_t dst_base, int dst_w, int sx, int sy, int dx, int dy,
+ int w, int h)
+{
+ struct v3d *v = &rl->v;
+ uint32_t ss0, ss1, ds0, ds1, reg58, reg59, sbase, c[6], b[4];
+ static const float seed[3][9] = {
+ { 255, 255, 255, 0, 0, 100, 0, 0, 1 },
+ { 255, 255, 255, 2, 0, 100, 0, 0, 1 },
+ { 255, 255, 255, 0, 2, 100, 0, 0, 1 },
+ };
+ int i, k;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ if (stride_codes((uint32_t)src_w * 2, &ss0, &ss1) != 0 ||
+ stride_codes((uint32_t)dst_w * 2, &ds0, &ds1) != 0)
+ return -1;
+ reg58 = (ss1 << 4) | ss0; /* SrcStride subfields */
+ reg59 = (ds1 << 12) | (ds0 << 8); /* DstStride subfields */
+ sbase = src_base + (uint32_t)sy * ((uint32_t)src_w * 2) +
+ (uint32_t)sx * 2;
+
+ c[0] = (4 << 12) | V3D_PE_SRCBASE; /* class-4 texture bind */
+ c[1] = sbase;
+ c[2] = reg58;
+ c[3] = (0x7FFu << 16) | 0x7FFu; /* UMask/VMask big (no wrap) */
+ c[4] = 0x10000; /* uscale 1.0 */
+ c[5] = 0x10000; /* vscale 1.0 */
+ v3d_emit(v, c, 6);
+ v3d_st(v, V3D_PE_SRCFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SRCFUNC, 1 << 4); /* REPLACE (copy source) */
+ v3d_st(v, V3D_PE_SRCFILTER, 0); /* point sample / BitBlt */
+ v3d_st(v, V3D_PE_DSTBASE, rl->scratch);
+ v3d_st(v, 59, 0x0100); /* scratch DstStride 256B */
+ v3d_st(v, V3D_PE_DSTFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | 128);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | 8);
+ v3d_st(v, V3D_PE_ALUMODE, 0xC);
+ v3d_st(v, V3D_PE_ZBUFMODE, 0);
+ v3d_st(v, V3D_PE_ZBUFWRMODE, 0);
+ v3d_emit1(v, (20 << 16) | V3D_GL_TRIANGLE); /* KXYZUVQ */
+ for (i = 0; i < 3; i++)
+ for (k = 0; k < 9; k++)
+ v3d_emitf(v, seed[i][k]);
+
+ v3d_st(v, V3D_PE_DSTBASE, dst_base);
+ v3d_st(v, 59, reg59); /* DstStride dual-shift */
+ v3d_st(v, V3D_PE_DSTFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | (uint32_t)dst_w);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | (uint32_t)v->height);
+ v3d_st(v, V3D_PE_PMASK, 0xFFFFFFFF);
+ v3d_st(v, 62, 0); /* UClamp off */
+ v3d_st(v, 63, 0); /* VClamp off */
+ v3d_st(v, V3D_PE_ALUMODE, 0xC);
+ v3d_st(v, V3D_PE_BLENDENABLE, 0);
+ v3d_st(v, V3D_PE_DSTRDDIS, 0);
+ v3d_st(v, 76, 0); /* TranspReject off */
+ b[0] = 30; /* microcode bitblt */
+ b[1] = ((uint32_t)dx << 16) | (uint32_t)dy;
+ b[2] = ((uint32_t)w << 16) | (uint32_t)h;
+ b[3] = 0; /* srcX=srcY=0 (base pre-offset) */
+ v3d_emit(v, b, 4);
+
+ v3d_st(v, V3D_PE_STRIDE, v->pe_stride | ((v->pe_stride >> 8) << 16));
+ v3d_st(v, V3D_PE_DSTBASE, rl->fb[rl->back]);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | v->width);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | v->height);
+ rl->cur_tex = (uint32_t)-1;
+ rl->cur_func = -1;
+ return 0;
+}
+
+int
+rlgl_copy_to_tex(struct rlgl *rl, uint32_t fb_base, int fb_h,
+ uint32_t tex_base, int tex_aw, int sx, int sy_gl, int dx, int dy,
+ int w, int h)
+{
+ struct v3d *v = &rl->v;
+ uint32_t fs0, fs1, ts0, ts1, reg58, reg59, c[6], b[4];
+ static const float seed[3][9] = {
+ { 255, 255, 255, 0, 0, 100, 0, 0, 1 },
+ { 255, 255, 255, 2, 0, 100, 0, 0, 1 },
+ { 255, 255, 255, 0, 2, 100, 0, 0, 1 },
+ };
+ int i, k, j;
+
+ if (w <= 0 || h <= 0)
+ return 0;
+ if (stride_codes((uint32_t)v->width * 2, &fs0, &fs1) != 0 ||
+ stride_codes((uint32_t)tex_aw * 2, &ts0, &ts1) != 0)
+ return -1;
+ reg58 = (fs1 << 4) | fs0; /* fb SrcStride */
+ reg59 = (ts1 << 12) | (ts0 << 8); /* texture DstStride */
+
+ c[0] = (4 << 12) | V3D_PE_SRCBASE;
+ c[1] = fb_base;
+ c[2] = reg58;
+ c[3] = (0x7FFu << 16) | 0x7FFu;
+ c[4] = 0x10000;
+ c[5] = 0x10000;
+ v3d_emit(v, c, 6);
+ v3d_st(v, V3D_PE_SRCFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SRCFUNC, 1 << 4); /* REPLACE */
+ v3d_st(v, V3D_PE_SRCFILTER, 0); /* point / BitBlt */
+ v3d_st(v, V3D_PE_DSTBASE, rl->scratch);
+ v3d_st(v, 59, 0x0100); /* scratch DstStride 256B */
+ v3d_st(v, V3D_PE_DSTFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | 128);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | 8);
+ v3d_st(v, V3D_PE_ALUMODE, 0xC);
+ v3d_st(v, V3D_PE_ZBUFMODE, 0);
+ v3d_st(v, V3D_PE_ZBUFWRMODE, 0);
+ v3d_emit1(v, (20 << 16) | V3D_GL_TRIANGLE);
+ for (i = 0; i < 3; i++)
+ for (k = 0; k < 9; k++)
+ v3d_emitf(v, seed[i][k]);
+
+ /* dest state = the texture surface */
+ v3d_st(v, V3D_PE_DSTBASE, tex_base);
+ v3d_st(v, 59, reg59);
+ v3d_st(v, V3D_PE_DSTFMT, RLGL_FMT_565);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | (uint32_t)tex_aw);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | (uint32_t)(dy + h));
+ v3d_st(v, V3D_PE_PMASK, 0xFFFFFFFF);
+ v3d_st(v, 62, 0);
+ v3d_st(v, 63, 0);
+ v3d_st(v, V3D_PE_ALUMODE, 0xC);
+ v3d_st(v, V3D_PE_BLENDENABLE, 0);
+ v3d_st(v, V3D_PE_DSTRDDIS, 0);
+ v3d_st(v, 76, 0);
+
+ for (j = 0; j < h; j++) {
+ b[0] = 30;
+ b[1] = ((uint32_t)dx << 16) | (uint32_t)(dy + j);
+ b[2] = ((uint32_t)w << 16) | 1u;
+ b[3] = ((uint32_t)sx << 16) |
+ (uint32_t)(fb_h - 1 - sy_gl - j);
+ v3d_emit(v, b, 4);
+ }
+
+ /* restore persistent draw state (see rlgl_copy_rect) */
+ v3d_st(v, V3D_PE_STRIDE, v->pe_stride | ((v->pe_stride >> 8) << 16));
+ v3d_st(v, V3D_PE_DSTBASE, rl->fb[rl->back]);
+ v3d_st(v, V3D_PE_SCISSORX, (0u << 16) | v->width);
+ v3d_st(v, V3D_PE_SCISSORY, (0u << 16) | v->height);
+ rl->cur_tex = (uint32_t)-1;
+ rl->cur_func = -1;
+ return 0;
+}
+
+void
+rlgl_clear(struct rlgl *rl, int color, uint32_t rgb565, int depth)
+{
+ struct v3d *v = &rl->v;
+ uint32_t val = rgb565 | (rgb565 << 16);
+
+ /* spec 2.8: clamps must be off for parallel-draw fills */
+ rlgl_tex_wrap(rl, 0, 0);
+ if (color)
+ v3d_clear(v, rl->fb[rl->back], v->stride, v->width * 2,
+ v->height, val);
+ if (depth)
+ v3d_clear(v, rl->zbuf, v->stride, v->width * 2,
+ v->height, 0xFFFFFFFFU);
+}
+
+/*
+ * Blit one row of w 565 pixels to the back buffer at window (x, wy).
+ */
+int
+rlgl_draw_row(struct rlgl *rl, int x, int wy, int w, const uint16_t *row565)
+{
+ struct v3d *v = &rl->v;
+ static uint32_t buf[2048 / 2];
+ uint32_t fbrow;
+ int i;
+
+ if ((x & 1) || (w & 1) || w <= 0 || w > 2048 ||
+ wy < 0 || wy >= (int)v->height || x < 0 || x + w > (int)v->width)
+ return -1;
+ fbrow = (uint32_t)((int)v->height - 1 - wy);
+ for (i = 0; i < w; i += 2)
+ buf[i / 2] = ((uint32_t)row565[i] << 16) | (uint32_t)row565[i + 1];
+ return v3d_upload(v, rl->fb[rl->back] + fbrow * v->stride +
+ (uint32_t)x * 2, buf, (uint32_t)w * 2);
+}
+
+void
+rlgl_tri(struct rlgl *rl, const struct rlgl_vtx *a,
+ const struct rlgl_vtx *b, const struct rlgl_vtx *c)
+{
+ struct v3d *v = &rl->v;
+ const struct rlgl_vtx *p[3];
+ int i;
+
+ p[0] = a; p[1] = b; p[2] = c;
+ rl->tris++;
+ /*
+ * KXYZUVQ (type 20) normally, with fog on, KFXYZUVQ (type 23)
+ */
+ v3d_emit1(v, ((rl->fog_on ? 23 : 20) << 16) | V3D_GL_TRIANGLE);
+ for (i = 0; i < 3; i++) {
+ v3d_emitf(v, p[i]->r);
+ v3d_emitf(v, p[i]->g);
+ v3d_emitf(v, p[i]->b);
+ if (rl->fog_on)
+ v3d_emitf(v, p[i]->f);
+ v3d_emitf(v, p[i]->x);
+ v3d_emitf(v, p[i]->y);
+ v3d_emitf(v, p[i]->z);
+ v3d_emitf(v, p[i]->u);
+ v3d_emitf(v, p[i]->v);
+ v3d_emitf(v, p[i]->q);
+ }
+}
+
+/*
+ * Native hardware lines.
+ */
+static void
+rlgl_emit_line(struct rlgl *rl, uint32_t cmd, const struct rlgl_vtx *a,
+ const struct rlgl_vtx *b)
+{
+ struct v3d *v = &rl->v;
+ const struct rlgl_vtx *p[2];
+ int i;
+
+ p[0] = a; p[1] = b;
+ v3d_emit1(v, (8 << 16) | cmd); /* KXYZ (type 8) */
+ for (i = 0; i < 2; i++) {
+ v3d_emitf(v, p[i]->r);
+ v3d_emitf(v, p[i]->g);
+ v3d_emitf(v, p[i]->b);
+ v3d_emitf(v, p[i]->x);
+ v3d_emitf(v, p[i]->y);
+ v3d_emitf(v, p[i]->z);
+ }
+}
+
+void
+rlgl_line(struct rlgl *rl, const struct rlgl_vtx *a, const struct rlgl_vtx *b)
+{
+
+ rl->tris++;
+ rlgl_emit_line(rl, V3D_GL_LINE, a, b);
+}
+
+void
+rlgl_aaline(struct rlgl *rl, const struct rlgl_vtx *a, const struct rlgl_vtx *b)
+{
+
+ rl->tris++;
+ rlgl_emit_line(rl, V3D_GL_AALINE, a, b);
+}
+
+/*
+ * Anti-aliased points (GL_POINT_SMOOTH) via microcode aapoint (cmd 50).
+ */
+#define RLGL_PTTEX_DIM 32
+#define RLGL_PTTEX_USCALE 0x1F8000 /* ~31.5 in 16.16 -> span [0,1] */
+
+static int
+rlgl_pt_tex_ensure(struct rlgl *rl)
+{
+ static uint16_t tex[RLGL_PTTEX_DIM * RLGL_PTTEX_DIM];
+ const float c = RLGL_PTTEX_DIM / 2.0f - 0.5f; /* texel centre */
+ const float rad = RLGL_PTTEX_DIM / 2.0f - 1.5f; /* disc radius */
+ int x, y;
+
+ if (rl->pt_tex.addr != 0)
+ return 0;
+ if (rlgl_tex_create(rl, &rl->pt_tex, RLGL_PTTEX_DIM, RLGL_PTTEX_DIM,
+ RLGL_FMT_4444) != 0)
+ return -1;
+ for (y = 0; y < RLGL_PTTEX_DIM; y++)
+ for (x = 0; x < RLGL_PTTEX_DIM; x++) {
+ float dx = (float)x - c, dy = (float)y - c;
+ float d2 = dx * dx + dy * dy; /* no sqrt: compare r^2 */
+ int a;
+
+ /*
+ * Radial alpha: opaque core, a several-texel linear
+ * coverage ramp at the rim
+ */
+ const float ramp = 3.0f; /* rim width, texels */
+ if (d2 <= (rad - ramp) * (rad - ramp))
+ a = 15; /* opaque core */
+ else if (d2 >= rad * rad)
+ a = 0; /* transparent */
+ else {
+ /* linear in true distance across [rad-ramp,rad] */
+ float d = (d2 - (rad - ramp) * (rad - ramp)) /
+ ((rad * rad) - (rad - ramp) * (rad - ramp));
+ a = (int)(15.0f * (1.0f - d) + 0.5f);
+ if (a < 0) a = 0;
+ if (a > 15) a = 15;
+ }
+ /* ARGB4444: alpha = coverage, RGB = white */
+ tex[y * RLGL_PTTEX_DIM + x] =
+ (uint16_t)((a << 12) | 0x0FFF);
+ }
+ return rlgl_tex_upload(rl, &rl->pt_tex, tex);
+}
+
+void
+rlgl_aapoint_begin(struct rlgl *rl)
+{
+ struct v3d *v = &rl->v;
+ static const float seed[3][9] = {
+ { 255, 255, 255, 1, 1, 100, 0, 0, 1 },
+ { 255, 255, 255, 3, 1, 100, 0, 0, 1 },
+ { 255, 255, 255, 1, 3, 100, 0, 0, 1 },
+ };
+ int i, k;
+
+ if (rlgl_pt_tex_ensure(rl) != 0)
+ return;
+ /* bind the coverage texture, uscale/vscale map [0,1] over any size */
+ v3d_texbind(v, rl->pt_tex.addr, rl->pt_tex.srcstride,
+ rl->pt_tex.w, rl->pt_tex.h, RLGL_PTTEX_USCALE, RLGL_PTTEX_USCALE);
+ v3d_st(v, V3D_PE_SRCFMT, RLGL_FMT_4444);
+ v3d_st(v, V3D_PE_SRCFILTER, 1 << 7); /* bilinear: smooth the rim */
+ rl->cur_tex = rl->pt_tex.addr;
+ set_srcfunc(rl, RLGL_ENV_MODULATE); /* colour = FGColor x white tex,
+ * SrcAlpha = TexAlpha (coverage)
+ * x FGColor-alpha (0xff) */
+ v3d_st(v, V3D_PE_ZBUFMODE, 0);
+ v3d_st(v, V3D_PE_ZBUFWRMODE, 0);
+ v3d_emit1(v, (20 << 16) | V3D_GL_TRIANGLE); /* KXYZUVQ */
+ for (i = 0; i < 3; i++)
+ for (k = 0; k < 9; k++)
+ v3d_emitf(v, seed[i][k]);
+}
+
+void
+rlgl_aapoint(struct rlgl *rl, const struct rlgl_vtx *a, float size)
+{
+ struct v3d *v = &rl->v;
+ int r = (int)(a->r + 0.5f), g = (int)(a->g + 0.5f);
+ int b = (int)(a->b + 0.5f);
+ uint32_t fg;
+
+ if (r < 0) r = 0; if (r > 255) r = 255;
+ if (g < 0) g = 0; if (g > 255) g = 255;
+ if (b < 0) b = 0; if (b > 255) b = 255;
+ /* FGColor 0xAARRGGBB: alpha 0xff so MODULATE SrcAlpha = TexAlpha */
+ fg = 0xFF000000u | ((uint32_t)r << 16) | ((uint32_t)g << 8) |
+ (uint32_t)b;
+ rl->tris++;
+ v3d_st(v, V3D_PE_FGCOLOR, fg);
+ v3d_emit1(v, (8 << 16) | V3D_GL_AAPOINT); /* KXYZ */
+ v3d_emitf(v, size); /* diameter */
+ v3d_emitf(v, a->r); v3d_emitf(v, a->g); v3d_emitf(v, a->b);
+ v3d_emitf(v, a->x); v3d_emitf(v, a->y); v3d_emitf(v, a->z);
+}
+
+void
+rlgl_aapoint_end(struct rlgl *rl)
+{
+
+ /* release the coverage-texture bind: force the next textured draw to
+ * rebind (which re-selects its own filter/env), and untextured draws
+ * to re-select NOTEXTURE; drop the bilinear filter we forced. */
+ v3d_st(&rl->v, V3D_PE_SRCFILTER, 0);
+ rl->cur_tex = 0;
+ set_srcfunc(rl, 0);
+}
+
+/*
+ * Emit one KXYZUVQ (or KFXYZUVQ when fog_on) vertex record
+ */
+static void
+rlgl_emit_vtx(struct v3d *v, const struct rlgl_vtx *p, int fog_on)
+{
+
+ v3d_emitf(v, p->r);
+ v3d_emitf(v, p->g);
+ v3d_emitf(v, p->b);
+ if (fog_on)
+ v3d_emitf(v, p->f);
+ v3d_emitf(v, p->x);
+ v3d_emitf(v, p->y);
+ v3d_emitf(v, p->z);
+ v3d_emitf(v, p->u);
+ v3d_emitf(v, p->v);
+ v3d_emitf(v, p->q);
+}
+
+/*
+ * Native strip/fan common core.
+ */
+static void
+rlgl_emit_run(struct rlgl *rl, uint32_t startcmd, uint32_t contword,
+ const struct rlgl_vtx *v, int n)
+{
+ struct v3d *vv = &rl->v;
+ int i;
+
+ if (n < 3)
+ return;
+ v3d_emit1(vv, ((rl->fog_on ? 23 : 20) << 16) | startcmd);
+ rlgl_emit_vtx(vv, &v[0], rl->fog_on);
+ rlgl_emit_vtx(vv, &v[1], rl->fog_on);
+ rlgl_emit_vtx(vv, &v[2], rl->fog_on);
+ for (i = 3; i < n; i++) {
+ v3d_emit1(vv, contword);
+ rlgl_emit_vtx(vv, &v[i], rl->fog_on);
+ }
+ rl->tris += (uint64_t)(n - 2);
+}
+
+void
+rlgl_tristrip(struct rlgl *rl, const struct rlgl_vtx *v, int n)
+{
+
+ rlgl_emit_run(rl, V3D_GL_TRISTRIP, V3D_GL_STRIP_CONT, v, n);
+}
+
+void
+rlgl_trifan(struct rlgl *rl, const struct rlgl_vtx *v, int n)
+{
+
+ rlgl_emit_run(rl, V3D_GL_TRIFAN, V3D_GL_FAN_CONT, v, n);
+}
+
+void
+rlgl_tris_idx(struct rlgl *rl, const float *verts9, const uint8_t *idx,
+ int ntris)
+{
+ struct v3d *v = &rl->v;
+ uint32_t *p;
+
+ if (ntris <= 0)
+ return;
+ p = v3d_reserve(v, (uint32_t)ntris * 28);
+ if (p == NULL)
+ return;
+ (void)rlvec.emit_tris(p, verts9, idx, ntris,
+ (20 << 16) | V3D_GL_TRIANGLE); /* KXYZUVQ */
+ v3d_commit(v, (uint32_t)ntris * 28);
+ rl->tris += (uint64_t)ntris;
+}
+
+int
+rlgl_finish(struct rlgl *rl)
+{
+
+ return v3d_sync(&rl->v);
+}
+
+int
+rlgl_swap(struct rlgl *rl)
+{
+ struct v3d *v = &rl->v;
+
+ if (!v->opt_nosync) {
+ if (v3d_sync(v) != 0)
+ return -1;
+ }
+ if (v3d_flip(v, rl->fb[rl->back]) != 0)
+ return -1;
+ rl->back ^= 1;
+ v3d_st(v, V3D_PE_DSTBASE, rl->fb[rl->back]);
+ rl->frames++;
+
+ if (v->opt_stats) {
+ uint64_t now = v3d_now_ns();
+
+ if (rl->last_swap_ns != 0) {
+ uint64_t d = now - rl->last_swap_ns;
+
+ rl->frame_ns_tot += d;
+ if (rl->frame_ns_min == 0 || d < rl->frame_ns_min)
+ rl->frame_ns_min = d;
+ if (d > rl->frame_ns_max)
+ rl->frame_ns_max = d;
+ }
+ rl->last_swap_ns = now;
+ /*
+ * Cumulative snapshot lines: diffing two RLGLSNAPs
+ * isolates the demo window from load/console frames.
+ */
+ if (v->opt_stats >= 2 && (rl->frames & 127) == 0)
+ printf("RLGLSNAP frames=%d ns=%llu submit_ns=%llu "
+ "sync_ns=%llu flip_ns=%llu submits=%llu "
+ "bytes=%llu tris=%llu uploads=%llu "
+ "upl_bytes=%llu\n",
+ rl->frames,
+ (unsigned long long)rl->frame_ns_tot,
+ (unsigned long long)v->st.submit_ns,
+ (unsigned long long)v->st.sync_ns,
+ (unsigned long long)v->st.flip_ns,
+ (unsigned long long)v->st.submits,
+ (unsigned long long)v->st.submit_bytes,
+ (unsigned long long)rl->tris,
+ (unsigned long long)v->st.uploads,
+ (unsigned long long)v->st.upload_bytes);
+ }
+ return 0;
+}
+
+void
+rlgl_stats_print(struct rlgl *rl)
+{
+ struct v3d_stats *s = &rl->v.st;
+ double nf = rl->frames > 0 ? (double)rl->frames : 1.0;
+ double ms = 1e6;
+
+ if (rl->stats_printed)
+ return;
+ rl->stats_printed = 1;
+ printf("RLGL frames=%d tris=%llu submits=%llu syncs=%llu "
+ "flips=%llu\n", rl->frames,
+ (unsigned long long)rl->tris,
+ (unsigned long long)s->submits,
+ (unsigned long long)s->syncs,
+ (unsigned long long)s->flips);
+ printf("RLGL words=%llu submit_bytes=%llu uploads=%llu "
+ "upload_bytes=%llu st_calls=%llu texbinds=%llu\n",
+ (unsigned long long)s->words,
+ (unsigned long long)s->submit_bytes,
+ (unsigned long long)s->uploads,
+ (unsigned long long)s->upload_bytes,
+ (unsigned long long)s->st_calls,
+ (unsigned long long)s->texbinds);
+ printf("RLGL per_frame tris=%.1f submits=%.2f bytes=%.0f "
+ "upload_bytes=%.0f\n", (double)rl->tris / nf,
+ (double)s->submits / nf, (double)s->submit_bytes / nf,
+ (double)s->upload_bytes / nf);
+ if (rl->v.opt_stats && rl->frames > 1) {
+ double blocked = (double)(s->submit_ns + s->sync_ns +
+ s->flip_ns);
+ double tot = (double)rl->frame_ns_tot;
+ /* first swap has no predecessor: nf-1 timed frames */
+ double tf = (double)(rl->frames - 1);
+
+ printf("RLGL avg_frame_ms=%.2f min=%.2f max=%.2f\n",
+ tot / tf / ms,
+ (double)rl->frame_ns_min / ms,
+ (double)rl->frame_ns_max / ms);
+ printf("RLGL avg_submit_ms=%.2f avg_sync_ms=%.2f "
+ "avg_flip_ms=%.2f avg_blocked_ms=%.2f "
+ "avg_build_ms=%.2f\n",
+ (double)s->submit_ns / nf / ms,
+ (double)s->sync_ns / nf / ms,
+ (double)s->flip_ns / nf / ms,
+ blocked / nf / ms,
+ (tot / tf - blocked / nf) / ms);
+ }
+}
diff --git a/src/mesa/drivers/verite/rlgl.h b/src/mesa/drivers/verite/rlgl.h
new file mode 100644
index 0000000..002134c
--- /dev/null
+++ b/src/mesa/drivers/verite/rlgl.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RLGL_H
+#define RLGL_H
+
+#include <stdint.h>
+#include "libv3d.h"
+
+/* texel formats (PE SrcFmt/DstFmt encodings) */
+#define RLGL_FMT_565 4
+#define RLGL_FMT_4444 5
+#define RLGL_FMT_1555 6
+
+/*
+ * blend factors
+ */
+#define RLGL_BL_ZERO 6 /* Blend0 */
+#define RLGL_BL_ONE 7 /* Blend1 */
+#define RLGL_BL_SRCALPHA 2
+#define RLGL_BL_INVSRCALPHA 3
+#define RLGL_BL_OTHERCOLOR 0 /* dst side: src color; src: dst */
+#define RLGL_BL_INVOTHERCOLOR 1
+#define RLGL_BL_OWNCOLOR 10 /* own color - no GL equivalent */
+#define RLGL_BL_INVOWNCOLOR 11
+/* legacy names (dst-side view), kept for minigl */
+#define RLGL_BL_SRCCOLOR RLGL_BL_OTHERCOLOR
+#define RLGL_BL_INVSRCCOLOR RLGL_BL_INVOTHERCOLOR
+
+struct rlgl_tex {
+ uint32_t addr; /* VRAM; 0 = not resident */
+ uint16_t w, h; /* texels, powers of two */
+ uint32_t srcstride; /* encoded (Src1<<4)|Src0 */
+ uint32_t fmt; /* RLGL_FMT_* */
+};
+
+struct rlgl {
+ struct v3d v;
+ uint32_t fb[2], zbuf;
+ uint32_t scratch; /* glCopyPixels seed scratch surface */
+ int back;
+ struct rlgl_tex pt_tex; /* AA-point radial coverage tex (lazy;
+ * addr 0 = not yet created) */
+ /* redundant-state cache */
+ uint32_t cur_tex;
+ int cur_func; /* PE SrcFunc currently set */
+ int env_mod; /* SrcFunc code for textured draws */
+ int fog_on; /* emit the KFXYZUVQ fog channel */
+ int frames;
+ /* perf: swap-to-swap frame timing (RLGL_STATS) + counters */
+ uint64_t tris;
+ uint64_t frame_ns_tot, frame_ns_min, frame_ns_max;
+ uint64_t last_swap_ns;
+ int stats_printed;
+};
+
+/* per-vertex layout handed to rlgl_tri: the KXYZUVQ order */
+struct rlgl_vtx {
+ float r, g, b; /* 0..255 */
+ float x, y; /* screen pixels */
+ float z; /* 0..65535, smaller = nearer */
+ float u, v; /* texels */
+ float q; /* 1/w (any consistent scale) */
+ float f; /* fog factor 0..255, 255 = no fog (fog_on only) */
+};
+
+/* diagnostic: 1 = disable redundant-state caches (VRMESA_NOCACHE probe) */
+extern int rlgl_force_rebind;
+
+int rlgl_init(struct rlgl *, const char *ucpath);
+void rlgl_shutdown(struct rlgl *);
+
+int rlgl_tex_init(struct rlgl_tex *, int w, int h, uint32_t fmt);
+int rlgl_tex_alloc(struct rlgl *, struct rlgl_tex *);
+int rlgl_tex_pyramid(struct rlgl *, struct rlgl_tex *levs, int nlev);
+int rlgl_tex_create(struct rlgl *, struct rlgl_tex *, int w, int h,
+ uint32_t fmt);
+void rlgl_tex_free(struct rlgl *, struct rlgl_tex *);
+int rlgl_tex_upload(struct rlgl *, struct rlgl_tex *,
+ const uint16_t *texels);
+int rlgl_tex_upload_rows(struct rlgl *, struct rlgl_tex *,
+ const uint16_t *texels, int y, int rows);
+void rlgl_tex_bind(struct rlgl *, const struct rlgl_tex *);
+void rlgl_tex_env(struct rlgl *, int modulate);
+/* PE SrcFunc codes (spec table: 1=replace 2=decal 3=modulate) */
+#define RLGL_ENV_REPLACE 1
+#define RLGL_ENV_DECAL 2
+#define RLGL_ENV_MODULATE 3
+void rlgl_tex_env_code(struct rlgl *, int srcfunc_code);
+/*
+ * Per-axis clamp-to-edge (UClamp b15 / VClamp b16 of SrcMode).
+ */
+void rlgl_tex_wrap(struct rlgl *, int uclamp, int vclamp);
+void rlgl_tex_filter(struct rlgl *, int bilinear);
+
+/* PE ZBufMode compare codes (silicon-proven: LT ztest, LE GLQuake) */
+#define RLGL_Z_LT 1
+#define RLGL_Z_LE 3
+
+void rlgl_depth_test(struct rlgl *, int enable_lt_or_le);
+void rlgl_depth_func(struct rlgl *, int enable, int pe_code);
+void rlgl_depth_mask(struct rlgl *, int write);
+void rlgl_blend(struct rlgl *, int enable, uint32_t srcf, uint32_t dstf);
+void rlgl_alpha_test(struct rlgl *, int enable, uint32_t thresh8);
+/* GL window-coord box (bottom-left origin); flips to the PE top-left */
+void rlgl_scissor(struct rlgl *, int x, int y, int w, int h);
+/* 565 plane write mask; args are glColorMask R/G/B booleans (alpha n/a) */
+void rlgl_color_mask(struct rlgl *, int r, int g, int b);
+/* PE raster op (ALUMode 4-bit ROP code); disabled restores COPY */
+void rlgl_logic_op(struct rlgl *, int enable, int code);
+/* PE 4x4 ordered dither on 565 writes (GL_DITHER) */
+void rlgl_dither(struct rlgl *, int enable);
+/*
+ * Per-vertex fog (GL_FOG)
+ */
+void rlgl_fog(struct rlgl *, int enable, uint32_t rgb888);
+
+void rlgl_clear(struct rlgl *, int color, uint32_t rgb565,
+ int depth);
+/*
+ * glDrawPixels fast path
+ */
+int rlgl_draw_row(struct rlgl *, int x, int wy, int w,
+ const uint16_t *row565);
+/*
+ * Hardware glCopyPixels (GL_COLOR)
+ */
+int rlgl_copy_rect(struct rlgl *, uint32_t src_base, int src_w,
+ uint32_t dst_base, int dst_w, int sx, int sy, int dx, int dy,
+ int w, int h);
+/*
+ * Hardware glCopyTexSubImage
+ */
+int rlgl_copy_to_tex(struct rlgl *, uint32_t fb_base, int fb_h,
+ uint32_t tex_base, int tex_aw, int sx, int sy_gl, int dx, int dy,
+ int w, int h);
+void rlgl_tri(struct rlgl *, const struct rlgl_vtx *,
+ const struct rlgl_vtx *, const struct rlgl_vtx *);
+/*
+ * Native hardware lines from a 2-vertex KXYZ stream (only r,g,b,x,y,z
+ * used).
+ */
+void rlgl_line(struct rlgl *, const struct rlgl_vtx *,
+ const struct rlgl_vtx *);
+void rlgl_aaline(struct rlgl *, const struct rlgl_vtx *,
+ const struct rlgl_vtx *);
+/*
+ * Native anti-aliased points (GL_POINT_SMOOTH)
+ */
+void rlgl_aapoint_begin(struct rlgl *);
+void rlgl_aapoint(struct rlgl *, const struct rlgl_vtx *, float size);
+void rlgl_aapoint_end(struct rlgl *);
+/*
+ * Native hardware primitive strips/fans
+ */
+void rlgl_tristrip(struct rlgl *, const struct rlgl_vtx *v, int n);
+void rlgl_trifan(struct rlgl *, const struct rlgl_vtx *v, int n);
+/*
+ * Bulk indexed emit: verts9 = packed 9-float wire records
+ * (r,g,b,x,y,z,u,v,q), idx = 3*ntris vertex indices into verts9.
+ */
+void rlgl_tris_idx(struct rlgl *, const float *verts9,
+ const uint8_t *idx, int ntris);
+int rlgl_swap(struct rlgl *);
+int rlgl_finish(struct rlgl *);
+void rlgl_stats_print(struct rlgl *);
+
+#endif /* RLGL_H */
diff --git a/src/mesa/drivers/verite/verite3dio.h b/src/mesa/drivers/verite/verite3dio.h
new file mode 100644
index 0000000..1337dc3
--- /dev/null
+++ b/src/mesa/drivers/verite/verite3dio.h
@@ -0,0 +1,107 @@
+/*
+ * Vendored from src/sys/dev/pci/verite3dio.h
+ */
+
+/* $NetBSD: verite3dio.h,v 1.1 2026/07/15 20:53:22 rkujawa Exp $ */
+
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * /dev/verite3d - expierimental 3D interface for veritefb(4)
+ *
+ * By design, it is completely independent of wsdisplay(4). It supports
+ * one exclusive client - opening the device stops the 2D microcode.
+ * Closing the device stops the 3D microcode and restores the console,
+ * in the state it was left behind.
+ *
+ * The client supplies its own RISC microcode (V3D_INIT) and owns
+ * the FIFO command stream. The kernel moves bytes (DMA) and tracks VRAM,
+ * but does NOT interpret the command stream. That is responsibility of
+ * the microcode (on the hardware side) and the userland process.
+ */
+
+#ifndef VERITE3DIO_H
+#define VERITE3DIO_H
+
+#include <sys/ioccom.h>
+
+#define V3D_RING_SLOTS 4
+#define V3D_SLOT_SIZE 65536
+
+#define V3D_VRAM_MMAP_OFF ((off_t)V3D_RING_SLOTS * V3D_SLOT_SIZE)
+
+/* Load client microcode into the foreign slot and cold-start it. */
+struct v3d_init {
+ uint64_t vi_ucode; /* in: user pointer to image */
+ uint32_t vi_size; /* in: bytes */
+ uint32_t vi_ctx_base; /* out: context save area (VRAM) */
+ uint32_t vi_memsize; /* out: total VRAM bytes */
+ uint32_t vi_pool_base; /* out: first V3D_ALLOC-managed byte */
+};
+#define V3D_INIT _IOWR('V', 0, struct v3d_init)
+
+struct v3d_submit {
+ uint32_t vs_slot; /* 0 to V3D_RING_SLOTS-1 */
+ uint32_t vs_len; /* bytes, word multiple */
+ uint32_t vs_swap; /* descriptor swap code 0..3 */
+};
+#define V3D_SUBMIT _IOW('V', 1, struct v3d_submit)
+
+/*
+ * Fence: send one word (the client microcode's sync command) and
+ * wait for the response word. In/out: word to send / word received.
+ */
+#define V3D_SYNC _IOWR('V', 2, uint32_t)
+
+struct v3d_alloc {
+ uint32_t va_size; /* in: bytes */
+ uint32_t va_align; /* in: byte alignment (0 = 4) */
+ uint32_t va_addr; /* out: VRAM byte address */
+};
+#define V3D_ALLOC _IOWR('V', 3, struct v3d_alloc)
+#define V3D_FREE _IOW('V', 4, uint32_t)
+
+struct v3d_mode {
+ uint32_t vm_depth; /* in: 8 or 16; 0 = query only */
+ uint32_t vm_frame_base; /* in: scanout base; 0 = keep */
+ uint32_t vm_width; /* out */
+ uint32_t vm_height; /* out */
+ uint32_t vm_stride; /* out: scanout line bytes */
+ uint32_t vm_pe_stride; /* out: PE Stride(3) dst encoding */
+};
+#define V3D_MODE _IOWR('V', 5, struct v3d_mode)
+
+/*
+ * vsync-waited FRAMEBASE flip.
+ */
+#define V3D_FLIP_NOWAIT 0x80000000U
+#define V3D_FLIP _IOW('V', 6, uint32_t)
+
+#endif /* VERITE3DIO_H */
diff --git a/src/mesa/drivers/verite/vrapi.c b/src/mesa/drivers/verite/vrapi.c
new file mode 100644
index 0000000..b2aa74d
--- /dev/null
+++ b/src/mesa/drivers/verite/vrapi.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * veritemesa public API
+ */
+
+#include <stdlib.h>
+#ifdef VERITE_INSTRUMENT
+#include <stdio.h>
+#endif
+
+#include "vrdrv.h"
+
+#include "GL/vrmesa.h"
+#include "context.h"
+#include "extensions.h"
+#include "imports.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+
+#ifdef VERITE_INSTRUMENT
+/*
+ * The single driver-layer perf accumulator (vrperf.h).
+ */
+struct vrperf g_vrp;
+
+/*
+ * RunPipeline wrapper
+ */
+static void
+vr_run_pipeline(GLcontext *ctx)
+{
+
+ VRP_ZE(VRP_Z_PIPELINE);
+ _tnl_run_pipeline(ctx);
+ VRP_ZX(VRP_Z_PIPELINE);
+}
+
+void
+vrPerfInit(vrmesa_context *vm)
+{
+ const char *p = getenv("VRMESA_PROF");
+
+ g_vrp.level = p ? atoi(p) : 0;
+ g_vrp.on = g_vrp.level >= 1;
+ g_vrp.rl = &vm->rl;
+ g_vrp.tb0 = vrp_tb64();
+ g_vrp.ns0 = v3d_now_ns();
+ /*
+ * Bridge the librlgl/libv3d _ns timers into VRPERF
+ */
+ if (g_vrp.on && vm->rl.v.opt_stats == 0)
+ vm->rl.v.opt_stats = 1;
+ atexit(vrPerfDump);
+}
+
+void
+vrPerfSwap(vrmesa_context *vm)
+{
+
+ (void)vm;
+ g_vrp.frames++;
+ /* cumulative snapshot, diff two lines to isolate a demo window */
+ if (g_vrp.level >= 2 && (g_vrp.frames & 127) == 0)
+ printf("VRPERFSNAP frame=%llu texres=%llu zfunc=%llu "
+ "blend=%llu fgcolor=%llu fences=%llu\n",
+ (unsigned long long)g_vrp.frames,
+ (unsigned long long)g_vrp.fb[VRP_FB_TEX_RESIDENCY],
+ (unsigned long long)g_vrp.fb[VRP_FB_DEPTHFUNC],
+ (unsigned long long)g_vrp.fb[VRP_FB_BLEND],
+ (unsigned long long)g_vrp.fgcolor_writes,
+ (unsigned long long)g_vrp.fences);
+}
+
+void
+vrPerfDump(void)
+{
+ static const char *zname[VRP_Z__N] = {
+ "pipeline", "render_start", "texvalidate", "tri_emit"
+ };
+ struct rlgl *rl = g_vrp.rl;
+ double tick_ns, nf;
+ uint64_t dtb;
+ int i;
+
+ if (g_vrp.printed || g_vrp.level < 1)
+ return;
+ g_vrp.printed = 1;
+
+ dtb = vrp_tb64() - g_vrp.tb0;
+ tick_ns = dtb ? (double)(v3d_now_ns() - g_vrp.ns0) / (double)dtb : 0.0;
+ nf = g_vrp.frames > 0 ? (double)g_vrp.frames : 1.0;
+
+ printf("VRPERF frames=%llu\n", (unsigned long long)g_vrp.frames);
+ printf("VRPERF fallback tex=%llu blend=%llu afunc=%llu zfunc=%llu "
+ "stipple=%llu smooth=%llu twoside=%llu specular=%llu "
+ "unfilled=%llu rmode=%llu texres=%llu alphagrad=%llu\n",
+ (unsigned long long)g_vrp.fb[VRP_FB_TEX_HWOK],
+ (unsigned long long)g_vrp.fb[VRP_FB_BLEND],
+ (unsigned long long)g_vrp.fb[VRP_FB_ALPHAFUNC],
+ (unsigned long long)g_vrp.fb[VRP_FB_DEPTHFUNC],
+ (unsigned long long)g_vrp.fb[VRP_FB_STIPPLE],
+ (unsigned long long)g_vrp.fb[VRP_FB_SMOOTH],
+ (unsigned long long)g_vrp.fb[VRP_FB_TWOSIDE],
+ (unsigned long long)g_vrp.fb[VRP_FB_SPECULAR],
+ (unsigned long long)g_vrp.fb[VRP_FB_UNFILLED_SUB],
+ (unsigned long long)g_vrp.fb[VRP_FB_RENDERMODE],
+ (unsigned long long)g_vrp.fb[VRP_FB_TEX_RESIDENCY],
+ (unsigned long long)g_vrp.fb[VRP_FB_TRI_ALPHAGRAD]);
+ printf("VRPERF texval dirty=%llu nlvl=%llu evict=%llu first=%llu "
+ "bindonly=%llu creates=%llu failv=%llu failu=%llu\n",
+ (unsigned long long)g_vrp.tv_dirty,
+ (unsigned long long)g_vrp.tv_nlevels,
+ (unsigned long long)g_vrp.tv_evict,
+ (unsigned long long)g_vrp.tv_first,
+ (unsigned long long)g_vrp.tv_bindonly,
+ (unsigned long long)g_vrp.tv_creates,
+ (unsigned long long)g_vrp.tv_failv,
+ (unsigned long long)g_vrp.tv_failu);
+ printf("VRPERF churn fgcolor=%llu mipbind=%llu filt=%llu fences=%llu\n",
+ (unsigned long long)g_vrp.fgcolor_writes,
+ (unsigned long long)g_vrp.mip_binds,
+ (unsigned long long)g_vrp.filt_changes,
+ (unsigned long long)g_vrp.fences);
+ printf("VRPERF cpu_ms_per_frame tick_ns=%.3f", tick_ns);
+ for (i = 0; i < VRP_Z__N; i++)
+ printf(" %s=%.2f", zname[i],
+ (double)g_vrp.zone[i] * tick_ns / nf / 1e6);
+ printf("\n");
+ if (rl != NULL)
+ printf("VRPERF gpu_wait_ms_per_frame submit=%.2f sync=%.2f "
+ "flip=%.2f | tris=%llu st_calls=%llu texbinds=%llu "
+ "submit_kb=%llu\n",
+ (double)rl->v.st.submit_ns / nf / 1e6,
+ (double)rl->v.st.sync_ns / nf / 1e6,
+ (double)rl->v.st.flip_ns / nf / 1e6,
+ (unsigned long long)rl->tris,
+ (unsigned long long)rl->v.st.st_calls,
+ (unsigned long long)rl->v.st.texbinds,
+ (unsigned long long)(rl->v.st.submit_bytes / 1024));
+}
+#endif /* VERITE_INSTRUMENT */
+
+vrMesaContext
+vrMesaCreateContext(const char *ucodepath)
+{
+ vrmesa_context *vmesa;
+ GLcontext *ctx;
+ struct dd_function_table functions;
+
+ if (ucodepath == NULL)
+ ucodepath = getenv("VERITE_UCODE");
+ if (ucodepath == NULL) {
+ _mesa_printf("vrMesaCreateContext: no microcode "
+ "(pass a path or set VERITE_UCODE)\n");
+ return NULL;
+ }
+
+ vmesa = CALLOC_STRUCT(vrmesa_context);
+ if (vmesa == NULL)
+ return NULL;
+
+ if (rlgl_init(&vmesa->rl, ucodepath) != 0) {
+ _mesa_free(vmesa);
+ return NULL;
+ }
+ vmesa->fg_alpha = ~0u; /* FGColor alpha cache: unset */
+
+ if (!_mesa_initialize_visual(&vmesa->glvis,
+ GL_TRUE, /* rgb */
+ GL_TRUE, /* double buffered */
+ GL_FALSE, /* stereo */
+ 5, 6, 5, 0, /* rgba bits */
+ 0, /* index bits */
+ 16, /* depth bits */
+ 0, /* stencil */
+ 0, 0, 0, 0, /* accum */
+ 0)) { /* samples */
+ rlgl_shutdown(&vmesa->rl);
+ _mesa_free(vmesa);
+ return NULL;
+ }
+
+ _mesa_init_driver_functions(&functions);
+ vrInitDDFuncs(&functions);
+
+ if (!_mesa_initialize_context(&vmesa->glctx, &vmesa->glvis, NULL,
+ &functions, (void *)vmesa)) {
+ rlgl_shutdown(&vmesa->rl);
+ _mesa_free(vmesa);
+ return NULL;
+ }
+ ctx = &vmesa->glctx;
+
+ vrInitTexConsts(ctx);
+
+ /* hardware depth+color, no software stencil/accum/alpha planes */
+ _mesa_initialize_framebuffer(&vmesa->glfb, &vmesa->glvis,
+ GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ _swrast_CreateContext(ctx);
+ _ac_CreateContext(ctx);
+ _tnl_CreateContext(ctx);
+ _swsetup_CreateContext(ctx);
+ _swsetup_Wakeup(ctx);
+
+ /*
+ * The PE fog unit iterates a per-vertex factor (KFXYZUVQ f term)
+ */
+ _tnl_allow_vertex_fog(ctx, GL_TRUE);
+ _tnl_allow_pixel_fog(ctx, GL_FALSE);
+
+ vrInitSpanFuncs(ctx);
+ vrInitTriFuncs(ctx);
+
+#ifdef VERITE_INSTRUMENT
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = vr_run_pipeline;
+#else
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+#endif
+
+ _mesa_enable_sw_extensions(ctx);
+
+ vrPerfInit(vmesa);
+
+ return (vrMesaContext)vmesa;
+}
+
+void
+vrMesaDestroyContext(vrMesaContext vrctx)
+{
+ vrmesa_context *vmesa = (vrmesa_context *)vrctx;
+ GLcontext *ctx;
+
+ if (vmesa == NULL)
+ return;
+ ctx = &vmesa->glctx;
+
+ if (vrMesaGetCurrentContext() == vrctx)
+ _mesa_make_current2(NULL, NULL, NULL);
+
+ _swsetup_DestroyContext(ctx);
+ _tnl_DestroyContext(ctx);
+ _ac_DestroyContext(ctx);
+ _swrast_DestroyContext(ctx);
+
+ _mesa_free_framebuffer_data(&vmesa->glfb);
+ _mesa_free_context_data(ctx);
+ vrPerfDump(); /* while g_vrp.rl is still valid */
+ rlgl_shutdown(&vmesa->rl);
+ _mesa_free(vmesa);
+}
+
+vrMesaContext
+vrMesaGetCurrentContext(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ return (vrMesaContext)ctx;
+}
+
+void
+vrMesaMakeCurrent(vrMesaContext vrctx)
+{
+ vrmesa_context *vmesa = (vrmesa_context *)vrctx;
+
+ if (vmesa == NULL) {
+ _mesa_make_current2(NULL, NULL, NULL);
+ return;
+ }
+ _mesa_make_current2(&vmesa->glctx, &vmesa->glfb, &vmesa->glfb);
+}
+
+void
+vrMesaSwapBuffers(void)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vrmesa_context *vmesa;
+
+ if (ctx == NULL)
+ return;
+ vmesa = VRMESA_CONTEXT(ctx);
+ _mesa_notifySwapBuffers(ctx);
+ rlgl_swap(&vmesa->rl);
+ /* rlgl_swap fences the engine before flipping */
+ vmesa->engine_dirty = GL_FALSE;
+ vrPerfSwap(vmesa);
+}
diff --git a/src/mesa/drivers/verite/vrdd.c b/src/mesa/drivers/verite/vrdd.c
new file mode 100644
index 0000000..36daf2b
--- /dev/null
+++ b/src/mesa/drivers/verite/vrdd.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * veritemesa device-driver functions
+ */
+
+#include "vrdrv.h"
+
+#include "context.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h" /* SWRAST_CONTEXT / _RasterMask */
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+
+static const GLubyte *
+vr_get_string(GLcontext *ctx, GLenum pname)
+{
+ (void)ctx;
+ switch (pname) {
+ case GL_VENDOR:
+ return (const GLubyte *)"Rendition";
+ case GL_RENDERER:
+ return (const GLubyte *)"Mesa Rendition Verite V2200";
+ default:
+ return NULL;
+ }
+}
+
+static void
+vr_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ vrmesa_context *vmesa;
+
+ (void)buffer;
+ if (ctx == NULL)
+ return;
+ vmesa = VRMESA_CONTEXT(ctx);
+ *width = vmesa->rl.v.width;
+ *height = vmesa->rl.v.height;
+}
+
+/* GL_CLEAR..GL_SET (0x1500..0x150F) -> PE ALUMode 4-bit ROP */
+static const GLubyte vr_rop[16] = {
+ 0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE,
+ 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF,
+};
+
+static void
+vr_update_state(GLcontext *ctx, GLuint new_state)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct rlgl *rl = &vmesa->rl;
+
+ _swrast_InvalidateState(ctx, new_state);
+ _swsetup_InvalidateState(ctx, new_state);
+ _ac_InvalidateState(ctx, new_state);
+ _tnl_InvalidateState(ctx, new_state);
+
+ /*
+ * PE state used only by the hardware triangle path
+ */
+ if (new_state & _NEW_DEPTH) {
+ /* GL_ALWAYS = compare off; writes are ZBufWrMode's job */
+ rlgl_depth_func(rl,
+ ctx->Depth.Test && ctx->Depth.Func != GL_ALWAYS,
+ ctx->Depth.Func == GL_LESS ? RLGL_Z_LT : RLGL_Z_LE);
+ rlgl_depth_mask(rl, ctx->Depth.Test && ctx->Depth.Mask);
+ }
+ if (new_state & _NEW_COLOR) {
+ GLuint srcf, dstf;
+ GLboolean na;
+
+ rlgl_color_mask(rl, ctx->Color.ColorMask[0],
+ ctx->Color.ColorMask[1], ctx->Color.ColorMask[2]);
+
+ /* honor GL_DITHER (default on): PE 4x4 dither on 565 */
+ rlgl_dither(rl, ctx->Color.DitherFlag);
+
+ if (ctx->Color._LogicOpEnabled) {
+ rlgl_logic_op(rl, 1,
+ vr_rop[ctx->Color.LogicOp - GL_CLEAR]);
+ rlgl_blend(rl, 0, 0, 0);
+ } else {
+ rlgl_logic_op(rl, 0, 0);
+ if (ctx->Color.BlendEnabled &&
+ vrBlendMap(ctx, &srcf, &dstf, &na))
+ rlgl_blend(rl, 1, srcf, dstf);
+ else
+ rlgl_blend(rl, 0, 0, 0);
+ }
+
+ /* TranspReject: reject SrcAlpha <= thresh */
+ if (ctx->Color.AlphaEnabled) {
+ GLint ref = (GLint)(ctx->Color.AlphaRef *
+ 255.0F + 0.5F);
+
+ switch (ctx->Color.AlphaFunc) {
+ case GL_GREATER:
+ rlgl_alpha_test(rl, 1, (uint32_t)ref);
+ break;
+ case GL_GEQUAL:
+ /* pass a >= ref == reject a <= ref-1 */
+ if (ref <= 0)
+ rlgl_alpha_test(rl, 0, 0);
+ else
+ rlgl_alpha_test(rl, 1,
+ (uint32_t)(ref - 1));
+ break;
+ case GL_NEVER:
+ rlgl_alpha_test(rl, 1, 255);
+ break;
+ default: /* ALWAYS or gated shapes */
+ rlgl_alpha_test(rl, 0, 0);
+ break;
+ }
+ } else
+ rlgl_alpha_test(rl, 0, 0);
+ }
+
+ if (new_state & _NEW_FOG) {
+ if (ctx->Fog.Enabled) {
+ GLubyte c[3];
+
+ UNCLAMPED_FLOAT_TO_UBYTE(c[0], ctx->Fog.Color[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(c[1], ctx->Fog.Color[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(c[2], ctx->Fog.Color[2]);
+ rlgl_fog(rl, 1, ((uint32_t)c[0] << 16) |
+ ((uint32_t)c[1] << 8) | (uint32_t)c[2]);
+ } else
+ rlgl_fog(rl, 0, 0);
+ }
+
+ if (new_state & _NEW_SCISSOR) {
+ if (ctx->Scissor.Enabled)
+ rlgl_scissor(rl, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height);
+ else
+ rlgl_scissor(rl, 0, 0, rl->v.width, rl->v.height);
+ }
+
+ vrCheckHwRender(ctx);
+}
+
+static void
+vr_clear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLbitfield rest = mask;
+ int cc = 0, cz = 0;
+
+ /* frame boundary for texture evict-pinning (once per GLQuake frame) */
+ vrTexNewFrame();
+
+ if (all && !ctx->Scissor.Enabled) {
+ if ((mask & DD_BACK_LEFT_BIT) != 0 &&
+ ctx->Color.ColorMask[0] && ctx->Color.ColorMask[1] &&
+ ctx->Color.ColorMask[2]) {
+ cc = 1;
+ rest &= ~DD_BACK_LEFT_BIT;
+ }
+ /* engine Z clear writes the max-Z pattern = depth 1.0 */
+ if ((mask & DD_DEPTH_BIT) != 0 && ctx->Depth.Mask &&
+ ctx->Depth.Clear == 1.0) {
+ cz = 1;
+ rest &= ~DD_DEPTH_BIT;
+ }
+ }
+
+ if (cc || cz) {
+ const GLfloat *c = ctx->Color.ClearColor;
+ GLuint r = (GLuint)(c[0] * 255.0F + 0.5F);
+ GLuint g = (GLuint)(c[1] * 255.0F + 0.5F);
+ GLuint b = (GLuint)(c[2] * 255.0F + 0.5F);
+ uint32_t rgb565;
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ rgb565 = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
+ rlgl_clear(&vmesa->rl, cc, rgb565, cz);
+ vmesa->engine_dirty = GL_TRUE;
+ }
+
+ if (rest != 0)
+ _swrast_Clear(ctx, rest, all, x, y, width, height);
+}
+
+/*
+ * Hardware glDrawPixels.
+ */
+static void
+vr_drawpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ static GLushort row565[2048];
+ GLint destX, destY, drawW, drawH, skipPix, skipRows, rowLen, r, i, ch;
+ const GLchan *src;
+
+ if (!ctx->Current.RasterPosValid)
+ return;
+ if ((format != GL_RGBA && format != GL_RGB) || type != CHAN_TYPE ||
+ ctx->_ImageTransferState != 0 || !ctx->Visual.rgbMode ||
+ (SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) != 0 ||
+ ctx->Texture._EnabledCoordUnits != 0 ||
+ unpack->Alignment != 1 || unpack->SwapBytes || unpack->LsbFirst ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+ goto slow;
+
+ destX = x; destY = y; drawW = width; drawH = height;
+ skipPix = unpack->SkipPixels; skipRows = unpack->SkipRows;
+ rowLen = unpack->RowLength > 0 ? unpack->RowLength : width;
+
+ /* clip to the draw buffer (mirrors swrast fast_draw_pixels) */
+ if (destX < ctx->DrawBuffer->_Xmin) {
+ skipPix += ctx->DrawBuffer->_Xmin - destX;
+ drawW -= ctx->DrawBuffer->_Xmin - destX;
+ destX = ctx->DrawBuffer->_Xmin;
+ }
+ if (destX + drawW > ctx->DrawBuffer->_Xmax)
+ drawW -= destX + drawW - ctx->DrawBuffer->_Xmax;
+ if (drawW <= 0)
+ return;
+ if (destY < ctx->DrawBuffer->_Ymin) {
+ skipRows += ctx->DrawBuffer->_Ymin - destY;
+ drawH -= ctx->DrawBuffer->_Ymin - destY;
+ destY = ctx->DrawBuffer->_Ymin;
+ }
+ if (destY + drawH > ctx->DrawBuffer->_Ymax)
+ drawH -= destY + drawH - ctx->DrawBuffer->_Ymax;
+ if (drawH <= 0)
+ return;
+
+ /* mem_write needs 32-bit alignment: even x and even width */
+ if ((destX & 1) || (drawW & 1) || drawW > 2048)
+ goto slow;
+
+ ch = (format == GL_RGBA) ? 4 : 3;
+ src = (const GLchan *)pixels + (skipRows * rowLen + skipPix) * ch;
+ for (r = 0; r < drawH; r++) {
+ const GLchan *p = src + (GLint)r * rowLen * ch;
+
+ for (i = 0; i < drawW; i++) {
+ GLchan cr = p[i * ch], cg = p[i * ch + 1],
+ cb = p[i * ch + 2];
+
+ row565[i] = (GLushort)(((cr & 0xf8) << 8) |
+ ((cg & 0xfc) << 3) | (cb >> 3));
+ }
+ (void)rlgl_draw_row(&vmesa->rl, destX, destY + r, drawW, row565);
+ }
+ vmesa->engine_dirty = GL_TRUE;
+ return;
+slow:
+ _swrast_DrawPixels(ctx, x, y, width, height, format, type, unpack,
+ pixels);
+}
+
+/* rl.fb[back] is the draw target, the other buffer is scanned out */
+uint32_t
+vr_fb_base(struct rlgl *rl, GLenum buffer)
+{
+
+ if (buffer == GL_FRONT || buffer == GL_FRONT_LEFT)
+ return rl->fb[rl->back ^ 1];
+ return rl->fb[rl->back]; /* GL_BACK / default */
+}
+
+/*
+ * Hardware glCopyPixels(GL_COLOR).
+ */
+static void
+vr_copypixels(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width,
+ GLsizei height, GLint destx, GLint desty, GLenum type)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct rlgl *rl = &vmesa->rl;
+ GLint fbW = (GLint)rl->v.width, fbH = (GLint)rl->v.height;
+ uint32_t sbase, dbase;
+ GLint sy_pe, dy_pe;
+ GLboolean overlap;
+
+ if (type != GL_COLOR || ctx->_ImageTransferState != 0 ||
+ !ctx->Visual.rgbMode ||
+ (SWRAST_CONTEXT(ctx)->_RasterMask & ~CLIP_BIT) != 0 ||
+ ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F)
+ goto slow;
+
+ /* both rects must lie fully inside their buffers (swrast handles
+ * the clipped/border cases correctly) */
+ if (width <= 0 || height <= 0 ||
+ srcx < 0 || srcy < 0 || srcx + width > fbW || srcy + height > fbH ||
+ destx < 0 || desty < 0 || destx + width > fbW ||
+ desty + height > fbH)
+ goto slow;
+
+ sbase = vr_fb_base(rl, ctx->Pixel.ReadBuffer);
+ dbase = vr_fb_base(rl, ctx->Color.DrawBuffer);
+
+ /*
+ * The copy hides the true src/dst relationship from the microcode's
+ * overlap-direction logic
+ */
+ overlap = (sbase == dbase) &&
+ !(destx >= srcx + width || destx + width <= srcx ||
+ desty >= srcy + height || desty + height <= srcy);
+ if (overlap)
+ goto slow;
+
+ /* GL window (bottom-left) -> PE surface (top-left) top edge */
+ sy_pe = fbH - srcy - height;
+ dy_pe = fbH - desty - height;
+ if (rlgl_copy_rect(rl, sbase, fbW, dbase, fbW, srcx, sy_pe,
+ destx, dy_pe, width, height) != 0)
+ goto slow;
+ vmesa->engine_dirty = GL_TRUE;
+ return;
+slow:
+ _swrast_CopyPixels(ctx, srcx, srcy, destx, desty, width, height, type);
+}
+
+static void
+vr_finish(GLcontext *ctx)
+{
+
+ vrFence(VRMESA_CONTEXT(ctx));
+}
+
+static void
+vr_flush(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+
+ if (vmesa->engine_dirty)
+ (void)v3d_flush(&vmesa->rl.v);
+}
+
+void
+vrInitDDFuncs(struct dd_function_table *functions)
+{
+
+ functions->GetString = vr_get_string;
+ functions->GetBufferSize = vr_get_buffer_size;
+ functions->UpdateState = vr_update_state;
+ functions->Clear = vr_clear;
+ functions->Finish = vr_finish;
+ functions->Flush = vr_flush;
+ functions->DrawPixels = vr_drawpixels;
+ functions->CopyPixels = vr_copypixels;
+ vrInitTexFuncs(functions);
+}
diff --git a/src/mesa/drivers/verite/vrdrv.h b/src/mesa/drivers/verite/vrdrv.h
new file mode 100644
index 0000000..9762e95
--- /dev/null
+++ b/src/mesa/drivers/verite/vrdrv.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Mesa driver for the Rendition Verite V2200 over librlgl
+ * (NetBSD /dev/verite3d) - "veritemesa".
+ */
+
+#ifndef VRDRV_H
+#define VRDRV_H
+
+#include "glheader.h"
+#include "mtypes.h"
+
+#include "rlgl.h"
+
+#include "vrperf.h"
+
+typedef struct vrmesa_context {
+ GLcontext glctx; /* base class -- must be first */
+ GLvisual glvis;
+ GLframebuffer glfb;
+
+ struct rlgl rl;
+
+ GLboolean hw_tris; /* state allows PE triangles */
+ GLboolean engine_dirty; /* PE work queued, spans must fence */
+ GLboolean span_front; /* swrast SetBuffer chose front */
+
+ /* hardware texture stage (vrtex.c) */
+ struct vr_texture *textures; /* all driver texture data */
+ GLuint lru_tick;
+ GLboolean tex_on; /* this render run is textured */
+ GLfloat tex_w, tex_h; /* texel scales for u/v emit */
+ GLfloat tex_off; /* 0.5 iff bilinear (GL footprint) */
+ GLfloat tex_base_w, tex_base_h; /* level-0 dims (LOD) */
+
+ /* per-polygon mipmapping (vrtris picks a level per triangle) */
+ struct vr_texture *tex_cur; /* validated binding */
+ GLboolean tex_mip; /* MIN filter is a mipmap one */
+ GLboolean tex_min_bilin; /* LINEAR_MIPMAP_* */
+ GLboolean tex_mag_bilin; /* MagFilter == LINEAR */
+ GLint cur_level; /* bound level (bind cache) */
+ GLint cur_bilin; /* SrcFilter cache (-1 unset) */
+
+ /* hardware blend: source alpha rides PE FGColor bits 31:24 */
+ GLboolean blend_alpha; /* hw blend factors read src alpha */
+ GLboolean atest_alpha; /* alpha test needs composed ColorAlpha */
+ GLuint fg_alpha; /* cached FGColor alpha (~0 = unset) */
+
+ /* swsetup's Render.Start, wrapped by vr_render_start */
+ void (*ss_render_start)(GLcontext *);
+ /* swsetup's current tri/quad/line/point funcs (restored on fallback) */
+ void (*ss_triangle)(GLcontext *, GLuint, GLuint, GLuint);
+ void (*ss_quad)(GLcontext *, GLuint, GLuint, GLuint,
+ GLuint);
+ void (*ss_line)(GLcontext *, GLuint, GLuint);
+ void (*ss_points)(GLcontext *, GLuint, GLuint);
+
+ void *ss_prim_verts, *ss_prim_elts;
+ GLboolean use_strips; /* VRMESA_STRIPS: opt-in native tri-fans */
+ GLboolean strips_ok; /* this run's state permits them */
+
+ void (*ss_build_vertices)(GLcontext *, GLuint, GLuint,
+ GLuint);
+ GLboolean use_fastbuild; /* VRMESA_NOFASTBUILD unset (default on) */
+ GLboolean fastbuild_ok; /* this run's inputs are fast-pathable */
+ GLboolean fb_tex, fb_fog; /* fast build emits texcoord0 / fog */
+} vrmesa_context;
+
+#define VRMESA_CONTEXT(ctx) ((vrmesa_context *)(ctx))
+
+/* vrdd.c */
+extern void vrInitDDFuncs(struct dd_function_table *functions);
+/* VRAM base of a GL_FRONT/GL_BACK color buffer (rl.fb[back] = draw) */
+extern uint32_t vr_fb_base(struct rlgl *rl, GLenum buffer);
+
+/* vrspan.c */
+extern void vrInitSpanFuncs(GLcontext *ctx);
+extern void vrFence(vrmesa_context *vmesa);
+
+/* vrtex.c */
+struct vr_texture;
+struct rlgl_tex;
+extern void vrInitTexConsts(GLcontext *ctx);
+extern void vrInitTexFuncs(struct dd_function_table *functions);
+extern GLboolean vrTexHwOk(GLcontext *ctx);
+extern GLboolean vrTexValidate(GLcontext *ctx);
+extern struct rlgl_tex *vrTexLevel(struct vr_texture *t, GLint level);
+extern GLint vrTexNumLevels(struct vr_texture *t);
+extern void vrTexNewFrame(void);
+
+/* vrtris.c */
+extern void vrInitTriFuncs(GLcontext *ctx);
+extern void vrCheckHwRender(GLcontext *ctx);
+extern GLboolean vrBlendMap(const GLcontext *ctx, GLuint *srcf,
+ GLuint *dstf, GLboolean *needs_alpha);
+
+#endif /* VRDRV_H */
diff --git a/src/mesa/drivers/verite/vrperf.h b/src/mesa/drivers/verite/vrperf.h
new file mode 100644
index 0000000..27c5487
--- /dev/null
+++ b/src/mesa/drivers/verite/vrperf.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * vrperf - veritemesa driver-layer performance instrumentation.
+ */
+#ifndef VRPERF_H
+#define VRPERF_H
+
+enum {
+ VRP_FB_TEX_HWOK, /* texture enabled but not PE-expressible */
+ VRP_FB_BLEND, /* blend func not in the PE map */
+ VRP_FB_ALPHAFUNC, /* alpha func not GREATER/GEQUAL/NEVER/ALWAYS */
+ VRP_FB_DEPTHFUNC, /* depth func not LESS/LEQUAL/ALWAYS */
+ VRP_FB_STIPPLE, /* DD_TRI_STIPPLE */
+ VRP_FB_SMOOTH, /* DD_TRI_SMOOTH */
+ VRP_FB_TWOSIDE, /* DD_TRI_LIGHT_TWOSIDE */
+ VRP_FB_SPECULAR, /* DD_SEPARATE_SPECULAR */
+ VRP_FB_UNFILLED_SUB, /* unfilled poly + a sub-mode HW can't do */
+ VRP_FB_RENDERMODE, /* RenderMode != GL_RENDER */
+ VRP_FB_TEX_RESIDENCY, /* gate passed but vrTexValidate could not fit */
+ VRP_FB_TRI_ALPHAGRAD, /* per-tri: real alpha gradient -> _swrast_Triangle */
+ VRP_FB__N
+};
+
+enum {
+ VRP_Z_PIPELINE, /* whole _tnl_run_pipeline (all CPU/frame) */
+ VRP_Z_RENDER_START, /* vr_render_start: our validate + texvalidate */
+ VRP_Z_TEXVALIDATE, /* vrTexValidate: texture convert/upload CPU */
+ VRP_Z_TRI_EMIT, /* per-tri vr_tri (level >= 3 only) */
+ VRP_Z__N
+};
+
+#ifdef VERITE_INSTRUMENT
+
+#include <stdint.h>
+
+struct vrperf {
+ int on; /* VRMESA_PROF >= 1 (gates hot sites) */
+ int level; /* full VRMESA_PROF value */
+ int printed; /* atexit/destroy double-print guard */
+ struct rlgl *rl; /* borrowed: surface librlgl/libv3d stats */
+
+ uint64_t fb[VRP_FB__N]; /* swrast-fallback histogram */
+ uint64_t frames; /* our own swap count */
+
+ /* state-churn / stall counters */
+ uint64_t fgcolor_writes; /* per-tri FGColor writes (vrtris.c) */
+ uint64_t mip_binds; /* per-poly level binds */
+ uint64_t filt_changes; /* per-poly filter switches */
+ uint64_t fences; /* vrFence real PE stalls (vrspan.c) */
+
+ /* texture-validate classification (the 1->19 fps diagnostic set) */
+ uint64_t tv_dirty; /* data changed -> re-upload */
+ uint64_t tv_nlevels; /* resident but fewer levels than wanted */
+ uint64_t tv_evict; /* an LRU victim was unloaded */
+ uint64_t tv_first; /* never-resident first upload */
+ uint64_t tv_bindonly; /* resident, no upload (fast path) */
+ uint64_t tv_creates; /* new vr_texture objects made */
+ uint64_t tv_failv; /* validate failed: could not fit base */
+ uint64_t tv_failu; /* validate failed: an upload errored */
+
+ uint64_t zone[VRP_Z__N];
+ uint64_t zone_t0[VRP_Z__N];
+ uint64_t tb0, ns0; /* one-time ns calibration anchors */
+};
+
+extern struct vrperf g_vrp;
+
+#if defined(__powerpc__)
+static __inline uint32_t
+vrp_tb(void)
+{
+ uint32_t t;
+
+ __asm__ volatile("mftb %0" : "=r"(t));
+ return t;
+}
+
+static __inline uint64_t
+vrp_tb64(void)
+{
+ uint32_t hi, lo, hi2;
+
+ do {
+ __asm__ volatile("mftbu %0" : "=r"(hi));
+ __asm__ volatile("mftb %0" : "=r"(lo));
+ __asm__ volatile("mftbu %0" : "=r"(hi2));
+ } while (hi != hi2);
+ return ((uint64_t)hi << 32) | lo;
+}
+#else
+static __inline uint32_t vrp_tb(void) { return (uint32_t)v3d_now_ns(); }
+static __inline uint64_t vrp_tb64(void) { return v3d_now_ns(); }
+#endif
+
+/*
+ * Counter tiers.
+ */
+#define VRP_COUNT(f) (g_vrp.f++)
+#define VRP_ADD(f, n) (g_vrp.f += (uint64_t)(n))
+#define VRP_FALLBACK(r) (g_vrp.fb[r]++)
+/* gated fallback bump for per-primitive sites (vr_tri alpha gradient) */
+#define VRP_FALLBACK_HOT(r) do { if (g_vrp.on) g_vrp.fb[r]++; } while (0)
+#define VRP_HOT(f) do { if (g_vrp.on) g_vrp.f++; } while (0)
+#define VRP_ZE(z) do { if (g_vrp.on) g_vrp.zone_t0[z] = vrp_tb(); } while (0)
+#define VRP_ZX(z) do { if (g_vrp.on) \
+ g_vrp.zone[z] += (uint32_t)(vrp_tb() - g_vrp.zone_t0[z]); } while (0)
+#define VRP_ZE3(z) do { if (g_vrp.level >= 3) g_vrp.zone_t0[z] = vrp_tb(); } while (0)
+#define VRP_ZX3(z) do { if (g_vrp.level >= 3) \
+ g_vrp.zone[z] += (uint32_t)(vrp_tb() - g_vrp.zone_t0[z]); } while (0)
+
+struct vrmesa_context;
+extern void vrPerfInit(struct vrmesa_context *);
+extern void vrPerfSwap(struct vrmesa_context *);
+extern void vrPerfDump(void);
+
+#else /* !VERITE_INSTRUMENT */
+
+#define VRP_COUNT(f) ((void)0)
+#define VRP_ADD(f, n) ((void)0)
+#define VRP_FALLBACK(r) ((void)0)
+#define VRP_FALLBACK_HOT(r) ((void)0)
+#define VRP_HOT(f) ((void)0)
+#define VRP_ZE(z) ((void)0)
+#define VRP_ZX(z) ((void)0)
+#define VRP_ZE3(z) ((void)0)
+#define VRP_ZX3(z) ((void)0)
+#define vrPerfInit(vm) ((void)0)
+#define vrPerfSwap(vm) ((void)0)
+#define vrPerfDump() ((void)0)
+
+#endif /* VERITE_INSTRUMENT */
+
+#endif /* VRPERF_H */
diff --git a/src/mesa/drivers/verite/vrspan.c b/src/mesa/drivers/verite/vrspan.c
new file mode 100644
index 0000000..82a9f73
--- /dev/null
+++ b/src/mesa/drivers/verite/vrspan.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * veritemesa swrast spans over the /dev/verite3d VRAM mmap window.
+ */
+
+#include "vrdrv.h"
+
+#include "imports.h"
+#include "swrast/swrast.h"
+
+void
+vrFence(vrmesa_context *vmesa)
+{
+
+ if (vmesa->engine_dirty) {
+ rlgl_finish(&vmesa->rl);
+ vmesa->engine_dirty = GL_FALSE;
+ VRP_COUNT(fences);
+ }
+}
+
+/*
+ * Base of the buffer swrast is currently addressing.
+ */
+static GLubyte *
+vr_span_base(vrmesa_context *vmesa)
+{
+ struct rlgl *rl = &vmesa->rl;
+ uint32_t fb;
+
+ vrFence(vmesa);
+ fb = vmesa->span_front ? rl->fb[rl->back ^ 1] : rl->fb[rl->back];
+ return (GLubyte *)(uintptr_t)v3d_vram(&rl->v) + fb;
+}
+
+static GLushort *
+vr_zrow(vrmesa_context *vmesa, GLint y)
+{
+ struct rlgl *rl = &vmesa->rl;
+
+ vrFence(vmesa);
+ return (GLushort *)((GLubyte *)(uintptr_t)v3d_vram(&rl->v) +
+ rl->zbuf + (size_t)(rl->v.height - 1 - y) * rl->v.stride);
+}
+
+static void
+vr_set_buffer(GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+
+ (void)buffer;
+ switch (bufferBit) {
+ case DD_FRONT_LEFT_BIT:
+ vmesa->span_front = GL_TRUE;
+ break;
+ case DD_BACK_LEFT_BIT:
+ vmesa->span_front = GL_FALSE;
+ break;
+ default:
+ _mesa_problem(ctx, "bad bufferBit in vr_set_buffer");
+ }
+}
+
+#define VR_SWAP16(x) ((GLushort)((((x) & 0xff) << 8) | ((x) >> 8)))
+
+#define NAME(PREFIX) PREFIX##_565
+#define SPAN_VARS \
+ vrmesa_context *vmesa = VRMESA_CONTEXT((GLcontext *)ctx); \
+ GLubyte *vrbuf = vr_span_base(vmesa); \
+ const GLuint vrstride = vmesa->rl.v.stride; \
+ const GLint vrheight = vmesa->rl.v.height;
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *)(vrbuf + \
+ (size_t)(vrheight - 1 - (Y)) * vrstride + (X) * 2)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
+ *P = VR_SWAP16((((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | \
+ ((B) >> 3))
+#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
+ *P = VR_SWAP16((((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | \
+ ((B) >> 3))
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+ do { \
+ GLushort px_ = VR_SWAP16(*P); \
+ R = (((px_ >> 8) & 0xf8) | ((px_ >> 11) & 0x7)); \
+ G = (((px_ >> 3) & 0xfc) | ((px_ >> 5) & 0x3)); \
+ B = (((px_ << 3) & 0xf8) | ((px_ ) & 0x7)); \
+ A = CHAN_MAX; \
+ } while (0)
+
+#include "swrast/s_spantemp.h"
+
+static void
+vr_write_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLdepth depth[], const GLubyte mask[])
+{
+ GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x;
+ GLuint i;
+
+ for (i = 0; i < n; i++)
+ if (mask == NULL || mask[i])
+ zrow[i] = VR_SWAP16((GLushort)depth[i]);
+}
+
+static void
+vr_write_mono_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLdepth depth, const GLubyte mask[])
+{
+ GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x;
+ GLuint i;
+
+ for (i = 0; i < n; i++)
+ if (mask == NULL || mask[i])
+ zrow[i] = VR_SWAP16((GLushort)depth);
+}
+
+static void
+vr_read_depth_span(GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLdepth depth[])
+{
+ const GLushort *zrow = vr_zrow(VRMESA_CONTEXT(ctx), y) + x;
+ GLuint i;
+
+ for (i = 0; i < n; i++)
+ depth[i] = VR_SWAP16(zrow[i]);
+}
+
+static void
+vr_write_depth_pixels(GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[], const GLdepth depth[],
+ const GLubyte mask[])
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0; i < n; i++)
+ if (mask == NULL || mask[i])
+ vr_zrow(vmesa, y[i])[x[i]] =
+ VR_SWAP16((GLushort)depth[i]);
+}
+
+static void
+vr_read_depth_pixels(GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[], GLdepth depth[])
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0; i < n; i++)
+ depth[i] = VR_SWAP16(vr_zrow(vmesa, y[i])[x[i]]);
+}
+
+void
+vrInitSpanFuncs(GLcontext *ctx)
+{
+ struct swrast_device_driver *swdd =
+ _swrast_GetDeviceDriverReference(ctx);
+
+ swdd->SetBuffer = vr_set_buffer;
+
+ swdd->WriteRGBASpan = write_rgba_span_565;
+ swdd->WriteRGBSpan = write_rgb_span_565;
+ swdd->WriteMonoRGBASpan = write_monorgba_span_565;
+ swdd->WriteRGBAPixels = write_rgba_pixels_565;
+ swdd->WriteMonoRGBAPixels = write_monorgba_pixels_565;
+ swdd->ReadRGBASpan = read_rgba_span_565;
+ swdd->ReadRGBAPixels = read_rgba_pixels_565;
+
+ swdd->WriteDepthSpan = vr_write_depth_span;
+ swdd->WriteMonoDepthSpan = vr_write_mono_depth_span;
+ swdd->ReadDepthSpan = vr_read_depth_span;
+ swdd->WriteDepthPixels = vr_write_depth_pixels;
+ swdd->ReadDepthPixels = vr_read_depth_pixels;
+}
diff --git a/src/mesa/drivers/verite/vrtex.c b/src/mesa/drivers/verite/vrtex.c
new file mode 100644
index 0000000..4f71dd3
--- /dev/null
+++ b/src/mesa/drivers/verite/vrtex.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * veritemesa hardware texture stage
+ */
+
+#include "vrdrv.h"
+
+#include "context.h"
+#include "imports.h"
+#include "texstore.h"
+#include "texobj.h"
+#include "swrast/swrast.h"
+
+#define VR_MAX_LEVELS 9 /* 256x256 .. 1x1 */
+
+struct vr_texture {
+ /* hw[0].addr == 0 -> not resident; mip chain in hw[1..] */
+ struct rlgl_tex hw[VR_MAX_LEVELS];
+ GLint nlevels; /* resident levels (1 = no mips) */
+ GLboolean has_alpha; /* uploaded as 4444, else 565 */
+ GLboolean dirty; /* core image newer than VRAM */
+ GLboolean capped; /* nlevels is all that fit VRAM;
+ * do not retry for more (anti-thrash) */
+ GLuint lru; /* last validate tick */
+ GLuint used_frame; /* frame last bound (evict pinning) */
+ struct gl_texture_object *obj;
+ struct vr_texture *next;
+};
+
+/*
+ * Frame counter for evict-pinning
+ */
+static GLuint g_vr_frame = 1;
+
+void
+vrTexNewFrame(void)
+{
+
+ g_vr_frame++;
+}
+
+/* vrtris.c reads the level array for per-triangle mip binds */
+struct rlgl_tex *
+vrTexLevel(struct vr_texture *t, GLint level)
+{
+
+ return &t->hw[level];
+}
+
+GLint
+vrTexNumLevels(struct vr_texture *t)
+{
+
+ return t->nlevels;
+}
+
+void
+vrInitTexConsts(GLcontext *ctx)
+{
+
+ ctx->Const.MaxTextureUnits = 1;
+ ctx->Const.MaxTextureImageUnits = 1;
+ ctx->Const.MaxTextureCoordUnits = 1;
+ /* 2^(9-1) = 256: mesaconf tex-256 scene proves the PE takes it */
+ ctx->Const.MaxTextureLevels = 9;
+}
+
+static struct vr_texture *
+vr_tex_data(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct vr_texture *t = tObj->DriverData;
+
+ if (t == NULL) {
+ t = CALLOC_STRUCT(vr_texture);
+ if (t == NULL)
+ return NULL;
+ t->obj = tObj;
+ t->dirty = GL_TRUE;
+ t->next = vmesa->textures;
+ vmesa->textures = t;
+ tObj->DriverData = t;
+ VRP_COUNT(tv_creates);
+ }
+ return t;
+}
+
+static void
+vr_tex_unload(vrmesa_context *vmesa, struct vr_texture *t)
+{
+ GLint i;
+
+ /*
+ * The mip pyramid is ONE contiguous allocation
+ */
+ if (t->hw[0].addr != 0)
+ rlgl_tex_free(&vmesa->rl, &t->hw[0]);
+ for (i = 1; i < VR_MAX_LEVELS; i++)
+ t->hw[i].addr = 0;
+ t->nlevels = 0;
+ /* addresses may be recycled: kill the bind cache */
+ vmesa->rl.cur_tex = 0;
+}
+
+static void
+vr_teximage2d(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 *texObj, struct gl_texture_image *texImage)
+{
+ struct vr_texture *t;
+
+ _mesa_store_teximage2d(ctx, target, level, internalFormat,
+ width, height, border, format, type, pixels, packing,
+ texObj, texImage);
+ t = vr_tex_data(ctx, texObj);
+ if (t != NULL)
+ t->dirty = GL_TRUE;
+}
+
+static void
+vr_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 *texObj, struct gl_texture_image *texImage)
+{
+ struct vr_texture *t;
+
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset,
+ width, height, format, type, pixels, packing, texObj,
+ texImage);
+ t = vr_tex_data(ctx, texObj);
+ if (t != NULL)
+ t->dirty = GL_TRUE; /* v1: full re-upload */
+}
+
+static void
+vr_delete_texture(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct vr_texture *t = tObj->DriverData;
+
+ if (t != NULL) {
+ struct vr_texture **pp;
+
+ vr_tex_unload(vmesa, t);
+ for (pp = &vmesa->textures; *pp != NULL;
+ pp = &(*pp)->next)
+ if (*pp == t) {
+ *pp = t->next;
+ break;
+ }
+ _mesa_free(t);
+ tObj->DriverData = NULL;
+ }
+ _mesa_delete_texture_object(ctx, tObj);
+}
+
+/*
+ * Hardware glCopyTexSubImage2D.
+ */
+static void
+vr_copytexsubimage2d(GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
+ GLsizei height)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct rlgl *rl = &vmesa->rl;
+ struct gl_texture_object *tObj = ctx->Texture.Unit[0].Current2D;
+ GLint fbW = (GLint)rl->v.width, fbH = (GLint)rl->v.height;
+ struct vr_texture *t = (tObj != NULL) ? tObj->DriverData : NULL;
+ GLboolean was_dirty = (t != NULL) ? t->dirty : GL_TRUE;
+
+ /*
+ * Keep the canonical core image correct in every case.
+ */
+ _swrast_copy_texsubimage2d(ctx, target, level, xoffset, yoffset,
+ x, y, width, height);
+
+ if (t == NULL)
+ return;
+
+ if (target != GL_TEXTURE_2D || level != tObj->BaseLevel ||
+ t->hw[0].addr == 0 || t->has_alpha || t->nlevels != 1 ||
+ was_dirty || ctx->_ImageTransferState != 0 ||
+ width <= 0 || height <= 0 ||
+ x < 0 || y < 0 || x + width > fbW || y + height > fbH) {
+ t->dirty = GL_TRUE; /* re-upload from the updated core */
+ return;
+ }
+
+ if (rlgl_copy_to_tex(rl, vr_fb_base(rl, ctx->Pixel.ReadBuffer), fbH,
+ t->hw[0].addr, t->hw[0].w, x, y, xoffset, yoffset,
+ width, height) != 0) {
+ t->dirty = GL_TRUE;
+ return;
+ }
+ t->dirty = GL_FALSE; /* VRAM matches the core copy */
+ vmesa->engine_dirty = GL_TRUE;
+}
+
+void
+vrInitTexFuncs(struct dd_function_table *functions)
+{
+
+ functions->TexImage2D = vr_teximage2d;
+ functions->TexSubImage2D = vr_texsubimage2d;
+ functions->CopyTexSubImage2D = vr_copytexsubimage2d;
+ functions->DeleteTexture = vr_delete_texture;
+}
+
+/*
+ * Can the PE render the CURRENT texture binding?
+ */
+GLboolean
+vrTexHwOk(GLcontext *ctx)
+{
+ const struct gl_texture_unit *unit = &ctx->Texture.Unit[0];
+ const struct gl_texture_object *tObj;
+ const struct gl_texture_image *img;
+
+ if (ctx->Texture._EnabledUnits != 0x1)
+ return GL_FALSE;
+ if (unit->_ReallyEnabled != TEXTURE_2D_BIT)
+ return GL_FALSE;
+ tObj = unit->Current2D;
+ if (tObj == NULL)
+ return GL_FALSE;
+ img = tObj->Image[0][tObj->BaseLevel];
+ if (img == NULL || img->Border != 0 ||
+ img->Width > 256 || img->Height > 256)
+ return GL_FALSE;
+ if (tObj->WrapS != GL_REPEAT && tObj->WrapS != GL_CLAMP_TO_EDGE &&
+ tObj->WrapS != GL_CLAMP)
+ return GL_FALSE;
+ if (tObj->WrapT != GL_REPEAT && tObj->WrapT != GL_CLAMP_TO_EDGE &&
+ tObj->WrapT != GL_CLAMP)
+ return GL_FALSE;
+ /*
+ * GL_CLAMP equals CLAMP_TO_EDGE under NEAREST sampling, but
+ * a LINEAR footprint mixes the border color at the edge
+ */
+ if (tObj->WrapS == GL_CLAMP || tObj->WrapT == GL_CLAMP) {
+ if (tObj->MagFilter == GL_LINEAR ||
+ tObj->MinFilter == GL_LINEAR ||
+ tObj->MinFilter == GL_LINEAR_MIPMAP_NEAREST ||
+ tObj->MinFilter == GL_LINEAR_MIPMAP_LINEAR)
+ return GL_FALSE;
+ }
+ /* all six MIN filters: mipmap ones ride per-poly selection */
+ if (tObj->MagFilter != GL_NEAREST && tObj->MagFilter != GL_LINEAR)
+ return GL_FALSE;
+ if (unit->EnvMode != GL_MODULATE && unit->EnvMode != GL_REPLACE &&
+ unit->EnvMode != GL_DECAL)
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+static GLuint
+vr_alloc_width(GLuint w)
+{
+
+ if (w < 2)
+ return 2;
+ if (w == 4)
+ return 8;
+ return w;
+}
+
+static int
+vr_tex_upload(vrmesa_context *vmesa, struct vr_texture *t,
+ const struct gl_texture_image *img, GLint level)
+{
+ GLuint w = img->Width, h = img->Height;
+ GLuint aw = vr_alloc_width(w);
+ GLushort *buf;
+ GLuint x, y;
+ int error;
+
+ if (img->FetchTexelc == NULL)
+ return -1;
+ buf = _mesa_malloc(aw * h * sizeof(GLushort));
+ if (buf == NULL)
+ return -1;
+ for (y = 0; y < h; y++)
+ for (x = 0; x < aw; x++) {
+ GLchan texel[4];
+
+ img->FetchTexelc((struct gl_texture_image *)img,
+ x < w ? x : w - 1, y, 0, texel);
+ buf[y * aw + x] = t->has_alpha ? (GLushort)
+ (((texel[3] & 0xf0) << 8) |
+ ((texel[0] & 0xf0) << 4) |
+ (texel[1] & 0xf0) | (texel[2] >> 4)) :
+ (GLushort)
+ (((texel[0] & 0xf8) << 8) |
+ ((texel[1] & 0xfc) << 3) | (texel[2] >> 3));
+ }
+ error = rlgl_tex_upload(&vmesa->rl, &t->hw[level], buf);
+ _mesa_free(buf);
+ return error;
+}
+
+static GLboolean
+vr_min_is_mip(GLenum f)
+{
+
+ return f != GL_NEAREST && f != GL_LINEAR;
+}
+
+static GLboolean
+vr_base_has_alpha(const struct gl_texture_image *img)
+{
+
+ switch (img->TexFormat->BaseFormat) {
+ case GL_RGBA:
+ case GL_ALPHA:
+ case GL_LUMINANCE_ALPHA:
+ case GL_INTENSITY:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+/*
+ * Make the current binding resident and bound
+ */
+GLboolean
+vrTexValidate(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ struct gl_texture_object *tObj = ctx->Texture.Unit[0].Current2D;
+ const struct gl_texture_image *img =
+ tObj->Image[0][tObj->BaseLevel];
+ struct vr_texture *t = vr_tex_data(ctx, tObj);
+
+ GLint want, i;
+ GLboolean was_resident;
+
+ VRP_ZE(VRP_Z_TEXVALIDATE);
+ if (t == NULL) {
+ VRP_COUNT(tv_failv);
+ VRP_ZX(VRP_Z_TEXVALIDATE);
+ return GL_FALSE;
+ }
+ t->lru = ++vmesa->lru_tick;
+ t->used_frame = g_vr_frame; /* pin: not evictable this frame */
+ was_resident = (t->hw[0].addr != 0);
+
+ /* levels wanted: full chain for mipmap MIN filters */
+ if (vr_min_is_mip(tObj->MinFilter)) {
+ want = 0;
+ while (want < VR_MAX_LEVELS - 1 &&
+ tObj->Image[0][tObj->BaseLevel + want] != NULL &&
+ (tObj->Image[0][tObj->BaseLevel + want]->Width > 1 ||
+ tObj->Image[0][tObj->BaseLevel + want]->Height > 1))
+ want++;
+ want++; /* include the 1x1 (or last) level */
+ } else
+ want = 1;
+
+ if (t->hw[0].addr != 0 &&
+ (t->dirty || (t->nlevels < want && !t->capped))) {
+ if (t->dirty)
+ VRP_COUNT(tv_dirty);
+ else
+ VRP_COUNT(tv_nlevels);
+ vr_tex_unload(vmesa, t);
+ }
+
+ if (t->hw[0].addr == 0) {
+ int nl;
+
+ if (!was_resident)
+ VRP_COUNT(tv_first);
+ t->has_alpha = vr_base_has_alpha(img);
+
+ /*
+ * Allocate the whole pyramid as ONE contiguous block
+ */
+ for (nl = want; nl >= 1; nl--) {
+ for (i = 0; i < nl; i++) {
+ const struct gl_texture_image *li =
+ tObj->Image[0][tObj->BaseLevel + i];
+
+ if (li == NULL ||
+ rlgl_tex_init(&t->hw[i],
+ vr_alloc_width(li->Width), li->Height,
+ t->has_alpha ? RLGL_FMT_4444 :
+ RLGL_FMT_565) != 0)
+ break;
+ }
+ if (i < nl) /* a level was missing/bad */
+ continue;
+
+ while (rlgl_tex_pyramid(&vmesa->rl, t->hw, nl) != 0) {
+ struct vr_texture *victim = NULL, *it;
+
+ for (it = vmesa->textures; it != NULL;
+ it = it->next)
+ if (it != t &&
+ it->hw[0].addr != 0 &&
+ it->used_frame != g_vr_frame &&
+ (victim == NULL ||
+ it->lru < victim->lru))
+ victim = it;
+ if (victim == NULL)
+ break; /* try fewer levels */
+ vr_tex_unload(vmesa, victim);
+ VRP_COUNT(tv_evict);
+ }
+ if (t->hw[0].addr != 0)
+ break; /* nl levels allocated */
+ }
+ if (t->hw[0].addr == 0) {
+ VRP_COUNT(tv_failv);
+ VRP_ZX(VRP_Z_TEXVALIDATE);
+ return GL_FALSE; /* not even the base fit */
+ }
+
+ for (i = 0; i < nl; i++) {
+ const struct gl_texture_image *li =
+ tObj->Image[0][tObj->BaseLevel + i];
+
+ if (vr_tex_upload(vmesa, t, li, i) != 0) {
+ vr_tex_unload(vmesa, t);
+ VRP_COUNT(tv_failu);
+ VRP_ZX(VRP_Z_TEXVALIDATE);
+ return GL_FALSE;
+ }
+ }
+ t->nlevels = nl;
+ t->capped = (nl < want);
+ t->dirty = GL_FALSE;
+ vmesa->engine_dirty = GL_TRUE;
+ } else {
+ VRP_COUNT(tv_bindonly); /* resident, no upload */
+ }
+
+ rlgl_tex_env_code(&vmesa->rl,
+ ctx->Texture.Unit[0].EnvMode == GL_MODULATE ?
+ RLGL_ENV_MODULATE :
+ (ctx->Texture.Unit[0].EnvMode == GL_DECAL ?
+ RLGL_ENV_DECAL : RLGL_ENV_REPLACE));
+ rlgl_tex_filter(&vmesa->rl, tObj->MagFilter == GL_LINEAR);
+ rlgl_tex_bind(&vmesa->rl, &t->hw[0]);
+ rlgl_tex_wrap(&vmesa->rl, tObj->WrapS != GL_REPEAT,
+ tObj->WrapT != GL_REPEAT);
+
+ if (_mesa_getenv("VRMESA_DEBUG"))
+ _mesa_printf("vrTexValidate: obj=%u nlvl=%d addr0=%x "
+ "min=%x\n", tObj->Name, t->nlevels, t->hw[0].addr,
+ tObj->MinFilter);
+
+ vmesa->tex_cur = t;
+ vmesa->tex_mip = vr_min_is_mip(tObj->MinFilter) && t->nlevels > 1;
+ vmesa->tex_min_bilin =
+ (tObj->MinFilter == GL_LINEAR_MIPMAP_NEAREST ||
+ tObj->MinFilter == GL_LINEAR_MIPMAP_LINEAR ||
+ tObj->MinFilter == GL_LINEAR);
+ vmesa->tex_mag_bilin = (tObj->MagFilter == GL_LINEAR);
+ vmesa->cur_level = 0;
+ vmesa->cur_bilin = vmesa->tex_mag_bilin;
+
+ vmesa->tex_w = vmesa->tex_base_w = (GLfloat)img->Width;
+ vmesa->tex_h = vmesa->tex_base_h = (GLfloat)img->Height;
+ vmesa->tex_off = vmesa->tex_mag_bilin ? 0.5F : 0.0F;
+ VRP_ZX(VRP_Z_TEXVALIDATE);
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/verite/vrtris.c b/src/mesa/drivers/verite/vrtris.c
new file mode 100644
index 0000000..48c270f
--- /dev/null
+++ b/src/mesa/drivers/verite/vrtris.c
@@ -0,0 +1,1085 @@
+/*
+ * Copyright (c) 2026 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Radoslaw Kujawa.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * veritemesa hardware triangles.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "vrdrv.h"
+
+#include "context.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+static unsigned long g_vr_nat_polys, g_vr_nat_tris;
+static unsigned long g_vr_pt_polys, g_vr_pt_tris;
+static unsigned long g_vr_cb_tris;
+
+static int g_vr_nocache;
+static int g_vr_noblendfan;
+static float g_vr_zbias;
+
+/*
+ * Window-Z finalizer.
+ */
+#define VR_ZSCALE (65000.0F / 65535.0F)
+
+static GLfloat
+vr_winz(GLfloat mesa_z)
+{
+ GLfloat z = mesa_z * VR_ZSCALE;
+
+ if (z < 0.0F)
+ return 0.0F;
+ if (z > 65000.0F)
+ return 65000.0F;
+ return z;
+}
+
+static void
+vr_emit_at(vrmesa_context *vmesa, GLfloat wx, GLfloat wy,
+ const SWvertex *v, const GLchan color[4], struct rlgl_vtx *o)
+{
+ const GLfloat w = (GLfloat)vmesa->rl.v.width;
+ const GLfloat h = (GLfloat)vmesa->rl.v.height;
+ GLfloat x = wx, y;
+
+ o->r = (GLfloat)color[0];
+ o->g = (GLfloat)color[1];
+ o->b = (GLfloat)color[2];
+
+ if (x < 0.0F) x = 0.0F;
+ if (x > w) x = w;
+ o->x = x;
+ y = h - wy;
+ if (y < 0.0F) y = 0.0F;
+ if (y > h) y = h;
+ o->y = y;
+ o->z = vr_winz(v->win[2]); /* rescale 65535->65000, see vr_winz */
+ /*
+ * u/v in texels, q = 1/w
+ */
+ if (vmesa->tex_on) {
+ o->u = v->texcoord[0][0] * vmesa->tex_w - vmesa->tex_off;
+ o->v = v->texcoord[0][1] * vmesa->tex_h - vmesa->tex_off;
+ } else {
+ o->u = 0.0F;
+ o->v = 0.0F;
+ }
+ o->q = v->win[3];
+ /*
+ * Fog factor for the KFXYZUVQ path.
+ */
+ o->f = CLAMP(v->fog, 0.0F, 1.0F) * 255.0F;
+}
+
+static void
+vr_emit_vtx(vrmesa_context *vmesa, const SWvertex *v,
+ const GLchan color[4], struct rlgl_vtx *o)
+{
+
+ vr_emit_at(vmesa, v->win[0], v->win[1], v, color, o);
+}
+
+/*
+ * PE blend factor mapping
+ */
+static GLboolean
+vr_blend_factor(GLenum f, GLboolean is_src, GLuint *code,
+ GLboolean *needs_alpha)
+{
+
+ switch (f) {
+ case GL_ZERO: *code = RLGL_BL_ZERO; break;
+ case GL_ONE: *code = RLGL_BL_ONE; break;
+ case GL_DST_ALPHA: *code = RLGL_BL_ONE; break;
+ case GL_ONE_MINUS_DST_ALPHA: *code = RLGL_BL_ZERO; break;
+ case GL_SRC_ALPHA:
+ *code = RLGL_BL_SRCALPHA;
+ *needs_alpha = GL_TRUE;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ *code = RLGL_BL_INVSRCALPHA;
+ *needs_alpha = GL_TRUE;
+ break;
+ /*
+ * Color-factor codes are SIDE-RELATIVE
+ */
+ case GL_SRC_COLOR:
+ *code = is_src ? RLGL_BL_OWNCOLOR : RLGL_BL_OTHERCOLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ *code = is_src ? RLGL_BL_INVOWNCOLOR :
+ RLGL_BL_INVOTHERCOLOR;
+ break;
+ case GL_DST_COLOR:
+ *code = is_src ? RLGL_BL_OTHERCOLOR : RLGL_BL_OWNCOLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ *code = is_src ? RLGL_BL_INVOTHERCOLOR :
+ RLGL_BL_INVOWNCOLOR;
+ break;
+ default:
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+GLboolean
+vrBlendMap(const GLcontext *ctx, GLuint *srcf, GLuint *dstf,
+ GLboolean *needs_alpha)
+{
+
+ *needs_alpha = GL_FALSE;
+ if (ctx->Color.BlendEquationRGB != GL_FUNC_ADD)
+ return GL_FALSE;
+ if (!vr_blend_factor(ctx->Color.BlendSrcRGB, GL_TRUE, srcf,
+ needs_alpha))
+ return GL_FALSE;
+ if (!vr_blend_factor(ctx->Color.BlendDstRGB, GL_FALSE, dstf,
+ needs_alpha))
+ return GL_FALSE;
+ return GL_TRUE;
+}
+
+/*
+ * Clamp a Mesa-space window Z
+ */
+static GLfloat
+vr_clampz(GLfloat z)
+{
+
+ if (z < 0.0F)
+ return 0.0F;
+ if (z > 65535.0F)
+ return 65535.0F;
+ return z;
+}
+
+/*
+ * Polygon offset (glPolygonOffset) computed exactly as swrast does at
+ * setup
+ */
+static GLfloat
+vr_poly_offset(GLcontext *ctx, const SWvertex *v0, const SWvertex *v1,
+ const SWvertex *v2)
+{
+ GLfloat ex = v0->win[0] - v2->win[0], ey = v0->win[1] - v2->win[1];
+ GLfloat fx = v1->win[0] - v2->win[0], fy = v1->win[1] - v2->win[1];
+ GLfloat cc = ex * fy - ey * fx;
+ GLfloat off = ctx->Polygon.OffsetUnits; /* * MRD (= 1) */
+
+ if (cc * cc > 1e-16F) {
+ GLfloat ez = v0->win[2] - v2->win[2];
+ GLfloat fz = v1->win[2] - v2->win[2];
+ GLfloat ooa = 1.0F / cc;
+ GLfloat dzdx = (ey * fz - ez * fy) * ooa;
+ GLfloat dzdy = (ez * fx - ex * fz) * ooa;
+ GLfloat m, nz;
+
+ if (dzdx < 0.0F) dzdx = -dzdx;
+ if (dzdy < 0.0F) dzdy = -dzdy;
+ m = dzdx > dzdy ? dzdx : dzdy;
+ off += m * ctx->Polygon.OffsetFactor;
+ /* clamp so no vertex Z goes below 0 (matches swrast) */
+ nz = -v0->win[2]; if (off < nz) off = nz;
+ nz = -v1->win[2]; if (off < nz) off = nz;
+ nz = -v2->win[2]; if (off < nz) off = nz;
+ }
+ return off;
+}
+
+static void
+vr_tri(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint eprov)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ const SWvertex *v0 = &verts[e0], *v1 = &verts[e1], *v2 = &verts[e2];
+ struct rlgl_vtx a, b, c;
+ const GLboolean flat = (ctx->Light.ShadeModel == GL_FLAT);
+ const GLchan *pc = verts[eprov].color;
+
+ if (vmesa->blend_alpha || vmesa->atest_alpha) {
+ GLuint a8 = flat ? pc[3] : v0->color[3];
+
+ if (!flat && (v1->color[3] != a8 || v2->color[3] != a8)) {
+ VRP_FALLBACK_HOT(VRP_FB_TRI_ALPHAGRAD);
+ _swrast_Triangle(ctx, v0, v1, v2);
+ return;
+ }
+ if (a8 != vmesa->fg_alpha) {
+ v3d_st(&vmesa->rl.v, V3D_PE_FGCOLOR, a8 << 24);
+ vmesa->fg_alpha = a8;
+ VRP_HOT(fgcolor_writes);
+ }
+ }
+
+ if (ctx->Polygon.CullFlag) {
+ /* window y is flipped on the PE: GL-CCW = negative area */
+ GLfloat area =
+ (v1->win[0] - v0->win[0]) * (v0->win[1] - v2->win[1]) -
+ (v2->win[0] - v0->win[0]) * (v0->win[1] - v1->win[1]);
+ GLboolean front = (area < 0.0F) ^
+ (ctx->Polygon.FrontFace == GL_CW);
+
+ if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+ return;
+ if (ctx->Polygon.CullFaceMode == GL_BACK && !front)
+ return;
+ if (ctx->Polygon.CullFaceMode == GL_FRONT && front)
+ return;
+ }
+
+ /*
+ * Per-polygon mipmapping
+ */
+ if (vmesa->tex_on && vmesa->tex_mip) {
+ const GLfloat bw = vmesa->tex_base_w;
+ const GLfloat bh = vmesa->tex_base_h;
+ GLfloat du1 = (v1->texcoord[0][0] - v0->texcoord[0][0]) * bw;
+ GLfloat dv1 = (v1->texcoord[0][1] - v0->texcoord[0][1]) * bh;
+ GLfloat du2 = (v2->texcoord[0][0] - v0->texcoord[0][0]) * bw;
+ GLfloat dv2 = (v2->texcoord[0][1] - v0->texcoord[0][1]) * bh;
+ GLfloat auv = du1 * dv2 - du2 * dv1;
+ GLfloat axy =
+ (v1->win[0] - v0->win[0]) * (v2->win[1] - v0->win[1]) -
+ (v2->win[0] - v0->win[0]) * (v1->win[1] - v0->win[1]);
+ GLfloat rho2;
+ GLint level = 0, nl = vrTexNumLevels(vmesa->tex_cur);
+ GLint bilin;
+ GLint lw, lh;
+
+ if (auv < 0.0F) auv = -auv;
+ if (axy < 0.0F) axy = -axy;
+ rho2 = (axy > 1e-12F) ? auv / axy : 0.0F;
+ if (rho2 > 1.0F) {
+ GLfloat lod = 0.5F * LOG2(rho2);
+
+ level = (GLint)(lod + 0.5F);
+ if (level >= nl)
+ level = nl - 1;
+ }
+ bilin = (level == 0 && rho2 <= 1.0F) ?
+ vmesa->tex_mag_bilin : vmesa->tex_min_bilin;
+ if (g_vr_nocache || level != vmesa->cur_level) {
+ rlgl_tex_bind(&vmesa->rl,
+ vrTexLevel(vmesa->tex_cur, level));
+ vmesa->cur_level = level;
+ VRP_HOT(mip_binds);
+ }
+ if (g_vr_nocache || bilin != vmesa->cur_bilin) {
+ rlgl_tex_filter(&vmesa->rl, bilin);
+ vmesa->cur_bilin = bilin;
+ VRP_HOT(filt_changes);
+ }
+ lw = (GLint)bw >> level;
+ lh = (GLint)bh >> level;
+ vmesa->tex_w = (GLfloat)(lw > 0 ? lw : 1);
+ vmesa->tex_h = (GLfloat)(lh > 0 ? lh : 1);
+ vmesa->tex_off = bilin ? 0.5F : 0.0F;
+ }
+
+ VRP_ZE3(VRP_Z_TRI_EMIT);
+ vr_emit_vtx(vmesa, v0, flat ? pc : v0->color, &a);
+ vr_emit_vtx(vmesa, v1, flat ? pc : v1->color, &b);
+ vr_emit_vtx(vmesa, v2, flat ? pc : v2->color, &c);
+ /* polygon offset: per-poly window-Z bias over the emitted z */
+ if (ctx->Polygon.OffsetFill) {
+ GLfloat off = vr_poly_offset(ctx, v0, v1, v2);
+
+ a.z = vr_winz(v0->win[2] + off);
+ b.z = vr_winz(v1->win[2] + off);
+ c.z = vr_winz(v2->win[2] + off);
+ }
+ rlgl_tri(&vmesa->rl, &a, &b, &c);
+ vmesa->engine_dirty = GL_TRUE;
+ VRP_ZX3(VRP_Z_TRI_EMIT);
+}
+
+static void
+vr_triangle(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2)
+{
+
+ g_vr_cb_tris++; /* clipped path / any Render.Triangle caller */
+ vr_tri(ctx, e0, e1, e2, e2);
+}
+
+static void
+vr_quad(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint e3)
+{
+
+ vr_tri(ctx, e0, e1, e2, e3);
+ vr_tri(ctx, e0, e2, e3, e3);
+}
+
+/* longest run collapsed to one native fan/strip, larger falls to per-tri */
+#define VR_MAX_RUN 128
+
+static void
+vr_strip_stat(void)
+{
+
+ if (_mesa_getenv("VRMESA_STRIPSTAT"))
+ _mesa_printf("VRSTRIP native_polys=%lu native_tris=%lu "
+ "pertri_polys=%lu pertri_tris=%lu clipped_tris=%lu\n",
+ g_vr_nat_polys, g_vr_nat_tris, g_vr_pt_polys, g_vr_pt_tris,
+ g_vr_cb_tris);
+}
+
+static GLuint
+vidx(const GLuint *elt, GLuint j)
+{
+
+ return elt ? elt[j] : j;
+}
+
+static GLboolean
+vr_native_run(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count,
+ GLboolean cull_uniform, GLuint flat_prov)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ const GLchan *fc = (flat_prov != ~0U) ?
+ verts[vidx(elt, flat_prov)].color : NULL;
+ struct rlgl_vtx buf[VR_MAX_RUN];
+ GLuint n = count - start, i;
+
+ if (n < 3 || n > VR_MAX_RUN)
+ return GL_FALSE;
+ if (ctx->Polygon.CullFlag) {
+ const SWvertex *v0, *v1, *v2;
+ GLfloat area;
+ GLboolean front;
+
+ /*
+ * A tri-strip's winding alternates per triangle, and a
+ * non-convex tri-fan's can flip
+ */
+ if (!cull_uniform)
+ return GL_FALSE;
+ v0 = &verts[vidx(elt, start)];
+ v1 = &verts[vidx(elt, start + 1)];
+ v2 = &verts[vidx(elt, start + 2)];
+ area = (v1->win[0] - v0->win[0]) * (v0->win[1] - v2->win[1]) -
+ (v2->win[0] - v0->win[0]) * (v0->win[1] - v1->win[1]);
+ front = (area < 0.0F) ^ (ctx->Polygon.FrontFace == GL_CW);
+ if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+ return GL_TRUE; /* whole run culled */
+ if (ctx->Polygon.CullFaceMode == GL_BACK && !front)
+ return GL_TRUE;
+ if (ctx->Polygon.CullFaceMode == GL_FRONT && front)
+ return GL_TRUE;
+ }
+ for (i = 0; i < n; i++) {
+ const SWvertex *v = &verts[vidx(elt, start + i)];
+
+ vr_emit_vtx(vmesa, v, fc ? fc : v->color, &buf[i]);
+ if (g_vr_zbias != 0.0F) {
+ buf[i].z -= g_vr_zbias;
+ if (buf[i].z < 0.0F)
+ buf[i].z = 0.0F;
+ }
+ }
+ rlgl_trifan(&vmesa->rl, buf, (int)n);
+ g_vr_nat_polys++;
+ g_vr_nat_tris += n - 2;
+ vmesa->engine_dirty = GL_TRUE;
+ return GL_TRUE;
+}
+
+static void
+vr_c_triangles(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ GLuint j;
+
+ for (j = start + 2; j < count; j += 3)
+ vr_tri(ctx, vidx(elt, j - 2), vidx(elt, j - 1), vidx(elt, j),
+ vidx(elt, j));
+}
+
+static void
+vr_c_tri_strip(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ GLuint j, parity = 0;
+
+ for (j = start + 2; j < count; j++, parity ^= 1)
+ vr_tri(ctx, vidx(elt, j - 2 + parity), vidx(elt, j - 1 - parity),
+ vidx(elt, j), vidx(elt, j));
+}
+
+static void
+vr_c_tri_fan(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLuint j;
+
+ if (vmesa->strips_ok && ctx->Light.ShadeModel == GL_SMOOTH &&
+ vr_native_run(ctx, elt, start, count, GL_FALSE, ~0U))
+ return;
+ g_vr_pt_polys++;
+ g_vr_pt_tris += count - start - 2;
+ for (j = start + 2; j < count; j++)
+ vr_tri(ctx, vidx(elt, start), vidx(elt, j - 1), vidx(elt, j),
+ vidx(elt, j));
+}
+
+static void
+vr_c_poly(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLboolean flat = (ctx->Light.ShadeModel == GL_FLAT);
+ GLuint j;
+
+ if (vmesa->strips_ok && vr_native_run(ctx, elt, start, count,
+ GL_TRUE, flat ? start : ~0U)) /* cull_uniform: convex */
+ return;
+ g_vr_pt_polys++;
+ g_vr_pt_tris += count - start - 2;
+ for (j = start + 2; j < count; j++)
+ vr_tri(ctx, vidx(elt, j - 1), vidx(elt, j), vidx(elt, start),
+ vidx(elt, start));
+}
+
+static void
+vr_c_quads(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ GLuint j;
+
+ for (j = start + 3; j < count; j += 4)
+ vr_quad(ctx, vidx(elt, j - 3), vidx(elt, j - 2),
+ vidx(elt, j - 1), vidx(elt, j));
+}
+
+static void
+vr_c_quad_strip(GLcontext *ctx, const GLuint *elt, GLuint start, GLuint count)
+{
+ GLuint j;
+
+ for (j = start + 3; j < count; j += 2)
+ vr_quad(ctx, vidx(elt, j - 1), vidx(elt, j - 3),
+ vidx(elt, j - 2), vidx(elt, j));
+}
+
+/* generate the {verts,elts} PrimTab wrappers around each run core */
+#define VR_TAB(core) \
+static void core##_verts(GLcontext *ctx, GLuint s, GLuint c, GLuint f) \
+{ \
+ (void)f; \
+ core(ctx, NULL, s, c); \
+} \
+static void core##_elts(GLcontext *ctx, GLuint s, GLuint c, GLuint f) \
+{ \
+ (void)f; \
+ core(ctx, TNL_CONTEXT(ctx)->vb.Elts, s, c); \
+}
+
+VR_TAB(vr_c_triangles)
+VR_TAB(vr_c_tri_strip)
+VR_TAB(vr_c_tri_fan)
+VR_TAB(vr_c_poly)
+VR_TAB(vr_c_quads)
+VR_TAB(vr_c_quad_strip)
+
+static tnl_render_func vr_tab_verts[GL_POLYGON + 2];
+static tnl_render_func vr_tab_elts[GL_POLYGON + 2];
+static GLboolean vr_tab_ready = GL_FALSE;
+
+static void
+vr_build_tables(TNLcontext *tnl)
+{
+ GLuint i;
+
+ if (vr_tab_ready)
+ return;
+ for (i = 0; i < GL_POLYGON + 2; i++) {
+ vr_tab_verts[i] = tnl->Driver.Render.PrimTabVerts[i];
+ vr_tab_elts[i] = tnl->Driver.Render.PrimTabElts[i];
+ }
+ vr_tab_verts[GL_TRIANGLES] = vr_c_triangles_verts;
+ vr_tab_verts[GL_TRIANGLE_STRIP] = vr_c_tri_strip_verts;
+ vr_tab_verts[GL_TRIANGLE_FAN] = vr_c_tri_fan_verts;
+ vr_tab_verts[GL_POLYGON] = vr_c_poly_verts;
+ vr_tab_verts[GL_QUADS] = vr_c_quads_verts;
+ vr_tab_verts[GL_QUAD_STRIP] = vr_c_quad_strip_verts;
+ vr_tab_elts[GL_TRIANGLES] = vr_c_triangles_elts;
+ vr_tab_elts[GL_TRIANGLE_STRIP] = vr_c_tri_strip_elts;
+ vr_tab_elts[GL_TRIANGLE_FAN] = vr_c_tri_fan_elts;
+ vr_tab_elts[GL_POLYGON] = vr_c_poly_elts;
+ vr_tab_elts[GL_QUADS] = vr_c_quads_elts;
+ vr_tab_elts[GL_QUAD_STRIP] = vr_c_quad_strip_elts;
+ vr_tab_ready = GL_TRUE;
+}
+
+/*
+ * Line as a perpendicular-offset quad (2 tris), width = Line._Width.
+ */
+static void
+vr_line(GLcontext *ctx, GLuint e0, GLuint e1)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ const SWvertex *v0 = &verts[e0], *v1 = &verts[e1];
+ const GLboolean flat = (ctx->Light.ShadeModel == GL_FLAT);
+ const GLchan *c0 = flat ? v1->color : v0->color;
+ const GLchan *c1 = v1->color; /* provoking = last vertex */
+ GLfloat dx = v1->win[0] - v0->win[0];
+ GLfloat dy = v1->win[1] - v0->win[1];
+ GLfloat len = (GLfloat)sqrt(dx * dx + dy * dy);
+ GLfloat hw = ctx->Line._Width * 0.5F;
+ GLfloat px, py;
+ struct rlgl_vtx a, b, c, d;
+
+ if (len < 1e-4F)
+ return; /* degenerate */
+ if (hw < 0.75F) {
+ GLfloat adx = dx < 0.0F ? -dx : dx;
+ GLfloat ady = dy < 0.0F ? -dy : dy;
+
+ if (adx > 0.5F && ady > 0.5F)
+ hw = 0.75F;
+ }
+ px = -dy / len * hw; /* perpendicular * half-width */
+ py = dx / len * hw;
+ vr_emit_at(vmesa, v0->win[0] + px, v0->win[1] + py, v0, c0, &a);
+ vr_emit_at(vmesa, v0->win[0] - px, v0->win[1] - py, v0, c0, &b);
+ vr_emit_at(vmesa, v1->win[0] - px, v1->win[1] - py, v1, c1, &c);
+ vr_emit_at(vmesa, v1->win[0] + px, v1->win[1] + py, v1, c1, &d);
+ rlgl_tri(&vmesa->rl, &a, &b, &c);
+ rlgl_tri(&vmesa->rl, &a, &c, &d);
+ vmesa->engine_dirty = GL_TRUE;
+}
+
+/*
+ * Native hardware line via the microcode's own line drawers
+ */
+static void
+vr_line_native(GLcontext *ctx, GLuint e0, GLuint e1, GLboolean aa)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ const SWvertex *v0 = &verts[e0], *v1 = &verts[e1];
+ const GLboolean flat = (ctx->Light.ShadeModel == GL_FLAT);
+ const GLchan *c0 = flat ? v1->color : v0->color;
+ const GLchan *c1 = v1->color; /* provoking = last vertex */
+ struct rlgl_vtx a, b;
+
+ vr_emit_vtx(vmesa, v0, c0, &a);
+ vr_emit_vtx(vmesa, v1, c1, &b);
+ a.x -= 0.5F; a.y -= 0.5F;
+ b.x -= 0.5F; b.y -= 0.5F;
+ if (aa)
+ rlgl_aaline(&vmesa->rl, &a, &b);
+ else
+ rlgl_line(&vmesa->rl, &a, &b);
+ vmesa->engine_dirty = GL_TRUE;
+}
+
+static void
+vr_hwline(GLcontext *ctx, GLuint e0, GLuint e1)
+{
+
+ vr_line_native(ctx, e0, e1, GL_FALSE);
+}
+
+static void
+vr_aaline(GLcontext *ctx, GLuint e0, GLuint e1)
+{
+
+ vr_line_native(ctx, e0, e1, GL_TRUE);
+}
+
+/* One point as a centered square (2 tris), half-side hs = Point._Size/2. */
+static void
+vr_point_emit(vrmesa_context *vmesa, const SWvertex *v, GLfloat hs)
+{
+ struct rlgl_vtx a, b, c, d;
+ GLfloat x = v->win[0], y = v->win[1];
+
+ vr_emit_at(vmesa, x - hs, y - hs, v, v->color, &a);
+ vr_emit_at(vmesa, x + hs, y - hs, v, v->color, &b);
+ vr_emit_at(vmesa, x + hs, y + hs, v, v->color, &c);
+ vr_emit_at(vmesa, x - hs, y + hs, v, v->color, &d);
+ rlgl_tri(&vmesa->rl, &a, &b, &c);
+ rlgl_tri(&vmesa->rl, &a, &c, &d);
+}
+
+static void
+vr_points(GLcontext *ctx, GLuint first, GLuint last)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat hs = ctx->Point._Size * 0.5F;
+ GLuint i;
+
+ for (i = first; i < last; i++) {
+ GLuint j = VB->Elts ? VB->Elts[i] : i;
+
+ if (VB->ClipMask[j])
+ continue;
+ vr_point_emit(vmesa, &verts[j], hs);
+ }
+ vmesa->engine_dirty = GL_TRUE;
+}
+
+/*
+ * Native anti-aliased points (GL_POINT_SMOOTH)
+ */
+static void
+vr_aapoints(GLcontext *ctx, GLuint first, GLuint last)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ const SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat sz = ctx->Point._Size;
+ GLuint i;
+
+ rlgl_aapoint_begin(&vmesa->rl);
+ for (i = first; i < last; i++) {
+ GLuint j = VB->Elts ? VB->Elts[i] : i;
+ struct rlgl_vtx a;
+
+ if (VB->ClipMask[j])
+ continue;
+ vr_emit_vtx(vmesa, &verts[j], verts[j].color, &a);
+ rlgl_aapoint(&vmesa->rl, &a, sz);
+ }
+ rlgl_aapoint_end(&vmesa->rl);
+ rlgl_depth_func(&vmesa->rl,
+ ctx->Depth.Test && ctx->Depth.Func != GL_ALWAYS,
+ ctx->Depth.Func == GL_LESS ? RLGL_Z_LT : RLGL_Z_LE);
+ /* Z-write only with the test enabled (see vr_update_state) */
+ rlgl_depth_mask(&vmesa->rl, ctx->Depth.Test && ctx->Depth.Mask);
+ vmesa->engine_dirty = GL_TRUE;
+}
+
+/*
+ * Unfilled triangle (glPolygonMode GL_LINE / GL_POINT).
+ */
+static void
+vr_unfilled_tri(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts;
+ SWvertex *v0 = &verts[e0], *v1 = &verts[e1], *v2 = &verts[e2];
+ const GLubyte *ef = TNL_CONTEXT(ctx)->vb.EdgeFlag;
+ GLfloat ex = v0->win[0] - v2->win[0], ey = v0->win[1] - v2->win[1];
+ GLfloat fx = v1->win[0] - v2->win[0], fy = v1->win[1] - v2->win[1];
+ GLfloat cc = ex * fy - ey * fx;
+ GLuint facing = (cc < 0.0F) ^ ctx->Polygon._FrontBit;
+ GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
+ GLchan s0[4], s1[4];
+ GLfloat z0 = 0, z1 = 0, z2 = 0;
+ GLboolean flat, offed = GL_FALSE;
+
+ if (mode == GL_FILL) { /* mixed modes: fill this face */
+ vr_tri(ctx, e0, e1, e2, e2);
+ return;
+ }
+ if (ctx->Polygon.CullFlag) { /* whole-face cull, per swsetup */
+ if (facing == 1 && ctx->Polygon.CullFaceMode != GL_FRONT)
+ return;
+ if (facing == 0 && ctx->Polygon.CullFaceMode != GL_BACK)
+ return;
+ }
+
+ flat = (ctx->Light.ShadeModel == GL_FLAT);
+ if (flat) {
+ COPY_CHAN4(s0, v0->color);
+ COPY_CHAN4(s1, v1->color);
+ COPY_CHAN4(v0->color, v2->color);
+ COPY_CHAN4(v1->color, v2->color);
+ }
+ if ((mode == GL_LINE && ctx->Polygon.OffsetLine) ||
+ (mode == GL_POINT && ctx->Polygon.OffsetPoint)) {
+ GLfloat off = vr_poly_offset(ctx, v0, v1, v2);
+
+ z0 = v0->win[2]; z1 = v1->win[2]; z2 = v2->win[2];
+ v0->win[2] = vr_clampz(z0 + off);
+ v1->win[2] = vr_clampz(z1 + off);
+ v2->win[2] = vr_clampz(z2 + off);
+ offed = GL_TRUE;
+ }
+
+ if (mode == GL_POINT) {
+ GLfloat hs = ctx->Point._Size * 0.5F;
+
+ if (ef[e0]) vr_point_emit(vmesa, v0, hs);
+ if (ef[e1]) vr_point_emit(vmesa, v1, hs);
+ if (ef[e2]) vr_point_emit(vmesa, v2, hs);
+ } else { /* GL_LINE */
+ if (ef[e0]) vr_line(ctx, e0, e1);
+ if (ef[e1]) vr_line(ctx, e1, e2);
+ if (ef[e2]) vr_line(ctx, e2, e0);
+ }
+ vmesa->engine_dirty = GL_TRUE;
+
+ if (offed) {
+ v0->win[2] = z0;
+ v1->win[2] = z1;
+ v2->win[2] = z2;
+ }
+ if (flat) {
+ COPY_CHAN4(v0->color, s0);
+ COPY_CHAN4(v1->color, s1);
+ }
+}
+
+/*
+ * Unfilled quad
+ */
+static void
+vr_unfilled_quad(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLubyte *ef = TNL_CONTEXT(ctx)->vb.EdgeFlag;
+ GLubyte ef1 = ef[v1], ef3 = ef[v3];
+
+ ef[v1] = 0;
+ vr_unfilled_tri(ctx, v0, v1, v3);
+ ef[v1] = ef1;
+ ef[v3] = 0;
+ vr_unfilled_tri(ctx, v1, v2, v3);
+ ef[v3] = ef3;
+}
+
+/*
+ * State gate for the v1 hardware path.
+ */
+void
+vrCheckHwRender(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ GLboolean hw = GL_TRUE;
+
+ vmesa->blend_alpha = GL_FALSE;
+ vmesa->atest_alpha = GL_FALSE;
+ if (ctx->Texture._EnabledUnits != 0 && !vrTexHwOk(ctx)) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_TEX_HWOK);
+ }
+ if (ctx->Color.BlendEnabled) {
+ GLuint srcf, dstf;
+ GLboolean na;
+
+ if (!vrBlendMap(ctx, &srcf, &dstf, &na)) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_BLEND);
+ } else
+ vmesa->blend_alpha = na;
+ }
+ if (ctx->Color.AlphaEnabled) {
+ /*
+ * TranspReject rejects SrcAlpha <= AlphaThres, and
+ * v_TranspReject is enable-only (redline), DUH.
+ */
+ GLenum f = ctx->Color.AlphaFunc;
+
+ if (f != GL_GREATER && f != GL_GEQUAL &&
+ f != GL_NEVER && f != GL_ALWAYS) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_ALPHAFUNC);
+ } else if (f != GL_ALWAYS &&
+ !(ctx->Texture._EnabledUnits == 0x1 &&
+ ctx->Texture.Unit[0].EnvMode == GL_REPLACE))
+ vmesa->atest_alpha = GL_TRUE;
+ }
+ /* fog now rides the KFXYZUVQ per-vertex f term + PE FogColor/En */
+ if (ctx->Depth.Test && ctx->Depth.Func != GL_LESS &&
+ ctx->Depth.Func != GL_LEQUAL && ctx->Depth.Func != GL_ALWAYS) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_DEPTHFUNC);
+ }
+ if (ctx->_TriangleCaps & (DD_TRI_STIPPLE | DD_TRI_SMOOTH |
+ DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) {
+ hw = GL_FALSE; /* offset rides a per-tri Z bias now */
+ /* split the mask so the histogram shows which cap gated */
+ if (ctx->_TriangleCaps & DD_TRI_STIPPLE)
+ VRP_FALLBACK(VRP_FB_STIPPLE);
+ if (ctx->_TriangleCaps & DD_TRI_SMOOTH)
+ VRP_FALLBACK(VRP_FB_SMOOTH);
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
+ VRP_FALLBACK(VRP_FB_TWOSIDE);
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ VRP_FALLBACK(VRP_FB_SPECULAR);
+ }
+ if ((ctx->_TriangleCaps & DD_TRI_UNFILLED) &&
+ (ctx->Line.SmoothFlag || ctx->Line.StippleFlag ||
+ ctx->Point.SmoothFlag || ctx->Point._Attenuated ||
+ ctx->Point.PointSprite)) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_UNFILLED_SUB);
+ }
+ if (ctx->RenderMode != GL_RENDER) {
+ hw = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_RENDERMODE);
+ }
+
+ vmesa->hw_tris = hw;
+}
+
+static void
+vr_build_vertices(GLcontext *ctx, GLuint start, GLuint end, GLuint newinputs)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct tnl_clipspace *vtx = &tnl->clipspace;
+ const GLfloat *m = ctx->Viewport._WindowMap.m;
+ SWvertex *vbuf;
+ const GLubyte *pin, *cin, *tin = NULL, *fin = NULL;
+ GLuint pstr, cstr, tstr = 0, fstr = 0, csize, tsize = 0, g;
+
+ if (!vmesa->fastbuild_ok) {
+ vmesa->ss_build_vertices(ctx, start, end, newinputs);
+ return;
+ }
+
+ newinputs |= vtx->new_inputs;
+ vtx->new_inputs = 0;
+ if (!newinputs)
+ return;
+
+ vbuf = (SWvertex *)vtx->vertex_buf;
+
+ pin = (const GLubyte *)VB->NdcPtr->data;
+ pstr = VB->NdcPtr->stride;
+ cin = (const GLubyte *)VB->ColorPtr[0]->data;
+ cstr = VB->ColorPtr[0]->stride;
+ csize = VB->ColorPtr[0]->size;
+ if (vmesa->fb_tex) {
+ tin = (const GLubyte *)VB->TexCoordPtr[0]->data;
+ tstr = VB->TexCoordPtr[0]->stride;
+ tsize = VB->TexCoordPtr[0]->size;
+ }
+ if (vmesa->fb_fog) {
+ fin = (const GLubyte *)VB->FogCoordPtr->data;
+ fstr = VB->FogCoordPtr->stride;
+ }
+
+ for (g = start; g < end; g++) {
+ SWvertex *o = &vbuf[g];
+ const GLfloat *ndc = (const GLfloat *)(pin + g * pstr);
+ const GLfloat *col = (const GLfloat *)(cin + g * cstr);
+
+ /* POS: EMIT_4F_VIEWPORT */
+ o->win[0] = m[0] * ndc[0] + m[12];
+ o->win[1] = m[5] * ndc[1] + m[13];
+ o->win[2] = m[10] * ndc[2] + m[14];
+ o->win[3] = ndc[3];
+
+ /* COLOR0: EMIT_4CHAN_4F_RGBA */
+ UNCLAMPED_FLOAT_TO_CHAN(o->color[0], col[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(o->color[1], col[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(o->color[2], col[2]);
+ if (csize == 4)
+ UNCLAMPED_FLOAT_TO_CHAN(o->color[3], col[3]);
+ else
+ o->color[3] = CHAN_MAX;
+
+ /* TEX0: EMIT_4F (insert_4f_{4,3,2,1} padding) */
+ if (vmesa->fb_tex) {
+ const GLfloat *t = (const GLfloat *)(tin + g * tstr);
+
+ o->texcoord[0][0] = t[0];
+ o->texcoord[0][1] = tsize >= 2 ? t[1] : 0.0F;
+ o->texcoord[0][2] = tsize >= 3 ? t[2] : 0.0F;
+ o->texcoord[0][3] = tsize >= 4 ? t[3] : 1.0F;
+ }
+
+ /* FOG: EMIT_1F */
+ if (vmesa->fb_fog)
+ o->fog = *(const GLfloat *)(fin + g * fstr);
+ }
+}
+
+static void
+vr_render_start(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ VRP_ZE(VRP_Z_RENDER_START);
+
+ /* swsetup validation: builds vertices, may re-choose funcs */
+ vmesa->ss_render_start(ctx);
+
+ {
+ const GLuint ri = tnl->render_inputs;
+ const GLuint allowed = _TNL_BIT_POS | _TNL_BIT_COLOR0 |
+ _TNL_BIT_FOG | _TNL_BIT_TEX(0);
+
+ vmesa->fb_tex = (ri & _TNL_BIT_TEX(0)) != 0;
+ vmesa->fb_fog = (ri & _TNL_BIT_FOG) != 0;
+ vmesa->fastbuild_ok = vmesa->use_fastbuild &&
+ (ri & _TNL_BIT_POS) && (ri & _TNL_BIT_COLOR0) &&
+ (ri & ~allowed) == 0 &&
+ tnl->clipspace.vertex_size == sizeof(SWvertex) &&
+ tnl->vb.NdcPtr != NULL &&
+ (tnl->vb.ColorPtr[0]->size == 3 ||
+ tnl->vb.ColorPtr[0]->size == 4);
+ }
+
+ if (_mesa_getenv("VRMESA_DEBUG"))
+ _mesa_printf("vr_render_start: hw=%d texen=%x mip=%d "
+ "texw=%.0f\n", vmesa->hw_tris,
+ ctx->Texture._EnabledUnits, vmesa->tex_mip,
+ vmesa->tex_w);
+
+ if (tnl->Driver.Render.Triangle != vr_triangle &&
+ tnl->Driver.Render.Triangle != vr_unfilled_tri) {
+ vmesa->ss_triangle = tnl->Driver.Render.Triangle;
+ vmesa->ss_quad = tnl->Driver.Render.Quad;
+ }
+ if (tnl->Driver.Render.Line != vr_line &&
+ tnl->Driver.Render.Line != vr_hwline &&
+ tnl->Driver.Render.Line != vr_aaline)
+ vmesa->ss_line = tnl->Driver.Render.Line;
+ if (tnl->Driver.Render.Points != vr_points &&
+ tnl->Driver.Render.Points != vr_aapoints)
+ vmesa->ss_points = tnl->Driver.Render.Points;
+
+ if (vmesa->hw_tris) {
+ if (ctx->Texture._EnabledUnits != 0) {
+ /* gate passed, but residency can still fail */
+ if (!vrTexValidate(ctx)) {
+ vmesa->tex_on = GL_FALSE;
+ VRP_FALLBACK(VRP_FB_TEX_RESIDENCY);
+ goto fallback;
+ }
+ vmesa->tex_on = GL_TRUE;
+ } else {
+ rlgl_tex_bind(&vmesa->rl, NULL);
+ vmesa->tex_on = GL_FALSE;
+ }
+ if (ctx->_TriangleCaps & DD_TRI_UNFILLED) {
+ tnl->Driver.Render.Triangle = vr_unfilled_tri;
+ tnl->Driver.Render.Quad = vr_unfilled_quad;
+ tnl->Driver.Render.PrimTabVerts = vmesa->ss_prim_verts;
+ tnl->Driver.Render.PrimTabElts = vmesa->ss_prim_elts;
+ vmesa->strips_ok = GL_FALSE;
+ } else {
+ tnl->Driver.Render.Triangle = vr_triangle;
+ tnl->Driver.Render.Quad = vr_quad;
+ tnl->Driver.Render.PrimTabVerts = vr_tab_verts;
+ tnl->Driver.Render.PrimTabElts = vr_tab_elts;
+ vmesa->strips_ok = vmesa->use_strips &&
+ !vmesa->tex_mip &&
+ !vmesa->blend_alpha && !vmesa->atest_alpha &&
+ !ctx->Polygon.OffsetFill &&
+ !(g_vr_noblendfan && ctx->Color.BlendEnabled);
+ }
+ /*
+ * Line dispatch:
+ * - stippled -> swrast
+ * - smooth + narrow + -> vr_aaline
+ * blending enabled
+ * - smooth + wide/ -> swrast (HW AA line is ~1px)
+ * no blend
+ * - plain + narrow -> vr_hwline
+ * - plain + wide -> vr_line thin-quad
+ */
+ if (ctx->Line.StippleFlag)
+ tnl->Driver.Render.Line = vmesa->ss_line;
+ else if (ctx->Line.SmoothFlag)
+ tnl->Driver.Render.Line =
+ (ctx->Color.BlendEnabled &&
+ ctx->Line._Width <= 1.5F) ?
+ vr_aaline : vmesa->ss_line;
+ else
+ tnl->Driver.Render.Line =
+ (ctx->Line._Width <= 1.5F) ? vr_hwline : vr_line;
+ /*
+ * Points: native AA point
+ */
+ if (ctx->Point.SmoothFlag && ctx->Color.BlendEnabled &&
+ ctx->Texture._EnabledUnits == 0 &&
+ !ctx->Point._Attenuated && !ctx->Point.PointSprite)
+ tnl->Driver.Render.Points = vr_aapoints;
+ else if (!ctx->Point.SmoothFlag && !ctx->Point._Attenuated &&
+ !ctx->Point.PointSprite)
+ tnl->Driver.Render.Points = vr_points;
+ else
+ tnl->Driver.Render.Points = vmesa->ss_points;
+ VRP_ZX(VRP_Z_RENDER_START);
+ return;
+ }
+fallback:
+ tnl->Driver.Render.Triangle = vmesa->ss_triangle;
+ tnl->Driver.Render.Quad = vmesa->ss_quad;
+ tnl->Driver.Render.Line = vmesa->ss_line;
+ tnl->Driver.Render.Points = vmesa->ss_points;
+ /* swrast fallback: everything dispatches through the restored funcs */
+ tnl->Driver.Render.PrimTabVerts = vmesa->ss_prim_verts;
+ tnl->Driver.Render.PrimTabElts = vmesa->ss_prim_elts;
+ vmesa->strips_ok = GL_FALSE;
+ VRP_ZX(VRP_Z_RENDER_START);
+}
+
+void
+vrInitTriFuncs(GLcontext *ctx)
+{
+ vrmesa_context *vmesa = VRMESA_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /* capture swsetup's Start (installed by _swsetup_Wakeup) */
+ vmesa->ss_render_start = tnl->Driver.Render.Start;
+ tnl->Driver.Render.Start = vr_render_start;
+
+ vmesa->ss_build_vertices = tnl->Driver.Render.BuildVertices;
+ tnl->Driver.Render.BuildVertices = vr_build_vertices;
+ vmesa->use_fastbuild = (_mesa_getenv("VRMESA_NOFASTBUILD") == NULL);
+
+ /*
+ * Capture swsetup's default per-mode render tables, then
+ * build our batch tables from them.
+ */
+ vmesa->ss_prim_verts = tnl->Driver.Render.PrimTabVerts;
+ vmesa->ss_prim_elts = tnl->Driver.Render.PrimTabElts;
+ vr_build_tables(tnl);
+ vmesa->use_strips = (_mesa_getenv("VRMESA_STRIPS") != NULL);
+ g_vr_nocache = (_mesa_getenv("VRMESA_NOCACHE") != NULL);
+ rlgl_force_rebind = g_vr_nocache;
+ g_vr_noblendfan = (_mesa_getenv("VRMESA_NOBLENDFAN") != NULL);
+ {
+ const char *zb = _mesa_getenv("VRMESA_ZBIAS");
+ g_vr_zbias = zb ? (float)atoi(zb) : 0.0F;
+ }
+ atexit(vr_strip_stat); /* VRMESA_STRIPSTAT fire-rate report */
+
+ vrCheckHwRender(ctx);
+}
diff --git a/src/mesa/drivers/windows/gdi/colors.h b/src/mesa/drivers/windows/gdi/colors.h
new file mode 100644
index 0000000..5ee66e8
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/colors.h
@@ -0,0 +1,539 @@
+/* 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 : liwei@aiar.xjtu.edu.cn
+ * 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
+ * (mark@rsinc.com).
+ */
+
+/* $Log: ddcolors.h 1997/6/14 by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Macros for pixel format defined
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.2 2004/08/25 15:59:48 brianp
+ * Silence gcc 3.4 warnings on ReactOS. Mostly unused var warnings. (patch 1015696)
+ *
+ * Revision 1.1 2003/07/24 03:47:46 kschultz
+ * Source code for GDI driver.
+ *
+ * Revision 1.3 2002/01/15 18:14:34 kschultz
+ * Fixed pixel color component problem and clear code for 24-bit Windows
+ * devices. (Jeff Lewis)
+ *
+ * Revision 1.2 2002/01/15 18:11:36 kschultz
+ * Remove trailing CR's. No logical changes.
+ *
+ * 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(liwei@aiar.xjtu.edu.cn)
+ * Add LUTs need for dithering
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.2 2004/08/25 15:59:48 brianp
+ * Silence gcc 3.4 warnings on ReactOS. Mostly unused var warnings. (patch 1015696)
+ *
+ * Revision 1.1 2003/07/24 03:47:46 kschultz
+ * Source code for GDI driver.
+ *
+ * Revision 1.3 2002/01/15 18:14:34 kschultz
+ * Fixed pixel color component problem and clear code for 24-bit Windows
+ * devices. (Jeff Lewis)
+ *
+ * Revision 1.2 2002/01/15 18:11:36 kschultz
+ * Remove trailing CR's. No logical changes.
+ *
+ * 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(liwei@aiar.xjtu.edu.cn)
+ * Add BGR8 Macro
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.2 2004/08/25 15:59:48 brianp
+ * Silence gcc 3.4 warnings on ReactOS. Mostly unused var warnings. (patch 1015696)
+ *
+ * Revision 1.1 2003/07/24 03:47:46 kschultz
+ * Source code for GDI driver.
+ *
+ * Revision 1.3 2002/01/15 18:14:34 kschultz
+ * Fixed pixel color component problem and clear code for 24-bit Windows
+ * devices. (Jeff Lewis)
+ *
+ * Revision 1.2 2002/01/15 18:11:36 kschultz
+ * Remove trailing CR's. No logical changes.
+ *
+ * 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(liwei@aiar.xjtu.edu.cn)
+ * 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)))
+
+#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,
+};
diff --git a/src/mesa/drivers/windows/gdi/gdi.dsp b/src/mesa/drivers/windows/gdi/gdi.dsp
new file mode 100644
index 0000000..886cbd6
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/gdi.dsp
@@ -0,0 +1,137 @@
+# Microsoft Developer Studio Project File - Name="gdi" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=gdi - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gdi.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gdi.mak" CFG="gdi - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gdi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "gdi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gdi - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GDI_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../../../src/mesa/main" /I "../../../../../src/mesa/glapi" /I "../../../../../src/mesa/math" /I "../../../../../src/mesa/transform" /I "../../../../../src/mesa/swrast" /I "../../../../../src/mesa/swrast_setup" /I "../../../../../include" /I "../../../../../src/mesa" /I "../../../../../src/mesa/shader" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GDI_EXPORTS" /D "BUILD_GL32" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 winmm.lib msvcrt.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib /out:"Release/OPENGL32.DLL"
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy import lib and dll
+PostBuild_Cmds=if not exist ..\..\..\..\..\lib md ..\..\..\..\..\lib copy Release\OPENGL32.LIB ..\..\..\..\..\lib copy Release\OPENGL32.DLL ..\..\..\..\..\lib
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "gdi - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GDI_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../../../src/mesa/main" /I "../../../../../src/mesa/glapi" /I "../../../../../src/mesa/math" /I "../../../../../src/mesa/transform" /I "../../../../../src/mesa/swrast" /I "../../../../../src/mesa/swrast_setup" /I "../../../../../include" /I "../../../../../src/mesa" /I "../../../../../src/mesa/shader" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GDI_EXPORTS" /D "BUILD_GL32" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib msvcrtd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /nodefaultlib /out:"Debug/OPENGL32.DLL" /pdbtype:sept
+# Begin Special Build Tool
+SOURCE="$(InputPath)"
+PostBuild_Desc=Copy import lib and dll
+PostBuild_Cmds=if not exist ..\..\..\..\..\lib md ..\..\..\..\..\lib copy Debug\OPENGL32.LIB ..\..\..\..\..\lib copy Debug\OPENGL32.DLL ..\..\..\..\..\lib
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "gdi - Win32 Release"
+# Name "gdi - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\..\common\driverfuncs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mesa.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\wgl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\wmesa.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\..\common\driverfuncs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\wmesadef.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/src/mesa/drivers/windows/gdi/mesa.def b/src/mesa/drivers/windows/gdi/mesa.def
new file mode 100644
index 0000000..a393149
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/mesa.def
@@ -0,0 +1,1057 @@
+; DO NOT EDIT - This file generated automatically by mesadef.py script
+DESCRIPTION 'Mesa (OpenGL work-alike) for Win32'
+VERSION 6.0
+;
+; Module definition file for Mesa (OPENGL32.DLL)
+;
+; Note: The OpenGL functions use the STDCALL
+; function calling convention. Microsoft's
+; OPENGL32 uses this convention and so must the
+; Mesa OPENGL32 so that the Mesa DLL can be used
+; as a drop-in replacement.
+;
+; The linker exports STDCALL entry points with
+; 'decorated' names; e.g., _glBegin@0, where the
+; trailing number is the number of bytes of
+; parameter data pushed onto the stack. The
+; callee is responsible for popping this data
+; off the stack, usually via a RETF n instruction.
+;
+; However, the Microsoft OPENGL32.DLL does not export
+; the decorated names, even though the calling convention
+; is STDCALL. So, this module definition file is
+; needed to force the Mesa OPENGL32.DLL to export the
+; symbols in the same manner as the Microsoft DLL.
+; Were it not for this problem, this file would not
+; be needed (for the gl* functions) since the entry
+; points are compiled with dllexport declspec.
+;
+; However, this file is still needed to export "internal"
+; Mesa symbols for the benefit of the OSMESA32.DLL.
+;
+EXPORTS
+ glNewList
+ glEndList
+ glCallList
+ glCallLists
+ glDeleteLists
+ glGenLists
+ glListBase
+ glBegin
+ glBitmap
+ 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
+ glEdgeFlag
+ glEdgeFlagv
+ glEnd
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexs
+ glIndexsv
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ 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
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glClipPlane
+ glColorMaterial
+ glCullFace
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glHint
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glPointSize
+ glPolygonMode
+ glPolygonStipple
+ glScissor
+ glShadeModel
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexImage1D
+ glTexImage2D
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glFeedbackBuffer
+ glSelectBuffer
+ glRenderMode
+ glInitNames
+ glLoadName
+ glPassThrough
+ glPopName
+ glPushName
+ glDrawBuffer
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearStencil
+ glClearDepth
+ glStencilMask
+ glColorMask
+ glDepthMask
+ glIndexMask
+ glAccum
+ glDisable
+ glEnable
+ glFinish
+ glFlush
+ glPopAttrib
+ glPushAttrib
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalPoint1
+ glEvalMesh2
+ glEvalPoint2
+ glAlphaFunc
+ glBlendFunc
+ glLogicOp
+ glStencilFunc
+ glStencilOp
+ glDepthFunc
+ glPixelZoom
+ glPixelTransferf
+ glPixelTransferi
+ glPixelStoref
+ glPixelStorei
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glReadBuffer
+ glCopyPixels
+ glReadPixels
+ glDrawPixels
+ glGetBooleanv
+ glGetClipPlane
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glIsEnabled
+ glIsList
+ glDepthRange
+ glFrustum
+ glLoadIdentity
+ glLoadMatrixf
+ glLoadMatrixd
+ glMatrixMode
+ glMultMatrixf
+ glMultMatrixd
+ glOrtho
+ glPopMatrix
+ glPushMatrix
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glTranslated
+ glTranslatef
+ glViewport
+ glArrayElement
+ glColorPointer
+ glDisableClientState
+ glDrawArrays
+ glDrawElements
+ glEdgeFlagPointer
+ glEnableClientState
+ glGetPointerv
+ glIndexPointer
+ glInterleavedArrays
+ glNormalPointer
+ glTexCoordPointer
+ glVertexPointer
+ glPolygonOffset
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glTexSubImage1D
+ glTexSubImage2D
+ glAreTexturesResident
+ glBindTexture
+ glDeleteTextures
+ glGenTextures
+ glIsTexture
+ glPrioritizeTextures
+ glIndexub
+ glIndexubv
+ glPopClientAttrib
+ glPushClientAttrib
+ glBlendColor
+ glBlendEquation
+ glDrawRangeElements
+ glColorTable
+ glColorTableParameterfv
+ glColorTableParameteriv
+ glCopyColorTable
+ glGetColorTable
+ glGetColorTableParameterfv
+ glGetColorTableParameteriv
+ glColorSubTable
+ glCopyColorSubTable
+ glConvolutionFilter1D
+ glConvolutionFilter2D
+ glConvolutionParameterf
+ glConvolutionParameterfv
+ glConvolutionParameteri
+ glConvolutionParameteriv
+ glCopyConvolutionFilter1D
+ glCopyConvolutionFilter2D
+ glGetConvolutionFilter
+ glGetConvolutionParameterfv
+ glGetConvolutionParameteriv
+ glGetSeparableFilter
+ glSeparableFilter2D
+ glGetHistogram
+ glGetHistogramParameterfv
+ glGetHistogramParameteriv
+ glGetMinmax
+ glGetMinmaxParameterfv
+ glGetMinmaxParameteriv
+ glHistogram
+ glMinmax
+ glResetHistogram
+ glResetMinmax
+ glTexImage3D
+ glTexSubImage3D
+ glCopyTexSubImage3D
+ 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
+ glLoadTransposeMatrixfARB
+ glLoadTransposeMatrixdARB
+ glMultTransposeMatrixfARB
+ glMultTransposeMatrixdARB
+ glSampleCoverageARB
+ glCompressedTexImage3DARB
+ glCompressedTexImage2DARB
+ glCompressedTexImage1DARB
+ glCompressedTexSubImage3DARB
+ glCompressedTexSubImage2DARB
+ glCompressedTexSubImage1DARB
+ glGetCompressedTexImageARB
+ glActiveTexture
+ glClientActiveTexture
+ glMultiTexCoord1d
+ glMultiTexCoord1dv
+ glMultiTexCoord1f
+ glMultiTexCoord1fv
+ glMultiTexCoord1i
+ glMultiTexCoord1iv
+ glMultiTexCoord1s
+ glMultiTexCoord1sv
+ glMultiTexCoord2d
+ glMultiTexCoord2dv
+ glMultiTexCoord2f
+ glMultiTexCoord2fv
+ glMultiTexCoord2i
+ glMultiTexCoord2iv
+ glMultiTexCoord2s
+ glMultiTexCoord2sv
+ glMultiTexCoord3d
+ glMultiTexCoord3dv
+ glMultiTexCoord3f
+ glMultiTexCoord3fv
+ glMultiTexCoord3i
+ glMultiTexCoord3iv
+ glMultiTexCoord3s
+ glMultiTexCoord3sv
+ glMultiTexCoord4d
+ glMultiTexCoord4dv
+ glMultiTexCoord4f
+ glMultiTexCoord4fv
+ glMultiTexCoord4i
+ glMultiTexCoord4iv
+ glMultiTexCoord4s
+ glMultiTexCoord4sv
+ glLoadTransposeMatrixf
+ glLoadTransposeMatrixd
+ glMultTransposeMatrixf
+ glMultTransposeMatrixd
+ glSampleCoverage
+ glCompressedTexImage3D
+ glCompressedTexImage2D
+ glCompressedTexImage1D
+ glCompressedTexSubImage3D
+ glCompressedTexSubImage2D
+ glCompressedTexSubImage1D
+ glGetCompressedTexImage
+ glBlendColorEXT
+ glPolygonOffsetEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+ glGetTexFilterFuncSGIS
+ glTexFilterFuncSGIS
+ glTexSubImage1DEXT
+ glTexSubImage2DEXT
+ glCopyTexImage1DEXT
+ glCopyTexImage2DEXT
+ glCopyTexSubImage1DEXT
+ glCopyTexSubImage2DEXT
+ glCopyTexSubImage3DEXT
+ glGetHistogramEXT
+ glGetHistogramParameterfvEXT
+ glGetHistogramParameterivEXT
+ glGetMinmaxEXT
+ glGetMinmaxParameterfvEXT
+ glGetMinmaxParameterivEXT
+ glHistogramEXT
+ glMinmaxEXT
+ glResetHistogramEXT
+ glResetMinmaxEXT
+ glConvolutionFilter1DEXT
+ glConvolutionFilter2DEXT
+ glConvolutionParameterfEXT
+ glConvolutionParameterfvEXT
+ glConvolutionParameteriEXT
+ glConvolutionParameterivEXT
+ glCopyConvolutionFilter1DEXT
+ glCopyConvolutionFilter2DEXT
+ glGetConvolutionFilterEXT
+ glGetConvolutionParameterfvEXT
+ glGetConvolutionParameterivEXT
+ glGetSeparableFilterEXT
+ glSeparableFilter2DEXT
+ glColorTableSGI
+ glColorTableParameterfvSGI
+ glColorTableParameterivSGI
+ glCopyColorTableSGI
+ glGetColorTableSGI
+ glGetColorTableParameterfvSGI
+ glGetColorTableParameterivSGI
+ glPixelTexGenSGIX
+ glPixelTexGenParameteriSGIS
+ glPixelTexGenParameterivSGIS
+ glPixelTexGenParameterfSGIS
+ glPixelTexGenParameterfvSGIS
+ glGetPixelTexGenParameterivSGIS
+ glGetPixelTexGenParameterfvSGIS
+ glTexImage4DSGIS
+ glTexSubImage4DSGIS
+ glAreTexturesResidentEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glIsTextureEXT
+ glPrioritizeTexturesEXT
+ glDetailTexFuncSGIS
+ glGetDetailTexFuncSGIS
+ glSharpenTexFuncSGIS
+ glGetSharpenTexFuncSGIS
+ glSampleMaskSGIS
+ glSamplePatternSGIS
+ glArrayElementEXT
+ glColorPointerEXT
+ glDrawArraysEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glIndexPointerEXT
+ glNormalPointerEXT
+ glTexCoordPointerEXT
+ glVertexPointerEXT
+ glBlendEquationEXT
+ glSpriteParameterfSGIX
+ glSpriteParameterfvSGIX
+ glSpriteParameteriSGIX
+ glSpriteParameterivSGIX
+ glPointParameterfEXT
+ glPointParameterfvEXT
+ glPointParameterfARB
+ glPointParameterfvARB
+ glPointParameterfSGIS
+ glPointParameterfvSGIS
+ glGetInstrumentsSGIX
+ glInstrumentsBufferSGIX
+ glPollInstrumentsSGIX
+ glReadInstrumentsSGIX
+ glStartInstrumentsSGIX
+ glStopInstrumentsSGIX
+ glFrameZoomSGIX
+ glTagSampleBufferSGIX
+ glReferencePlaneSGIX
+ glFlushRasterSGIX
+ glColorSubTableEXT
+ glCopyColorSubTableEXT
+ glHintPGI
+ glColorTableEXT
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glGetListParameterfvSGIX
+ glGetListParameterivSGIX
+ glListParameterfSGIX
+ glListParameterfvSGIX
+ glListParameteriSGIX
+ glListParameterivSGIX
+ glIndexMaterialEXT
+ glIndexFuncEXT
+ glLockArraysEXT
+ glUnlockArraysEXT
+ glCullParameterdvEXT
+ glCullParameterfvEXT
+ glFragmentColorMaterialSGIX
+ glFragmentLightfSGIX
+ glFragmentLightfvSGIX
+ glFragmentLightiSGIX
+ glFragmentLightivSGIX
+ glFragmentLightModelfSGIX
+ glFragmentLightModelfvSGIX
+ glFragmentLightModeliSGIX
+ glFragmentLightModelivSGIX
+ glFragmentMaterialfSGIX
+ glFragmentMaterialfvSGIX
+ glFragmentMaterialiSGIX
+ glFragmentMaterialivSGIX
+ glGetFragmentLightfvSGIX
+ glGetFragmentLightivSGIX
+ glGetFragmentMaterialfvSGIX
+ glGetFragmentMaterialivSGIX
+ glLightEnviSGIX
+ glDrawRangeElementsEXT
+ glSecondaryColor3bEXT
+ glSecondaryColor3bvEXT
+ glSecondaryColor3dEXT
+ glSecondaryColor3dvEXT
+ glSecondaryColor3fEXT
+ glSecondaryColor3fvEXT
+ glSecondaryColor3iEXT
+ glSecondaryColor3ivEXT
+ glSecondaryColor3sEXT
+ glSecondaryColor3svEXT
+ glSecondaryColor3ubEXT
+ glSecondaryColor3ubvEXT
+ glSecondaryColor3uiEXT
+ glSecondaryColor3uivEXT
+ glSecondaryColor3usEXT
+ glSecondaryColor3usvEXT
+ glSecondaryColorPointerEXT
+ glMultiDrawArraysEXT
+ glMultiDrawElementsEXT
+ glFogCoordfEXT
+ glFogCoordfvEXT
+ glFogCoorddEXT
+ glFogCoorddvEXT
+ glFogCoordPointerEXT
+ glBlendFuncSeparateEXT
+ glBlendFuncSeparateINGR
+ glVertexWeightfEXT
+ glVertexWeightfvEXT
+ glVertexWeightPointerEXT
+ glFlushVertexArrayRangeNV
+ glVertexArrayRangeNV
+ glCombinerParameterfvNV
+ glCombinerParameterfNV
+ glCombinerParameterivNV
+ glCombinerParameteriNV
+ glCombinerInputNV
+ glCombinerOutputNV
+ glFinalCombinerInputNV
+ glGetCombinerInputParameterfvNV
+ glGetCombinerInputParameterivNV
+ glGetCombinerOutputParameterfvNV
+ glGetCombinerOutputParameterivNV
+ glGetFinalCombinerInputParameterfvNV
+ glGetFinalCombinerInputParameterivNV
+ glResizeBuffersMESA
+ glWindowPos2dMESA
+ glWindowPos2dvMESA
+ glWindowPos2fMESA
+ glWindowPos2fvMESA
+ glWindowPos2iMESA
+ glWindowPos2ivMESA
+ glWindowPos2sMESA
+ glWindowPos2svMESA
+ glWindowPos3dMESA
+ glWindowPos3dvMESA
+ glWindowPos3fMESA
+ glWindowPos3fvMESA
+ glWindowPos3iMESA
+ glWindowPos3ivMESA
+ glWindowPos3sMESA
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+ glMultiModeDrawArraysIBM
+ glMultiModeDrawElementsIBM
+ glTbufferMask3DFX
+ glSampleMaskEXT
+ glSamplePatternEXT
+ glWindowPos2dARB
+ glWindowPos2fARB
+ glWindowPos2iARB
+ glWindowPos2sARB
+ glWindowPos2dvARB
+ glWindowPos2fvARB
+ glWindowPos2ivARB
+ glWindowPos2svARB
+ glWindowPos3dARB
+ glWindowPos3fARB
+ glWindowPos3iARB
+ glWindowPos3sARB
+ glWindowPos3dvARB
+ glWindowPos3fvARB
+ glWindowPos3ivARB
+ glWindowPos3svARB
+ glAreProgramsResidentNV
+ glBindProgramNV
+ glDeleteProgramsNV
+ glExecuteProgramNV
+ glGenProgramsNV
+ glGetProgramParameterdvNV
+ glGetProgramParameterfvNV
+ glGetProgramivNV
+ glGetProgramStringNV
+ glGetTrackMatrixivNV
+ glGetVertexAttribdvNV
+ glGetVertexAttribfvNV
+ glGetVertexAttribivNV
+ glGetVertexAttribPointervNV
+ glIsProgramNV
+ glLoadProgramNV
+ glProgramParameter4dNV
+ glProgramParameter4dvNV
+ glProgramParameter4fNV
+ glProgramParameter4fvNV
+ glProgramParameters4dvNV
+ glProgramParameters4fvNV
+ glRequestResidentProgramsNV
+ glTrackMatrixNV
+ glVertexAttribPointerNV
+ glVertexAttrib1dNV
+ glVertexAttrib1dvNV
+ glVertexAttrib1fNV
+ glVertexAttrib1fvNV
+ glVertexAttrib1sNV
+ glVertexAttrib1svNV
+ glVertexAttrib2dNV
+ glVertexAttrib2dvNV
+ glVertexAttrib2fNV
+ glVertexAttrib2fvNV
+ glVertexAttrib2sNV
+ glVertexAttrib2svNV
+ glVertexAttrib3dNV
+ glVertexAttrib3dvNV
+ glVertexAttrib3fNV
+ glVertexAttrib3fvNV
+ glVertexAttrib3sNV
+ glVertexAttrib3svNV
+ glVertexAttrib4dNV
+ glVertexAttrib4dvNV
+ glVertexAttrib4fNV
+ glVertexAttrib4fvNV
+ glVertexAttrib4sNV
+ glVertexAttrib4svNV
+ glVertexAttrib4ubNV
+ glVertexAttrib4ubvNV
+ glVertexAttribs1dvNV
+ glVertexAttribs1fvNV
+ glVertexAttribs1svNV
+ glVertexAttribs2dvNV
+ glVertexAttribs2fvNV
+ glVertexAttribs2svNV
+ glVertexAttribs3dvNV
+ glVertexAttribs3fvNV
+ glVertexAttribs3svNV
+ glVertexAttribs4dvNV
+ glVertexAttribs4fvNV
+ glVertexAttribs4svNV
+ glVertexAttribs4ubvNV
+ glPointParameteriNV
+ glPointParameterivNV
+ glBlendFuncSeparate
+ glFogCoordf
+ glFogCoordfv
+ glFogCoordd
+ glFogCoorddv
+ glFogCoordPointer
+ glMultiDrawArrays
+ glMultiDrawElements
+ glPointParameterf
+ glPointParameterfv
+ glPointParameteri
+ glPointParameteriv
+ glSecondaryColor3b
+ glSecondaryColor3bv
+ glSecondaryColor3d
+ glSecondaryColor3dv
+ glSecondaryColor3f
+ glSecondaryColor3fv
+ glSecondaryColor3i
+ glSecondaryColor3iv
+ glSecondaryColor3s
+ glSecondaryColor3sv
+ glSecondaryColor3ub
+ glSecondaryColor3ubv
+ glSecondaryColor3ui
+ glSecondaryColor3uiv
+ glSecondaryColor3us
+ glSecondaryColor3usv
+ glSecondaryColorPointer
+ glWindowPos2d
+ glWindowPos2dv
+ glWindowPos2f
+ glWindowPos2fv
+ glWindowPos2i
+ glWindowPos2iv
+ glWindowPos2s
+ glWindowPos2sv
+ glWindowPos3d
+ glWindowPos3dv
+ glWindowPos3f
+ glWindowPos3fv
+ glWindowPos3i
+ glWindowPos3iv
+ glWindowPos3s
+ glWindowPos3sv
+ glActiveStencilFaceEXT
+ glDeleteFencesNV
+ glGenFencesNV
+ glIsFenceNV
+ glTestFenceNV
+ glGetFenceivNV
+ glFinishFenceNV
+ glSetFenceNV
+ glVertexAttrib1sARB
+ glVertexAttrib1fARB
+ glVertexAttrib1dARB
+ glVertexAttrib2sARB
+ glVertexAttrib2fARB
+ glVertexAttrib2dARB
+ glVertexAttrib3sARB
+ glVertexAttrib3fARB
+ glVertexAttrib3dARB
+ glVertexAttrib4sARB
+ glVertexAttrib4fARB
+ glVertexAttrib4dARB
+ glVertexAttrib4NubARB
+ glVertexAttrib1svARB
+ glVertexAttrib1fvARB
+ glVertexAttrib1dvARB
+ glVertexAttrib2svARB
+ glVertexAttrib2fvARB
+ glVertexAttrib2dvARB
+ glVertexAttrib3svARB
+ glVertexAttrib3fvARB
+ glVertexAttrib3dvARB
+ glVertexAttrib4bvARB
+ glVertexAttrib4svARB
+ glVertexAttrib4ivARB
+ glVertexAttrib4ubvARB
+ glVertexAttrib4usvARB
+ glVertexAttrib4uivARB
+ glVertexAttrib4fvARB
+ glVertexAttrib4dvARB
+ glVertexAttrib4NbvARB
+ glVertexAttrib4NsvARB
+ glVertexAttrib4NivARB
+ glVertexAttrib4NubvARB
+ glVertexAttrib4NusvARB
+ glVertexAttrib4NuivARB
+ glVertexAttribPointerARB
+ glEnableVertexAttribArrayARB
+ glDisableVertexAttribArrayARB
+ glProgramStringARB
+ glBindProgramARB
+ glDeleteProgramsARB
+ glGenProgramsARB
+ glIsProgramARB
+ glProgramEnvParameter4dARB
+ glProgramEnvParameter4dvARB
+ glProgramEnvParameter4fARB
+ glProgramEnvParameter4fvARB
+ glProgramLocalParameter4dARB
+ glProgramLocalParameter4dvARB
+ glProgramLocalParameter4fARB
+ glProgramLocalParameter4fvARB
+ glGetProgramEnvParameterdvARB
+ glGetProgramEnvParameterfvARB
+ glGetProgramLocalParameterdvARB
+ glGetProgramLocalParameterfvARB
+ glGetProgramivARB
+ glGetProgramStringARB
+ glGetVertexAttribdvARB
+ glGetVertexAttribfvARB
+ glGetVertexAttribivARB
+ glGetVertexAttribPointervARB
+ glProgramNamedParameter4fNV
+ glProgramNamedParameter4dNV
+ glProgramNamedParameter4fvNV
+ glProgramNamedParameter4dvNV
+ glGetProgramNamedParameterfvNV
+ glGetProgramNamedParameterdvNV
+ glBindBufferARB
+ glBufferDataARB
+ glBufferSubDataARB
+ glDeleteBuffersARB
+ glGenBuffersARB
+ glGetBufferParameterivARB
+ glGetBufferPointervARB
+ glGetBufferSubDataARB
+ glIsBufferARB
+ glMapBufferARB
+ glUnmapBufferARB
+ glDepthBoundsEXT
+ glGenQueriesARB
+ glDeleteQueriesARB
+ glIsQueryARB
+ glBeginQueryARB
+ glEndQueryARB
+ glGetQueryivARB
+ glGetQueryObjectivARB
+ glGetQueryObjectuivARB
+ glBindBuffer
+ glBufferData
+ glBufferSubData
+ glDeleteBuffers
+ glGenBuffers
+ glGetBufferParameteriv
+ glGetBufferPointerv
+ glGetBufferSubData
+ glIsBuffer
+ glMapBuffer
+ glUnmapBuffer
+ glGenQueries
+ glDeleteQueries
+ glIsQuery
+ glBeginQuery
+ glEndQuery
+ glGetQueryiv
+ glGetQueryObjectiv
+ glGetQueryObjectuiv
+;
+; WGL API
+ wglChoosePixelFormat
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglDescribePixelFormat
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetLayerPaletteEntries
+ wglGetPixelFormat
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglSetPixelFormat
+ wglShareLists
+ wglSwapBuffers
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+;
+; Mesa internals - mostly for OSMESA
+ _ac_CreateContext
+ _ac_DestroyContext
+ _ac_InvalidateState
+ _glapi_get_context
+ _glapi_get_proc_address
+ _mesa_buffer_data
+ _mesa_buffer_map
+ _mesa_buffer_subdata
+ _mesa_bzero
+ _mesa_calloc
+ _mesa_choose_tex_format
+ _mesa_compressed_texture_size
+ _mesa_create_framebuffer
+ _mesa_create_visual
+ _mesa_delete_buffer_object
+ _mesa_delete_texture_object
+ _mesa_destroy_framebuffer
+ _mesa_destroy_visual
+ _mesa_enable_1_3_extensions
+ _mesa_enable_1_4_extensions
+ _mesa_enable_1_5_extensions
+ _mesa_enable_sw_extensions
+ _mesa_error
+ _mesa_free
+ _mesa_free_context_data
+ _mesa_get_current_context
+ _mesa_init_default_imports
+ _mesa_init_driver_functions
+ _mesa_initialize_context
+ _mesa_make_current
+ _mesa_memcpy
+ _mesa_memset
+ _mesa_new_buffer_object
+ _mesa_new_texture_object
+ _mesa_problem
+ _mesa_ResizeBuffersMESA
+ _mesa_store_compressed_teximage1d
+ _mesa_store_compressed_teximage2d
+ _mesa_store_compressed_teximage3d
+ _mesa_store_compressed_texsubimage1d
+ _mesa_store_compressed_texsubimage2d
+ _mesa_store_compressed_texsubimage3d
+ _mesa_store_teximage1d
+ _mesa_store_teximage2d
+ _mesa_store_teximage3d
+ _mesa_store_texsubimage1d
+ _mesa_store_texsubimage2d
+ _mesa_store_texsubimage3d
+ _mesa_strcmp
+ _mesa_test_proxy_teximage
+ _mesa_Viewport
+ _swrast_Accum
+ _swrast_alloc_buffers
+ _swrast_Bitmap
+ _swrast_CopyPixels
+ _swrast_DrawBuffer
+ _swrast_DrawPixels
+ _swrast_GetDeviceDriverReference
+ _swrast_Clear
+ _swrast_choose_line
+ _swrast_choose_triangle
+ _swrast_CopyColorSubTable
+ _swrast_CopyColorTable
+ _swrast_CopyConvolutionFilter1D
+ _swrast_CopyConvolutionFilter2D
+ _swrast_copy_teximage1d
+ _swrast_copy_teximage2d
+ _swrast_copy_texsubimage1d
+ _swrast_copy_texsubimage2d
+ _swrast_copy_texsubimage3d
+ _swrast_CreateContext
+ _swrast_DestroyContext
+ _swrast_InvalidateState
+ _swrast_ReadPixels
+ _swrast_zbuffer_address
+ _swsetup_Wakeup
+ _swsetup_CreateContext
+ _swsetup_DestroyContext
+ _swsetup_InvalidateState
+ _tnl_CreateContext
+ _tnl_DestroyContext
+ _tnl_InvalidateState
+ _tnl_MakeCurrent
+ _tnl_run_pipeline
diff --git a/src/mesa/drivers/windows/gdi/wgl.c b/src/mesa/drivers/windows/gdi/wgl.c
new file mode 100644
index 0000000..920929c
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/wgl.c
@@ -0,0 +1,639 @@
+/* $Id: wgl.c,v 1.6 2004/08/30 08:37:57 dborca Exp $ */
+
+/*
+* 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.
+*
+*/
+
+/*
+* File name : wgl.c
+* WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru
+* Some things originated from the 3Dfx WGL functions
+*/
+
+#ifdef WIN32
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+//#include <GL/glu.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <stdio.h>
+#include <tchar.h>
+#include "wmesadef.h"
+#include "GL/wmesa.h"
+#include "mtypes.h"
+#include "glapi.h"
+
+#define MAX_MESA_ATTRS 20
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLboolean doubleBuffered;
+};
+
+struct __pixelformat__ pix[] =
+{
+ /* Double Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ /* Single Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_FALSE
+ },
+ /* Double Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ /* Single Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_FALSE
+ },
+};
+
+int qt_pix = sizeof(pix) / sizeof(pix[0]);
+
+typedef struct {
+ WMesaContext ctx;
+ HDC hdc;
+} MesaWglCtx;
+
+#define MESAWGL_CTX_MAX_COUNT 20
+
+static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
+
+static unsigned ctx_count = 0;
+static int ctx_current = -1;
+static unsigned curPFD = 0;
+
+WGLAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ (void) hglrcSrc; (void) hglrcDst; (void) mask;
+ return(FALSE);
+}
+
+WGLAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ int i = 0;
+ if(!(hWnd = WindowFromDC(hdc)))
+ {
+ SetLastError(0);
+ return(NULL);
+ }
+ if (!ctx_count)
+ {
+ for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++)
+ {
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ }
+ }
+ for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == NULL )
+ {
+ wgl_ctx[i].ctx = WMesaCreateContext( hWnd, NULL, GL_TRUE,
+ pix[curPFD-1].doubleBuffered,
+ pix[curPFD-1].pfd.cAlphaBits ? GL_TRUE : GL_FALSE);
+ if (wgl_ctx[i].ctx == NULL)
+ break;
+ wgl_ctx[i].hdc = hdc;
+ ctx_count++;
+ return ((HGLRC)wgl_ctx[i].ctx);
+ }
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc)
+{
+ int i;
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ WMesaMakeCurrent((PWMC) hglrc);
+ WMesaDestroyContext();
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ ctx_count--;
+ return(TRUE);
+ }
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ (void) hdc; (void) iLayerPlane;
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID)
+{
+ if (ctx_current < 0)
+ return 0;
+ else
+ return (HGLRC) wgl_ctx[ctx_current].ctx;
+}
+
+WGLAPI HDC GLAPIENTRY wglGetCurrentDC(VOID)
+{
+ if (ctx_current < 0)
+ return 0;
+ else
+ return wgl_ctx[ctx_current].hdc;
+}
+
+WGLAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc)
+{
+ int i;
+
+ /* new code suggested by Andy Sy */
+ if (!hdc || !hglrc) {
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+ return TRUE;
+ }
+
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ wgl_ctx[i].hdc = hdc;
+ WMesaMakeCurrent( (WMesaContext) hglrc );
+ ctx_current = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+WGLAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ (void) hglrc1; (void) hglrc2;
+ return(TRUE);
+}
+
+
+static FIXED FixedFromDouble(double d)
+{
+ long l = (long) (d * 65536L);
+ return *(FIXED *) (void *) &l;
+}
+
+
+/*
+** This is cribbed from FX/fxwgl.c, and seems to implement support
+** for bitmap fonts where the wglUseFontBitmapsA() code implements
+** support for outline fonts. In combination they hopefully give
+** fairly generic support for fonts.
+*/
+static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar,
+ DWORD numChars, DWORD listBase)
+{
+#define VERIFY(a) a
+
+ TEXTMETRIC metric;
+ BITMAPINFO *dibInfo;
+ HDC bitDevice;
+ COLORREF tempColor;
+ int i;
+
+ VERIFY(GetTextMetrics(fontDevice, &metric));
+
+ dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1);
+ dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibInfo->bmiHeader.biPlanes = 1;
+ dibInfo->bmiHeader.biBitCount = 1;
+ dibInfo->bmiHeader.biCompression = BI_RGB;
+
+ bitDevice = CreateCompatibleDC(fontDevice);
+ // HDC bitDevice = CreateDC("DISPLAY", NULL, NULL, NULL);
+ // VERIFY(bitDevice);
+
+ // Swap fore and back colors so the bitmap has the right polarity
+ tempColor = GetBkColor(bitDevice);
+ SetBkColor(bitDevice, GetTextColor(bitDevice));
+ SetTextColor(bitDevice, tempColor);
+
+ // Place chars based on base line
+ VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0);
+
+ for(i = 0; i < (int)numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = i + firstChar;
+
+ // Find how high/wide this character is
+ VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size));
+
+ // Create the output bitmap
+ charWidth = size.cx;
+ charHeight = size.cy;
+ bmapWidth = ((charWidth + 31) / 32) * 32; // Round up to the next multiple of 32 bits
+ bmapHeight = charHeight;
+ bitObject = CreateCompatibleBitmap(bitDevice,
+ bmapWidth,
+ bmapHeight);
+ //VERIFY(bitObject);
+
+ // Assign the output bitmap to the device
+ origBmap = SelectObject(bitDevice, bitObject);
+ (void) VERIFY(origBmap);
+
+ VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) );
+
+ // Use our source font on the device
+ VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT)));
+
+ // Draw the character
+ VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1));
+
+ // Unselect our bmap object
+ VERIFY(SelectObject(bitDevice, origBmap));
+
+ // Convert the display dependant representation to a 1 bit deep DIB
+ numBytes = (bmapWidth * bmapHeight) / 8;
+ bmap = malloc(numBytes);
+ dibInfo->bmiHeader.biWidth = bmapWidth;
+ dibInfo->bmiHeader.biHeight = bmapHeight;
+ res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap,
+ dibInfo,
+ DIB_RGB_COLORS);
+ //VERIFY(res);
+
+ // Create the GL object
+ glNewList(i + listBase, GL_COMPILE);
+ glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent,
+ charWidth, 0.0,
+ bmap);
+ glEndList();
+ // CheckGL();
+
+ // Destroy the bmap object
+ DeleteObject(bitObject);
+
+ // Deallocate the bitmap data
+ free(bmap);
+ }
+
+ // Destroy the DC
+ VERIFY(DeleteDC(bitDevice));
+
+ free(dibInfo);
+
+ return TRUE;
+#undef VERIFY
+}
+
+WGLAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first,
+ DWORD count, DWORD listBase)
+{
+ int i;
+ GLuint font_list;
+ DWORD size;
+ GLYPHMETRICS gm;
+ HANDLE hBits;
+ LPSTR lpBits;
+ MAT2 mat;
+ int success = TRUE;
+
+ if (count == 0)
+ return FALSE;
+
+ font_list = listBase;
+
+ mat.eM11 = FixedFromDouble(1);
+ mat.eM12 = FixedFromDouble(0);
+ mat.eM21 = FixedFromDouble(0);
+ mat.eM22 = FixedFromDouble(-1);
+
+ memset(&gm,0,sizeof(gm));
+
+ /*
+ ** If we can't get the glyph outline, it may be because this is a fixed
+ ** font. Try processing it that way.
+ */
+ if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat)
+ == GDI_ERROR )
+ {
+ return wglUseFontBitmaps_FX( hdc, first, count, listBase );
+ }
+
+ /*
+ ** Otherwise process all desired characters.
+ */
+ for (i = 0; i < (int)count; i++)
+ {
+ DWORD err;
+
+ glNewList( font_list+i, GL_COMPILE );
+
+ /* allocate space for the bitmap/outline */
+ size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, NULL, &mat);
+ if (size == GDI_ERROR)
+ {
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ hBits = GlobalAlloc(GHND, size+1);
+ lpBits = GlobalLock(hBits);
+
+ err =
+ GetGlyphOutline(hdc, /* handle to device context */
+ first + i, /* character to query */
+ GGO_BITMAP, /* format of data to return */
+ &gm, /* pointer to structure for metrics*/
+ size, /* size of buffer for data */
+ lpBits, /* pointer to buffer for data */
+ &mat /* pointer to transformation */
+ /* matrix structure */
+ );
+
+ if (err == GDI_ERROR)
+ {
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ err = GetLastError();
+ success = FALSE;
+ continue;
+ }
+
+ glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
+ -gm.gmptGlyphOrigin.x,
+ gm.gmptGlyphOrigin.y,
+ gm.gmCellIncX,gm.gmCellIncY,
+ (const GLubyte * )lpBits);
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ }
+
+ return success;
+}
+
+
+WGLAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
+{
+ (void) hdc; (void) first; (void) count; (void) listBase;
+ return FALSE;
+}
+
+WGLAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ (void) hdc; (void) first; (void) count;
+ (void) listBase; (void) deviation; (void) extrusion; (void) format;
+ (void) lpgmf;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ (void) hdc; (void) first; (void) count;
+ (void) listBase; (void) deviation; (void) extrusion; (void) format;
+ (void) lpgmf;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc,int iPixelFormat,
+ int iLayerPlane,UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ (void) hdc; (void) iPixelFormat; (void) iLayerPlane; (void) nBytes; (void) plpd;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ CONST COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
+{
+ (void) hdc; (void) iLayerPlane; (void) bRealize;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ (void) fuPlanes;
+ if( !hdc )
+ {
+ WMesaSwapBuffers();
+ return(TRUE);
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i,best = -1,bestdelta = 0x7FFFFFFF,delta,qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ for(i = 0;i < qt_valid_pix;i++)
+ {
+ delta = 0;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) &&
+ !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) &&
+ !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_GDI) &&
+ !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_OPENGL) &&
+ !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
+ continue;
+ if(ppfd->iPixelType != pix[i].pfd.iPixelType)
+ delta++;
+ if(ppfd->cAlphaBits != pix[i].pfd.cAlphaBits)
+ delta++;
+ if(delta < bestdelta)
+ {
+ best = i + 1;
+ bestdelta = delta;
+ if(bestdelta == 0)
+ break;
+ }
+ }
+ if(best == -1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ return(best);
+}
+
+WGLAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(ppfd == NULL)
+ return(qt_valid_pix);
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || nBytes != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(0);
+ }
+ *ppfd = pix[iPixelFormat - 1].pfd;
+ return(qt_valid_pix);
+}
+
+/*
+* GetProcAddress - return the address of an appropriate extension
+*/
+WGLAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc)
+{
+ PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc);
+ if (p)
+ return p;
+
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc)
+{
+ (void) hdc;
+ if(curPFD == 0)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ return(curPFD);
+}
+
+WGLAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
+ PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
+{
+ (void) hdc;
+ if (ctx_current < 0)
+ return FALSE;
+
+ if(wgl_ctx[ctx_current].ctx == NULL) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ WMesaSwapBuffers();
+ return(TRUE);
+}
+
+#endif /* WIN32 */
diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c
new file mode 100644
index 0000000..ea13a31
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/wmesa.c
@@ -0,0 +1,3353 @@
+
+/*
+ * Windows (Win32) device driver for Mesa 3.4
+ *
+ * Original author:
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially borrowed from the
+ * Windows NT driver for Mesa 1.8 , written by Mark Leaming
+ * (mark@rsinc.com).
+ *
+ * Updated for Mesa 4.0 by Karl Schultz (kschultz@sourceforge.net)
+ */
+
+#ifdef NDEBUG
+#pragma auto_inline(on)
+#pragma inline_depth(255)
+#pragma inline_recursion(on)
+#endif
+
+#include "wmesadef.h"
+#include <GL/wmesa.h>
+//#include "mesa_extend.h"
+
+#include "glheader.h"
+#include "colors.h"
+#include "context.h"
+#include "colormac.h"
+#include "dd.h"
+#include "depth.h"
+#include "extensions.h"
+#include "imports.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/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/s_alphabuf.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 "drivers/common/driverfuncs.h"
+
+/* Dither not tested for Mesa 4.0 */
+#ifdef DITHER
+#ifdef USE_WING
+#include <wing.h>
+#endif // USE_WING
+#endif
+
+#ifdef __CYGWIN32__
+#include "macros.h"
+#include <string.h>
+#define CopyMemory memcpy
+#endif
+
+/* Stereo and parallel not tested for Mesa 4.0. */
+#define NO_STEREO
+#if !defined(NO_STEREO)
+#include "gl\glu.h"
+#include "stereo.h"
+#endif
+
+#define NO_PARALLEL
+#if !defined(NO_PARALLEL)
+#include "parallel.h"
+#endif
+
+
+/* File global varaibles */
+struct DISPLAY_OPTIONS {
+ int stereo;
+ int fullScreen;
+ int mode;
+ int bpp;
+};
+
+struct DISPLAY_OPTIONS displayOptions =
+{
+ 0, // stereo
+ 0, // fullScreen
+ 0, // full screen mode (1,2,3,4)
+ 0 // bpp (8,16,24,32)
+};
+GLenum stereoCompile = GL_FALSE ;
+GLenum stereoShowing = GL_FALSE ;
+GLenum stereoBuffer = GL_FALSE;
+#if !defined(NO_STEREO)
+GLint displayList = MAXIMUM_DISPLAY_LIST ;
+#endif
+GLint stereo_flag = 0 ;
+
+static PWMC Current = NULL;
+WMesaContext WC = NULL;
+
+#ifdef COMPILE_SETPIXEL
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200
+#define FORCEINLINE __forceinline
+#else
+#define FORCEINLINE __inline
+#endif
+
+FORCEINLINE void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ pwc->wmSetPixel(pwc,iScanLine,iPixel,r,g,b);
+}
+
+void ChooseSetPixel(PWMC pwc);
+
+#endif // COMPILE_SETPIXEL
+
+/* 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)
+
+#define DITHER_RGB_TO_8BIT_SETUP \
+GLubyte pixelDithered;
+
+#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline) \
+{ \
+ char unsigned redtemp, greentemp, bluetemp, paletteindex; \
+ 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]); \
+ paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp];\
+ pixelDithered = aWinGHalftoneTranslation[paletteindex]; \
+}
+
+#ifdef DDRAW
+static BOOL DDInit( WMesaContext wc, HWND hwnd);
+static void DDFree( WMesaContext wc);
+static HRESULT DDRestoreAll( WMesaContext wc );
+static void DDDeleteOffScreen(WMesaContext wc);
+static BOOL DDCreateOffScreen(WMesaContext wc);
+
+// define this to use the GDI Rectangle call to
+// clear the back buffer. Otherwise will manually
+// set the pixels. On an NVidia GEForce 2MX under Windows XP
+// and DirectX 8 , defining this makes apps run much much faster
+#define USE_GDI_TO_CLEAR 1
+#endif
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
+BOOL wmDeleteBackingStore(PWMC pwc);
+void wmCreatePalette( PWMC pwdc );
+BOOL wmSetDibColors(PWMC pwc);
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+BOOL wmFlush(PWMC pwc);
+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
+ );
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+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 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;
+}
+
+
+/*
+ * 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);
+#ifdef USE_MAPPED_FILE
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+#endif
+ return TRUE;
+}
+
+
+/*
+ * 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;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return TRUE;
+}
+
+#if 0
+// D.R.S. 10/30/01 - this function is never referenced
+/*
+ * This function copies one scan line in a DIB section to another
+ */
+BOOL wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans,
+ UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
+{
+ UINT uiScans = 0;
+ LPBYTE pDest = pwc->pbPixels;
+ DWORD dwNextScan = uiScanWidth;
+ DWORD dwNewScan = uiNewWidth;
+ DWORD dwScanWidth = (uiScanWidth * nBypp);
+
+ /*
+ * We need to round up to the nearest DWORD
+ * and multiply by the number of bytes per
+ * pixel
+ */
+ dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
+ dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
+
+ for(uiScans = 0; uiScans < uiNumScans; uiScans++){
+ CopyMemory(pDest, pBits, dwScanWidth);
+ pBits += dwNextScan;
+ pDest += dwNewScan;
+ }
+ return TRUE;
+}
+#endif // 0
+
+#if defined(FAST_RASTERIZERS)
+
+#define PIXELADDR(X,Y) \
+ ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* \
+ Current->ScanWidth + (X)*nBypp)
+#define PIXELADDR1( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X))
+#define PIXELADDR2( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2)
+#define PIXELADDR4( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4)
+
+#endif // 0
+
+BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y);
+
+#if 0 /* unused */
+
+/* Finish all pending operations and synchronize. */
+static void finish(GLcontext* ctx)
+{
+ /* No op */
+ (void) ctx;
+}
+
+#endif /* unused */
+
+static void flush(GLcontext* ctx)
+{
+ (void) ctx;
+ if((Current->rgb_flag &&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current);
+ }
+
+}
+
+
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ (void) ctx;
+ Current->clearpixel = index;
+}
+
+
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color( GLcontext* ctx, const GLfloat color[4] )
+{
+ GLubyte col[4];
+ (void) ctx;
+ 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 void clear(GLcontext* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ 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_LEFT_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) {
+#if defined(USE_GDI_TO_CLEAR)
+#if defined(DDRAW)
+ // D.R.S. 10/29/01 on my system (Pentium 4 with nvidia GeForce2 MX card,
+ // this is almose 100 times faster that the code below
+ HDC DC=NULL;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=NULL;
+ HBRUSH Old_Brush=NULL;
+ Current->lpDDSOffScreen->lpVtbl->Unlock(Current->lpDDSOffScreen,NULL);
+ Current->lpDDSOffScreen->lpVtbl->GetDC(Current->lpDDSOffScreen,&DC);
+ Old_Pen=SelectObject(DC,Pen);
+ 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);
+ Current->lpDDSOffScreen->lpVtbl->ReleaseDC(Current->lpDDSOffScreen,DC);
+ while (Current->lpDDSOffScreen->lpVtbl->Lock(Current->lpDDSOffScreen,NULL, &(Current->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING);
+
+ mask &= ~DD_BACK_LEFT_BIT;
+#else
+ /* 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+Current->rectSurface.left,Current->rectSurface.top+y,x+width+Current->rectSurface.left,y+height+Current->rectSurface.top);
+
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ mask &= ~DD_BACK_LEFT_BIT;
+#endif // DDRAW
+#else
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ /*LPWORD lpw = (LPWORD)Current->pbPixels; */
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+ /* Double-buffering - clear back buffer */
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+ int mult = 4;
+
+
+ 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);
+ }
+ else 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 == 3){
+ BYTE r, g, b;
+ r = GetRValue(Current->clearpixel);
+ g = GetGValue(Current->clearpixel);
+ b = GetBValue(Current->clearpixel);
+ iSize = Current->width;
+ while (i < iSize) {
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb++ = r;
+ i++;
+ }
+ lpb = Current->pbPixels + Current->ScanWidth;
+ mult = 3;
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+ else
+ dwColor = 0;
+
+ if (nBypp != 3)
+ {
+ /* clear a line */
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ 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*mult);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ mask &= ~DD_BACK_LEFT_BIT;
+#endif // defined(USE_GDI_TO_CLEAR)
+ } /* 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+Current->rectSurface.left,Current->rectSurface.top+y,x+width+Current->rectSurface.left,y+height+Current->rectSurface.top);
+
+ 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 )
+{
+ (void) ctx;
+ 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 void set_buffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+ GLuint bufferBit )
+{
+ (void) ctx; (void) colorBuffer; (void) bufferBit;
+ /* XXX todo - examine bufferBit and set read/write pointers */
+ return;
+}
+
+
+
+/* Return characteristics of the output buffer. */
+static void buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ /*GET_CURRENT_CONTEXT(ctx);*/
+ int New_Size;
+ RECT CR;
+ (void) buffer;
+
+ 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){
+#ifdef DDRAW
+ DDDeleteOffScreen(Current);
+ DDCreateOffScreen(Current);
+#else
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+#endif
+ }
+
+ /* Resize OsmesaBuffer if in Parallel mode */
+#if !defined(NO_PARALLEL)
+ if(parallelFlag)
+ PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
+ Current->rgb_flag == GL_TRUE ? Current->pbPixels:
+ Current->ScreenMem);
+#endif
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+/* Accelerated routines are not implemented in 4.0. See OSMesa for ideas. */
+
+#if 0 /* unused */
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+ (void) ctx; (void) first; (void) last;
+}
+
+#endif /* unused */
+
+/* Return pointer to accelerated points function */
+extern tnl_points_func choose_points_function( GLcontext* ctx )
+{
+ (void) ctx;
+ return NULL;
+}
+
+#if 0 /* unused */
+
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0,
+ GLuint v1, GLuint pv )
+{
+ (void) ctx; (void) v0; (void) v1; (void) pv;
+}
+
+static tnl_line_func choose_line_function( GLcontext* ctx )
+{
+ (void) ctx;
+}
+
+#endif /* unused */
+
+/**********************************************************************/
+/***** 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[] )
+{
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ (void) ctx;
+ 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[])
+{
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ (void) ctx;
+ 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[] )
+{
+ PWMC pwc = Current;
+ (void) ctx;
+
+ 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[] )
+{
+ PWMC pwc = Current;
+ (void) ctx;
+
+ 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[])
+{
+ GLuint i;
+ PWMC pwc = Current;
+ (void) ctx;
+ 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
+ {
+ HDC DC=DD_GETDC;
+ ULONG pixel = RGB( color[RCOMP], color[GCOMP], color[BCOMP] );
+ 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[] )
+{
+ GLuint i;
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ PWMC pwc = Current;
+ /*HDC DC=DD_GETDC;*/
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ PWMC pwc = Current;
+ /*HDC DC=DD_GETDC;*/
+ (void) ctx;
+ 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[])
+{
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ (void) ctx;
+ 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] )
+{
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ (void) ctx;
+ 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[] )
+{
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ (void) ctx;
+ 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 const GLubyte *get_string(GLcontext *ctx, GLenum name)
+{
+ (void) ctx;
+ if (name == GL_RENDERER) {
+ return (GLubyte *) "Mesa Windows";
+ }
+ else {
+ return NULL;
+ }
+}
+
+static void wmesa_update_state( GLcontext *ctx, GLuint new_state );
+
+static void SetFunctionPointers( struct dd_function_table *functions )
+{
+ functions->GetString = get_string;
+ functions->UpdateState = wmesa_update_state;
+ functions->ResizeBuffers = _swrast_alloc_buffers;
+ functions->GetBufferSize = buffer_size;
+
+ functions->Clear = clear;
+
+ functions->Flush = flush;
+ functions->ClearIndex = clear_index;
+ functions->ClearColor = clear_color;
+ functions->Enable = enable;
+}
+
+
+static void SetSWrastPointers(GLcontext *ctx)
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ swdd->SetBuffer = set_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;
+}
+
+
+static void wmesa_update_state( 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.
+ */
+#ifndef SET_FPOINTERS_ONCE
+ SetFunctionPointers(&ctx->Driver);
+ SetSWrastPointers(ctx);
+#if 0
+ ctx->Driver.GetString = get_string;
+ ctx->Driver.UpdateState = wmesa_update_state;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ 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.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+ ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+ ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+ ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+ ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+ ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+
+ 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;
+
+ swdd->SetBuffer = set_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;
+#endif // 0
+#endif // !SET_FPOINTERS_ONCE
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+
+
+
+/**********************************************************************/
+/***** WMesa API Functions *****/
+/**********************************************************************/
+
+#if 0 /* unused */
+
+#define PAL_SIZE 256
+static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
+{
+ int i;
+ HDC hdc;
+ struct
+ {
+ WORD Version;
+ WORD NumberOfEntries;
+ PALETTEENTRY aEntries[PAL_SIZE];
+ } Palette;
+ Palette.Version = 0x300;
+ Palette.NumberOfEntries = PAL_SIZE;
+ hdc=GetDC(NULL);
+ if (Pal!=NULL)
+ GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
+ else
+ GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ for(i = 0; i <PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ Palette.aEntries[255].peRed = 255;
+ Palette.aEntries[255].peGreen = 255;
+ Palette.aEntries[255].peBlue = 255;
+ Palette.aEntries[255].peFlags = 0;
+ Palette.aEntries[0].peRed = 0;
+ Palette.aEntries[0].peGreen = 0;
+ Palette.aEntries[0].peBlue = 0;
+ Palette.aEntries[0].peFlags = 0;
+ }
+ else
+ {
+ int nStaticColors;
+ int nUsableColors;
+ nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
+ for (i=0; i<nStaticColors; i++)
+ Palette.aEntries[i].peFlags = 0;
+ nUsableColors = PAL_SIZE-nStaticColors;
+ for (; i<nUsableColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (; i<PAL_SIZE-nStaticColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = 0;
+ }
+ ReleaseDC(NULL,hdc);
+ for (i=0; i<PAL_SIZE; i++)
+ {
+ aRGB[i].rgbRed=Palette.aEntries[i].peRed;
+ aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
+ aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
+ aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
+ }
+}
+
+#endif /* unused */
+
+WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag,
+ GLboolean alpha_flag )
+{
+ RECT CR;
+ WMesaContext c;
+ GLboolean true_color_flag;
+ struct dd_function_table functions;
+ (void) Pal;
+
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return NULL;
+
+ c->Window=hWnd;
+ c->hDC = GetDC(hWnd);
+ true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8;
+#ifdef DDRAW
+ if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE;
+#endif
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+#ifdef USE_WING
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+#else
+ c->hPalHalfTone = CreateHalftonePalette(c->hDC);
+#endif
+ }
+ 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;
+ }
+ GetClientRect(c->Window,&CR);
+ c->width=CR.right;
+ c->height=CR.bottom;
+ if (db_flag)
+ {
+ c->db_flag = 1;
+ /* Double buffered */
+#ifndef DDRAW
+ {
+ wmCreateBackingStore(c, c->width, c->height);
+
+ }
+#endif
+ }
+ else
+ {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+#ifdef DDRAW
+ if (DDInit(c,hWnd) == GL_FALSE) {
+ free( (void *) c );
+ exit(1);
+ }
+#endif
+
+
+ c->gl_visual = _mesa_create_visual(rgb_flag,
+ db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8, /* r, g, b bits */
+ alpha_flag ? 8 : 0, /* alpha bits */
+ 0, /* index bits */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16,/* accum_bits */
+ alpha_flag ? 16 : 0, /* alpha accum */
+ 1);
+
+ if (!c->gl_visual) {
+ return NULL;
+ }
+
+ _mesa_init_driver_functions(&functions);
+ SetFunctionPointers(&functions);
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = _mesa_create_context( c->gl_visual, NULL,
+ &functions, (void *) c );
+
+ if (!c->gl_ctx) {
+ _mesa_destroy_visual( c->gl_visual );
+ free(c);
+ return NULL;
+ }
+
+ _mesa_enable_sw_extensions(c->gl_ctx);
+ _mesa_enable_1_3_extensions(c->gl_ctx);
+ _mesa_enable_1_4_extensions(c->gl_ctx);
+
+ c->gl_buffer = _mesa_create_framebuffer( c->gl_visual,
+ c->gl_visual->depthBits > 0,
+ c->gl_visual->stencilBits > 0,
+ c->gl_visual->accumRedBits > 0,
+ alpha_flag /* s/w alpha */ );
+ if (!c->gl_buffer) {
+ _mesa_destroy_visual( c->gl_visual );
+ _mesa_free_context_data( c->gl_ctx );
+ free(c);
+ return NULL;
+ }
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ {
+ GLcontext *ctx = c->gl_ctx;
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+
+#ifdef SET_FPOINTERS_ONCE
+ /*SetFunctionPointers(ctx);*/
+ SetSWrastPointers(ctx);
+#endif // SET_FPOINTERS_ONCE
+ _swsetup_Wakeup( ctx );
+ }
+#ifdef COMPILE_SETPIXEL
+ ChooseSetPixel(c);
+#endif
+ return c;
+}
+
+void WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+ ReleaseDC(c->Window,c->hDC);
+ WC = c;
+ if(c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+
+ _swsetup_DestroyContext( c->gl_ctx );
+ _tnl_DestroyContext( c->gl_ctx );
+ _ac_DestroyContext( c->gl_ctx );
+ _swrast_DestroyContext( c->gl_ctx );
+
+ _mesa_destroy_visual( c->gl_visual );
+ _mesa_destroy_framebuffer( c->gl_buffer );
+ _mesa_free_context_data( c->gl_ctx );
+ free( (void *) c->gl_ctx);
+
+ if (c->db_flag)
+#ifdef DDRAW
+ DDFree(c);
+#else
+ wmDeleteBackingStore(c);
+#endif
+ free( (void *) c );
+#if !defined(NO_PARALLEL)
+ if(parallelMachine)
+ PRDestroyRenderBuffer();
+#endif
+
+ // Destroyed context no longer valid
+ WMesaMakeCurrent( NULL );
+}
+
+
+void WMesaMakeCurrent( WMesaContext c )
+{
+ if(!c){
+ Current = c;
+ return;
+ }
+
+ if(Current == c)
+ return;
+
+ Current = c;
+ wmesa_update_state(c->gl_ctx, 0);
+ _mesa_make_current(c->gl_ctx, c->gl_buffer);
+ if (Current->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport to window size */
+ _mesa_Viewport( 0, 0, Current->width, Current->height );
+ Current->gl_ctx->Scissor.Width = Current->width;
+ Current->gl_ctx->Scissor.Height = Current->height;
+ }
+ if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){
+ WMesaPaletteChange(c->hPalHalfTone);
+ }
+}
+
+
+
+void WMesaSwapBuffers( void )
+{
+/* HDC DC = Current->hDC;*/
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (Current && Current->gl_ctx == ctx)
+ _mesa_notifySwapBuffers(ctx);
+
+ if (Current->db_flag)
+ wmFlush(Current);
+}
+
+
+
+void WMesaPaletteChange(HPALETTE Pal)
+{
+#ifndef DDRAW
+ int vRet;
+#endif
+ LPPALETTEENTRY pPal;
+ if (Current && (Current->rgb_flag==GL_FALSE ||
+ Current->dither_flag == GL_TRUE))
+ {
+ pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY));
+ Current->hPal=Pal;
+ GetPaletteEntries( Pal, 0, 256, pPal );
+#ifdef DDRAW
+ Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT,
+ pPal, &(Current->lpDDPal), NULL);
+ if (Current->lpDDPal)
+ Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,
+ Current->lpDDPal);
+#else
+ vRet = SetDIBColorTable(Current->dib.hDC, 0, 256, (RGBQUAD*)pPal);
+#endif
+ free( pPal );
+ }
+}
+
+
+
+
+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
+};
+
+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 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);
+
+}
+
+
+void
+#ifdef COMPILE_SETPIXEL
+
+wmSetPixelDefault(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if (Current->db_flag)
+ {
+#ifdef DDRAW
+ HDC hdc = NULL;
+ Current->lpDDSOffScreen->lpVtbl->Unlock(Current->lpDDSOffScreen,NULL);
+ Current->lpDDSOffScreen->lpVtbl->GetDC(Current->lpDDSOffScreen,&hdc);
+ SetPixelV(hdc,iPixel, iScanLine, RGB(r,g,b));
+ Current->lpDDSOffScreen->lpVtbl->ReleaseDC(Current->lpDDSOffScreen,hdc);
+ while (Current->lpDDSOffScreen->lpVtbl->Lock(Current->lpDDSOffScreen,NULL, &(Current->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING);
+#else
+ SetPixelV(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+#endif
+ }
+ else
+ {
+ SetPixelV(Current->hDC, iPixel+pwc->rectSurface.left, pwc->rectSurface.top+iScanLine, RGB(r,g,b));
+ }
+}
+#else
+wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if (Current->db_flag)
+ {
+ LPBYTE lpb = pwc->pbPixels;
+ UINT nBypp = pwc->cColorBits >> 3;
+
+ 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)
+ {
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb = r;
+ }
+ else if (nBypp == 4)
+ *((LPDWORD)lpb) = BGR32(r,g,b);
+ }
+ else
+ {
+ SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+ }
+}
+#endif
+#ifdef COMPILE_SETPIXEL
+void wmSetPixel4(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ LPDWORD lpdw = ((LPDWORD)(pwc->pbPixels + pwc->ScanWidth * iScanLine)) + iPixel;
+ *lpdw = BGR32(r,g,b);
+// LPBYTE lpb = pwc->pbPixels + pwc->ScanWidth * iScanLine + iPixel + iPixel + iPixel + iPixel;
+// *((LPDWORD)lpb) = BGR32(r,g,b);
+}
+
+void wmSetPixel3(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ LPBYTE lpb = pwc->pbPixels + pwc->ScanWidth * iScanLine + iPixel + iPixel + iPixel;
+ *lpb++ = b;
+ *lpb++ = g;
+ *lpb = r;
+}
+
+void wmSetPixel2(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ LPWORD lpw = ((LPWORD)(pwc->pbPixels + pwc->ScanWidth * iScanLine)) + iPixel;
+ *lpw = BGR16(r,g,b);
+// LPBYTE lpb = pwc->pbPixels + pwc->ScanWidth * iScanLine + iPixel + iPixel;
+// *((LPWORD)lpb) = BGR16(r,g,b);
+}
+
+void wmSetPixel1(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ LPBYTE lpb = pwc->pbPixels + pwc->ScanWidth * iScanLine + iPixel;
+ *lpb = BGR8(r,g,b);
+}
+
+void wmSetPixel1Dither(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ LPBYTE lpb = pwc->pbPixels + pwc->ScanWidth * iScanLine + iPixel;
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+}
+
+
+void ChooseSetPixel(PWMC pwc)
+{
+ UINT nBypp = (pwc ) ? pwc->cColorBits >> 3 : 0;
+ switch(nBypp)
+ {
+ case 1:
+ pwc->wmSetPixel = pwc->dither_flag ? &wmSetPixel1Dither : &wmSetPixel1;
+ break;
+ case 2:
+ pwc->wmSetPixel = &wmSetPixel2;
+ break;
+ case 3:
+ pwc->wmSetPixel = &wmSetPixel3;
+ break;
+ case 4:
+ pwc->wmSetPixel = &wmSetPixel4;
+ break;
+ default:
+ pwc->wmSetPixel = &wmSetPixelDefault;
+ break;
+ }
+}
+
+#endif
+
+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;
+ (void) hDC;
+ (void) pbmi;
+
+ 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);
+#ifdef USE_MAPPED_FILE
+ 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));
+#endif // USE_MAPPED_FILE
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+#ifdef USE_MAPPED_FILE
+
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ (void **)&(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+#else
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ (void **)&(pwc->pbPixels),
+ 0,
+ 0);
+#endif // USE_MAPPED_FILE
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+/*
+ * Blit memory DC to screen DC
+ */
+BOOL wmFlush(PWMC pwc)
+{
+ BOOL bRet = 0;
+/* DWORD dwErr = 0;*/
+#ifdef DDRAW
+ HRESULT ddrval;
+#endif
+
+ if(pwc->db_flag){
+#ifdef DDRAW
+ if (pwc->lpDDSOffScreen == NULL)
+ if(DDCreateOffScreen(pwc) == GL_FALSE)
+ return FALSE;
+
+ pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL);
+
+ while( 1 )
+ {
+ ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary,
+ &(pwc->rectSurface),
+ pwc->lpDDSOffScreen,
+ &(pwc->rectOffScreen),
+ 0, NULL );
+
+ if( ddrval == DD_OK )
+ {
+ break;
+ }
+ if( ddrval == DDERR_SURFACELOST )
+ {
+ if(!DDRestoreAll(pwc))
+ {
+ break;
+ }
+ }
+ if( ddrval != DDERR_WASSTILLDRAWING )
+ {
+ break;
+ }
+ }
+
+ while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen,
+ NULL, &(pwc->ddsd), 0, NULL) ==
+ DDERR_WASSTILLDRAWING)
+ ;
+
+ if(ddrval != DD_OK)
+ dwErr = GetLastError();
+#else
+ bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+#endif
+ }
+
+ return(TRUE);
+
+}
+
+
+/* The following code is added by Li Wei to enable stereo display */
+
+#if !defined(NO_STEREO)
+
+static void __gluMakeIdentityf(GLfloat m[16])
+{
+ m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
+ m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
+ m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
+ m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
+}
+
+static void normalize(float v[3])
+{
+ float r;
+
+ r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
+ if (r == 0.0) return;
+
+ v[0] /= r;
+ v[1] /= r;
+ v[2] /= r;
+}
+
+static void cross(float v1[3], float v2[3], float result[3])
+{
+ result[0] = v1[1]*v2[2] - v1[2]*v2[1];
+ result[1] = v1[2]*v2[0] - v1[0]*v2[2];
+ result[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+
+static void
+__gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
+ GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
+ GLdouble upz)
+{
+ int i;
+ float forward[3], side[3], up[3];
+ GLfloat m[4][4];
+
+ forward[0] = centerx - eyex;
+ forward[1] = centery - eyey;
+ forward[2] = centerz - eyez;
+
+ up[0] = upx;
+ up[1] = upy;
+ up[2] = upz;
+
+ normalize(forward);
+
+ /* Side = forward x up */
+ cross(forward, up, side);
+ normalize(side);
+
+ /* Recompute up as: up = side x forward */
+ cross(side, forward, up);
+
+ __gluMakeIdentityf(&m[0][0]);
+ m[0][0] = side[0];
+ m[1][0] = side[1];
+ m[2][0] = side[2];
+
+ m[0][1] = up[0];
+ m[1][1] = up[1];
+ m[2][1] = up[2];
+
+ m[0][2] = -forward[0];
+ m[1][2] = -forward[1];
+ m[2][2] = -forward[2];
+
+ glMultMatrixf(&m[0][0]);
+ glTranslated(-eyex, -eyey, -eyez);
+}
+
+GLfloat viewDistance = 1.0;
+
+void WMesaShowStereo(GLuint list)
+{
+
+ GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ GLfloat cm[16];
+ GLint matrix_mode;
+ /* Must use double Buffer */
+ if( ! Current-> db_flag )
+ return;
+
+
+ glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
+
+ WMesaViewport(Current->gl_ctx,0,Current->height/2,
+ Current->width,Current->height/2);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(GL_MODELVIEW);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ __gluLookAt(viewDistance/2,0.0,0.0 ,
+ viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ glMultMatrixf( cm );
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen;
+ glCallList( list );
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ __gluLookAt(-viewDistance/2,0.0,0.0 ,
+ -viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ glMultMatrixf(cm);
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch;
+ glCallList(list);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(matrix_mode);
+
+ glFlush();
+
+ WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height);
+ WMesaSwapBuffers();
+}
+
+void toggleStereoMode()
+{
+ if(!Current->db_flag)
+ return;
+ if(!stereo_flag){
+ stereo_flag = 1;
+ if(stereoBuffer==GL_FALSE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ {
+ Current->ScanWidth = Current->pitch*2;
+ }
+ }
+ else {
+ stereo_flag = 0;
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ Current->ScanWidth = Current->pitch;
+ Current->pbPixels = Current->addrOffScreen;
+ }
+}
+
+/* if in stereo mode, the following function is called */
+void glShowStereo(GLuint list)
+{
+ WMesaShowStereo(list);
+}
+
+#endif /* NO_STEREO */
+
+#if !defined(NO_PARALLEL)
+
+void toggleParallelMode(void)
+{
+ if(!parallelFlag){
+ parallelFlag = GL_TRUE;
+ if(parallelMachine==GL_FALSE){
+ PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
+ Current->cColorBits/8,
+ Current->width ,Current->height,
+ Current->ScanWidth,
+ Current->rgb_flag? Current->pbPixels:
+ Current->ScreenMem);
+ parallelMachine = GL_TRUE;
+ }
+ }
+ else {
+ parallelFlag = GL_FALSE;
+ if(parallelMachine==GL_TRUE){
+ PRDestroyRenderBuffer();
+ parallelMachine=GL_FALSE;
+ ReadyForNextFrame = GL_TRUE;
+ }
+
+ /***********************************************
+ * Seems something wrong!!!!
+ ************************************************/
+
+ WMesaMakeCurrent(Current);
+#if !defined(NO_STEREO)
+ stereo_flag = GL_FALSE ;
+#endif
+ }
+}
+
+void PRShowRenderResult(void)
+{
+ int flag = 0;
+ if(!glImageRendered())
+ return;
+
+ if (parallelFlag)
+ {
+ WMesaSwapBuffers();
+ }
+
+}
+#endif /* NO_PARALLEL */
+
+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];
+}
+
+#ifdef DDRAW
+/*
+ * restoreAll
+ *
+ * restore all lost objects
+ */
+HRESULT DDRestoreAll( WMesaContext wc )
+{
+ HRESULT ddrval;
+
+ ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary);
+ if( ddrval == DD_OK )
+ {
+ ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen);
+ }
+ return ddrval;
+
+} /* restoreAll */
+
+
+/*
+ * This function is called if the initialization function fails
+ */
+BOOL initFail( HWND hwnd, WMesaContext wc )
+{
+ DDFree(wc);
+ MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK );
+ return FALSE;
+
+} /* initFail */
+
+
+static void DDDeleteOffScreen(WMesaContext wc)
+{
+ if( wc->lpDDSOffScreen != NULL )
+ {
+ wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL);
+ wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen);
+ wc->lpDDSOffScreen = NULL;
+ }
+
+}
+
+static void DDFreePrimarySurface(WMesaContext wc)
+{
+ if( wc->lpDDSPrimary != NULL )
+ {
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC);
+ wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary);
+ wc->lpDDSPrimary = NULL;
+ }
+}
+
+static BOOL DDCreatePrimarySurface(WMesaContext wc)
+{
+ HRESULT ddrval;
+// DDSCAPS ddscaps;
+ wc->ddsd.dwSize = sizeof( wc->ddsd );
+ wc->ddsd.dwFlags = DDSD_CAPS;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd),
+ &(wc->lpDDSPrimary), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(wc->hwnd , wc);
+ }
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, &(wc->hDC));
+ return TRUE;
+}
+
+static BOOL DDCreateOffScreen(WMesaContext wc)
+{
+ POINT pt;
+ HRESULT ddrval;
+ if(wc->lpDD == NULL)
+ return FALSE;
+ GetClientRect( wc->hwnd, &(wc->rectOffScreen) );
+ wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top;
+ wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd),
+ &(wc->lpDDSOffScreen), NULL );
+ if( ddrval != DD_OK )
+ {
+ return FALSE;
+ }
+
+ while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL,
+ &(wc->ddsd), 0, NULL) ==
+ DDERR_WASSTILLDRAWING)
+ ;
+
+ if(wc->ddsd.lpSurface==NULL)
+ return initFail(wc->hwnd, wc);
+
+ wc->ScreenMem = wc->pbPixels = wc->addrOffScreen =
+ (PBYTE)(wc->ddsd.lpSurface);
+ wc->ScanWidth = wc->pitch = wc->ddsd.lPitch;
+ if (stereo_flag)
+ wc->ScanWidth = wc->ddsd.lPitch*2;
+
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ wmSetPixelFormat(wc, wc->hDC);
+ return TRUE;
+}
+
+typedef
+struct tagWMesaContextList
+{
+ WMesaContext wc;
+ struct tagWMesaContextList *next;
+}WMesaContextList;
+
+WMesaContextList *head = 0;
+
+void AddContext(WMesaContext wc)
+{
+ WMesaContextList *lst = (WMesaContextList *)malloc(sizeof(WMesaContextList));
+ lst->wc = wc;
+ if( head )
+ lst->next = head;
+ head = lst;
+}
+
+WMesaContext FindContext(HWND hWnd)
+{
+ WMesaContextList *tmp = head;
+ while(tmp)
+ {
+ if( tmp->wc->hwnd == hWnd )
+ return tmp->wc;
+ tmp = tmp->next;
+ }
+ return NULL;
+}
+
+void RemoveContext(HWND hWnd)
+{
+ WMesaContextList *tmp = head;
+ if(tmp )
+ {
+ if( tmp->wc->hwnd == hWnd )
+ {
+ WMesaContextList *lst = tmp;
+
+ head = tmp->next;
+ free((void *)lst);
+ }
+ else
+ while(tmp->next)
+ {
+ if( tmp->next->wc->hwnd == hWnd )
+ {
+ WMesaContextList *lst = tmp->next;
+ tmp->next = tmp->next->next;
+ free((void *)lst);
+ }
+ tmp = tmp->next;
+ }
+ }
+}
+
+static LRESULT CALLBACK MyWndProc(HWND hwnd,UINT message,WPARAM wParam, LPARAM lParam)
+{
+ WMesaContext wc;
+
+ if (Current==0 || Current->hwnd != hwnd)
+ wc=FindContext(hwnd);
+ else
+ wc=Current;
+
+
+ if( wc )
+ {
+ LRESULT lret = CallWindowProc((WNDPROC)(wc->oldWndProc),hwnd,message,wParam,lParam);
+ if( message = WM_MOVE )
+ {
+ POINT pt = {0};
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ ClientToScreen( hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ }
+ return lret;
+ }
+ return 0L;
+}
+
+/*
+ * doInit - do work required for every instance of the application:
+ * create the window, initialize data
+ */
+static BOOL DDInit( WMesaContext wc, HWND hwnd)
+{
+ HRESULT ddrval;
+// DWORD dwFrequency;
+
+// LPDIRECTDRAW lpDD; // DirectDraw object
+// LPDIRECTDRAW2 lpDD2;
+ LPDIRECTDRAWCLIPPER pcClipper = NULL;
+
+ wc->fullScreen = displayOptions.fullScreen;
+ wc->gMode = displayOptions.mode;
+ wc->hwnd = hwnd;
+ stereo_flag = displayOptions.stereo;
+ if(wc->db_flag!= GL_TRUE)
+ stereo_flag = GL_FALSE;
+ /*
+ * create the main DirectDraw object
+ */
+ ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd,wc);
+ }
+
+ // Get exclusive mode if requested
+ if(wc->fullScreen)
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd,
+ DDSCL_EXCLUSIVE |
+ DDSCL_FULLSCREEN );
+ }
+ else
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd,
+ DDSCL_NORMAL );
+ }
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd , wc);
+ }
+
+
+ if(ddrval != DD_OK)
+ return initFail(hwnd , wc);
+
+
+ switch( wc->gMode )
+ {
+ case 1:
+ ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480,
+ displayOptions.bpp);
+ break;
+ case 2:
+ ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600,
+ displayOptions.bpp);
+ break;
+ case 3:
+ ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768,
+ displayOptions.bpp);
+ break;
+ case 4:
+ ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864,
+ displayOptions.bpp);
+ break;
+ case 5:
+ ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024,
+ displayOptions.bpp);
+ break;
+ }
+
+ if( ddrval != DD_OK )
+ {
+ printf("Can't modify display mode, current mode used\n");
+ }
+ switch(ddrval){
+ case DDERR_INVALIDOBJECT:
+ break;
+ case DDERR_INVALIDPARAMS:
+ break;
+ case DDERR_UNSUPPORTEDMODE:
+ ;
+ }
+
+ if(DDCreatePrimarySurface(wc) == GL_FALSE)
+ return initFail(hwnd, wc);
+
+ if(wc->db_flag)
+ DDCreateOffScreen(wc);
+
+ if( FAILED( ddrval = wc->lpDD->lpVtbl->CreateClipper(wc->lpDD, 0, &pcClipper, NULL ) ) )
+ return E_FAIL;
+
+ if( FAILED( ddrval = pcClipper->lpVtbl->SetHWnd(pcClipper, 0, wc->hwnd ) ) )
+ {
+ pcClipper->lpVtbl->Release(pcClipper);
+ return E_FAIL;
+ }
+
+ if( FAILED( ddrval = wc->lpDDSPrimary->lpVtbl->SetClipper(wc->lpDDSPrimary, pcClipper ) ) )
+ {
+ pcClipper->lpVtbl->Release(pcClipper);
+ return E_FAIL;
+ }
+
+ // Done with clipper
+ pcClipper->lpVtbl->Release(pcClipper);
+ AddContext(wc);
+ // Hook the window so we can update the drawing rectangle when the window moves
+ wc->oldWndProc = SetWindowLong(wc->hwnd,GWL_WNDPROC,(LONG)MyWndProc);
+
+ return TRUE;
+
+} /* DDInit */
+
+static void DDFree( WMesaContext wc)
+{
+ RemoveContext(wc->hwnd);
+ SetWindowLong(wc->hwnd,GWL_WNDPROC,(LONG)(wc->oldWndProc));
+ wc->oldWndProc = 0;
+ if( wc->lpDD != NULL )
+ {
+ DDFreePrimarySurface(wc);
+ DDDeleteOffScreen(wc);
+ wc->lpDD->lpVtbl->Release(wc->lpDD);
+ wc->lpDD = NULL;
+ }
+ // Clean up the screen on exit
+ RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
+ RDW_ALLCHILDREN );
+
+}
+#endif
+
+void WMesaMove(void)
+{
+ WMesaContext wc = Current;
+ POINT pt;
+ if (Current != NULL){
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ }
+}
+
+
+/************************************************
+ * Mesa 4.0 - These triangle rasterizers are not
+ * implemented in this version of the Windows
+ * driver. They could be implemented for a
+ * potential performance improvement.
+ * See OSMesa for an example of the approach
+ * to use.
+ * This old code is left in this file in case
+ * it is useful. However, it may end up looking
+ * a lot more like the OSMesa code.
+ ************************************************/
+
+
+#if defined(FAST_RASTERIZERS)
+
+
+/*
+ * Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+ * shortcut.
+ */
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+/**********************************************************************/
+/*** Triangle rendering ***/
+/**********************************************************************/
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = FixedToInt(ffi); \
+ zRow[i] = z; \
+ } \
+ ffi += fdidx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->IndexPtr->data[pv]; \
+ (*ctx->Driver.Index)( ctx, index );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = index; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = FixedToInt(ffi); \
+ ffi += fdidx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->IndexPtr->data[pv]; \
+ (*ctx->Driver.Index)( ctx, index );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = index; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+*/
+static void smooth_DITHER8_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb), xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy);\
+ *pixel = pixelDithered; \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+
+static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy); \
+ *pixel = pixelDithered; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+// #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+#endif
+/************** END DEAD TRIANGLE CODE ***********************/
+
+#if 0 /* unused */
+
+static tnl_triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ (void) ctx;
+#if 0
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ int depth = wmesa->cColorBits;
+
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Texture._EnabledUnits) return NULL;
+ if (!wmesa->db_flag) return NULL;
+ if (ctx->swrast->_RasterMask & MULTI_DRAW_BIT) return NULL;
+
+ /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ {
+ if ( ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return smooth_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->Light.ShadeModel==GL_FLAT
+ && ctx->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return flat_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->_RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_triangle;
+ case PF_INDEX8:
+ return smooth_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ if ( ctx->_RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_FLAT
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_triangle;
+ case PF_INDEX8:
+ return flat_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ return NULL;
+ }
+#endif
+}
+
+#endif /* unused */
+
+/*
+ * Define a new viewport and reallocate auxillary buffers if the size of
+ * the window (color buffer) has changed.
+ */
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ (void) ctx; (void) x; (void) y; (void) width; (void) height;
+ assert(0); /* I don't think that this is being used. */
+#if 0
+ /* Save viewport */
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+
+ /* compute scale and bias values */
+/* Pre-Keith 3.1 changes
+ ctx->Viewport.Map.m[Sx] = (GLfloat) width / 2.0F;
+ ctx->Viewport.Map.m[Tx] = ctx->Viewport.Sx + x;
+ ctx->Viewport.Map.m[Sy] = (GLfloat) height / 2.0F;
+ ctx->Viewport.Map.m[Ty] = ctx->Viewport.Sy + y;
+*/
+ ctx->Viewport.WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TX] = ctx->Viewport.WindowMap.m[MAT_SX] + x;
+ ctx->Viewport.WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TY] = ctx->Viewport.WindowMap.m[MAT_SY] + y;
+#endif
+}
diff --git a/src/mesa/drivers/windows/gdi/wmesadef.h b/src/mesa/drivers/windows/gdi/wmesadef.h
new file mode 100644
index 0000000..3c267aa
--- /dev/null
+++ b/src/mesa/drivers/windows/gdi/wmesadef.h
@@ -0,0 +1,175 @@
+/* File name : wmesadef.h
+ * Version : 2.3
+ *
+ * Header file for display driver for Mesa 2.3 under
+ * Windows95, WindowsNT and Win32
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * 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
+ * (mark@rsinc.com).
+ */
+
+/*
+ * $Log: wmesadef.h,v
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jt
+ * Imported source
+
+ * Revision 1.3 1999/01/03 03:08:57 brian
+ * Ted Jump's change
+ *
+ * Initial version 1997/6/14 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ */
+
+/*
+ * $Log: wmesadef.h,v
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jt
+ * Imported source
+
+ * Revision 1.3 1999/01/03 03:08:57 brian
+ * Ted Jump's change
+ *
+ * Revision 2.1 1996/11/15 10:54:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * a new element added to wmesa_context :
+ * dither_flag
+ */
+
+/*
+ * $Log: wmesadef.h,v
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jt
+ * Imported source
+
+ * Revision 1.3 1999/01/03 03:08:57 brian
+ * Ted Jump's change
+ *
+ * Revision 2.0 1996/11/15 10:54:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Initial revision
+ */
+
+
+
+#ifndef DDMESADEF_H
+#define DDMESADEF_H
+
+// uncomment this to use DirectDraw driver
+//#define DDRAW 1
+// uncomment this to use a pointer to a function for setting the pixels
+// in the buffer
+#define COMPILE_SETPIXEL 1
+// uncomment this to enable the fast win32 rasterizers ( commented out for MesaGL 4.0 )
+// #define FAST_RASTERIZERS 1
+// uncomment this to enable setting function pointers once inside of
+// WMesaCreateContext instead of on every call to wmesa_update_state()
+#define SET_FPOINTERS_ONCE 1
+
+
+#include <windows.h>
+#include <GL\gl.h>
+#include "context.h"
+#ifdef DDRAW
+#define DIRECTDRAW_VERSION 0x0100
+ #include <ddraw.h>
+#endif
+//#include "profile.h"
+
+#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;
+
+#ifdef COMPILE_SETPIXEL
+struct wmesa_context;
+typedef void (*SETPIXELTYPE)(struct wmesa_context *pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+#endif
+
+typedef struct wmesa_context{
+ GLcontext *gl_ctx; /* The core GL/Mesa context */
+ GLvisual *gl_visual; /* Describes the buffers */
+ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
+
+
+ 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;
+
+#ifdef DDRAW
+ LPDIRECTDRAW lpDD; // DirectDraw object
+// LPDIRECTDRAW2 lpDD2; // DirectDraw object
+ LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary surface
+ LPDIRECTDRAWSURFACE lpDDSOffScreen; // DirectDraw off screen surface
+ LPDIRECTDRAWPALETTE lpDDPal; // DirectDraw palette
+ BOOL bActive; // is application active?
+ DDSURFACEDESC ddsd; // surface description
+ int fullScreen; // fullscreen ?
+ int gMode ; // fullscreen mode
+ LONG oldWndProc; // old Window proc. we need to hook WM_MOVE message to update the drawing rectangle
+#endif
+ RECT rectOffScreen;
+ RECT rectSurface;
+ HWND hwnd;
+ DWORD pitch;
+ PBYTE addrOffScreen;
+#ifdef COMPILE_SETPIXEL
+ SETPIXELTYPE wmSetPixel;
+#endif // COMPILE_SETPIXEL
+//#ifdef PROFILE
+// MESAPROF profile;
+//#endif
+} *PWMC;
+
+
+#define PAGE_FILE 0xffffffff
+
+
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/ddlog.c b/src/mesa/drivers/windows/gldirect/ddlog.c
new file mode 100644
index 0000000..4ae79e2
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/ddlog.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#define STRICT
+#include <windows.h>
+
+#include "ddlog.h"
+#include "gld_driver.h"
+
+// ***********************************************************************
+
+static char ddlogbuf[256];
+static FILE* fpDDLog = NULL; // Log file pointer
+static char szDDLogName[_MAX_PATH] = {"gldirect.log"}; // Filename of the log
+static DDLOG_loggingMethodType ddlogLoggingMethod = DDLOG_NONE; // Default to No Logging
+static DDLOG_severityType ddlogDebugLevel;
+static BOOL bUIWarning = FALSE; // MessageBox warning ?
+
+// ***********************************************************************
+
+void ddlogOpen(
+ DDLOG_loggingMethodType LoggingMethod,
+ DDLOG_severityType Severity)
+{
+ if (fpDDLog != NULL) {
+ // Tried to re-open the log
+ ddlogMessage(DDLOG_WARN, "Tried to re-open the log file\n");
+ return;
+ }
+
+ ddlogLoggingMethod = LoggingMethod;
+ ddlogDebugLevel = Severity;
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fpDDLog = fopen(szDDLogName, "wt");
+ if (fpDDLog == NULL)
+ return;
+ }
+
+ ddlogMessage(DDLOG_SYSTEM, "\n");
+ ddlogMessage(DDLOG_SYSTEM, "-> Logging Started\n");
+}
+
+// ***********************************************************************
+
+void ddlogClose()
+{
+ // Determine whether the log is already closed
+ if (fpDDLog == NULL && ddlogLoggingMethod == DDLOG_NORMAL)
+ return; // Nothing to do.
+
+ ddlogMessage(DDLOG_SYSTEM, "<- Logging Ended\n");
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+}
+
+// ***********************************************************************
+
+void ddlogMessage(
+ DDLOG_severityType severity,
+ LPSTR message)
+{
+ char buf[256];
+
+ // Bail if logging is disabled
+ if (ddlogLoggingMethod == DDLOG_NONE)
+ return;
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF)
+ fpDDLog = fopen(szDDLogName, "at");
+
+ if (fpDDLog == NULL)
+ return;
+
+ if (severity >= ddlogDebugLevel) {
+ sprintf(buf, "DDLog: (%s) %s", ddlogSeverityMessages[severity], message);
+ fputs(buf, fpDDLog); // Write string to file
+ OutputDebugString(buf); // Echo to debugger
+ }
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF) {
+ fflush(fpDDLog); // Write info to disk
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+
+ // Popup message box if critical error
+ if (bUIWarning && severity == DDLOG_CRITICAL) {
+ MessageBox(NULL, buf, "GLDirect", MB_OK | MB_ICONWARNING | MB_TASKMODAL);
+ }
+}
+
+// ***********************************************************************
+
+// Write a string value to the log file
+void ddlogError(
+ DDLOG_severityType severity,
+ LPSTR message,
+ HRESULT hResult)
+{
+#ifdef _USE_GLD3_WGL
+ char dxErrStr[1024];
+ _gldDriver.GetDXErrorString(hResult, &dxErrStr[0], sizeof(dxErrStr));
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, dxErrStr);
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#else
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, DDErrorToString(hResult));
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#endif
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogPrintf(
+ DDLOG_severityType severity,
+ LPSTR message,
+ ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ vsprintf(ddlogbuf, message, args);
+ va_end(args);
+
+ lstrcat(ddlogbuf, "\n");
+
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogWarnOption(
+ BOOL bWarnOption)
+{
+ bUIWarning = bWarnOption;
+}
+
+// ***********************************************************************
+
+void ddlogPathOption(
+ LPSTR szPath)
+{
+ char szPathName[_MAX_PATH];
+
+ strcpy(szPathName, szPath);
+ strcat(szPathName, "\\");
+ strcat(szPathName, szDDLogName);
+ strcpy(szDDLogName, szPathName);
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/ddlog.h b/src/mesa/drivers/windows/gldirect/ddlog.h
new file mode 100644
index 0000000..d64067e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/ddlog.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#ifndef __DDLOG_H
+#define __DDLOG_H
+
+#include <stdio.h>
+
+#ifndef _USE_GLD3_WGL
+#include "dderrstr.h" // ddraw/d3d error string
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DDLOG_NONE = 0, // No log output
+ DDLOG_NORMAL = 1, // Log is kept open
+ DDLOG_CRASHPROOF = 2, // Log is closed and flushed
+ DDLOG_METHOD_FORCE_DWORD = 0x7fffffff,
+} DDLOG_loggingMethodType;
+
+// Denotes type of message sent to the logging functions
+typedef enum {
+ DDLOG_INFO = 0, // Information only
+ DDLOG_WARN = 1, // Warning only
+ DDLOG_ERROR = 2, // Notify user of an error
+ DDLOG_CRITICAL = 3, // Exceptionally severe error
+ DDLOG_SYSTEM = 4, // System message. Not an error
+ // but must always be printed.
+ DDLOG_SEVERITY_FORCE_DWORD = 0x7fffffff, // Make enum dword
+} DDLOG_severityType;
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define GLDLOG_INFO DDLOG_INFO
+#define GLDLOG_WARN DDLOG_WARN
+#define GLDLOG_ERROR DDLOG_ERROR
+#define GLDLOG_CRITICAL DDLOG_CRITICAL
+#define GLDLOG_SYSTEM DDLOG_SYSTEM
+#endif
+
+// The message that will be output to the log
+static const char *ddlogSeverityMessages[] = {
+ "INFO",
+ "WARN",
+ "ERROR",
+ "*CRITICAL*",
+ "System",
+};
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ddlogOpen(DDLOG_loggingMethodType LoggingMethod, DDLOG_severityType Severity);
+void ddlogClose();
+void ddlogMessage(DDLOG_severityType severity, LPSTR message);
+void ddlogError(DDLOG_severityType severity, LPSTR message, HRESULT hResult);
+void ddlogPrintf(DDLOG_severityType severity, LPSTR message, ...);
+void ddlogWarnOption(BOOL bWarnOption);
+void ddlogPathOption(LPSTR szPath);
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define gldLogMessage ddlogMessage
+#define gldLogError ddlogError
+#define gldLogPrintf ddlogPrintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c
new file mode 100644
index 0000000..c504be5
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -0,0 +1,2213 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Context handling.
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+
+// Get compile errors without this. KeithH
+#include "scitech.h" // ibool, etc.
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+#endif // _USE_GLD3_WGL
+
+// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
+// if it is no longer being built as part of GLDirect. (DaveM)
+
+// ***********************************************************************
+
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+
+char szResourceWarning[] =
+"GLDirect does not have enough video memory resources\n"
+"to support the requested OpenGL rendering context.\n\n"
+"You may have to reduce the current display resolution\n"
+"to obtain satisfactory OpenGL performance.\n";
+
+char szDDrawWarning[] =
+"GLDirect is unable to initialize DirectDraw for the\n"
+"requested OpenGL rendering context.\n\n"
+"You will have to check the DirectX control panel\n"
+"for further information.\n";
+
+char szD3DWarning[] =
+"GLDirect is unable to initialize Direct3D for the\n"
+"requested OpenGL rendering context.\n\n"
+"You may have to change the display mode resolution\n"
+"color depth or check the DirectX control panel for\n"
+"further information.\n";
+
+char szBPPWarning[] =
+"GLDirect is unable to use the selected color depth for\n"
+"the requested OpenGL rendering context.\n\n"
+"You will have to change the display mode resolution\n"
+"color depth with the Display Settings control panel.\n";
+
+int nContextError = GLDERR_NONE;
+
+// ***********************************************************************
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+extern DWORD dwLogging;
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
+CRITICAL_SECTION CriticalSection; // for serialized access
+DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context
+DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format
+#endif
+HGLRC iCurrentContext = 0; // Index of current context (static)
+BOOL bContextReady = FALSE; // Context state ready ?
+
+DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list
+
+// ***********************************************************************
+
+static BOOL bHaveWin95 = FALSE;
+static BOOL bHaveWinNT = FALSE;
+static BOOL bHaveWin2K = FALSE;
+
+/****************************************************************************
+REMARKS:
+Detect the installed OS type.
+****************************************************************************/
+static void DetectOS(void)
+{
+ OSVERSIONINFO VersionInformation;
+ LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
+
+ VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
+
+ GetVersionEx(lpVersionInformation);
+
+ switch (VersionInformation.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ bHaveWin95 = TRUE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ bHaveWin95 = FALSE;
+ if (VersionInformation.dwMajorVersion <= 4) {
+ bHaveWinNT = TRUE;
+ bHaveWin2K = FALSE;
+ }
+ else {
+ bHaveWinNT = FALSE;
+ bHaveWin2K = TRUE;
+ }
+ break;
+ case VER_PLATFORM_WIN32s:
+ bHaveWin95 = FALSE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ }
+}
+
+// ***********************************************************************
+
+HWND hWndEvent = NULL; // event monitor window
+HWND hWndLastActive = NULL; // last active client window
+LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
+
+// ***********************************************************************
+
+// Checks if the HGLRC is valid in range of context list.
+BOOL dglIsValidContext(
+ HGLRC a)
+{
+ return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
+}
+
+// ***********************************************************************
+
+// Convert a HGLRC to a pointer into the context list.
+DGL_ctx* dglGetContextAddress(
+ const HGLRC a)
+{
+ if (dglIsValidContext(a))
+ return &ctxlist[(int)a-1];
+ return NULL;
+}
+
+// ***********************************************************************
+
+// Return the current HGLRC (however it may be stored for multi-threading).
+HGLRC dglGetCurrentContext(void)
+{
+#ifdef GLD_THREADS
+ HGLRC hGLRC;
+ // load from thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ hGLRC = iCurrentContext;
+ }
+ }
+ // load from global static var
+ else {
+ hGLRC = iCurrentContext;
+ }
+ return hGLRC;
+#else
+ return iCurrentContext;
+#endif
+}
+
+// ***********************************************************************
+
+// Set the current HGLRC (however it may be stored for multi-threading).
+void dglSetCurrentContext(HGLRC hGLRC)
+{
+#ifdef GLD_THREADS
+ // store in thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iCurrentContext = hGLRC;
+ }
+ }
+ // store in global static var
+ else {
+ iCurrentContext = hGLRC;
+ }
+#else
+ iCurrentContext = hGLRC;
+#endif
+}
+
+// ***********************************************************************
+
+// Return the current HDC only for a currently active HGLRC.
+HDC dglGetCurrentDC(void)
+{
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+
+ hGLRC = dglGetCurrentContext();
+ if (hGLRC) {
+ lpCtx = dglGetContextAddress(hGLRC);
+ return lpCtx->hDC;
+ }
+ return 0;
+}
+
+// ***********************************************************************
+
+void dglInitContextState()
+{
+ int i;
+ WNDCLASS wc;
+
+#ifdef GLD_THREADS
+ // Allocate thread local storage indexes for current context and pixel format
+ dwTLSCurrentContext = TlsAlloc();
+ dwTLSPixelFormat = TlsAlloc();
+#endif
+
+ dglSetCurrentContext(NULL); // No current rendering context
+
+ // Clear all context data
+ ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++)
+ ctxlist[i].bAllocated = FALSE; // Flag context as unused
+
+ // This section of code crashes the dll in circumstances where the app
+ // creates and destroys contexts.
+/*
+ // Register the class for our event monitor window
+ wc.style = 0;
+ wc.lpfnWndProc = GLD_EventWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "GLDIRECT";
+ RegisterClass(&wc);
+
+ // Create the non-visible window to monitor all broadcast messages
+ hWndEvent = CreateWindowEx(
+ WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
+ 0,0,0,0,
+ NULL,NULL,GetModuleHandle(NULL),NULL);
+*/
+
+#ifdef GLD_THREADS
+ // Create a critical section object for serializing access to
+ // DirectDraw and DDStereo create/destroy functions in multiple threads
+ if (glb.bMultiThreaded)
+ InitializeCriticalSection(&CriticalSection);
+#endif
+
+ // Context state is now initialized and ready
+ bContextReady = TRUE;
+}
+
+// ***********************************************************************
+
+void dglDeleteContextState()
+{
+ int i;
+ static BOOL bOnceIsEnough = FALSE;
+
+ // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
+ if (bOnceIsEnough)
+ return;
+ bOnceIsEnough = TRUE;
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated == TRUE) {
+ ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ }
+
+ // Context state is no longer ready
+ bContextReady = FALSE;
+
+ // If executed when DLL unloads, DDraw objects may be invalid.
+ // So catch any page faults with this exception handler.
+__try {
+
+ // Release final DirectDraw interfaces
+ if (glb.bDirectDrawPersistant) {
+// RELEASE(glb.lpGlobalPalette);
+// RELEASE(glb.lpDepth4);
+// RELEASE(glb.lpBack4);
+// RELEASE(glb.lpPrimary4);
+// RELEASE(glb.lpDD4);
+ }
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
+}
+
+ // Destroy our event monitor window
+ if (hWndEvent) {
+ DestroyWindow(hWndEvent);
+ hWndEvent = hWndLastActive = NULL;
+ }
+
+#ifdef GLD_THREADS
+ // Destroy the critical section object
+ if (glb.bMultiThreaded)
+ DeleteCriticalSection(&CriticalSection);
+
+ // Release thread local storage indexes for current HGLRC and pixel format
+ TlsFree(dwTLSPixelFormat);
+ TlsFree(dwTLSCurrentContext);
+#endif
+}
+
+// ***********************************************************************
+
+// Application Window message handler interception
+static LONG __stdcall dglWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DGL_ctx* lpCtx = NULL;
+ LONG lpfnWndProc = 0L;
+ int i;
+ HGLRC hGLRC;
+ RECT rect;
+ PAINTSTRUCT ps;
+ BOOL bQuit = FALSE;
+ BOOL bMain = FALSE;
+ LONG rc;
+
+ // Get the window's message handler *before* it is unhooked in WM_DESTROY
+
+ // Is this the main window?
+ if (hwnd == glb.hWndActive) {
+ bMain = TRUE;
+ lpfnWndProc = glb.lpfnWndProc;
+ }
+ // Search for DGL context matching window handle
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].hWnd == hwnd) {
+ lpCtx = &ctxlist[i];
+ lpfnWndProc = lpCtx->lpfnWndProc;
+ break;
+ }
+ }
+ // Not one of ours...
+ if (!lpfnWndProc)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ // Intercept messages amd process *before* passing on to window
+ switch (msg) {
+#ifdef _USE_GLD3_WGL
+ case WM_DISPLAYCHANGE:
+ glb.bPixelformatsDirty = TRUE;
+ break;
+#endif
+ case WM_ACTIVATEAPP:
+ glb.bAppActive = (BOOL)wParam;
+ ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
+ break;
+ case WM_ERASEBKGND:
+ // Eat the GDI erase event for the GL window
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ lpCtx->bGDIEraseBkgnd = TRUE;
+ return TRUE;
+ case WM_PAINT:
+ // Eat the invalidated update region if render scene is in progress
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ if (lpCtx->bFrameStarted) {
+ if (GetUpdateRect(hwnd, &rect, FALSE)) {
+ BeginPaint(hwnd, &ps);
+ EndPaint(hwnd, &ps);
+ ValidateRect(hwnd, &rect);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ // Call the appropriate window message handler
+ rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
+
+ // Intercept messages and process *after* passing on to window
+ switch (msg) {
+ case WM_QUIT:
+ case WM_DESTROY:
+ bQuit = TRUE;
+ if (lpCtx && lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ break;
+#if 0
+ case WM_SIZE:
+ // Resize surfaces to fit window but not viewport (in case app did not bother)
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ w = LOWORD(lParam);
+ h = HIWORD(lParam);
+ if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
+ if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
+ dglWglResizeBuffers(lpCtx->glCtx, FALSE);
+ }
+ break;
+#endif
+ }
+
+ // If the main window is quitting, then so should we...
+ if (bMain && bQuit) {
+ ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
+ dglDeleteContextState();
+ dglExitDriver();
+ }
+
+ return rc;
+}
+
+// ***********************************************************************
+
+// Driver Window message handler
+static LONG __stdcall GLD_EventWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (msg) {
+ // May be sent by splash screen dialog on exit
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
+ SetForegroundWindow(glb.hWndActive);
+ return 0;
+ }
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+// ***********************************************************************
+
+// Intercepted Keyboard handler for detecting hot keys.
+LRESULT CALLBACK dglKeyProc(
+ int code,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hWnd, hWndFrame;
+ HGLRC hGLRC = NULL;
+ DGL_ctx* lpCtx = NULL;
+ int cmd = 0, dx1 = 0, dx2 = 0, i;
+ static ibool bAltPressed = false;
+ static ibool bCtrlPressed = false;
+ static ibool bShiftPressed = false;
+ RECT r, rf, rc;
+ POINT pt;
+ ibool bForceReshape = false;
+
+ return CallNextHookEx(hKeyHook, code, wParam, lParam);
+}
+
+// ***********************************************************************
+
+HWND hWndMatch;
+
+// Window handle enumeration procedure.
+BOOL CALLBACK dglEnumChildProc(
+ HWND hWnd,
+ LPARAM lParam)
+{
+ RECT rect;
+
+ // Find window handle with matching client rect.
+ GetClientRect(hWnd, &rect);
+ if (EqualRect(&rect, (RECT*)lParam)) {
+ hWndMatch = hWnd;
+ return FALSE;
+ }
+ // Continue with next child window.
+ return TRUE;
+}
+
+// ***********************************************************************
+
+// Find window handle with matching client rect.
+HWND dglFindWindowRect(
+ RECT* pRect)
+{
+ hWndMatch = NULL;
+ EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
+ return hWndMatch;
+}
+
+// ***********************************************************************
+#ifndef _USE_GLD3_WGL
+void dglChooseDisplayMode(
+ DGL_ctx *lpCtx)
+{
+ // Note: Choose an exact match if possible.
+
+ int i;
+ DWORD area;
+ DWORD bestarea;
+ DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer
+ DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best
+
+ lpDDSD = glb.lpDisplayModes;
+ for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
+ if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight == lpCtx->dwHeight))
+ goto matched; // Mode has been exactly matched
+ // Choose modes that are larger in both dimensions than
+ // the window, but smaller in area than the current best.
+ if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight >= lpCtx->dwHeight))
+ {
+ if (lpBestDDSD == NULL) {
+ lpBestDDSD = lpDDSD;
+ bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ continue;
+ }
+ area = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ if (area < bestarea) {
+ lpBestDDSD = lpDDSD;
+ bestarea = area;
+ }
+ }
+ }
+
+ // Safety check
+ if (lpBestDDSD == NULL) {
+ ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
+ return;
+ }
+
+ lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
+ lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
+matched:
+ ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
+ lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
+}
+#endif // _USE_GLD3_WGL
+// ***********************************************************************
+
+static BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+void dglTestForBrokenCards(
+ DGL_ctx *lpCtx)
+{
+#ifndef _GLD3
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+
+ // Sanity check.
+ if (lpCtx == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
+ return;
+ }
+
+ if (lpCtx->lpDD4 == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
+ return;
+ }
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
+ return;
+
+ // Useful info. Log it.
+ ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
+
+ // Vendor 1: ATI
+ if (dddi.dwVendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
+ glb.bUseMipmaps = FALSE;
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
+ glb.bEmulateAlphaTest = TRUE;
+ }
+
+ // Vendor 2: Matrox
+ if (dddi.dwVendorId == 0x102B) {
+ // Test: Matrox G400 stencil buffer support does not work for AutoCAD
+ if (dddi.dwDeviceId == 0x0525) {
+ lpCtx->lpPF->pfd.cStencilBits = 0;
+ if (lpCtx->lpPF->iZBufferPF != -1) {
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
+ }
+ }
+ }
+#endif // _GLD3
+}
+
+// ***********************************************************************
+
+BOOL dglCreateContextBuffers(
+ HDC a,
+ DGL_ctx *lpCtx,
+ BOOL bFallback)
+{
+ HRESULT hResult;
+
+ int i;
+// HGLRC hGLRC;
+// DGL_ctx* lpCtx;
+
+#ifndef _USE_GLD3_WGL
+ DWORD dwFlags;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description
+ D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer
+#endif // _USE_GLD3_WGL
+
+ float inv_aspect;
+
+ GLenum bDoubleBuffer; // TRUE if double buffer required
+ GLenum bDepthBuffer; // TRUE if depth buffer required
+
+ const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd;
+
+ // Vars for Mesa visual
+ DWORD dwDepthBits = 0;
+ DWORD dwStencilBits = 0;
+ DWORD dwAlphaBits = 0;
+ DWORD bAlphaSW = GL_FALSE;
+ DWORD bDouble = GL_FALSE;
+
+ DDSURFACEDESC2 ddsd2DisplayMode;
+ BOOL bFullScrnWin = FALSE; // fullscreen-size window ?
+ DDBLTFX ddbltfx;
+ DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
+ BOOL bBogusWindow = FALSE; // non-drawable window ?
+ DWORD dwColorRef = 0; // GDI background color
+ RECT rcDst; // GDI window rect
+ POINT pt; // GDI window point
+
+ // Palette used for creating default global palette
+ PALETTEENTRY ppe[256];
+
+#ifndef _USE_GLD3_WGL
+ // Vertex buffer description. Used for creation of vertex buffers
+ D3DVERTEXBUFFERDESC vbufdesc;
+#endif // _USE_GLD3_WGL
+
+#define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
+ nContextError = GLDERR_NONE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw object creation or DDS start
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check for back buffer
+ bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+ // Since we always do back buffering, check if we emulate front buffering
+ lpCtx->EmulateSingle =
+ (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+#if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
+ lpCtx->EmulateSingle |=
+ (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
+#endif
+
+ // Check for depth buffer
+ bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
+
+ lpCtx->bDoubleBuffer = bDoubleBuffer;
+ lpCtx->bDepthBuffer = bDepthBuffer;
+
+ // Set the Fullscreen flag for the context.
+// lpCtx->bFullscreen = glb.bFullscreen;
+
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
+ // Check for non-window DC = memory DC ?
+ if (lpCtx->hWnd == NULL) {
+ // bitmap memory contexts are always single-buffered
+ lpCtx->EmulateSingle = TRUE;
+ bBogusWindow = TRUE;
+ ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
+ if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ bBogusWindow = TRUE;
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
+ lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
+
+ ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
+ lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // What if app only zeroes one dimension instead of both? (DaveM)
+ if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
+ // Make the buffer size something sensible
+ lpCtx->dwWidth = 8;
+ lpCtx->dwHeight = 8;
+ }
+
+ // Set defaults
+ lpCtx->dwModeWidth = lpCtx->dwWidth;
+ lpCtx->dwModeHeight = lpCtx->dwHeight;
+/*
+ // Find best display mode for fullscreen
+ if (glb.bFullscreen || !glb.bPrimary) {
+ dglChooseDisplayMode(lpCtx);
+ }
+*/
+ // Misc initialisation
+ lpCtx->bCanRender = FALSE; // No rendering allowed yet
+ lpCtx->bSceneStarted = FALSE;
+ lpCtx->bFrameStarted = FALSE;
+
+ // Detect OS (specifically 'Windows 2000' or 'Windows XP')
+ DetectOS();
+
+ // NOTE: WinNT not supported
+ ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
+
+ // Test for Fullscreen
+ if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
+ if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
+ (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
+ {
+ // Workaround for some apps that crash when going fullscreen.
+ //lpCtx->bFullscreen = TRUE;
+ }
+
+ }
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
+#else
+ // Check if DirectDraw has already been created by original GLRC (DaveM)
+ if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
+ lpCtx->lpDD4 = glb.lpDD4;
+ IDirectDraw4_AddRef(lpCtx->lpDD4);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create DirectDraw object
+ if (glb.bPrimary)
+ hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
+ else {
+ // A non-primary device is to be used.
+ // Force context to be Fullscreen, secondary adaptors can not
+ // be used in a window.
+ hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
+ lpCtx->bFullscreen = TRUE;
+ }
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpCtx->lpDD4);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Cache DirectDraw interface for subsequent GLRCs
+ if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
+ glb.lpDD4 = lpCtx->lpDD4;
+ IDirectDraw4_AddRef(glb.lpDD4);
+ glb.bDirectDraw = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Now we have a DD4 interface we can check for broken cards
+ dglTestForBrokenCards(lpCtx);
+
+ // Test if primary device can use flipping instead of blitting
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ lpCtx->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ // We have a fullscreen-size window
+ bFullScrnWin = TRUE;
+ // OK to use DirectDraw fullscreen mode ?
+ if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
+ lpCtx->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
+ }
+ }
+ // Cache the display mode dimensions
+ lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
+ lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
+ lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
+
+ // Check for non-RGB desktop resolution
+ if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
+ ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
+ ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
+ nContextError = GLDERR_BPP;
+ goto return_with_error;
+ }
+#endif // _USE_GLD3_WGL
+
+ ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
+ lpCtx->dwWidth,
+ lpCtx->dwHeight,
+ lpCtx->bFullscreen ? "fullscreen" : "windowed");
+
+#ifndef _USE_GLD3_WGL
+ // Obtain ddraw caps
+ ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
+ lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
+ if (glb.bHardware) {
+ // Get HAL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
+ } else {
+ // Get HEL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
+ }
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_INFO,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ // Query for DX6 Direct3D3 interface
+ hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpCtx->lpD3D3);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Context creation
+ if (lpCtx->bFullscreen) {
+ // FULLSCREEN
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release persistant primary surface if fullscreen mode
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
+ lpCtx->dwModeWidth,
+ lpCtx->dwModeHeight,
+ lpPFD->cColorBits,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
+ goto return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ lpCtx->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
+ lpCtx->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
+ goto return_with_error;
+ }
+ // Has Primary surface already been created for original GLRC ?
+ // Note this can only be applicable for windowed modes
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ lpCtx->lpFront4 = glb.lpPrimary4;
+ IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
+ // Update the window on the default clipper
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+ goto SkipPrimaryCreate;
+ }
+
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Cache Primary surface for subsequent GLRCs
+ // Note this can only be applicable to subsequent windowed modes
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = lpCtx->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
+ goto return_with_error;
+ }
+SkipPrimaryCreate:
+
+ if (bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+ // Re-use original back buffer if persistant buffers exist
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
+ IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
+ } else {
+ lpCtx->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Z-buffer
+ //
+ lpCtx->bStencil = FALSE; // Default to no stencil buffer
+ if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Create a z-buffer
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
+ IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
+ else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ lpCtx->lpDepth4),
+ "dglCreateContext: Attach Zbuffer");
+ if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
+ lpCtx->bStencil = TRUE;
+ ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
+ }
+ }
+
+ // Clear all back buffers and Z-buffers in case of memory recycling.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+ if (lpCtx->lpDepth4)
+ IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+
+ // Now that we have a Z-buffer we can create the 3D device
+ hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
+ &glb.d3dGuid,
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ &lpCtx->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(lpCtx);
+
+ // Obtain the D3D Device Description
+ D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
+ TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
+ &D3DHWDevDesc,
+ &D3DHELDevDesc),
+ "dglCreateContext: GetCaps failed");
+
+ // Choose the relevant description and cache it in the context.
+ // We will use this description later for caps checking
+ memcpy( &lpCtx->D3DDevDesc,
+ glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
+ sizeof(D3DDEVICEDESC));
+
+ // Now we can examine the texture formats
+ if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
+ goto return_with_error;
+ }
+
+ // Get the pixel format of the back buffer
+ lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
+ if (bDoubleBuffer)
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpBack4,
+ &lpCtx->ddpfRender);
+ else
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpFront4,
+ &lpCtx->ddpfRender);
+
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
+ goto return_with_error;
+ }
+ // Find a pixel packing function suitable for this surface
+ pxClassifyPixelFormat(&lpCtx->ddpfRender,
+ &lpCtx->fnPackFunc,
+ &lpCtx->fnUnpackFunc,
+ &lpCtx->fnPackSpanFunc);
+
+ // Viewport
+ hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ // Initialise the viewport
+ // Note screen coordinates are used for viewport clipping since D3D
+ // transform operations are not used in the GLD CAD driver. (DaveM)
+ inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
+
+ lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
+ lpCtx->d3dViewport.dwX = 0;
+ lpCtx->d3dViewport.dwY = 0;
+ lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
+ lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
+ lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
+ lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
+ lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
+ lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
+ lpCtx->d3dViewport.dvMinZ = 0.0f;
+ lpCtx->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ lpCtx->dwBPP = lpPFD->cColorBits;
+ lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
+
+ // Set last texture to NULL
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ lpCtx->ColorOp[i] = D3DTOP_DISABLE;
+ lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
+ lpCtx->tObj[i] = NULL;
+ }
+
+ // Default to perspective correct texture mapping
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
+
+ // Set the default culling mode
+ lpCtx->cullmode = D3DCULL_NONE;
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
+
+ // Disable specular
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
+ // Disable subpixel correction
+// dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
+ // Disable dithering
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
+
+ // Initialise the primitive caches
+// lpCtx->dwNextLineVert = 0;
+// lpCtx->dwNextTriVert = 0;
+
+ // Init the global texture palette
+ lpCtx->lpGlobalPalette = NULL;
+
+ // Init the HW/SW usage counters
+// lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
+
+ //
+ // Create two D3D vertex buffers.
+ // One will hold the pre-transformed data with the other one
+ // being used to hold the post-transformed & clipped verts.
+ //
+#if 0 // never used (DaveM)
+ vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
+ vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+ if (glb.bHardware == FALSE)
+ vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vbufdesc.dwNumVertices = 32768; // For the time being
+
+ // Source vertex buffer
+ vbufdesc.dwFVF = DGL_LVERTEX;
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
+ goto return_with_error;
+ }
+
+ // Destination vertex buffer
+ vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
+ if(FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
+ goto return_with_error;
+ }
+#endif
+
+#endif _USE_GLD3_WGL
+
+ //
+ // Now create the Mesa context
+ //
+
+ // Create the Mesa visual
+ if (lpPFD->cDepthBits)
+ dwDepthBits = 16;
+ if (lpPFD->cStencilBits)
+ dwStencilBits = 8;
+ if (lpPFD->cAlphaBits) {
+ dwAlphaBits = 8;
+ bAlphaSW = GL_TRUE;
+ }
+ if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
+ bDouble = GL_TRUE;
+// lpCtx->EmulateSingle =
+// (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glVis = _mesa_create_visual(
+ GL_TRUE, // RGB mode
+ bDouble, /* double buffer */
+ GL_FALSE, // stereo
+ lpPFD->cRedBits,
+ lpPFD->cGreenBits,
+ lpPFD->cBlueBits,
+ dwAlphaBits,
+ 0, // index bits
+ dwDepthBits,
+ dwStencilBits,
+ lpPFD->cAccumRedBits, // accum bits
+ lpPFD->cAccumGreenBits, // accum bits
+ lpPFD->cAccumBlueBits, // accum bits
+ lpPFD->cAccumAlphaBits, // accum alpha bits
+ 1 // num samples
+ );
+#else // _USE_GLD3_WGL
+ lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
+ GL_TRUE, // RGB mode
+ bAlphaSW, // Is an alpha buffer required?
+ bDouble, // Is an double-buffering required?
+ GL_FALSE, // stereo
+ dwDepthBits, // depth_size
+ dwStencilBits, // stencil_size
+ lpPFD->cAccumBits, // accum_size
+ 0, // colour-index bits
+ lpPFD->cRedBits, // Red bit count
+ lpPFD->cGreenBits, // Green bit count
+ lpPFD->cBlueBits, // Blue bit count
+ dwAlphaBits // Alpha bit count
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glVis == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+#else
+ // Create the Mesa context
+ lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
+ lpCtx->glVis, // Mesa visual
+ NULL, // share list context
+ (void *)lpCtx, // Pointer to our driver context
+ GL_TRUE // Direct context flag
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glCtx == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
+ goto return_with_error;
+ }
+
+ // Create the Mesa framebuffer
+#ifdef _USE_GLD3_WGL
+ lpCtx->glBuffer = _mesa_create_framebuffer(
+ lpCtx->glVis,
+ lpCtx->glVis->depthBits > 0,
+ lpCtx->glVis->stencilBits > 0,
+ lpCtx->glVis->accumRedBits > 0,
+ GL_FALSE //swalpha
+ );
+#else
+ lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glBuffer == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Init Mesa internals
+ _swrast_CreateContext( lpCtx->glCtx );
+ _ac_CreateContext( lpCtx->glCtx );
+ _tnl_CreateContext( lpCtx->glCtx );
+ _swsetup_CreateContext( lpCtx->glCtx );
+
+ _gldDriver.InitialiseMesa(lpCtx);
+
+ lpCtx->glCtx->imports.warning = _gld_mesa_warning;
+ lpCtx->glCtx->imports.fatal = _gld_mesa_fatal;
+
+#else
+ // Tell Mesa how many texture stages we have
+ glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
+ // Only use as many Units as the spec requires
+ if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
+ glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
+ lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
+ ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures);
+
+ // Set the max texture size.
+ // NOTE: clamped to a max of 1024 for extra performance!
+ lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
+
+// Texture resize takes place elsewhere. KH
+// NOTE: This was added to workaround an issue with the Intel app.
+#if 0
+ lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
+#else
+ lpCtx->glCtx->Const.MaxTextureSize = 1024;
+#endif
+
+ // Setup the Display Driver pointers
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Initialise all the Direct3D renderstates
+ dglInitStateD3D(lpCtx->glCtx);
+
+#if 0
+ // Signal a reload of texture state on next glBegin
+ lpCtx->m_texHandleValid = FALSE;
+ lpCtx->m_mtex = FALSE;
+ lpCtx->m_texturing = FALSE;
+#else
+ // Set default texture unit state
+// dglSetTexture(lpCtx, 0, NULL);
+// dglSetTexture(lpCtx, 1, NULL);
+#endif
+
+ //
+ // Set the global texture palette to default values.
+ //
+
+ // Clear the entire palette
+ ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
+
+ // Fill the palette with a default colour.
+ // A garish colour is used to catch bugs. Here Magenta is used.
+ for (i=0; i < 256; i++) {
+ ppe[i].peRed = 255;
+ ppe[i].peGreen = 0;
+ ppe[i].peBlue = 255;
+ }
+
+ RELEASE(lpCtx->lpGlobalPalette);
+
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
+ hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
+ else
+ hResult = IDirectDraw4_CreatePalette(
+ lpCtx->lpDD4,
+ DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ ppe,
+ &(lpCtx->lpGlobalPalette),
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
+ lpCtx->lpGlobalPalette = NULL;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
+ IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
+
+#endif // _USE_GLD3_WGL
+
+ // ** If we have made it to here then we can enable rendering **
+ lpCtx->bCanRender = TRUE;
+
+// ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+
+return_with_error:
+ // Clean up before returning.
+ // This is critical for secondary devices.
+
+ lpCtx->bCanRender = FALSE;
+
+#ifdef _USE_GLD3_WGL
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ // Destroy driver data
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
+ RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
+
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ RELEASE(lpCtx->lpBack4);
+ RELEASE(lpCtx->lpFront4);
+ else
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ RELEASE(lpCtx->lpD3D3);
+ RELEASE(lpCtx->lpDD4);
+ RELEASE(lpCtx->lpDD1);
+#endif // _USE_GLD3_WGL
+
+ lpCtx->bAllocated = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+
+#undef DDLOG_CRITICAL_OR_WARN
+}
+
+// ***********************************************************************
+
+HGLRC dglCreateContext(
+ HDC a,
+ const DGL_pixelFormat *lpPF)
+{
+ int i;
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+ static BOOL bWarnOnce = TRUE;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char szMsg[256];
+ HWND hWnd;
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return NULL;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
+
+ // Find next free context.
+ // Also ensure that only one Fullscreen context is created at any one time.
+ hGLRC = 0; // Default to Not Found
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated) {
+ if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
+ break;
+ } else {
+ hGLRC = (HGLRC)(i+1);
+ break;
+ }
+ }
+
+ // Bail if no GLRC was found
+ if (!hGLRC)
+ return NULL;
+
+ // Set the context pointer
+ lpCtx = dglGetContextAddress(hGLRC);
+ // Make sure that context is zeroed before we do anything.
+ // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
+ // even though only one context is ever used by the app, so keep it clean. (DaveM)
+ ZeroMemory(lpCtx, sizeof(DGL_ctx));
+ lpCtx->bAllocated = TRUE;
+ // Flag that buffers need creating on next wglMakeCurrent call.
+ lpCtx->bHasBeenCurrent = FALSE;
+ lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
+ lpCtx->bCanRender = FALSE;
+
+ // Create all the internal resources here, not in dglMakeCurrent().
+ // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
+ // We now try context allocations twice, first with video memory,
+ // then again with system memory. This is similar to technique
+ // used for dglWglResizeBuffers(). (DaveM)
+ if (lpCtx->bHasBeenCurrent == FALSE) {
+ if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
+ if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
+ bWarnOnce = FALSE;
+ switch (nContextError) {
+ case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
+ case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
+ case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
+ case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
+ default: strcpy(szMsg, "");
+ }
+ if (strlen(szMsg))
+ MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ // Only need to try again if memory error
+ if (nContextError == GLDERR_MEM) {
+ ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
+ }
+ else {
+ ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
+ return NULL;
+ }
+ }
+ }
+
+ // Now that we have a hWnd, we can intercept the WindowProc.
+ hWnd = lpCtx->hWnd;
+ if (hWnd) {
+ // Only hook individual window handler once if not hooked before.
+ lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
+ if (lpfnWndProc != (LONG)dglWndProc) {
+ lpCtx->lpfnWndProc = lpfnWndProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ // Find the parent window of the app too.
+ if (glb.hWndActive == NULL) {
+ while (hWnd != NULL) {
+ glb.hWndActive = hWnd;
+ hWnd = GetParent(hWnd);
+ }
+ // Hook the parent window too.
+ lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
+ if (glb.hWndActive == lpCtx->hWnd)
+ glb.lpfnWndProc = lpCtx->lpfnWndProc;
+ else if (lpfnWndProc != (LONG)dglWndProc)
+ glb.lpfnWndProc = lpfnWndProc;
+ if (glb.lpfnWndProc)
+ SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
+
+ return hGLRC;
+}
+
+// ***********************************************************************
+// Make a DirectGL context current
+// Used by wgl functions and dgl functions
+BOOL dglMakeCurrent(
+ HDC a,
+ HGLRC b)
+{
+ int context;
+ DGL_ctx* lpCtx;
+ HWND hWnd;
+ BOOL bNeedResize = FALSE;
+ BOOL bWindowChanged, bContextChanged;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ DWORD dwThreadId = GetCurrentThreadId();
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ context = (int)b; // This is as a result of STRICT!
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
+
+ // If the HGLRC is NULL then make no context current;
+ // Ditto if the HDC is NULL either. (DaveM)
+ if (context == 0 || a == 0) {
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(NULL, NULL);
+#else
+ (*mesaFuncs.gl_make_current)(NULL, NULL);
+#endif
+ dglSetCurrentContext(0);
+ return TRUE;
+ }
+
+ // Make sure the HGLRC is in range
+ if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Find address of context and make sure that it has been allocated
+ lpCtx = dglGetContextAddress(b);
+ if (!lpCtx->bAllocated) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check if window has changed
+ hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
+ bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
+ bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
+
+ // If the window has changed, make sure the clipper is updated. (DaveM)
+ if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
+ lpCtx->hWnd = hWnd;
+#ifndef _USE_GLD3_WGL
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+#endif // _USE_GLD3_WGL
+ }
+
+ // Make sure hDC and hWnd is current. (DaveM)
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = hWnd;
+ hWndLastActive = hWnd;
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ // Check if buffers need to be re-sized;
+ // If so, wait until Mesa GL stuff is setup before re-sizing;
+ if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
+ lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
+ bNeedResize = TRUE;
+
+ // Now we can update our globals
+ dglSetCurrentContext(b);
+
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#else
+ (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
+
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Insure DirectDraw surfaces fit current window DC
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#endif // _USE_GLD3_WGL
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // We have to clear D3D back buffer and render state if emulated front buffering
+ // for different window (but not context) like in Solid Edge.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
+ && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
+#ifdef _USE_GLD3_WGL
+// IDirect3DDevice8_EndScene(lpCtx->pDev);
+// lpCtx->bSceneStarted = FALSE;
+ lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ }
+
+ // The first time we call MakeCurrent we set the initial viewport size
+ if (lpCtx->bHasBeenCurrent == FALSE)
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ lpCtx->bHasBeenCurrent = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglDeleteContext(
+ HGLRC a)
+{
+ DGL_ctx* lpCtx;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char argstr[256];
+
+#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
+
+ // Make sure the HGLRC is in range
+ if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Make sure context is valid
+ lpCtx = dglGetContextAddress(a);
+ if (!lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+ // Make sure context is de-activated
+ if (a == dglGetCurrentContext()) {
+ ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
+ dglMakeCurrent(NULL, NULL);
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // We are about to destroy all Direct3D objects.
+ // Therefore we must disable rendering
+ lpCtx->bCanRender = FALSE;
+
+ // This exception handler was installed to catch some
+ // particularly nasty apps. Console apps that call exit()
+ // fall into this catagory (i.e. Win32 Glut).
+
+ // VC cannot successfully implement multiple exception handlers
+ // if more than one exception occurs. Therefore reverting back to
+ // single exception handler as Keith originally had it. (DaveM)
+
+#define WARN_MESSAGE(p) strcpy(argstr, (#p));
+#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
+
+__try {
+#ifdef _USE_GLD3_WGL
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
+ SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
+
+ // Delete the global palette
+ SAFE_RELEASE(lpCtx->lpGlobalPalette);
+
+ // Clean up.
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ SAFE_RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ SAFE_RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ SAFE_RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ SAFE_RELEASE(lpCtx->lpBack4);
+ SAFE_RELEASE(lpCtx->lpFront4);
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ SAFE_RELEASE(lpCtx->lpD3D3);
+ SAFE_RELEASE(lpCtx->lpDD4);
+ SAFE_RELEASE(lpCtx->lpDD1);
+#endif // _ULSE_GLD3_WGL
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
+}
+
+ // Restore the window message handler because this context may be used
+ // again by another window with a *different* message handler. (DaveM)
+ if (lpCtx->lpfnWndProc) {
+ SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
+ lpCtx->lpfnWndProc = (LONG)NULL;
+ }
+
+ lpCtx->bAllocated = FALSE; // This context is now free for use
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglSwapBuffers(
+ HDC hDC)
+{
+ RECT rSrcRect; // Source rectangle
+ RECT rDstRect; // Destination rectangle
+ POINT pt;
+ HRESULT hResult;
+
+ DDBLTFX bltFX;
+ DWORD dwBlitFlags;
+ DDBLTFX *lpBltFX;
+
+// DWORD dwThreadId = GetCurrentThreadId();
+ HGLRC hGLRC = dglGetCurrentContext();
+ DGL_ctx *lpCtx = dglGetContextAddress(hGLRC);
+ HWND hWnd;
+
+ HDC hDCAux; // for memory DC
+ int x,y,w,h; // for memory DC BitBlt
+
+#if 0 // Perhaps not a good idea. Called too often. KH
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ if (!lpCtx) {
+ return TRUE; //FALSE; // No current context
+ }
+
+ if (!lpCtx->bCanRender) {
+ // Don't return false else some apps will bail.
+ return TRUE;
+ }
+
+ hWnd = lpCtx->hWnd;
+ if (hDC != lpCtx->hDC) {
+ ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
+ hWnd = WindowFromDC(hDC);
+ }
+
+#ifndef _USE_GLD3_WGL
+ // Ensure that the surfaces exist before we tell
+ // the device to render to them.
+ IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
+
+ // Make sure that the vertex caches have been emptied
+// dglStateChange(lpCtx);
+
+ // Some OpenGL programs don't issue a glFinish - check for it here.
+ if (lpCtx->bSceneStarted) {
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ }
+#endif
+
+#if 0
+ // If the calling app is not active then we don't need to Blit/Flip.
+ // We can therefore simply return TRUE.
+ if (!glb.bAppActive)
+ return TRUE;
+ // Addendum: This is WRONG! We should bail if the app is *minimized*,
+ // not merely if the app is just plain 'not active'.
+ // KeithH, 27/May/2000.
+#endif
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(hDC, &rSrcRect) == ERROR)
+ return TRUE;
+ // Use GDI BitBlt instead from compatible DirectDraw DC
+ x = rSrcRect.left;
+ y = rSrcRect.top;
+ w = rSrcRect.right - rSrcRect.left;
+ h = rSrcRect.bottom - rSrcRect.top;
+
+ // Ack. DX8 does not have a GetDC() function...
+ // TODO: Defer to DX7 or DX9 drivers... (DaveM)
+ return TRUE;
+ }
+
+ // Bail if window client region is not drawable, like in Solid Edge
+ if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
+ return TRUE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifdef _USE_GLD3_WGL
+ // Notify Mesa of impending swap, so Mesa can flush internal buffers.
+ _mesa_notifySwapBuffers(lpCtx->glCtx);
+ // Now perform driver buffer swap
+ _gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
+#else
+ if (lpCtx->bFullscreen) {
+ // Sync with retrace if required
+ if (glb.bWaitForRetrace) {
+ IDirectDraw4_WaitForVerticalBlank(
+ lpCtx->lpDD4,
+ DDWAITVB_BLOCKBEGIN,
+ 0);
+ }
+
+ // Perform the fullscreen flip
+ TRY(IDirectDrawSurface4_Flip(
+ lpCtx->lpFront4,
+ NULL,
+ DDFLIP_WAIT),
+ "dglSwapBuffers: Flip");
+ } else {
+ // Calculate current window position and size
+ pt.x = pt.y = 0;
+ ClientToScreen(hWnd, &pt);
+ GetClientRect(hWnd, &rDstRect);
+ if (rDstRect.right > lpCtx->dwModeWidth)
+ rDstRect.right = lpCtx->dwModeWidth;
+ if (rDstRect.bottom > lpCtx->dwModeHeight)
+ rDstRect.bottom = lpCtx->dwModeHeight;
+ OffsetRect(&rDstRect, pt.x, pt.y);
+ rSrcRect.left = rSrcRect.top = 0;
+ rSrcRect.right = lpCtx->dwWidth;
+ rSrcRect.bottom = lpCtx->dwHeight;
+ if (rSrcRect.right > lpCtx->dwModeWidth)
+ rSrcRect.right = lpCtx->dwModeWidth;
+ if (rSrcRect.bottom > lpCtx->dwModeHeight)
+ rSrcRect.bottom = lpCtx->dwModeHeight;
+
+ if (glb.bWaitForRetrace) {
+ // Sync the blit to the vertical retrace
+ ZeroMemory(&bltFX, sizeof(bltFX));
+ bltFX.dwSize = sizeof(bltFX);
+ bltFX.dwDDFX = DDBLTFX_NOTEARING;
+ dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
+ lpBltFX = &bltFX;
+ } else {
+ dwBlitFlags = DDBLT_WAIT;
+ lpBltFX = NULL;
+ }
+
+ // Perform the actual blit
+ TRY(IDirectDrawSurface4_Blt(
+ lpCtx->lpFront4,
+ &rDstRect,
+ lpCtx->lpBack4, // Blit source
+ &rSrcRect,
+ dwBlitFlags,
+ lpBltFX),
+ "dglSwapBuffers: Blt");
+ }
+#endif // _USE_GLD3_WGL
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
+
+ // Render frame is completed
+ ValidateRect(hWnd, NULL);
+ lpCtx->bFrameStarted = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.h b/src/mesa/drivers/windows/gldirect/dglcontext.h
new file mode 100644
index 0000000..5c433b8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: OpenGL context handling.
+*
+****************************************************************************/
+
+#ifndef __DGLCONTEXT_H
+#define __DGLCONTEXT_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <GL\gl.h>
+
+#ifdef _USE_GLD3_WGL
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "context.h" // Mesa context
+#else
+ #include <ddraw.h>
+ #include <d3d.h>
+
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "d3dvertex.h"
+
+ #include "DirectGL.h"
+
+ #include "context.h" // Mesa context
+ #include "vb.h" // Mesa vertex buffer
+#endif // _USE_GLD3_WGL
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+// TODO: Use a list instead of this constant!
+#define DGL_MAX_CONTEXTS 32
+
+// Structure for describing an OpenGL context
+#ifdef _USE_GLD3_WGL
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+
+ // Pointer to private driver data (this also contains the drawable).
+ void *glPriv;
+
+ // Mesa vars:
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+
+ // Shared driver vars:
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+ BOOL bStencil; // TRUE if this context has stencil
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+} DGL_ctx;
+
+#define GLD_context DGL_ctx
+#define GLD_GET_CONTEXT(c) (GLD_context*)(c)->DriverCtx
+
+#else // _USE_GLD3_WGL
+
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+ //
+ // Mesa context vars:
+ //
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+ int iZBufferPF; // Index of Zbuffer pixel format
+
+ // Vertex buffer: one-to-one correlation with Mesa's vertex buffer.
+ // This will be filled by our setup function (see d3dvsetup.c)
+ DGL_TLvertex gWin[VB_SIZE]; // Transformed and lit vertices
+// DGL_Lvertex gObj[VB_SIZE]; // Lit vertices in object coordinates.
+
+ // Indices for DrawIndexedPrimitive.
+ // Clipped quads are drawn seperately, so use VB_SIZE.
+ // 6 indices are needed to make 2 triangles for each possible quad
+// WORD wIndices[(VB_SIZE / 4) * 6];
+ WORD wIndices[32768];
+
+ //
+ // Device driver vars:
+ //
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+
+ // DirectX COM interfaces, postfixed with the interface number
+ IDirectDraw *lpDD1;
+ IDirectDraw4 *lpDD4;
+ IDirect3D3 *lpD3D3;
+ IDirect3DDevice3 *lpDev3;
+ IDirect3DViewport3 *lpViewport3;
+ IDirectDrawSurface4 *lpFront4;
+ IDirectDrawSurface4 *lpBack4;
+ IDirectDrawSurface4 *lpDepth4;
+
+ // Vertex buffers
+ BOOL bD3DPipeline; // True if using D3D geometry pipeline
+ IDirect3DVertexBuffer *m_vbuf; // Unprocessed vertices
+ IDirect3DVertexBuffer *m_pvbuf; // Processed vertices ready to be rendered
+
+ D3DTEXTUREOP ColorOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ D3DTEXTUREOP AlphaOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ struct gl_texture_object *tObj[MAX_TEXTURE_UNITS];
+
+ DDCAPS ddCaps; // DirectDraw caps
+ D3DDEVICEDESC D3DDevDesc; // Direct3D Device description
+
+ DDPIXELFORMAT ddpfRender; // Pixel format of the render buffer
+ DDPIXELFORMAT ddpfDepth; // Pixel format of the depth buffer
+
+ BOOL bStencil; // TRUE is this context has stencil
+
+ PX_packFunc fnPackFunc; // Pixel packing function for SW
+ PX_unpackFunc fnUnpackFunc; // Pixel unpacking function for SW
+ PX_packSpanFunc fnPackSpanFunc; // Pixel span packer
+
+ D3DVIEWPORT2 d3dViewport; // D3D Viewport object
+
+ D3DCULL cullmode; // Direct3D cull mode
+ D3DCOLOR curcolor; // Current color
+ DWORD dwColorPF; // Current color, in format of target surface
+ D3DCOLOR d3dClearColor; // Clear color
+ D3DCOLOR ConstantColor; // For flat shading
+ DWORD dwClearColorPF; // Clear color, in format of target surface
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Primitive caches
+// DGL_vertex LineCache[DGL_MAX_LINE_VERTS];
+// DGL_vertex TriCache[DGL_MAX_TRI_VERTS];
+// DWORD dwNextLineVert;
+// DWORD dwNextTriVert;
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+ // Shared texture palette
+ IDirectDrawPalette *lpGlobalPalette;
+
+ // Usage counters.
+ // One of these counters will be incremented when we choose
+ // between hardware and software rendering functions.
+// DWORD dwHWUsageCount; // Hardware usage count
+// DWORD dwSWUsageCount; // Software usage count
+
+ // Texture state flags.
+// BOOL m_texturing; // TRUE is texturing
+// BOOL m_mtex; // TRUE if multitexture
+// BOOL m_texHandleValid; // TRUE if tex state valid
+
+ // Renderstate caches to ensure no redundant state changes
+ DWORD dwRS[256]; // Renderstates
+ DWORD dwTSS[2][24]; // Texture-stage states
+ LPDIRECT3DTEXTURE2 lpTex[2]; // Texture (1 per stage)
+
+ DWORD dwMaxTextureSize; // Max texture size:
+ // clamped to 1024.
+
+} DGL_ctx;
+#endif // _USE_GLD3_WGL
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HHOOK hKeyHook;
+LRESULT CALLBACK dglKeyProc(int code,WPARAM wParam,LPARAM lParam);
+
+void dglInitContextState();
+void dglDeleteContextState();
+BOOL dglIsValidContext(HGLRC a);
+DGL_ctx* dglGetContextAddress(const HGLRC a);
+HDC dglGetCurrentDC(void);
+HGLRC dglGetCurrentContext(void);
+HGLRC dglCreateContext(HDC a, const DGL_pixelFormat *lpPF);
+BOOL dglMakeCurrent(HDC a, HGLRC b);
+BOOL dglDeleteContext(HGLRC a);
+BOOL dglSwapBuffers(HDC hDC);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglglobals.c b/src/mesa/drivers/windows/gldirect/dglglobals.c
new file mode 100644
index 0000000..c633e3b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglglobals.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Global variables.
+*
+****************************************************************************/
+
+#include "dglglobals.h"
+
+// =======================================================================
+// Global Variables
+// =======================================================================
+
+char szCopyright[] = "Copyright (c) 1998 SciTech Software, Inc.";
+char szDllName[] = "Scitech GLDirect";
+char szErrorTitle[] = "GLDirect Error";
+
+DGL_globals glb;
+
+// Shared result variable
+HRESULT hResult;
+
+// ***********************************************************************
+
+// Patch function for missing function in Mesa
+int finite(
+ double x)
+{
+ return _finite(x);
+};
+
+// ***********************************************************************
+
+void dglInitGlobals()
+{
+ // Zero all fields just in case
+ memset(&glb, 0, sizeof(glb));
+
+ // Set the global defaults
+ glb.bPrimary = FALSE; // Not the primary device
+ glb.bHardware = FALSE; // Not a hardware device
+// glb.bFullscreen = FALSE; // Not running fullscreen
+ glb.bSquareTextures = FALSE; // Device does not need sq
+ glb.bPAL8 = FALSE; // Device cannot do 8bit
+ glb.dwMemoryType = DDSCAPS_SYSTEMMEMORY;
+ glb.dwRendering = DGL_RENDER_D3D;
+
+ glb.bWaitForRetrace = TRUE; // Sync to vertical retrace
+ glb.bFullscreenBlit = FALSE;
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL; // Pixel format list
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+ glb.nTextureFormatCount = 0;
+ glb.lpTextureFormat = NULL;
+#endif // _USE_GLD3_WGL
+
+ glb.wMaxSimultaneousTextures = 1;
+
+ // Enable support for multitexture, if available.
+ glb.bMultitexture = TRUE;
+
+ // Enable support for mipmapping
+ glb.bUseMipmaps = TRUE;
+
+ // Alpha emulation via chroma key
+ glb.bEmulateAlphaTest = FALSE;
+
+ // Use Mesa pipeline always (for compatibility)
+ glb.bForceMesaPipeline = FALSE;
+
+ // Init support for multiple GLRCs
+ glb.bDirectDraw = FALSE;
+ glb.bDirectDrawPrimary = FALSE;
+ glb.bDirect3D = FALSE;
+ glb.bDirect3DDevice = FALSE;
+ glb.bDirectDrawStereo = FALSE;
+ glb.iDirectDrawStereo = 0;
+ glb.hWndActive = NULL;
+ // Init DirectX COM interfaces for multiple GLRCs
+// glb.lpDD4 = NULL;
+// glb.lpPrimary4 = NULL;
+// glb.lpBack4 = NULL;
+// glb.lpDepth4 = NULL;
+// glb.lpGlobalPalette = NULL;
+
+ // Init special support options
+ glb.bMessageBoxWarnings = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+
+ // Do not assume single-precision-only FPU (for compatibility)
+ glb.bFastFPU = FALSE;
+
+ // Allow hot-key support
+ glb.bHotKeySupport = TRUE;
+
+ // Default to single-threaded support (for simplicity)
+ glb.bMultiThreaded = FALSE;
+
+ // Use application-specific customizations (for end-user convenience)
+ glb.bAppCustomizations = TRUE;
+
+#ifdef _USE_GLD3_WGL
+ // Registry/ini-file settings for GLDirect 3.x
+ glb.dwAdapter = 0; // Primary DX8 adapter
+ glb.dwTnL = 1; // MesaSW TnL
+ glb.dwMultisample = 0; // Multisample Off
+ glb.dwDriver = 2; // Direct3D HW
+
+ // Signal a pixelformat list rebuild
+ glb.bPixelformatsDirty = TRUE;
+#endif
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglglobals.h b/src/mesa/drivers/windows/gldirect/dglglobals.h
new file mode 100644
index 0000000..995f1cd
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglglobals.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Globals.
+*
+****************************************************************************/
+
+#ifndef __DGLGLOBALS_H
+#define __DGLGLOBALS_H
+
+#include "dglcontext.h"
+#include "dglpf.h" // Pixel format
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DGL_RENDER_MESASW = 0,
+ DGL_RENDER_D3D = 1,
+ DGL_RENDER_FORCE_DWORD = 0x7ffffff,
+} DGL_renderType;
+
+#ifdef _USE_GLD3_WGL
+
+// Same as DGL_renderType? KeithH
+typedef enum {
+ GLDS_DRIVER_MESA_SW = 0, // Mesa SW rendering
+ GLDS_DRIVER_REF = 1, // Direct3D Reference Rasteriser
+ GLDS_DRIVER_HAL = 2, // Direct3D HW rendering
+} GLDS_DRIVER;
+
+typedef enum {
+ GLDS_TNL_DEFAULT = 0, // Choose best TnL method
+ GLDS_TNL_MESA = 1, // Mesa TnL
+ GLDS_TNL_D3DSW = 2, // D3D Software TnL
+ GLDS_TNL_D3DHW = 3, // D3D Hardware TnL
+} GLDS_TNL;
+
+typedef enum {
+ GLDS_MULTISAMPLE_NONE = 0,
+ GLDS_MULTISAMPLE_FASTEST = 1,
+ GLDS_MULTISAMPLE_NICEST = 2,
+} GLDS_MULTISAMPLE;
+#endif
+
+typedef struct {
+ // Registry settings
+ char szDDName[MAX_DDDEVICEID_STRING]; // DirectDraw device name
+ char szD3DName[MAX_DDDEVICEID_STRING]; // Direct3D driver name
+ BOOL bPrimary; // Is ddraw device the Primary device?
+ BOOL bHardware; // Is the d3d driver a Hardware driver?
+#ifndef _USE_GLD3_WGL
+ GUID ddGuid; // GUID of the ddraw device
+ GUID d3dGuid; // GUID of the direct3d driver
+#endif // _USE_GLD3_WGL
+// BOOL bFullscreen; // Force fullscreen - only useful for primary adaptors.
+ BOOL bSquareTextures; // Does this driver require square textures?
+ DWORD dwRendering; // Type of rendering required
+
+ BOOL bWaitForRetrace; // Sync to vertical retrace
+ BOOL bFullscreenBlit; // Use Blt instead of Flip in fullscreen modes
+
+ // Multitexture
+ BOOL bMultitexture;
+
+ BOOL bUseMipmaps;
+
+ DWORD dwMemoryType; // Sysmem or Vidmem
+
+ // Global palette
+ BOOL bPAL8;
+ DDPIXELFORMAT ddpfPAL8;
+
+ // Multitexture
+ WORD wMaxSimultaneousTextures;
+
+ // Win32 internals
+ BOOL bAppActive; // Keep track of Alt-Tab
+ LONG lpfnWndProc; // WndProc of calling app
+
+ // Pixel Format Descriptior list.
+ int nPixelFormatCount;
+ DGL_pixelFormat *lpPF;
+#ifndef _USE_GLD3_WGL
+ // ZBuffer pixel formats
+ int nZBufferPFCount; // Count of Zbuffer pixel formats
+ DDPIXELFORMAT *lpZBufferPF; // ZBuffer pixel formats
+
+ // Display modes (for secondary devices)
+ int nDisplayModeCount;
+ DDSURFACEDESC2 *lpDisplayModes;
+
+ // Texture pixel formats
+ int nTextureFormatCount;
+ DGL_textureFormat *lpTextureFormat;
+#endif // _USE_GLD3_WGL
+ // Alpha emulation via chroma key
+ BOOL bEmulateAlphaTest;
+
+ // Geom pipeline override.
+ // If this is set TRUE then the D3D pipeline will never be used,
+ // and the Mesa pipline will always be used.
+ BOOL bForceMesaPipeline;
+
+#ifdef _USE_GLD3_WGL
+ BOOL bPixelformatsDirty; // Signal a list rebuild
+#endif
+
+ // Additional globals to support multiple GL rendering contexts, GLRCs
+ BOOL bDirectDraw; // DirectDraw interface exists ?
+ BOOL bDirectDrawPrimary; // DirectDraw primary surface exists ?
+ BOOL bDirect3D; // Direct3D interface exists ?
+ BOOL bDirect3DDevice; // Direct3D device exists ?
+
+ BOOL bDirectDrawStereo; // DirectDraw Stereo driver started ?
+ int iDirectDrawStereo; // DirectDraw Stereo driver reference count
+ HWND hWndActive; // copy of active window
+
+ // Copies of DirectX COM interfaces for re-referencing across multiple GLRCs
+// IDirectDraw4 *lpDD4; // copy of DirectDraw interface
+// IDirectDrawSurface4 *lpPrimary4; // copy of DirectDraw primary surface
+// IDirectDrawSurface4 *lpBack4;
+// IDirectDrawSurface4 *lpDepth4;
+// IDirectDrawPalette *lpGlobalPalette;
+
+ // Aids for heavy-duty MFC-windowed OGL apps, like AutoCAD
+ BOOL bMessageBoxWarnings; // popup message box warning
+ BOOL bDirectDrawPersistant; // DirectDraw is persisitant
+ BOOL bPersistantBuffers; // DirectDraw buffers persisitant
+
+ // FPU setup option for CAD precision (AutoCAD) vs GAME speed (Quake)
+ BOOL bFastFPU; // single-precision-only FPU ?
+
+ // Hot-Key support, like for real-time stereo parallax adjustments
+ BOOL bHotKeySupport; // hot-key support ?
+
+ // Multi-threaded support, for apps like 3DStudio
+ BOOL bMultiThreaded; // multi-threaded ?
+
+ // Detect and use app-specific customizations for apps like 3DStudio
+ BOOL bAppCustomizations; // app customizations ?
+
+#ifdef _USE_GLD3_WGL
+ DWORD dwAdapter; // Primary DX8 adapter
+ DWORD dwTnL; // MesaSW TnL
+ DWORD dwMultisample; // Multisample Off
+ DWORD dwDriver; // Direct3D HW
+ void *pDrvPrivate; // Driver-specific data
+#endif
+
+} DGL_globals;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DGL_globals glb;
+
+void dglInitGlobals();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglmacros.h b/src/mesa/drivers/windows/gldirect/dglmacros.h
new file mode 100644
index 0000000..aed0f21
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglmacros.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Useful generic macros.
+*
+****************************************************************************/
+
+#ifndef __DGLMACROS_H
+#define __DGLMACROS_H
+
+#include <ddraw.h>
+
+// Define the relevant RELEASE macro depending on C or C++
+#if !defined(__cplusplus) || defined(CINTERFACE)
+ // Standard C version
+ #define RELEASE(x) if (x!=NULL) { x->lpVtbl->Release(x); x=NULL; }
+#else
+ // C++ version
+ #define RELEASE(x) if (x!=NULL) { x->Release(); x=NULL; }
+#endif
+
+// We don't want a message *every* time we call an unsupported function
+#define UNSUPPORTED(x) \
+ { \
+ static BOOL bFirstTime = TRUE; \
+ if (bFirstTime) { \
+ bFirstTime = FALSE; \
+ ddlogError(DDLOG_WARN, (x), DDERR_CURRENTLYNOTAVAIL); \
+ } \
+ }
+
+#define DGL_CHECK_CONTEXT \
+ if (ctx == NULL) return;
+
+// Don't render if bCanRender is not TRUE.
+#define DGL_CHECK_RENDER \
+ if (!dgl->bCanRender) return;
+
+#if 0
+#define TRY(a,b) (a)
+#define TRY_ERR(a,b) (a)
+#else
+// hResult should be defined in the function
+// Return codes should be checked via SUCCEDDED and FAILED macros
+#define TRY(a,b) \
+ { \
+ if (FAILED(hResult=(a))) \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ }
+
+// hResult is a global
+// The label exit_with_error should be defined within the calling scope
+#define TRY_ERR(a,b) \
+ { \
+ if (FAILED(hResult=(a))) { \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ goto exit_with_error; \
+ } \
+ }
+#endif // #if 1
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglpf.c b/src/mesa/drivers/windows/gldirect/dglpf.c
new file mode 100644
index 0000000..65e389d
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglpf.c
@@ -0,0 +1,620 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#include "dglpf.h"
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+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";
+
+// ***********************************************************************
+// 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
+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, 5, // Green bits, shift
+ 5, 10, // 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
+ },
+ -1, // No depth/stencil buffer
+};
+
+// ***********************************************************************
+// Return the count of the number of bits in a Bit Mask.
+int BitCount(
+ DWORD dw)
+{
+ int i;
+
+ if (dw == 0)
+ return 0; // account for non-RGB mode
+
+ for (i=0; dw; dw=dw>>1)
+ i += (dw & 1);
+ return i;
+}
+
+// ***********************************************************************
+
+DWORD BitShift(
+ DWORD dwMaskIn)
+{
+ DWORD dwShift, dwMask;
+
+ if (dwMaskIn == 0)
+ return 0; // account for non-RGB mode
+
+ for (dwShift=0, dwMask=dwMaskIn; !(dwMask&1); dwShift++, dwMask>>=1);
+
+ return dwShift;
+}
+
+// ***********************************************************************
+
+BOOL IsValidPFD(int iPFD)
+{
+ DGL_pixelFormat *lpPF;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if ((glb.lpPF == NULL) ||
+ (glb.nPixelFormatCount == 0))
+ return FALSE;
+
+ // Check PFD range
+ if ( (iPFD < 1) || (iPFD > glb.nPixelFormatCount) ) {
+ ddlogMessage(DDLOG_ERROR, "PFD out of range\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Make a pointer to the pixel format
+ lpPF = &glb.lpPF[iPFD-1];
+
+ // Check size
+ if (lpPF->pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ ddlogMessage(DDLOG_ERROR, "Bad PFD size\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Check version
+ if (lpPF->pfd.nVersion != 1) {
+ ddlogMessage(DDLOG_ERROR, "PFD is not Version 1\n");
+ return FALSE; // PFD is invalid
+ }
+
+ return TRUE; // PFD is valid
+}
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+
+int iEnumCount; // Enumeration count
+DWORD dwDisplayBitDepth; // Bit depth of current display mode
+
+// ***********************************************************************
+
+HRESULT WINAPI EnumDisplayModesCallback(
+ DDSURFACEDESC2* pddsd,
+ void *pvContext)
+{
+ DWORD dwModeDepth;
+ DDSURFACEDESC2 *lpDisplayMode;
+ char buf[32];
+
+ // Check parameters
+ if (pddsd == NULL)
+ return DDENUMRET_CANCEL;
+
+ dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
+ lpDisplayMode = (DDSURFACEDESC2 *)pvContext;
+
+ // Check mode for compatability with device.
+ if (dwModeDepth != dwDisplayBitDepth)
+ return DDENUMRET_OK;
+
+ if (lpDisplayMode != NULL) {
+ memcpy(&lpDisplayMode[iEnumCount], pddsd, sizeof(DDSURFACEDESC2));
+ sprintf(buf, TEXT("Mode: %ld x %ld x %ld\n"),
+ pddsd->dwWidth, pddsd->dwHeight, dwModeDepth);
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+
+ iEnumCount++;
+
+ return DDENUMRET_OK;
+}
+
+// ***********************************************************************
+
+HRESULT CALLBACK d3dEnumZBufferFormatsCallback(
+ DDPIXELFORMAT* pddpf,
+ VOID* lpZBufferPF )
+{
+ char buf[64];
+
+ if(pddpf == NULL)
+ return D3DENUMRET_CANCEL;
+
+ if (pddpf->dwFlags & DDPF_ZBUFFER) {
+ if (lpZBufferPF == NULL) {
+ // Pass 1. Merely counting the PF
+ glb.nZBufferPFCount++;
+ } else {
+ // Pass 2. Save the PF
+ if (pddpf->dwFlags & DDPF_STENCILBUFFER) {
+ sprintf(buf, " %d: Z=%d S=%d\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth,
+ pddpf->dwStencilBitDepth);
+ } else {
+ sprintf(buf, " %d: Z=%d S=0\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth);
+ }
+ ddlogMessage(DDLOG_INFO, buf);
+
+ memcpy(&glb.lpZBufferPF[iEnumCount++],
+ pddpf,
+ sizeof(DDPIXELFORMAT));
+ }
+ }
+
+ return D3DENUMRET_OK;
+}
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+BOOL IsStencilSupportBroken(LPDIRECTDRAW4 lpDD4)
+{
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+ BOOL bBroken = FALSE;
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return FALSE;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpDD4, &dddi, 0)))
+ return FALSE;
+
+ // Matrox G400 stencil buffer support does not draw anything in AutoCAD,
+ // but ordinary Z buffers draw shaded models fine. (DaveM)
+ if (dddi.dwVendorId == 0x102B) { // Matrox
+ if (dddi.dwDeviceId == 0x0525) { // G400
+ bBroken = TRUE;
+ }
+ }
+
+ return bBroken;
+}
+
+// ***********************************************************************
+
+void dglBuildPixelFormatList()
+{
+ int i;
+ char buf[128];
+ char cat[8];
+ HRESULT hRes;
+ DGL_pixelFormat *lpPF;
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.BuildPixelformatList();
+#else
+ IDirectDraw *lpDD1 = NULL;
+ IDirectDraw4 *lpDD4 = NULL;
+ IDirect3D3 *lpD3D3 = NULL;
+ DDSURFACEDESC2 ddsdDisplayMode;
+
+ DWORD dwRb, dwGb, dwBb, dwAb; // Bit counts
+ DWORD dwRs, dwGs, dwBs, dwAs; // Bit shifts
+ DWORD dwPixelType; // RGB or color index
+
+ // Set defaults
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+
+ //
+ // Examine the hardware for depth and stencil
+ //
+
+ if (glb.bPrimary)
+ hRes = DirectDrawCreate(NULL, &lpDD1, NULL);
+ else
+ hRes = DirectDrawCreate(&glb.ddGuid, &lpDD1, NULL);
+
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: DirectDrawCreate failed", hRes);
+ return;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hRes = IDirectDraw_QueryInterface(
+ lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpDD4);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (DD4) failed", hRes);
+ goto clean_up;
+ }
+
+
+ // Retrieve caps of current display mode
+ ZeroMemory(&ddsdDisplayMode, sizeof(ddsdDisplayMode));
+ ddsdDisplayMode.dwSize = sizeof(ddsdDisplayMode);
+ hRes = IDirectDraw4_GetDisplayMode(lpDD4, &ddsdDisplayMode);
+ if (FAILED(hRes))
+ goto clean_up;
+
+ dwDisplayBitDepth = ddsdDisplayMode.ddpfPixelFormat.dwRGBBitCount;
+ dwPixelType = (dwDisplayBitDepth <= 8) ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
+ dwRb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+ dwRs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+
+ if (BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask)) {
+ dwAb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ dwAs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ } else {
+ dwAb = 0;
+ dwAs = 0;
+ }
+
+ // Query for available display modes
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Display Modes:\n");
+
+ // Pass 1: Determine count
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ NULL,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ if (iEnumCount == 0) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: No display modes found");
+ goto clean_up;
+ }
+ glb.lpDisplayModes = (DDSURFACEDESC2 *)calloc(iEnumCount,
+ sizeof(DDSURFACEDESC2));
+ if (glb.lpDisplayModes == NULL) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: DDSURFACEDESC2 calloc failed");
+ goto clean_up;
+ }
+ glb.nDisplayModeCount = iEnumCount;
+ // Pass 2: Save modes
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ (void *)glb.lpDisplayModes,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ // Query for IDirect3D3 interface
+ hRes = IDirectDraw4_QueryInterface(
+ lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpD3D3);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (D3D3) failed", hRes);
+ goto clean_up;
+ }
+
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "ZBuffer formats:\n");
+
+ // Pass 1. Count the ZBuffer pixel formats
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ NULL);
+
+ if (FAILED(hRes))
+ goto clean_up;
+
+ if (glb.nZBufferPFCount) {
+ glb.lpZBufferPF = (DDPIXELFORMAT *)calloc(glb.nZBufferPFCount,
+ sizeof(DDPIXELFORMAT));
+ if(glb.lpZBufferPF == NULL)
+ goto clean_up;
+
+ // Pass 2. Cache the ZBuffer pixel formats
+ iEnumCount = 0; // (Used by the enum function)
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ glb.lpZBufferPF);
+
+ if (FAILED(hRes))
+ goto clean_up;
+ }
+
+ // Remove stencil support for boards which don't work for AutoCAD;
+ // Matrox G400 does not work, but NVidia TNT2 and ATI Rage128 do... (DaveM)
+ if (IsStencilSupportBroken(lpDD4)) {
+ for (i=0; i<iEnumCount; i++)
+ if (glb.lpZBufferPF[i].dwFlags & DDPF_STENCILBUFFER)
+ glb.nZBufferPFCount--;
+ }
+
+ // One each for every ZBuffer pixel format (including no depth buffer)
+ // Times-two because duplicated for single buffering (as opposed to double)
+ glb.nPixelFormatCount = 2 * (glb.nZBufferPFCount + 1);
+ glb.lpPF = (DGL_pixelFormat *)calloc(glb.nPixelFormatCount,
+ sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ goto clean_up;
+ //
+ // Fill in the pixel formats
+ // Note: Depth buffer bits are really (dwZBufferBitDepth-dwStencilBitDepth)
+ // but this will pass wierd numbers to the OpenGL app. (?)
+ //
+
+ pfTemplateHW.pfd.iPixelType = dwPixelType;
+ pfTemplateHW.pfd.cColorBits = dwDisplayBitDepth;
+ pfTemplateHW.pfd.cRedBits = dwRb;
+ pfTemplateHW.pfd.cGreenBits = dwGb;
+ pfTemplateHW.pfd.cBlueBits = dwBb;
+ pfTemplateHW.pfd.cAlphaBits = dwAb;
+ pfTemplateHW.pfd.cRedShift = dwRs;
+ pfTemplateHW.pfd.cGreenShift = dwGs;
+ pfTemplateHW.pfd.cBlueShift = dwBs;
+ pfTemplateHW.pfd.cAlphaShift = dwAs;
+
+ lpPF = glb.lpPF;
+
+ // Fill in the double-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ }
+ // Fill in the single-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ // Remove double-buffer flag. Could use XOR instead...
+ lpPF->pfd.dwFlags &= (~(PFD_DOUBLEBUFFER));
+ // Insert GDI flag for single buffered format only.
+ lpPF->pfd.dwFlags |= PFD_SUPPORT_GDI;
+ }
+#endif // _USE_GLD3_WGL
+
+ // Lets dump the list to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Pixel Formats:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ for (i=0, lpPF = glb.lpPF; i<glb.nPixelFormatCount; i++, lpPF++) {
+ sprintf(buf, "0x%02x ", i+1);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+ if(lpPF->pfd.dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(lpPF->pfd.dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(lpPF->pfd.bReserved) sprintf(cat, " %d ", lpPF->pfd.bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cRedBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cGreenBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cBlueBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAlphaBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAuxBuffers) sprintf(cat, "%2d ", lpPF->pfd.cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cDepthBits) sprintf(cat, "%2d ", lpPF->pfd.cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cStencilBits) sprintf(cat, "%2d ", lpPF->pfd.cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumRedBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumGreenBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumBlueBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumAlphaBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+#ifndef _USE_GLD3_WGL
+clean_up:
+ // Release COM objects
+ RELEASE(lpD3D3);
+ RELEASE(lpDD4);
+ RELEASE(lpDD1);
+
+ // Popup warning message if non RGB color mode
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
+
+void dglReleasePixelFormatList()
+{
+ glb.nPixelFormatCount = 0;
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ glb.lpPF = NULL;
+ }
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ if (glb.lpZBufferPF) {
+ free(glb.lpZBufferPF);
+ glb.lpZBufferPF = NULL;
+ }
+ glb.nDisplayModeCount = 0;
+ if (glb.lpDisplayModes) {
+ free(glb.lpDisplayModes);
+ glb.lpDisplayModes = NULL;
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglpf.h b/src/mesa/drivers/windows/gldirect/dglpf.h
new file mode 100644
index 0000000..8a7e38c
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglpf.h
@@ -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 (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#ifndef __DGLPF_H
+#define __DGLPF_H
+
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PIXELFORMATDESCRIPTOR pfd; // Win32 Pixel Format Descriptor
+#ifdef _USE_GLD3_WGL
+ // Driver-specific data.
+ // Example: The DX8 driver uses this to hold an index into a
+ // list of depth-stencil descriptions.
+ DWORD dwDriverData;
+#else
+ int iZBufferPF; // Index of depth buffer pixel format
+#endif
+} DGL_pixelFormat;
+
+#include "dglglobals.h"
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL IsValidPFD(int iPFD);
+void dglBuildPixelFormatList();
+void dglReleasePixelFormatList();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglwgl.c b/src/mesa/drivers/windows/gldirect/dglwgl.c
new file mode 100644
index 0000000..a1b7e5d
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglwgl.c
@@ -0,0 +1,2958 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#include "dglwgl.h"
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+#include "glu.h" // MUST USE MICROSOFT'S GLU32!
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+// Need to export wgl* functions if using GLD3,
+// otherwise export GLD2 DGL_* functions.
+#ifdef _USE_GLD3_WGL
+#define _GLD_WGL_EXPORT(a) wgl##a
+#else
+#define _GLD_WGL_EXPORT(a) DGL_##a
+#endif
+
+// Calls into Mesa 4.x are different
+#ifdef _USE_GLD3_WGL
+#include "dlist.h"
+#include "drawpix.h"
+#include "get.h"
+#include "matrix.h"
+// NOTE: All the _GLD* macros now call the gl* functions direct.
+// This ensures that the correct internal pathway is taken. KeithH
+#define _GLD_glNewList glNewList
+#define _GLD_glBitmap glBitmap
+#define _GLD_glEndList glEndList
+#define _GLD_glDeleteLists glDeleteLists
+#define _GLD_glGetError glGetError
+#define _GLD_glTranslatef glTranslatef
+#define _GLD_glBegin glBegin
+#define _GLD_glVertex2fv glVertex2fv
+#define _GLD_glEnd glEnd
+#define _GLD_glNormal3f glNormal3f
+#define _GLD_glVertex3f glVertex3f
+#define _GLD_glVertex3fv glVertex3fv
+#else // _USE_GLD3_WGL
+#define _GLD_glNewList (*mesaFuncs.glNewList)
+#define _GLD_glBitmap (*mesaFuncs.glBitmap)
+#define _GLD_glEndList (*mesaFuncs.glEndList)
+#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
+#define _GLD_glGetError (*mesaFuncs.glGetError)
+#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
+#define _GLD_glBegin (*mesaFuncs.glBegin)
+#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
+#define _GLD_glEnd (*mesaFuncs.glEnd)
+#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
+#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
+#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+// Emulate SGI DDK calls.
+#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
+#define __wglFree(a) GlobalFree((a))
+
+// ***********************************************************************
+
+// Mesa glu.h and MS glu.h call these different things...
+//#define GLUtesselator GLUtriangulatorObj
+//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
+
+// For wglFontOutlines
+
+typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
+typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
+typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
+typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
+typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
+
+static HINSTANCE gluModuleHandle;
+static gluNewTessProto gluNewTessProc;
+static gluDeleteTessProto gluDeleteTessProc;
+static gluTessBeginPolygonProto gluTessBeginPolygonProc;
+static gluTessBeginContourProto gluTessBeginContourProc;
+static gluTessVertexProto gluTessVertexProc;
+static gluTessEndContourProto gluTessEndContourProc;
+static gluTessEndPolygonProto gluTessEndPolygonProc;
+static gluTessPropertyProto gluTessPropertyProc;
+static gluTessNormalProto gluTessNormalProc;
+static gluTessCallbackProto gluTessCallbackProc;
+
+static HFONT hNewFont, hOldFont;
+static FLOAT ScaleFactor;
+
+#define LINE_BUF_QUANT 4000
+#define VERT_BUF_QUANT 4000
+
+static FLOAT* LineBuf;
+static DWORD LineBufSize;
+static DWORD LineBufIndex;
+static FLOAT* VertBuf;
+static DWORD VertBufSize;
+static DWORD VertBufIndex;
+static GLenum TessErrorOccurred;
+
+static int AppendToLineBuf(
+ FLOAT value);
+
+static int AppendToVertBuf(
+ FLOAT value);
+
+static int DrawGlyph(
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static void FreeLineBuf(void);
+
+static void FreeVertBuf(void);
+
+static long GetWord(
+ UCHAR** p);
+
+static long GetDWord(
+ UCHAR** p);
+
+static double GetFixed(
+ UCHAR** p);
+
+static int InitLineBuf(void);
+
+static int InitVertBuf(void);
+
+static HFONT CreateHighResolutionFont(
+ HDC hDC);
+
+static int MakeDisplayListFromGlyph(
+ DWORD listName,
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static BOOL LoadGLUTesselator(void);
+static BOOL UnloadGLUTesselator(void);
+
+static int MakeLinesFromArc(
+ FLOAT x0,
+ FLOAT y0,
+ FLOAT x1,
+ FLOAT y1,
+ FLOAT x2,
+ FLOAT y2,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviationSquared);
+
+static int MakeLinesFromGlyph( UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTLine( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount);
+
+static int MakeLinesFromTTPolycurve( UCHAR** pp,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTPolygon( UCHAR** pp,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTQSpline( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount,
+ FLOAT chordalDeviation);
+
+static void CALLBACK TessCombine( double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData);
+
+static void CALLBACK TessError( GLenum error);
+
+static void CALLBACK TessVertexOutData( FLOAT p[3],
+ GLfloat z);
+
+// ***********************************************************************
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLWGL.C vars for multi-threaded support")
+extern CRITICAL_SECTION CriticalSection;
+extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
+#endif
+int curPFD = 0; // Current PFD (static)
+
+// ***********************************************************************
+
+int dglGetPixelFormat(void)
+{
+#ifdef GLD_THREADS
+ int iPixelFormat;
+ // get thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iPixelFormat = curPFD;
+ }
+ }
+ // get global static var
+ else {
+ iPixelFormat = curPFD;
+ }
+ return iPixelFormat;
+#else
+ return curPFD;
+#endif
+}
+
+// ***********************************************************************
+
+void dglSetPixelFormat(int iPixelFormat)
+{
+#ifdef GLD_THREADS
+ // set thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ curPFD = iPixelFormat;
+ }
+ }
+ // set global static var
+ else {
+ curPFD = iPixelFormat;
+ }
+#else
+ curPFD = iPixelFormat;
+#endif
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
+ HDC a,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ DGL_pixelFormat *lpPF = glb.lpPF;
+
+ PIXELFORMATDESCRIPTOR ppfdBest;
+ int i;
+ int bestIndex = -1;
+ int numPixelFormats;
+ DWORD dwFlags;
+
+ char buf[128];
+ char cat[8];
+
+ DWORD dwAllFlags =
+ PFD_DRAW_TO_WINDOW |
+ PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI |
+ PFD_SUPPORT_OPENGL |
+ PFD_GENERIC_FORMAT |
+ PFD_NEED_PALETTE |
+ PFD_NEED_SYSTEM_PALETTE |
+ PFD_DOUBLEBUFFER |
+ PFD_STEREO |
+ /*PFD_SWAP_LAYER_BUFFERS |*/
+ PFD_DOUBLEBUFFER_DONTCARE |
+ PFD_STEREO_DONTCARE |
+ PFD_SWAP_COPY |
+ PFD_SWAP_EXCHANGE |
+ PFD_GENERIC_ACCELERATED |
+ 0;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // List may not be built until dglValidate() is called! KeithH
+ lpPF = glb.lpPF;
+
+ //
+ // Lets print the input pixel format to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ //
+ ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ sprintf(buf, " . ");
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+ if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+ //
+ // Examine the flags for correctness
+ //
+ dwFlags = ppfd->dwFlags;
+ if (dwFlags != (dwFlags & dwAllFlags))
+ {
+ /* error: bad dwFlags */
+ ddlogPrintf(DDLOG_WARN,
+ "ChoosePixelFormat: bad flags (0x%x)",
+ dwFlags & (~dwAllFlags));
+ // Mask illegal flags and continue
+ dwFlags = dwFlags & dwAllFlags;
+ }
+
+ switch (ppfd->iPixelType) {
+ case PFD_TYPE_RGBA:
+ case PFD_TYPE_COLORINDEX:
+ break;
+ default:
+ /* error: bad iPixelType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
+ return 0;
+ }
+
+ switch (ppfd->iLayerType) {
+ case PFD_MAIN_PLANE:
+ case PFD_OVERLAY_PLANE:
+ case PFD_UNDERLAY_PLANE:
+ break;
+ default:
+ /* error: bad iLayerType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
+ return 0;
+ }
+
+ numPixelFormats = glb.nPixelFormatCount;
+
+ /* loop through candidate pixel format descriptors */
+ for (i=0; i<numPixelFormats; ++i) {
+ PIXELFORMATDESCRIPTOR ppfdCandidate;
+
+ memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
+
+ /*
+ ** Check attributes which must match
+ */
+ if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
+ continue;
+ }
+
+ if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
+ continue;
+ }
+
+ if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
+ (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
+ if ((dwFlags & PFD_DOUBLEBUFFER) !=
+ (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
+ {
+ continue;
+ }
+ }
+
+// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
+ if ((dwFlags & PFD_STEREO) !=
+ (ppfdCandidate.dwFlags & PFD_STEREO))
+ {
+ continue;
+ }
+// }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
+ continue;
+ }
+
+ if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
+ continue;
+ }
+
+ if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
+ continue;
+ }
+
+ /*
+ ** See if candidate is better than the previous best choice
+ */
+ if (bestIndex == -1) {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cColorBits > ppfdBest.cColorBits &&
+ ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
+ (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
+ ppfdCandidate.cColorBits < ppfdBest.cColorBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits
+ && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits
+ && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
+ ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
+ (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
+ ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cStencilBits &&
+ ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers &&
+ ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+ }
+
+ if (bestIndex != -1) {
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
+ return bestIndex + 1;
+ }
+
+ // Return the pixelformat that has the most capabilities.
+ // ** NOTE: This is only possible due to the way the list
+ // of pixelformats is built. **
+ // Now picks best pixelformat. KeithH
+ bestIndex = numPixelFormats; // most capable double buffer format
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
+ return (bestIndex);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
+ HGLRC a,
+ HGLRC b,
+ UINT c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+ UNSUPPORTED("wglCopyContext")
+ return FALSE; // Failed
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
+ HDC a)
+{
+ int ipf;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // Check that the current PFD is valid
+ ipf = dglGetPixelFormat();
+ if (!IsValidPFD(ipf))
+ return (HGLRC)0;
+
+ return dglCreateContext(a, &glb.lpPF[ipf-1]);
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
+ HDC a,
+ int b)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("wglCreateLayerContext")
+ return NULL; // Failed
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
+ HGLRC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglDeleteContext(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
+ HDC hDC,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_DescribeLayerPlane")
+
+// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
+ HDC a,
+ int b,
+ UINT c,
+ LPPIXELFORMATDESCRIPTOR d)
+{
+ UINT nSize;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ if (d == NULL) // Calling app requires max number of PF's
+ return glb.nPixelFormatCount;
+
+ // The supplied buffer may be larger than the info that we
+ // will be copying.
+ if (c > sizeof(PIXELFORMATDESCRIPTOR))
+ nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ else
+ nSize = c;
+
+ // Setup an empty PFD before doing validation check
+ memset(d, 0, nSize);
+ d->nSize = nSize;
+ d->nVersion = 1;
+
+ if (!IsValidPFD(b))
+ return 0; // Bail if PFD index is invalid
+
+ memcpy(d, &glb.lpPF[b-1].pfd, nSize);
+
+ return glb.nPixelFormatCount;
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentContext();
+}
+
+// ***********************************************************************
+
+HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentDC();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
+ LPCSTR a)
+{
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ UNSUPPORTED("DGL_GetDefaultProcAddress")
+ return NULL;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_GetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetPixelFormat();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
+ LPCSTR a)
+{
+ PROC dglGetProcAddressD3D(LPCSTR a);
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+#ifdef _USE_GLD3_WGL
+ return _gldDriver.wglGetProcAddress(a);
+#else
+ return dglGetProcAddressD3D(a);
+#endif
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
+ HDC a,
+ HGLRC b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglMakeCurrent(a, b);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
+ HDC a,
+ int b,
+ BOOL c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_RealizeLayerPalette")
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ CONST COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_SetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
+ HDC a,
+ int b,
+ CONST PIXELFORMATDESCRIPTOR *c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if (IsValidPFD(b)) {
+ ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
+ dglSetPixelFormat(b);
+ return TRUE;
+ } else {
+ ddlogPrintf(DDLOG_ERROR,
+ "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
+ return FALSE;
+ }
+}
+
+// ***********************************************************************
+/*
+ * Share lists between two gl_context structures.
+ * This was added for WIN32 WGL function support, since wglShareLists()
+ * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
+ */
+//
+// Copied from GLD2.x. KeithH
+//
+static GLboolean _gldShareLists(
+ GLcontext *ctx1,
+ GLcontext *ctx2)
+{
+ /* Sanity check context pointers */
+ if (ctx1 == NULL || ctx2 == NULL)
+ return GL_FALSE;
+ /* Sanity check shared list pointers */
+ if (ctx1->Shared == NULL || ctx2->Shared == NULL)
+ return GL_FALSE;
+ /* Decrement reference count on sharee to release previous list */
+ ctx2->Shared->RefCount--;
+#if 0 /* 3DStudio exits on this memory release */
+ if (ctx2->Shared->RefCount == 0)
+ free_shared_state(ctx2, ctx2->Shared);
+#endif
+ /* Re-assign list from sharer to sharee and increment reference count */
+ ctx2->Shared = ctx1->Shared;
+ ctx1->Shared->RefCount++;
+ return GL_TRUE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
+ HGLRC a,
+ HGLRC b)
+{
+ DGL_ctx *dgl1, *dgl2;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Mesa supports shared lists, but you need to supply the shared
+ // GL context info when calling gl_create_context(). An auxiliary
+ // function gl_share_lists() has been added to update the shared
+ // list info after the GL contexts have been created. (DaveM)
+ dgl1 = dglGetContextAddress(a);
+ dgl2 = dglGetContextAddress(b);
+ if (dgl1->bAllocated && dgl2->bAllocated) {
+#ifdef _USE_GLD3_WGL
+ return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
+#else
+ return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
+#endif
+ }
+ return FALSE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
+ HDC a,
+ UINT b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+// ***********************************************************************
+// Note: This ResizeBuffers() function may be called from
+// either MESA glViewport() or GLD wglMakeCurrent().
+
+BOOL dglWglResizeBuffers(
+ GLcontext *ctx,
+ BOOL bDefaultDriver)
+{
+ DGL_ctx *dgl = NULL;
+ RECT rcScreenRect;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ IDirectDrawClipper *lpddClipper = NULL;
+ DWORD dwFlags;
+ HRESULT hResult;
+
+ DWORD dwMemoryType;
+
+ int i;
+ struct gl_texture_object *tObj;
+ struct gl_texture_image *image;
+
+ BOOL bWasFullscreen;
+ BOOL bSaveDesktop;
+ BOOL bFullScrnWin = FALSE;
+ DDSURFACEDESC2 ddsd2DisplayMode;
+
+ DDBLTFX ddbltfx;
+ POINT pt;
+ RECT rcDst;
+#ifdef _USE_GLD3_WGL
+ GLD_displayMode glddm;
+#endif
+
+#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Sanity checks
+ if (ctx == NULL)
+ return FALSE;
+ dgl = ctx->DriverCtx;
+ if (dgl == NULL)
+ return FALSE;
+
+ // Get the window size and calculate its dimensions
+ if (dgl->hWnd == NULL) {
+ // Check for non-window DC = memory DC ?
+ if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ }
+ else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ dwWidth = rcScreenRect.right - rcScreenRect.left;
+ dwHeight = rcScreenRect.bottom - rcScreenRect.top;
+ CopyRect(&dgl->rcScreenRect, &rcScreenRect);
+
+ // This will occur on Alt-Tab
+ if ((dwWidth == 0) && (dwHeight == 0)) {
+ //dgl->bCanRender = FALSE;
+ return TRUE; // No resize possible!
+ }
+
+ // Some apps zero only 1 dimension for non-visible window... (DaveM)
+ if ((dwWidth == 0) || (dwHeight == 0)) {
+ dwWidth = 8;
+ dwHeight = 8;
+ }
+
+ // Test to see if a resize is required.
+ // Note that the dimensions will be the same if a prior resize attempt failed.
+ if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
+ return TRUE; // No resize required
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
+#ifndef _USE_GLD3_WGL
+ // Work out where we want our surfaces created
+ dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
+#endif // _USE_GLD3_WGL
+
+ // Note previous fullscreen vs window display status
+ bWasFullscreen = dgl->bFullscreen;
+
+#ifdef _USE_GLD3_WGL
+ if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
+ if ( (dwWidth == glddm.Width) &&
+ (dwHeight == glddm.Height) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = glddm.Width;
+ dgl->dwModeHeight = glddm.Height;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > glddm.Width)
+ dgl->dwWidth = glddm.Width;
+ if (dgl->dwHeight > glddm.Height)
+ dgl->dwHeight = glddm.Height;
+#else // _USE_GLD3_WGL
+ // Window resize may have changed to fullscreen
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ dgl->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
+ dgl->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
+ dgl->dwHeight = ddsd2DisplayMode.dwHeight;
+#endif // _USE_GLD3_WGL
+
+ // Note if fullscreen vs window display has changed?
+ bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
+ // Save the desktop primary surface from being destroyed
+ // whenever remaining in windowed mode, since the stereo mode
+ // switches are expensive...
+
+#ifndef _USE_GLD3_WGL
+ // Don't need to re-allocate persistant buffers. (DaveM)
+ // Though we should clear the back buffers to hide artifacts.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+ return TRUE;
+ }
+
+ // Ensure all rendering is complete
+ if (ctx->Driver.Finish)
+ (*ctx->Driver.Finish)(ctx);
+ if (dgl->bSceneStarted == TRUE) {
+ IDirect3DDevice3_EndScene(dgl->lpDev3);
+ dgl->bSceneStarted = FALSE;
+ }
+#endif // _USE_GLD3_WGL
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw and DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifndef _USE_GLD3_WGL
+ // Release existing surfaces
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+#endif // _USE_GLD3_WGL
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+
+ // Set defaults
+ dgl->dwModeWidth = dgl->dwWidth;
+ dgl->dwModeHeight = dgl->dwHeight;
+
+#ifdef _USE_GLD3_WGL
+ if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
+ goto cleanup_and_return_with_error;
+#else // _USE_GLD3_WGL
+
+ if (dgl->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release the persistant DirectDraw primary surface
+ // if switching to fullscreen mode. So if application wants
+ // persistant display in fullscreen mode, a fullscreen-size
+ // window should be used instead via fullscreen-blit option.
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
+ dgl->dwModeWidth,
+ dgl->dwModeHeight,
+ dgl->dwBPP,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (dgl->bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ dgl->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ // Ditto if persistant DirectDraw primary
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ goto DoClipperOnly;
+
+ // WINDOWED
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
+ dgl->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Cache the primary surface for persistant DirectDraw state
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = dgl->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+DoClipperOnly:
+ // Update the window for the original clipper
+ if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
+ IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ RELEASE(lpddClipper);
+ }
+
+ if (dgl->bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ } else {
+ dgl->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Zbuffer
+ //
+ if (dgl->bDepthBuffer) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[dgl->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Create a z-buffer
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ dgl->lpDepth4),
+ "dglResize: Attach Zbuffer");
+
+ }
+
+ // Clear the newly resized back buffers for the window client area.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+
+ //
+ // Now that we have a zbuffer we can create the 3D device
+ //
+ hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
+ bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ &dgl->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(dgl);
+
+ //
+ // Viewport
+ //
+ hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Initialise the viewport
+ dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
+ dgl->d3dViewport.dwX = 0;
+ dgl->d3dViewport.dwY = 0;
+ dgl->d3dViewport.dwWidth = dgl->dwWidth;
+ dgl->d3dViewport.dwHeight = dgl->dwHeight;
+ dgl->d3dViewport.dvClipX = 0;
+ dgl->d3dViewport.dvClipY = 0;
+ dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
+ dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
+// dgl->d3dViewport.dvMinZ = 0.0f;
+// dgl->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
+ "dglResize: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // (Re)Initialise all the Direct3D renderstates
+ dglInitStateD3D(ctx);
+
+ // Now we have to recreate all of our textures (+ mipmaps).
+ // Luckily, Mesa has a list of them.
+ tObj = ctx->Shared->TexObjectList;
+ while (tObj != NULL) {
+ if (tObj->DriverData) {
+ // We could call our TexImage function directly, but it's
+ // safer to use the driver pointer.
+ for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+ image = tObj->Image[i];
+ if (image) {
+ switch (tObj->Dimensions){
+ case 1:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
+ break;
+ case 2:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ tObj = tObj->Next;
+ }
+
+ // Re-Bind each texture Unit
+ for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
+ tObj = ctx->Texture.Unit[i].Current;
+ if (tObj) {
+ DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
+ hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
+ }
+ }
+ }
+#endif // _USE_GLD3_WGL
+
+ dgl->bCanRender = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // SUCCESS.
+ return TRUE;
+
+cleanup_and_return_with_error:
+ // Relase all interfaces before returning.
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyDrawable(dgl);
+#else // _USE_GLD3_WGL
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+
+#undef DDLOG_CRITICAL_OR_WARN
+#endif // _USE_GLD3_WGL
+
+ // Mark context as not being able to render
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for bitmap fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+/*****************************************************************************
+**
+** InvertGlyphBitmap.
+**
+** Invert the bitmap so that it suits OpenGL's representation.
+** Each row starts on a double word boundary.
+**
+*****************************************************************************/
+
+static void InvertGlyphBitmap(
+ int w,
+ int h,
+ DWORD *fptr,
+ DWORD *tptr)
+{
+ int dWordsInRow = (w+31)/32;
+ int i, j;
+ DWORD *tmp = tptr;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ tptr += ((h-1)*dWordsInRow);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < dWordsInRow; j++) {
+ *(tptr + j) = *(fptr + j);
+ }
+ tptr -= dWordsInRow;
+ fptr += dWordsInRow;
+ }
+}
+
+// ***********************************************************************
+
+/*****************************************************************************
+ * wglUseFontBitmaps
+ *
+ * Converts a subrange of the glyphs in a GDI font to OpenGL display
+ * lists.
+ *
+ * Extended to support any GDI font, not just TrueType fonts. (DaveM)
+ *
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
+ HDC hDC,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ int i, ox, oy, ix, iy;
+ int w, h;
+ int iBufSize, iCurBufSize = 0;
+ DWORD *bitmapBuffer = NULL;
+ DWORD *invertedBitmapBuffer = NULL;
+ BOOL bSuccessOrFail = TRUE;
+ BOOL bTrueType = FALSE;
+ TEXTMETRIC tm;
+ GLYPHMETRICS gm;
+ RASTERIZER_STATUS rs;
+ MAT2 mat;
+ SIZE size;
+ RECT rect;
+ HDC hDCMem;
+ HBITMAP hBitmap;
+ BITMAPINFO bmi;
+ HFONT hFont;
+
+ // Validate SciTech DirectGL license
+ if (!dglValidate())
+ return FALSE;
+
+ // Set up a unity matrix.
+ ZeroMemory(&mat, sizeof(mat));
+ mat.eM11.value = 1;
+ mat.eM22.value = 1;
+
+ // Test to see if selected font is TrueType or not
+ ZeroMemory(&tm, sizeof(tm));
+ if (!GetTextMetrics(hDC, &tm)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
+ return (FALSE);
+ }
+ bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
+
+ // Test to see if TRUE-TYPE capabilities are installed
+ // (only necessary if TrueType font selected)
+ ZeroMemory(&rs, sizeof(rs));
+ if (bTrueType) {
+ if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
+ return (FALSE);
+ }
+ if (!(rs.wFlags & TT_ENABLED)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
+ return (FALSE);
+ }
+ }
+
+ // Trick to get the current font handle
+ hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+ SelectObject(hDC, hFont);
+
+ // Have memory device context available for holding bitmaps of font glyphs
+ hDCMem = CreateCompatibleDC(hDC);
+ SelectObject(hDCMem, hFont);
+ SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
+ SetBkColor(hDCMem, 0);
+
+ for (i = first; (DWORD) i < (first + count); i++) {
+ // Find out how much space is needed for the bitmap so we can
+ // Set the buffer size correctly.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap size of glyph
+ iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ 0, NULL, &mat);
+ if (iBufSize == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+ else {
+ // Use generic GDI support to compute bitmap size of glyph
+ w = tm.tmMaxCharWidth;
+ h = tm.tmHeight;
+ if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
+ w = size.cx;
+ h = size.cy;
+ }
+ iBufSize = w * h;
+ // Use DWORD multiple for compatibility
+ iBufSize += 3;
+ iBufSize /= 4;
+ iBufSize *= 4;
+ }
+
+ // If we need to allocate Larger Buffers, then do so - but allocate
+ // An extra 50 % so that we don't do too many mallocs !
+ if (iBufSize > iCurBufSize) {
+ if (bitmapBuffer) {
+ __wglFree(bitmapBuffer);
+ }
+ if (invertedBitmapBuffer) {
+ __wglFree(invertedBitmapBuffer);
+ }
+
+ iCurBufSize = iBufSize * 2;
+ bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+ invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+
+ if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+
+ // If we fail to get the Glyph data, delete the display lists
+ // Created so far and return FALSE.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap of glyph
+ if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ w = gm.gmBlackBoxX;
+ h = gm.gmBlackBoxY;
+ ox = gm.gmptGlyphOrigin.x;
+ oy = gm.gmptGlyphOrigin.y;
+ ix = gm.gmCellIncX;
+ iy = gm.gmCellIncY;
+ }
+ else {
+ // Use generic GDI support to create bitmap of glyph
+ ZeroMemory(bitmapBuffer, iBufSize);
+
+ if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
+ // Only create bitmaps for actual font glyphs
+ hBitmap = CreateBitmap(w, h, 1, 1, NULL);
+ SelectObject(hDCMem, hBitmap);
+ // Make bitmap of current font glyph
+ SetRect(&rect, 0, 0, w, h);
+ DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
+ // Make copy of bitmap in our local buffer
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = -h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
+ DeleteObject(hBitmap);
+ }
+ else {
+ // Otherwise use empty display list for non-existing glyph
+ iBufSize = 0;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ ox = 0;
+ oy = tm.tmDescent;
+ ix = w;
+ iy = 0;
+ }
+
+ // Create an OpenGL display list.
+ _GLD_glNewList((listBase + i), GL_COMPILE);
+
+ // Some fonts have no data for the space character, yet advertise
+ // a non-zero size.
+ if (0 == iBufSize) {
+ _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
+ } else {
+ // Invert the Glyph data.
+ InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
+
+ // Render an OpenGL bitmap and invert the origin.
+ _GLD_glBitmap(w, h,
+ (GLfloat) ox, (GLfloat) (h-oy),
+ (GLfloat) ix, (GLfloat) iy,
+ (GLubyte *) invertedBitmapBuffer);
+ }
+
+ // Close this display list.
+ _GLD_glEndList();
+ }
+
+ if (bSuccessOrFail == FALSE) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
+ _GLD_glDeleteLists((i+listBase), (i-first));
+ }
+
+ // Release resources used
+ DeleteObject(hFont);
+ DeleteDC(hDCMem);
+
+ if (bitmapBuffer)
+ __wglFree(bitmapBuffer);
+ if (invertedBitmapBuffer)
+ __wglFree(invertedBitmapBuffer);
+
+ return(bSuccessOrFail);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
+ HDC a,
+ DWORD b,
+ DWORD c,
+ DWORD d)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for outline TrueType fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+void * __wglRealloc(
+ void *oldPtr,
+ size_t newSize)
+{
+ void *newPtr = NULL;
+
+ if (newSize != 0) {
+ newPtr = (void *) GlobalAlloc(GPTR, newSize);
+ if (oldPtr && newPtr) {
+ DWORD oldSize = GlobalSize(oldPtr);
+
+ memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
+ GlobalFree(oldPtr);
+ }
+ } else if (oldPtr) {
+ GlobalFree(oldPtr);
+ }
+ if (newPtr == NULL) {
+ return NULL; /* XXX out of memory error */
+ }
+ return newPtr;
+}
+
+// ***********************************************************************
+
+
+/*****************************************************************************
+ * wglUseFontOutlinesW
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
+ chordalDeviation, extrusion, format, lpgmf);
+}
+
+/*****************************************************************************
+ * wglUseFontOutlinesA
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
+ {
+ DWORD glyphIndex;
+ UCHAR* glyphBuf;
+ DWORD glyphBufSize;
+
+
+ /*
+ * Flush any previous OpenGL errors. This allows us to check for
+ * new errors so they can be reported via the function return value.
+ */
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+
+ /*
+ * Make sure that the current font can be sampled accurately.
+ */
+ hNewFont = CreateHighResolutionFont(hDC);
+ if (!hNewFont)
+ return FALSE;
+
+ hOldFont = SelectObject(hDC, hNewFont);
+ if (!hOldFont)
+ return FALSE;
+
+ /*
+ * Preallocate a buffer for the outline data, and track its size:
+ */
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+
+ /*
+ * Process each glyph in the given range:
+ */
+ for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+ {
+ GLYPHMETRICS glyphMetrics;
+ DWORD glyphSize;
+ static MAT2 matrix =
+ {
+ {0, 1}, {0, 0},
+ {0, 0}, {0, 1}
+ };
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat =
+ &glyphMetricsFloatArray[glyphIndex - first];
+
+
+ /*
+ * Determine how much space is needed to store the glyph's
+ * outlines. If our glyph buffer isn't large enough,
+ * resize it.
+ */
+ glyphSize = GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ 0,
+ NULL,
+ &matrix
+ );
+ if (glyphSize < 0)
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ if (glyphSize > glyphBufSize)
+ {
+ __wglFree(glyphBuf);
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+ }
+
+
+ /*
+ * Get the glyph's outlines.
+ */
+ if (GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ glyphBufSize,
+ glyphBuf,
+ &matrix
+ ) < 0)
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+
+ glyphMetricsFloat->gmfBlackBoxX =
+ (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
+ glyphMetricsFloat->gmfBlackBoxY =
+ (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.x =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.y =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncX =
+ (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncY =
+ (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
+
+ /*
+ * Turn the glyph into a display list:
+ */
+ if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
+ glyphBuf,
+ glyphSize,
+ glyphMetricsFloat,
+ chordalDeviation + ScaleFactor,
+ extrusion,
+ format))
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+ /*
+ * Clean up temporary storage and return. If an error occurred,
+ * clear all OpenGL error flags and return FAILURE status;
+ * otherwise just return SUCCESS.
+ */
+ __wglFree(glyphBuf);
+
+ SelectObject(hDC, hOldFont);
+
+ if (_GLD_glGetError() == GL_NO_ERROR)
+ return TRUE; /*WGL_STATUS_SUCCESS*/
+ else
+ {
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+
+/*****************************************************************************
+ * CreateHighResolutionFont
+ *
+ * Gets metrics for the current font and creates an equivalent font
+ * scaled to the design units of the font.
+ *
+ *****************************************************************************/
+
+static HFONT
+CreateHighResolutionFont(HDC hDC)
+ {
+ UINT otmSize;
+ OUTLINETEXTMETRIC *otm;
+ LONG fontHeight, fontWidth, fontUnits;
+ LOGFONT logFont;
+
+ otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
+ if (otmSize == 0)
+ return NULL;
+
+ otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
+ if (otm == NULL)
+ return NULL;
+
+ otm->otmSize = otmSize;
+ if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
+ return NULL;
+
+ fontHeight = otm->otmTextMetrics.tmHeight -
+ otm->otmTextMetrics.tmInternalLeading;
+ fontWidth = otm->otmTextMetrics.tmAveCharWidth;
+ fontUnits = (LONG) otm->otmEMSquare;
+
+ ScaleFactor = 1.0F / (FLOAT) fontUnits;
+
+ logFont.lfHeight = - ((LONG) fontUnits);
+ logFont.lfWidth = (LONG)
+ ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfWeight = otm->otmTextMetrics.tmWeight;
+ logFont.lfItalic = otm->otmTextMetrics.tmItalic;
+ logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
+ logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
+ logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
+ logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logFont.lfQuality = DEFAULT_QUALITY;
+ logFont.lfPitchAndFamily =
+ otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
+ strcpy(logFont.lfFaceName,
+ (char *)otm + (int)otm->otmpFaceName);
+
+ hNewFont = CreateFontIndirect(&logFont);
+ if (hNewFont == NULL)
+ return NULL;
+
+ __wglFree(otm);
+
+ return hNewFont;
+ }
+
+
+
+/*****************************************************************************
+ * MakeDisplayListFromGlyph
+ *
+ * Converts the outline of a glyph to an OpenGL display list.
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+MakeDisplayListFromGlyph( IN DWORD listName,
+ IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ int status;
+
+ _GLD_glNewList(listName, GL_COMPILE);
+ status = DrawGlyph( glyphBuf,
+ glyphSize,
+ chordalDeviation,
+ extrusion,
+ format);
+
+ _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
+ glyphMetricsFloat->gmfCellIncY,
+ 0.0F);
+ _GLD_glEndList();
+
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * DrawGlyph
+ *
+ * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
+ * as needed, and then draws the glyph. Tessellation of the quadratic splines
+ * in the outline is controlled by "chordalDeviation", and the drawing
+ * primitives (lines or polygons) are selected by "format".
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+DrawGlyph( IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ INT status = 0;
+ FLOAT* p;
+ DWORD loop;
+ DWORD point;
+ GLUtesselator* tess = NULL;
+
+
+ /*
+ * Initialize the global buffer into which we place the outlines:
+ */
+ if (!InitLineBuf())
+ goto exit;
+
+
+ /*
+ * Convert the glyph outlines to a set of polyline loops.
+ * (See MakeLinesFromGlyph() for the format of the loop data
+ * structure.)
+ */
+ if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
+ goto exit;
+ p = LineBuf;
+
+
+ /*
+ * Now draw the loops in the appropriate format:
+ */
+ if (format == WGL_FONT_LINES)
+ {
+ /*
+ * This is the easy case. Just draw the outlines.
+ */
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ _GLD_glBegin(GL_LINE_LOOP);
+ for (point = (DWORD) *p++; point; --point)
+ {
+ _GLD_glVertex2fv(p);
+ p += 2;
+ }
+ _GLD_glEnd();
+ }
+ status = 1;
+ }
+
+ else if (format == WGL_FONT_POLYGONS)
+ {
+ double v[3];
+ FLOAT *save_p = p;
+ GLfloat z_value;
+
+ /*
+ * This is the hard case. We have to set up a tessellator
+ * to convert the outlines into a set of polygonal
+ * primitives, which the tessellator passes to some
+ * auxiliary routines for drawing.
+ */
+ if (!LoadGLUTesselator())
+ goto exit;
+ if (!InitVertBuf())
+ goto exit;
+ if (!(tess = gluNewTessProc()))
+ goto exit;
+ gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
+ gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
+ (void(CALLBACK *)()) TessVertexOutData);
+ gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
+ gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
+ gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
+ gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
+
+ TessErrorOccurred = 0;
+ _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
+ v[2] = 0.0;
+ z_value = 0.0f;
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ gluTessBeginContourProc(tess);
+
+ for (point = (DWORD) *p++; point; --point)
+ {
+ v[0] = p[0];
+ v[1] = p[1];
+ gluTessVertexProc(tess, v, p);
+ p += 2;
+ }
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+
+ status = !TessErrorOccurred;
+
+ /* Extrusion code */
+ if (extrusion) {
+ DWORD loops;
+ GLfloat thickness = (GLfloat) -extrusion;
+ FLOAT *vert, *vert2;
+ DWORD count;
+
+ p = save_p;
+ loops = (DWORD) *p++;
+
+ for (loop = 0; loop < loops; loop++) {
+ GLfloat dx, dy, len;
+ DWORD last;
+
+ count = (DWORD) *p++;
+ _GLD_glBegin(GL_QUAD_STRIP);
+
+ /* Check if the first and last vertex are identical
+ * so we don't draw the same quad twice.
+ */
+ vert = p + (count-1)*2;
+ last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
+
+ for (point = 0; point <= last; point++) {
+ vert = p + 2 * (point % last);
+ vert2 = p + 2 * ((point+1) % last);
+
+ dx = vert[0] - vert2[0];
+ dy = vert[1] - vert2[1];
+ len = (GLfloat)sqrt(dx * dx + dy * dy);
+
+ _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], thickness);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], 0.0f);
+ }
+
+ _GLD_glEnd();
+ p += count*2;
+ }
+
+ /* Draw the back face */
+ p = save_p;
+ v[2] = thickness;
+ _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
+ gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
+
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ count = (DWORD) *p++;
+
+ gluTessBeginContourProc(tess);
+
+ for (point = 0; point < count; point++)
+ {
+ vert = p + ((count-point-1)<<1);
+ v[0] = vert[0];
+ v[1] = vert[1];
+ gluTessVertexProc(tess, v, vert);
+ }
+ p += count*2;
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+ }
+
+#if DEBUG
+ if (TessErrorOccurred)
+ printf("Tessellation error %s\n",
+ gluErrorString(TessErrorOccurred));
+#endif
+ }
+
+
+exit:
+ FreeLineBuf();
+ if (tess)
+ gluDeleteTessProc(tess);
+ // UnloadGLUTesselator();
+ FreeVertBuf();
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * LoadGLUTesselator
+ *
+ * Maps the glu32.dll module and gets function pointers for the
+ * tesselator functions.
+ *****************************************************************************/
+
+static BOOL
+LoadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ return TRUE;
+
+ {
+ extern HINSTANCE hInstanceOpenGL;
+ char *gluName = "GLU32.DLL";
+// char name[256];
+// char *ptr;
+// int len;
+
+/*
+ len = GetModuleFileName(hInstanceOpenGL, name, 255);
+ if (len != 0)
+ {
+ ptr = name+len-1;
+ while (ptr > name && *ptr != '\\')
+ ptr--;
+ if (*ptr == '\\')
+ ptr++;
+ if (!stricmp(ptr, "cosmogl.dll"))
+ {
+ gluName = "COSMOGLU.DLL";
+ }
+ else if (!stricmp(ptr, "opengl32.dll"))
+ {
+ gluName = "GLU32.DLL";
+ }
+ }
+*/
+ if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
+ return FALSE;
+ }
+
+ if ((gluNewTessProc = (gluNewTessProto)
+ GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
+ return FALSE;
+
+ if ((gluDeleteTessProc = (gluDeleteTessProto)
+ GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginContourProc = (gluTessBeginContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessVertexProc = (gluTessVertexProto)
+ GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndContourProc = (gluTessEndContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessPropertyProc = (gluTessPropertyProto)
+ GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
+ return FALSE;
+
+ if ((gluTessNormalProc = (gluTessNormalProto)
+ GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
+ return FALSE;
+
+ if ((gluTessCallbackProc = (gluTessCallbackProto)
+ GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+
+/*****************************************************************************
+ * UnloadGLUTesselator
+ *
+ * Unmaps the glu32.dll module.
+ *****************************************************************************/
+
+static BOOL
+UnloadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ if (FreeLibrary(gluModuleHandle) == FALSE)
+ return FALSE;
+ gluModuleHandle = NULL;
+ }
+
+
+
+/*****************************************************************************
+ * TessVertexOut
+ *
+ * Used by tessellator to handle output vertexes.
+ *****************************************************************************/
+
+static void CALLBACK
+TessVertexOut(FLOAT p[3])
+ {
+ GLfloat v[2];
+
+ v[0] = p[0] * ScaleFactor;
+ v[1] = p[1] * ScaleFactor;
+ _GLD_glVertex2fv(v);
+ }
+
+static void CALLBACK
+TessVertexOutData(FLOAT p[3], GLfloat z)
+{
+ GLfloat v[3];
+
+ v[0] = (GLfloat) p[0];
+ v[1] = (GLfloat) p[1];
+ v[2] = z;
+ _GLD_glVertex3fv(v);
+}
+
+
+/*****************************************************************************
+ * TessCombine
+ *
+ * Used by tessellator to handle self-intersecting contours and degenerate
+ * geometry.
+ *****************************************************************************/
+
+static void CALLBACK
+TessCombine(double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData)
+ {
+ if (!AppendToVertBuf((FLOAT) coords[0])
+ || !AppendToVertBuf((FLOAT) coords[1])
+ || !AppendToVertBuf((FLOAT) coords[2]))
+ TessErrorOccurred = GL_OUT_OF_MEMORY;
+ *outData = VertBuf + (VertBufIndex - 3);
+ }
+
+
+
+/*****************************************************************************
+ * TessError
+ *
+ * Saves the last tessellator error code in the global TessErrorOccurred.
+ *****************************************************************************/
+
+static void CALLBACK
+TessError(GLenum error)
+ {
+ TessErrorOccurred = error;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromGlyph
+ *
+ * Converts the outline of a glyph from the TTPOLYGON format to a simple
+ * array of floating-point values containing one or more loops.
+ *
+ * The first element of the output array is a count of the number of loops.
+ * The loop data follows this count. Each loop consists of a count of the
+ * number of vertices it contains, followed by the vertices. Each vertex
+ * is an X and Y coordinate. For example, a single triangle might be
+ * described by this array:
+ *
+ * 1., 3., 0., 0., 1., 0., 0., 1.
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * #loops #verts x1 y1 x2 y2 x3 y3
+ *
+ * A two-loop glyph would look like this:
+ *
+ * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
+ *
+ * Line segments from the TTPOLYGON are transferred to the output array in
+ * the obvious way. Quadratic splines in the TTPOLYGON are converted to
+ * collections of line segments
+ *****************************************************************************/
+
+static int
+MakeLinesFromGlyph(IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation)
+ {
+ UCHAR* p;
+ int status = 0;
+
+
+ /*
+ * Pick up all the polygons (aka loops) that make up the glyph:
+ */
+ if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
+ goto exit;
+
+ p = glyphBuf;
+ while (p < glyphBuf + glyphSize)
+ {
+ if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
+ goto exit;
+ LineBuf[0] += 1.0F; /* increment loop count */
+ }
+
+ status = 1;
+
+exit:
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolygon
+ *
+ * Converts a TTPOLYGONHEADER and its associated curve structures into a
+ * single polyline loop in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
+ IN FLOAT chordalDeviation)
+ {
+ DWORD polySize;
+ UCHAR* polyStart;
+ DWORD vertexCountIndex;
+
+ /*
+ * Record where the polygon data begins, and where the loop's
+ * vertex count resides:
+ */
+ polyStart = *pp;
+ vertexCountIndex = LineBufIndex;
+ if (!AppendToLineBuf(0.0F))
+ return 0;
+
+ /*
+ * Extract relevant data from the TTPOLYGONHEADER:
+ */
+ polySize = GetDWord(pp);
+ if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
+ return 0;
+ LineBuf[vertexCountIndex] += 1.0F;
+
+ /*
+ * Process each of the TTPOLYCURVE structures in the polygon:
+ */
+ while (*pp < polyStart + polySize)
+ if (!MakeLinesFromTTPolycurve( pp,
+ vertexCountIndex,
+ chordalDeviation))
+ return 0;
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolyCurve
+ *
+ * Converts the lines and splines in a single TTPOLYCURVE structure to points
+ * in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviation)
+ {
+ WORD type;
+ WORD pointCount;
+
+
+ /*
+ * Pick up the relevant fields of the TTPOLYCURVE structure:
+ */
+ type = (WORD) GetWord(pp);
+ pointCount = (WORD) GetWord(pp);
+
+ /*
+ * Convert the "curve" to line segments:
+ */
+ if (type == TT_PRIM_LINE)
+ return MakeLinesFromTTLine( pp,
+ vertexCountIndex,
+ pointCount);
+ else if (type == TT_PRIM_QSPLINE)
+ return MakeLinesFromTTQSpline( pp,
+ vertexCountIndex,
+ pointCount,
+ chordalDeviation);
+ else
+ return 0;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTLine
+ *
+ * Converts points from the polyline in a TT_PRIM_LINE structure to
+ * equivalent points in the global LineBuf.
+ *****************************************************************************/
+static int
+MakeLinesFromTTLine( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount)
+ {
+ /*
+ * Just copy the line segments into the line buffer (converting
+ * type as we go):
+ */
+ LineBuf[vertexCountIndex] += pointCount;
+ while (pointCount--)
+ {
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
+ || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTQSpline
+ *
+ * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
+ * structure to polyline points in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount,
+ IN FLOAT chordalDeviation)
+ {
+ FLOAT x0, y0, x1, y1, x2, y2;
+ WORD point;
+
+ /*
+ * Process each of the non-interpolated points in the outline.
+ * To do this, we need to generate two interpolated points (the
+ * start and end of the arc) for each non-interpolated point.
+ * The first interpolated point is always the one most recently
+ * stored in LineBuf, so we just extract it from there. The
+ * second interpolated point is either the average of the next
+ * two points in the QSpline, or the last point in the QSpline
+ * if only one remains.
+ */
+ for (point = 0; point < pointCount - 1; ++point)
+ {
+ x0 = LineBuf[LineBufIndex - 2];
+ y0 = LineBuf[LineBufIndex - 1];
+
+ x1 = (FLOAT) GetFixed(pp);
+ y1 = (FLOAT) GetFixed(pp);
+
+ if (point == pointCount - 2)
+ {
+ /*
+ * This is the last arc in the QSpline. The final
+ * point is the end of the arc.
+ */
+ x2 = (FLOAT) GetFixed(pp);
+ y2 = (FLOAT) GetFixed(pp);
+ }
+ else
+ {
+ /*
+ * Peek at the next point in the input to compute
+ * the end of the arc:
+ */
+ x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
+ y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
+ /*
+ * Push the point back onto the input so it will
+ * be reused as the next off-curve point:
+ */
+ *pp -= 8;
+ }
+
+ if (!MakeLinesFromArc( x0, y0,
+ x1, y1,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviation * chordalDeviation))
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromArc
+ *
+ * Subdivides one arc of a quadratic spline until the chordal deviation
+ * tolerance requirement is met, then places the resulting set of line
+ * segments in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromArc( IN FLOAT x0,
+ IN FLOAT y0,
+ IN FLOAT x1,
+ IN FLOAT y1,
+ IN FLOAT x2,
+ IN FLOAT y2,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviationSquared)
+ {
+ FLOAT x01;
+ FLOAT y01;
+ FLOAT x12;
+ FLOAT y12;
+ FLOAT midPointX;
+ FLOAT midPointY;
+ FLOAT deltaX;
+ FLOAT deltaY;
+
+ /*
+ * Calculate midpoint of the curve by de Casteljau:
+ */
+ x01 = 0.5F * (x0 + x1);
+ y01 = 0.5F * (y0 + y1);
+ x12 = 0.5F * (x1 + x2);
+ y12 = 0.5F * (y1 + y2);
+ midPointX = 0.5F * (x01 + x12);
+ midPointY = 0.5F * (y01 + y12);
+
+
+ /*
+ * Estimate chordal deviation by the distance from the midpoint
+ * of the curve to its non-interpolated control point. If this
+ * distance is greater than the specified chordal deviation
+ * constraint, then subdivide. Otherwise, generate polylines
+ * from the three control points.
+ */
+ deltaX = midPointX - x1;
+ deltaY = midPointY - y1;
+ if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
+ {
+ MakeLinesFromArc( x0, y0,
+ x01, y01,
+ midPointX, midPointY,
+ vertexCountIndex,
+ chordalDeviationSquared);
+
+ MakeLinesFromArc( midPointX, midPointY,
+ x12, y12,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviationSquared);
+ }
+ else
+ {
+ /*
+ * The "pen" is already at (x0, y0), so we don't need to
+ * add that point to the LineBuf.
+ */
+ if (!AppendToLineBuf(x1)
+ || !AppendToLineBuf(y1)
+ || !AppendToLineBuf(x2)
+ || !AppendToLineBuf(y2))
+ return 0;
+ LineBuf[vertexCountIndex] += 2.0F;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitLineBuf
+ *
+ * Initializes the global LineBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitLineBuf(void)
+ {
+ if (!(LineBuf = (FLOAT*)
+ __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ LineBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitVertBuf
+ *
+ * Initializes the global VertBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitVertBuf(void)
+ {
+ if (!(VertBuf = (FLOAT*)
+ __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ VertBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToLineBuf
+ *
+ * Appends one floating-point value to the global LineBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *****************************************************************************/
+
+static int
+AppendToLineBuf(FLOAT value)
+ {
+ if (LineBufIndex >= LineBufSize)
+ {
+ FLOAT* f;
+
+ f = (FLOAT*) __wglRealloc(LineBuf,
+ (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
+ if (!f)
+ return 0;
+ LineBuf = f;
+ }
+ LineBuf[LineBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToVertBuf
+ *
+ * Appends one floating-point value to the global VertBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *
+ * Note that we can't realloc this one, because the tessellator is using
+ * pointers into it.
+ *****************************************************************************/
+
+static int
+AppendToVertBuf(FLOAT value)
+ {
+ if (VertBufIndex >= VertBufSize)
+ return 0;
+ VertBuf[VertBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * FreeLineBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeLineBuf(void)
+ {
+ if (LineBuf)
+ {
+ __wglFree(LineBuf);
+ LineBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * FreeVertBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeVertBuf(void)
+ {
+ if (VertBuf)
+ {
+ __wglFree(VertBuf);
+ VertBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * GetWord
+ *
+ * Fetch the next 16-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[1] << 8) + (*p)[0];
+ *p += 2;
+ return value;
+ }
+
+
+
+/*****************************************************************************
+ * GetDWord
+ *
+ * Fetch the next 32-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetDWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
+ *p += 4;
+ return value;
+ }
+
+
+
+
+/*****************************************************************************
+ * GetFixed
+ *
+ * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
+ * convert it to floating-point, and increment the stream pointer to the next
+ * unscanned byte.
+ *****************************************************************************/
+
+static double GetFixed(
+ UCHAR** p)
+{
+ long hiBits, loBits;
+ double value;
+
+ loBits = GetWord(p);
+ hiBits = GetWord(p);
+ value = (double) ((hiBits << 16) | loBits) / 65536.0;
+
+ return value * ScaleFactor;
+}
+
+// ***********************************************************************
+
diff --git a/src/mesa/drivers/windows/gldirect/dglwgl.h b/src/mesa/drivers/windows/gldirect/dglwgl.h
new file mode 100644
index 0000000..c488ff9
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglwgl.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#ifndef __DGLWGL_H
+#define __DGLWGL_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <GL\gl.h>
+
+#include "dglcontext.h"
+#include "dglglobals.h"
+#include "dglmacros.h"
+#include "ddlog.h"
+#include "dglpf.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PROC proc;
+ char *name;
+} DGL_extension;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _USE_GLD3_WGL
+int APIENTRY DGL_ChoosePixelFormat(HDC a, CONST PIXELFORMATDESCRIPTOR *ppfd);
+BOOL APIENTRY DGL_CopyContext(HGLRC a, HGLRC b, UINT c);
+HGLRC APIENTRY DGL_CreateContext(HDC a);
+HGLRC APIENTRY DGL_CreateLayerContext(HDC a, int b);
+BOOL APIENTRY DGL_DeleteContext(HGLRC a);
+BOOL APIENTRY DGL_DescribeLayerPlane(HDC a, int b, int c, UINT d, LPLAYERPLANEDESCRIPTOR e);
+int APIENTRY DGL_DescribePixelFormat(HDC a, int b, UINT c, LPPIXELFORMATDESCRIPTOR d);
+HGLRC APIENTRY DGL_GetCurrentContext(void);
+HDC APIENTRY DGL_GetCurrentDC(void);
+PROC APIENTRY DGL_GetDefaultProcAddress(LPCSTR a);
+int APIENTRY DGL_GetLayerPaletteEntries(HDC a, int b, int c, int d, COLORREF *e);
+int APIENTRY DGL_GetPixelFormat(HDC a);
+PROC APIENTRY DGL_GetProcAddress(LPCSTR a);
+BOOL APIENTRY DGL_MakeCurrent(HDC a, HGLRC b);
+BOOL APIENTRY DGL_RealizeLayerPalette(HDC a, int b, BOOL c);
+int APIENTRY DGL_SetLayerPaletteEntries(HDC a, int b, int c, int d, CONST COLORREF *e);
+BOOL APIENTRY DGL_SetPixelFormat(HDC a, int b, CONST PIXELFORMATDESCRIPTOR *c);
+BOOL APIENTRY DGL_ShareLists(HGLRC a, HGLRC b);
+BOOL APIENTRY DGL_SwapBuffers(HDC a);
+BOOL APIENTRY DGL_SwapLayerBuffers(HDC a, UINT b);
+BOOL APIENTRY DGL_UseFontBitmapsA(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontBitmapsW(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontOutlinesA(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+BOOL APIENTRY DGL_UseFontOutlinesW(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+#endif //_USE_GLD3_WGL
+
+BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dll_main.c b/src/mesa/drivers/windows/gldirect/dll_main.c
new file mode 100644
index 0000000..04f6466
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dll_main.c
@@ -0,0 +1,816 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+// INITGUID must only be defined once.
+// Don't put it in a shared header file!
+// GLD3 uses dxguid.lib, so INITGUID must *not* be used!
+#ifndef _USE_GLD3_WGL
+#define INITGUID
+#endif // _USE_GLD3_WGL
+
+#include "dllmain.h"
+
+#include "snap/graphics.h"
+#include "drvlib/os/os.h"
+
+#ifdef _USE_GLD3_WGL
+typedef void (APIENTRY *LPDGLSPLASHSCREEN)(int, int, char*);
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+BOOL bInitialized = FALSE; // callback driver initialized?
+BOOL bExited = FALSE; // callback driver exited this instance?
+HINSTANCE hInstanceDll = NULL; // DLL instance handle
+
+static BOOL bDriverValidated = FALSE; // prior validation status
+static BOOL bSplashScreen = TRUE; // Splash Screen ?
+static BOOL bValidINIFound = FALSE; // Have we found a valid INI file?
+
+HHOOK hKeyHook = NULL; // global keyboard handler hook
+
+// Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+int _gld_bMultiThreaded = FALSE;
+
+// ***********************************************************************
+
+DWORD dwLogging = 0; // Logging flag
+DWORD dwDebugLevel = 0; // Log debug level
+
+char szLogPath[_MAX_PATH] = {"\0"}; // Log file path
+char szSNAPPath[_MAX_PATH] = {"\0"}; // SNAP driver path
+
+#ifndef _USE_GLD3_WGL
+DGL_wglFuncs wglFuncs = {
+ sizeof(DGL_wglFuncs),
+ DGL_ChoosePixelFormat,
+ DGL_CopyContext,
+ DGL_CreateContext,
+ DGL_CreateLayerContext,
+ DGL_DeleteContext,
+ DGL_DescribeLayerPlane,
+ DGL_DescribePixelFormat,
+ DGL_GetCurrentContext,
+ DGL_GetCurrentDC,
+ DGL_GetDefaultProcAddress,
+ DGL_GetLayerPaletteEntries,
+ DGL_GetPixelFormat,
+ DGL_GetProcAddress,
+ DGL_MakeCurrent,
+ DGL_RealizeLayerPalette,
+ DGL_SetLayerPaletteEntries,
+ DGL_SetPixelFormat,
+ DGL_ShareLists,
+ DGL_SwapBuffers,
+ DGL_SwapLayerBuffers,
+ DGL_UseFontBitmapsA,
+ DGL_UseFontBitmapsW,
+ DGL_UseFontOutlinesA,
+ DGL_UseFontOutlinesW,
+};
+
+DGL_mesaFuncs mesaFuncs = {
+ sizeof(DGL_mesaFuncs),
+};
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+typedef struct {
+ DWORD dwDriver; // 0=SciTech SW, 1=Direct3D SW, 2=Direct3D HW
+ BOOL bMipmapping; // 0=off, 1=on
+ BOOL bMultitexture; // 0=off, 1=on
+ BOOL bWaitForRetrace; // 0=off, 1=on
+ BOOL bFullscreenBlit; // 0=off, 1=on
+ BOOL bFastFPU; // 0=off, 1=on
+ BOOL bDirectDrawPersistant;// 0=off, 1=on
+ BOOL bPersistantBuffers; // 0=off, 1=on
+ DWORD dwLogging; // 0=off, 1=normal, 2=crash-proof
+ DWORD dwLoggingSeverity; // 0=all, 1=warnings+errors, 2=errors only
+ BOOL bMessageBoxWarnings;// 0=off, 1=on
+ BOOL bMultiThreaded; // 0=off, 1=on
+ BOOL bAppCustomizations; // 0=off, 1=on
+ BOOL bHotKeySupport; // 0=off, 1=on
+ BOOL bSplashScreen; // 0=off, 1=on
+
+#ifdef _USE_GLD3_WGL
+ //
+ // New for GLDirect 3.0
+ //
+ DWORD dwAdapter; // DX8 adpater ordinal
+ DWORD dwTnL; // Transform & Lighting type
+ DWORD dwMultisample; // DX8 multisample type
+#endif // _USE_GLD3_WGL
+} INI_settings;
+
+static INI_settings ini;
+
+// ***********************************************************************
+
+BOOL APIENTRY DGL_initDriver(
+#ifdef _USE_GLD3_WGL
+ void)
+{
+#else
+ DGL_wglFuncs *lpWglFuncs,
+ DGL_mesaFuncs *lpMesaFuncs)
+{
+ // Check for valid pointers
+ if ((lpWglFuncs == NULL) || (lpMesaFuncs == NULL))
+ return FALSE;
+
+ // Check for valid structs
+ if (lpWglFuncs->dwSize != sizeof(DGL_wglFuncs)) {
+ return FALSE;
+ }
+
+ // Check for valid structs
+ if (lpMesaFuncs->dwSize != sizeof(DGL_mesaFuncs)) {
+ return FALSE;
+ }
+
+ // Copy the Mesa functions
+ memcpy(&mesaFuncs, lpMesaFuncs, sizeof(DGL_mesaFuncs));
+
+ // Pass back the wgl functions
+ memcpy(lpWglFuncs, &wglFuncs, sizeof(DGL_wglFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Finally initialize the callback driver
+ if (!dglInitDriver())
+ return FALSE;
+
+ return TRUE;
+};
+
+// ***********************************************************************
+
+BOOL ReadINIFile(
+ HINSTANCE hInstance)
+{
+ char szModuleFilename[MAX_PATH];
+ char szSystemDirectory[MAX_PATH];
+ const char szSectionName[] = "Config";
+ char szINIFile[MAX_PATH];
+ int pos;
+
+ // Now using the DLL module handle. KeithH, 24/May/2000.
+ // Addendum: GetModuleFileName(NULL, ... returns process filename,
+ // GetModuleFileName(hModule, ... returns DLL filename,
+
+ // Get the dll path and filename.
+ GetModuleFileName(hInstance, &szModuleFilename[0], MAX_PATH); // NULL for current process
+ // Get the System directory.
+ GetSystemDirectory(&szSystemDirectory[0], MAX_PATH);
+
+ // Test to see if DLL is in system directory.
+ if (strnicmp(szModuleFilename, szSystemDirectory, strlen(szSystemDirectory))==0) {
+ // DLL *is* in system directory.
+ // Return FALSE to indicate that registry keys should be read.
+ return FALSE;
+ }
+
+ // Compose filename of INI file
+ strcpy(szINIFile, szModuleFilename);
+ pos = strlen(szINIFile);
+ while (szINIFile[pos] != '\\') {
+ pos--;
+ }
+ szINIFile[pos+1] = '\0';
+ // Use run-time DLL path for log file too
+ strcpy(szLogPath, szINIFile);
+ szLogPath[pos] = '\0';
+ // Complete full INI file path
+ strcat(szINIFile, "gldirect.ini");
+
+ // Read settings from private INI file.
+ // Note that defaults are contained in the calls.
+ ini.dwDriver = GetPrivateProfileInt(szSectionName, "dwDriver", 2, szINIFile);
+ ini.bMipmapping = GetPrivateProfileInt(szSectionName, "bMipmapping", 1, szINIFile);
+ ini.bMultitexture = GetPrivateProfileInt(szSectionName, "bMultitexture", 1, szINIFile);
+ ini.bWaitForRetrace = GetPrivateProfileInt(szSectionName, "bWaitForRetrace", 0, szINIFile);
+ ini.bFullscreenBlit = GetPrivateProfileInt(szSectionName, "bFullscreenBlit", 0, szINIFile);
+ ini.bFastFPU = GetPrivateProfileInt(szSectionName, "bFastFPU", 1, szINIFile);
+ ini.bDirectDrawPersistant = GetPrivateProfileInt(szSectionName, "bPersistantDisplay", 0, szINIFile);
+ ini.bPersistantBuffers = GetPrivateProfileInt(szSectionName, "bPersistantResources", 0, szINIFile);
+ ini.dwLogging = GetPrivateProfileInt(szSectionName, "dwLogging", 0, szINIFile);
+ ini.dwLoggingSeverity = GetPrivateProfileInt(szSectionName, "dwLoggingSeverity", 0, szINIFile);
+ ini.bMessageBoxWarnings = GetPrivateProfileInt(szSectionName, "bMessageBoxWarnings", 0, szINIFile);
+ ini.bMultiThreaded = GetPrivateProfileInt(szSectionName, "bMultiThreaded", 0, szINIFile);
+ ini.bAppCustomizations = GetPrivateProfileInt(szSectionName, "bAppCustomizations", 1, szINIFile);
+ ini.bHotKeySupport = GetPrivateProfileInt(szSectionName, "bHotKeySupport", 0, szINIFile);
+ ini.bSplashScreen = GetPrivateProfileInt(szSectionName, "bSplashScreen", 1, szINIFile);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ ini.dwAdapter = GetPrivateProfileInt(szSectionName, "dwAdapter", 0, szINIFile);
+ // dwTnL now defaults to zero (chooses TnL at runtime). KeithH
+ ini.dwTnL = GetPrivateProfileInt(szSectionName, "dwTnL", 0, szINIFile);
+ ini.dwMultisample = GetPrivateProfileInt(szSectionName, "dwMultisample", 0, szINIFile);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dllReadRegistry(
+ HINSTANCE hInstance)
+{
+ // Read settings from INI file, if available
+ bValidINIFound = FALSE;
+ if (ReadINIFile(hInstance)) {
+ const char *szRendering[3] = {
+ "SciTech Software Renderer",
+ "Direct3D MMX Software Renderer",
+ "Direct3D Hardware Renderer"
+ };
+ // Set globals
+ glb.bPrimary = 1;
+ glb.bHardware = (ini.dwDriver == 2) ? 1 : 0;
+#ifndef _USE_GLD3_WGL
+ memset(&glb.ddGuid, 0, sizeof(glb.ddGuid));
+ glb.d3dGuid = (ini.dwDriver == 2) ? IID_IDirect3DHALDevice : IID_IDirect3DRGBDevice;
+#endif // _USE_GLD3_WGL
+ strcpy(glb.szDDName, "Primary");
+ strcpy(glb.szD3DName, szRendering[ini.dwDriver]);
+ glb.dwRendering = ini.dwDriver;
+ glb.bUseMipmaps = ini.bMipmapping;
+ glb.bMultitexture = ini.bMultitexture;
+ glb.bWaitForRetrace = ini.bWaitForRetrace;
+ glb.bFullscreenBlit = ini.bFullscreenBlit;
+ glb.bFastFPU = ini.bFastFPU;
+ glb.bDirectDrawPersistant = ini.bDirectDrawPersistant;
+ glb.bPersistantBuffers = ini.bPersistantBuffers;
+ dwLogging = ini.dwLogging;
+ dwDebugLevel = ini.dwLoggingSeverity;
+ glb.bMessageBoxWarnings = ini.bMessageBoxWarnings;
+ glb.bMultiThreaded = ini.bMultiThreaded;
+ glb.bAppCustomizations = ini.bAppCustomizations;
+ glb.bHotKeySupport = ini.bHotKeySupport;
+ bSplashScreen = ini.bSplashScreen;
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwAdapter = ini.dwAdapter;
+ glb.dwDriver = ini.dwDriver;
+ glb.dwTnL = ini.dwTnL;
+ glb.dwMultisample = ini.dwMultisample;
+#endif
+ bValidINIFound = TRUE;
+ return TRUE;
+ }
+ // Read settings from registry
+ else {
+ HKEY hReg;
+ DWORD cbValSize;
+ DWORD dwType = REG_SZ; // Registry data type for strings
+ BOOL bRegistryError;
+ BOOL bSuccess;
+
+#define REG_READ_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegQueryValueEx( hReg, (a), \
+ NULL, NULL, (LPBYTE)&(b), &cbValSize )) \
+ bRegistryError = TRUE;
+
+#define REG_READ_DEVICEID(a, b) \
+ cbValSize = MAX_DDDEVICEID_STRING; \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+#define REG_READ_STRING(a, b) \
+ cbValSize = sizeof((b)); \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+ // Read settings from the registry.
+
+ // Open the registry key for the current user if it exists.
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ // Otherwise open the registry key for the local machine.
+ if (!bSuccess)
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(DIRECTGL_REG_KEY_ROOT,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (!bSuccess)
+ return FALSE;
+
+ bRegistryError = FALSE;
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PRIMARY, glb.bPrimary);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_HW, glb.bHardware);
+#ifndef _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DD_GUID, glb.ddGuid);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_GUID, glb.d3dGuid);
+#endif // _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_LOGGING, dwLogging);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DEBUGLEVEL, dwDebugLevel);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_RENDERING, glb.dwRendering);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITEXTURE, glb.bMultitexture);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_WAITFORRETRACE, glb.bWaitForRetrace);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FULLSCREENBLIT, glb.bFullscreenBlit);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_USEMIPMAPS, glb.bUseMipmaps);
+
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_DD_NAME, glb.szDDName);
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_D3D_NAME, glb.szD3DName);
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MSGBOXWARNINGS, glb.bMessageBoxWarnings);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTDISPLAY, glb.bDirectDrawPersistant);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTBUFFERS, glb.bPersistantBuffers);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FASTFPU, glb.bFastFPU);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_HOTKEYS, glb.bHotKeySupport);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITHREAD, glb.bMultiThreaded);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_APPCUSTOM, glb.bAppCustomizations);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_SPLASHSCREEN, bSplashScreen);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwDriver = glb.dwRendering;
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_ADAPTER, glb.dwAdapter);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_TNL, glb.dwTnL);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTISAMPLE, glb.dwMultisample);
+#endif
+
+ RegCloseKey(hReg);
+
+ // Open the global registry key for GLDirect
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (bSuccess) {
+ // Read the installation path for GLDirect
+ REG_READ_STRING("InstallLocation",szLogPath);
+ RegCloseKey(hReg);
+ }
+
+ if (bRegistryError || !bSuccess)
+ return FALSE;
+ else
+ return TRUE;
+
+#undef REG_READ_DWORD
+#undef REG_READ_DEVICEID
+#undef REG_READ_STRING
+ }
+}
+
+// ***********************************************************************
+
+BOOL dllWriteRegistry(
+ void )
+{
+ HKEY hReg;
+ DWORD dwCreateDisposition, cbValSize;
+ BOOL bRegistryError = FALSE;
+
+#define REG_WRITE_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegSetValueEx( hReg, (a), \
+ 0, REG_DWORD, (LPBYTE)&(b), cbValSize )) \
+ bRegistryError = TRUE;
+
+ if (ERROR_SUCCESS == RegCreateKeyEx( DIRECTGL_REG_KEY_ROOT, DIRECTGL_REG_SETTINGS_KEY,
+ 0, NULL, 0, KEY_WRITE, NULL, &hReg,
+ &dwCreateDisposition )) {
+ RegFlushKey(hReg); // Make sure keys are written to disk
+ RegCloseKey(hReg);
+ hReg = NULL;
+ }
+
+ if (bRegistryError)
+ return FALSE;
+ else
+ return TRUE;
+
+#undef REG_WRITE_DWORD
+}
+
+// ***********************************************************************
+
+void dglInitHotKeys(HINSTANCE hInstance)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Install global keyboard interceptor
+ hKeyHook = SetWindowsHookEx(WH_KEYBOARD, dglKeyProc, hInstance, 0);
+}
+
+// ***********************************************************************
+
+void dglExitHotKeys(void)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Remove global keyboard interceptor
+ if (hKeyHook)
+ UnhookWindowsHookEx(hKeyHook);
+ hKeyHook = NULL;
+}
+
+// ***********************************************************************
+
+// Note: This app-customization step must be performed in both the main
+// OpenGL32 driver and the callback driver DLLs for multithreading option.
+void dglSetAppCustomizations(void)
+{
+ char szModuleFileName[MAX_PATH];
+ int iSize = MAX_PATH;
+
+ // Get the currently loaded EXE filename.
+ GetModuleFileName(NULL, &szModuleFileName[0], MAX_PATH); // NULL for current process
+ strupr(szModuleFileName);
+ iSize = strlen(szModuleFileName);
+
+ // Check for specific EXEs and adjust global settings accordingly
+
+ // NOTE: In GLD3.x "bDirectDrawPersistant" corresponds to IDirect3D8 and
+ // "bPersistantBuffers" corresponds to IDirect3DDevice8. KeithH
+
+ // Case 1: 3DStudio must be multi-threaded
+ // Added: Discreet GMAX (3DStudio MAX 4 for gamers. KeithH)
+ if (strstr(szModuleFileName, "3DSMAX.EXE")
+ || strstr(szModuleFileName, "3DSVIZ.EXE")
+ || strstr(szModuleFileName, "GMAX.EXE")) {
+ glb.bMultiThreaded = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 2: Solid Edge must use pre-allocated resources for all GLRCs
+ if (strstr(szModuleFileName, "PART.EXE")
+ || strstr(szModuleFileName, "ASSEMBL.EXE")
+ || strstr(szModuleFileName, "DRAFT.EXE")
+ || strstr(szModuleFileName, "SMARTVW.EXE")
+ || strstr(szModuleFileName, "SMETAL.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 3: Sudden Depth creates and destroys GLRCs on paint commands
+ if (strstr(szModuleFileName, "SUDDEPTH.EXE")
+ || strstr(szModuleFileName, "SUDDEMO.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ glb.bFullscreenBlit = TRUE;
+ return;
+ }
+
+ // Case 4: StereoGraphics test apps create and destroy GLRCs on paint commands
+ if (strstr(szModuleFileName, "REDBLUE.EXE")
+ || strstr(szModuleFileName, "DIAGNOSE.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 5: Pipes screen savers share multiple GLRCs for same window
+ if (strstr(szModuleFileName, "PIPES.SCR")
+ || (strstr(szModuleFileName, "PIPES") && strstr(szModuleFileName, ".SCR"))) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 6: AutoVue uses sub-viewport ops which are temporarily broken in stereo window
+ if (strstr(szModuleFileName, "AVWIN.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+ // Case 7: Quake3 is waiting for DDraw objects to be released at exit
+ if (strstr(szModuleFileName, "QUAKE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ glb.bFullscreenBlit = FALSE;
+ return;
+ }
+ // Case 8: Reflection GLX server is unable to switch contexts at run-time
+ if (strstr(szModuleFileName, "RX.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bMessageBoxWarnings = FALSE;
+ return;
+ }
+ // Case 9: Original AutoCAD 2000 must share DDraw objects across GLRCs
+ if (strstr(szModuleFileName, "ACAD.EXE")) {
+ glb.bFastFPU = FALSE;
+ if (GetModuleHandle("wopengl6.hdi") != NULL) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ }
+ return;
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglInitDriver(void)
+{
+ UCHAR szExeName[MAX_PATH];
+ const char *szRendering[] = {
+ "Mesa Software",
+ "Direct3D RGB SW",
+ "Direct3D HW",
+ };
+ static ibool bWarnOnce = false;
+
+ // Already initialized?
+ if (bInitialized)
+ return TRUE;
+
+ // Moved from DllMain DLL_PROCESS_ATTACH:
+
+ // (Re-)Init defaults
+ dglInitGlobals();
+
+ // Read registry or INI file settings
+ if (!dllReadRegistry(hInstanceDll)) {
+ if (!bWarnOnce)
+ MessageBox( NULL, "GLDirect has not been configured.\n\n"
+ "Please run the configuration program\n"
+ "before using GLDirect with applications.\n",
+ "GLDirect", MB_OK | MB_ICONWARNING);
+ bWarnOnce = true;
+ return FALSE;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Must do this as early as possible.
+ // Need to read regkeys/ini-file first though.
+ gldInitDriverPointers(glb.dwDriver);
+
+ // Create private driver globals
+ _gldDriver.CreatePrivateGlobals();
+#endif
+ // Overide settings with application customizations
+ if (glb.bAppCustomizations)
+ dglSetAppCustomizations();
+
+//#ifndef _USE_GLD3_WGL
+ // Set the global memory type to either sysmem or vidmem
+ glb.dwMemoryType = glb.bHardware ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY;
+//#endif
+
+ // Multi-threaded support overides persistant display support
+ if (glb.bMultiThreaded)
+ glb.bDirectDrawPersistant = glb.bPersistantBuffers = FALSE;
+
+ // Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+ _gld_bMultiThreaded = glb.bMultiThreaded;
+
+ // Start logging
+ ddlogPathOption(szLogPath);
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+ ddlogOpen((DDLOG_loggingMethodType)dwLogging,
+ (DDLOG_severityType)dwDebugLevel);
+
+ // Obtain the name of the calling app
+ ddlogMessage(DDLOG_SYSTEM, "Driver : SciTech GLDirect 4.0\n");
+ GetModuleFileName(NULL, szExeName, sizeof(szExeName));
+ ddlogPrintf(DDLOG_SYSTEM, "Executable : %s", szExeName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "DirectDraw device: %s", glb.szDDName);
+ ddlogPrintf(DDLOG_SYSTEM, "Direct3D driver : %s", glb.szD3DName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Rendering type : %s", szRendering[glb.dwRendering]);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Multithreaded : %s", glb.bMultiThreaded ? "Enabled" : "Disabled");
+ ddlogPrintf(DDLOG_SYSTEM, "Display resources: %s", glb.bDirectDrawPersistant ? "Persistant" : "Instanced");
+ ddlogPrintf(DDLOG_SYSTEM, "Buffer resources : %s", glb.bPersistantBuffers ? "Persistant" : "Instanced");
+
+ dglInitContextState();
+ dglBuildPixelFormatList();
+ //dglBuildTextureFormatList();
+
+ // D3D callback driver is now successfully initialized
+ bInitialized = TRUE;
+ // D3D callback driver is now ready to be exited
+ bExited = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void dglExitDriver(void)
+{
+
+ // Only need to clean up once per instance:
+ // May be called implicitly from DLL_PROCESS_DETACH,
+ // or explicitly from DGL_exitDriver().
+ if (bExited)
+ return;
+ bExited = TRUE;
+
+ // DDraw objects may be invalid when DLL unloads.
+__try {
+
+ // Clean-up sequence (moved from DLL_PROCESS_DETACH)
+#ifndef _USE_GLD3_WGL
+ dglReleaseTextureFormatList();
+#endif
+ dglReleasePixelFormatList();
+ dglDeleteContextState();
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyPrivateGlobals();
+#endif
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglExitDriver.");
+}
+
+ // Close the log file
+ ddlogClose();
+}
+
+// ***********************************************************************
+
+int WINAPI DllMain(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ // Cache DLL instance handle
+ hInstanceDll = hInstance;
+
+ // Flag that callback driver has yet to be initialized
+ bInitialized = bExited = FALSE;
+
+#ifndef _USE_GLD3_WGL
+ // Init internal Mesa function pointers
+ memset(&mesaFuncs, 0, sizeof(DGL_mesaFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Init defaults
+ dglInitGlobals();
+
+ // Defer rest of DLL initialization to 1st WGL function call
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Call exit clean-up sequence
+ dglExitDriver();
+ break;
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_exitDriver(void)
+{
+ // Call exit clean-up sequence
+ dglExitDriver();
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_reinitDriver(void)
+{
+ // Force init sequence again
+ bInitialized = bExited = FALSE;
+ dglInitDriver();
+}
+
+// ***********************************************************************
+
+int WINAPI DllInitialize(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ // Some Watcom compiled executables require this.
+ return DllMain(hInstance, fdwReason, pvReserved);
+}
+
+// ***********************************************************************
+
+void DGL_LoadSplashScreen(int piReg, char* pszUser)
+{
+ HINSTANCE hSplashDll = NULL;
+ LPDGLSPLASHSCREEN dglSplashScreen = NULL;
+ static BOOL bOnce = FALSE;
+ static int iReg = 0;
+ static char szUser[255] = {"\0"};
+
+ // Display splash screen at all?
+ if (!bSplashScreen)
+ return;
+
+ // Only display splash screen once
+ if (bOnce)
+ return;
+ bOnce = TRUE;
+
+ // Make local copy of string for passing to DLL
+ if (pszUser)
+ strcpy(szUser, pszUser);
+ iReg = piReg;
+
+ // Load Splash Screen DLL
+ // (If it fails to load for any reason, we don't care...)
+ hSplashDll = LoadLibrary("gldsplash.dll");
+ if (hSplashDll) {
+ // Execute the Splash Screen function
+ dglSplashScreen = (LPDGLSPLASHSCREEN)GetProcAddress(hSplashDll, "GLDSplashScreen");
+ if (dglSplashScreen)
+ (*dglSplashScreen)(1, iReg, szUser);
+ // Don't unload the DLL since splash screen dialog is modeless now
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglValidate()
+{
+ char *szCaption = "SciTech GLDirect Driver";
+ UINT uType = MB_OK | MB_ICONEXCLAMATION;
+
+#ifdef _USE_GLD3_WGL
+ // (Re)build pixelformat list
+ if (glb.bPixelformatsDirty)
+ _gldDriver.BuildPixelformatList();
+#endif
+
+ // Check to see if we have already validated
+ if (bDriverValidated && bInitialized)
+ return TRUE;
+
+ // Since all (most) the WGL functions must be validated at this point,
+ // this also insure that the callback driver is completely initialized.
+ if (!bInitialized)
+ if (!dglInitDriver()) {
+ MessageBox(NULL,
+ "The GLDirect driver could not initialize.\n\n"
+ "Please run the configuration program to\n"
+ "properly configure the driver, or else\n"
+ "re-run the installation program.", szCaption, uType);
+ _exit(1); // Bail
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
diff --git a/src/mesa/drivers/windows/gldirect/dllmain.h b/src/mesa/drivers/windows/gldirect/dllmain.h
new file mode 100644
index 0000000..d898c31
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dllmain.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+#ifndef __DLLMAIN_H
+#define __DLLMAIN_H
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#ifndef _USE_GLD3_WGL
+#include "DirectGL.h"
+#endif // _USE_GLD3_WGL
+
+#include "gldirect/regkeys.h"
+#include "dglglobals.h"
+#include "ddlog.h"
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif // _USE_GLD3_WGL
+
+#include "dglwgl.h"
+
+extern BOOL bInitialized;
+
+BOOL dglInitDriver(void);
+void dglExitDriver(void);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
new file mode 100644
index 0000000..1eb19ca
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
@@ -0,0 +1,40 @@
+/* $Id: gld_debug_clip.c,v 1.1 2004/04/20 11:13:11 alanh 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:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_clip.c HACK")
+
+void _math_test_all_cliptest_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
new file mode 100644
index 0000000..00c428b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
@@ -0,0 +1,40 @@
+/* $Id: gld_debug_norm.c,v 1.1 2004/04/20 11:13:11 alanh 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:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_norm.c HACK")
+
+void _math_test_all_normal_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
new file mode 100644
index 0000000..d6e64b8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
@@ -0,0 +1,42 @@
+/* $Id: gld_debug_xform.c,v 1.1 2004/04/20 11:13:11 alanh 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.
+ */
+
+/*
+ * Updated for P6 architecture by Gareth Hughes.
+ */
+
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_xform.c HACK")
+
+void _math_test_all_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_dispatch.c b/src/mesa/drivers/windows/gldirect/gld_dispatch.c
new file mode 100644
index 0000000..e05d767
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_dispatch.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+*
+* 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: Thread-aware dispatch table.
+*
+****************************************************************************/
+
+#include "glheader.h"
+#include "glapi.h"
+#include "glapitable.h"
+#include "mtypes.h"
+#include "context.h"
+
+#define KEYWORD1
+#define KEYWORD2 GLAPIENTRY
+#if defined(USE_MGL_NAMESPACE)
+ #define NAME(func) mgl##func
+#else
+ #define NAME(func) gl##func
+#endif
+
+#if 0
+// Altered these to get the dispatch table from
+// the current context of the calling thread.
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (gc->CurrentDispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (gc->CurrentDispatch->FUNC) ARGS
+#else // #if 0
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (_glapi_Dispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (_glapi_Dispatch->FUNC) ARGS
+#endif // #if 0
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#include "glapitemp.h"
diff --git a/src/mesa/drivers/windows/gldirect/gld_driver.c b/src/mesa/drivers/windows/gldirect/gld_driver.c
new file mode 100644
index 0000000..f7c5756
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_driver.c
@@ -0,0 +1,279 @@
+/****************************************************************************
+*
+* 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 functions and interfaces
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "gld_driver.h"
+#include "ddlog.h"
+#include "glheader.h"
+
+// For glGetString().
+#include "common_x86_asm.h"
+
+//---------------------------------------------------------------------------
+
+static char *szDriverError = "Driver used before initialisation!";
+
+// This holds our dynamically created OpenGL renderer string.
+// 256 chars should be plenty - remember that some apps display this.
+static char _gldRendererString[256];
+
+static char *szVendor = "SciTech Software, Inc.";
+
+//---------------------------------------------------------------------------
+
+extern BOOL gldGetDXErrorString_DX(HRESULT hr, char *buf, int nBufSize);
+
+extern BOOL gldCreateDrawable_MesaSW(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_MesaSW(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_MesaSW(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_MesaSW(void);
+extern BOOL gldDestroyPrivateGlobals_MesaSW(void);
+extern BOOL gldBuildPixelformatList_MesaSW(void);
+extern BOOL gldInitialiseMesa_MesaSW(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_MesaSW(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_MesaSW(LPCSTR a);
+extern BOOL gldGetDisplayMode_MesaSW(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+extern BOOL gldCreateDrawable_DX(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_DX(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_DX(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_DX(void);
+extern BOOL gldDestroyPrivateGlobals_DX(void);
+extern BOOL gldBuildPixelformatList_DX(void);
+extern BOOL gldInitialiseMesa_DX(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_DX(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_DX(LPCSTR a);
+extern BOOL gldGetDisplayMode_DX(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+//---------------------------------------------------------------------------
+// NOP functions. Called if proper driver functions are not set.
+//---------------------------------------------------------------------------
+
+static BOOL _gldDriverError(void)
+{
+ ddlogMessage(DDLOG_CRITICAL, szDriverError);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDXErrorString_ERROR(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreateDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _ResizeDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyDrawable_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreatePrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyPrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _BuildPixelformatList_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+
+static BOOL _InitialiseMesa_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _SwapBuffers_ERROR(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static PROC _GetProcAddress_ERROR(
+ LPCSTR a)
+{
+ _gldDriverError();
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDisplayMode_ERROR(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+// Functions useful to all drivers
+//---------------------------------------------------------------------------
+
+const GLubyte* _gldGetStringGeneric(
+ GLcontext *ctx,
+ GLenum name)
+{
+ if (!ctx)
+ return NULL;
+
+ switch (name) {
+ case GL_RENDERER:
+ sprintf(_gldRendererString, "GLDirect 4.0 %s%s%s%s (%s %s)",
+ _mesa_x86_cpu_features ? "/x86" : "",
+ cpu_has_mmx ? "/MMX" : "",
+ cpu_has_3dnow ? "/3DNow!" : "",
+ cpu_has_xmm ? "/SSE" : "",
+ __DATE__, __TIME__);
+ return (const GLubyte *) _gldRendererString;
+ case GL_VENDOR:
+ return (const GLubyte *) szVendor;
+ default:
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Global driver function pointers, initially set to functions that
+// will report an error when called.
+//---------------------------------------------------------------------------
+
+GLD_driver _gldDriver = {
+ _GetDXErrorString_ERROR,
+ _CreateDrawable_ERROR,
+ _ResizeDrawable_ERROR,
+ _DestroyDrawable_ERROR,
+ _CreatePrivateGlobals_ERROR,
+ _DestroyPrivateGlobals_ERROR,
+ _BuildPixelformatList_ERROR,
+ _InitialiseMesa_ERROR,
+ _SwapBuffers_ERROR,
+ _GetProcAddress_ERROR,
+ _GetDisplayMode_ERROR
+};
+
+//---------------------------------------------------------------------------
+// Init function. Should be called as soon as regkeys/ini-settings are read.
+//---------------------------------------------------------------------------
+
+BOOL gldInitDriverPointers(
+ DWORD dwDriver)
+{
+ _gldDriver.GetDXErrorString = gldGetDXErrorString_DX;
+
+ if (dwDriver == GLDS_DRIVER_MESA_SW) {
+ // Mesa Software driver
+ _gldDriver.CreateDrawable = gldCreateDrawable_MesaSW;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_MesaSW;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_MesaSW;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_MesaSW;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_MesaSW;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_MesaSW;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_MesaSW;
+ _gldDriver.SwapBuffers = gldSwapBuffers_MesaSW;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_MesaSW;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_MesaSW;
+ return TRUE;
+ }
+
+ if ((dwDriver == GLDS_DRIVER_REF) || (dwDriver == GLDS_DRIVER_HAL)) {
+ // Direct3D driver, either HW or SW
+ _gldDriver.CreateDrawable = gldCreateDrawable_DX;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_DX;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_DX;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_DX;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_DX;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_DX;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_DX;
+ _gldDriver.SwapBuffers = gldSwapBuffers_DX;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_DX;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_DX;
+ return TRUE;
+ };
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/gld_driver.h b/src/mesa/drivers/windows/gldirect/gld_driver.h
new file mode 100644
index 0000000..01a46a8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_driver.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+* 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 functions and interfaces
+*
+****************************************************************************/
+
+#ifndef _GLD_DRIVER_H
+#define _GLD_DRIVER_H
+
+// This file is only useful is we're using the new GLD3 WGL code.
+#ifdef _USE_GLD3_WGL
+
+#include "dglcontext.h"
+
+// Same as DX8 D3DDISPLAYMODE
+typedef struct {
+ DWORD Width;
+ DWORD Height;
+ DWORD Refresh;
+ DWORD BPP;
+} GLD_displayMode;
+
+typedef struct {
+ // Returns a string for a given HRESULT error code.
+ BOOL (*GetDXErrorString)(HRESULT hr, char *buf, int nBufSize);
+
+ // Driver functions for managing drawables.
+ // Functions must respect persistant buffers / persistant interface.
+ // NOTE: Persistant interface is: DirectDraw, pre-DX8; Direct3D, DX8 and above.
+ BOOL (*CreateDrawable)(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*ResizeDrawable)(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*DestroyDrawable)(DGL_ctx *ctx);
+
+ // Create/Destroy private globals belonging to driver
+ BOOL (*CreatePrivateGlobals)(void);
+ BOOL (*DestroyPrivateGlobals)(void);
+
+ // Build pixelformat list
+ BOOL (*BuildPixelformatList)(void);
+
+ // Initialise Mesa's driver pointers
+ BOOL (*InitialiseMesa)(DGL_ctx *ctx);
+
+ // Swap buffers
+ BOOL (*SwapBuffers)(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+
+ // wglGetProcAddress()
+ PROC (*wglGetProcAddress)(LPCSTR a);
+
+ BOOL (*GetDisplayMode)(DGL_ctx *ctx, GLD_displayMode *glddm);
+} GLD_driver;
+
+extern GLD_driver _gldDriver;
+
+BOOL gldInitDriverPointers(DWORD dwDriver);
+const GLubyte* _gldGetStringGeneric(GLcontext *ctx, GLenum name);
+
+#endif // _USE_GLD3_WGL
+
+#endif // _GLD_DRIVER_H
diff --git a/src/mesa/drivers/windows/gldirect/gldlame8.c b/src/mesa/drivers/windows/gldirect/gldlame8.c
new file mode 100644
index 0000000..5ac519c
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gldlame8.c
@@ -0,0 +1,181 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: GLDirect utility for determining lame boards/drivers.
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <d3d8.h>
+
+/*
+Ack. Broken out from gldlame.c because of broken D3D headers. KeithH
+*/
+
+/****************************************************************************
+REMARKS:
+Scans list of DirectDraw devices for specific device IDs.
+****************************************************************************/
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+static __inline BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3D8 device for "lameness" with respect to GLDirect.
+This is done on per-chipset basis, as in GLD CAD driver (DGLCONTEXT.C).
+If bTestForWHQL is set then the device is tested to see if it is
+certified, and bIsWHQL is set to indicate TRUE or FALSE. Otherwise bIsWHQL
+is not set. [WHQL = Windows Hardware Quality Labs]
+
+NOTE: There is a one- or two-second time penalty incurred in determining
+ the WHQL certification date.
+****************************************************************************/
+BOOL IsThisD3D8Lame(
+ IDirect3D8 *pD3D,
+ DWORD dwAdapter,
+ BOOL bTestForWHQL,
+ BOOL *bIsWHQL)
+{
+ DWORD dwFlags = bTestForWHQL ? 0 : D3DENUM_NO_WHQL_LEVEL;
+ D3DADAPTER_IDENTIFIER8 d3dai;
+ HRESULT hr;
+
+ hr = IDirect3D8_GetAdapterIdentifier(pD3D, dwAdapter, dwFlags, &d3dai);
+ if (FAILED(hr))
+ return TRUE; // Definitely lame if adapter details can't be obtained!
+
+ if (bTestForWHQL) {
+ *bIsWHQL = d3dai.WHQLLevel ? TRUE : FALSE;
+ }
+
+ // Vendor 1: ATI
+ if (d3dai.VendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, d3dai.DeviceId, sizeof(devATIRagePro)))
+ return TRUE; // bad mipmapping
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, d3dai.DeviceId, sizeof(devATIRageIIplus)))
+ return TRUE; // bad HW alpha testing
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3DDevice8 device for "lameness" with respect to GLDirect.
+This is done by querying for particular caps, as in GLD CPL (CPLMAIN.CPP).
+****************************************************************************/
+BOOL IsThisD3D8DeviceLame(
+ IDirect3DDevice8 *pDev)
+{
+ D3DCAPS8 d3dCaps;
+ HRESULT hr;
+
+ hr = IDirect3DDevice8_GetDeviceCaps(pDev, &d3dCaps);
+ if (FAILED(hr))
+ return TRUE;
+
+ // Test 1: Perspective-correct textures
+ // Any card that cannot do perspective-textures is *exceptionally* lame.
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 2: Bilinear filtering
+ if (!(d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 3: Mipmapping
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 4: Depth-test modes (?)
+
+ // Test 5: Blend Modes -- Based on DX7 D3DIM MTEXTURE.CPP caps test
+
+ // Accept devices that can do multipass, alpha blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_INVSRCALPHA) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_SRCALPHA)) )
+ return TRUE;
+
+ // Accept devices that can do multipass, color blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_SRCCOLOR) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_ZERO)) )
+ return TRUE;
+
+ // Accept devices that really support multiple textures.
+ if( !((d3dCaps.MaxTextureBlendStages > 1 ) &&
+ (d3dCaps.MaxSimultaneousTextures > 1 ) &&
+ (d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATE )) )
+ return TRUE;
+
+ return FALSE; // Not lame
+}
diff --git a/src/mesa/drivers/windows/gldirect/opengl32.def b/src/mesa/drivers/windows/gldirect/opengl32.def
new file mode 100644
index 0000000..b213b6e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/opengl32.def
@@ -0,0 +1,488 @@
+;****************************************************************************
+;*
+;* 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=glAccum @1
+ glAlphaFunc=glAlphaFunc @2
+ glAreTexturesResident=glAreTexturesResident @3
+ glArrayElement=glArrayElement @4
+ glBegin=glBegin @5
+ glBindTexture=glBindTexture @6
+ glBitmap=glBitmap @7
+ glBlendFunc=glBlendFunc @8
+ glCallList=glCallList @9
+ glCallLists=glCallLists @10
+ glClear=glClear @11
+ glClearAccum=glClearAccum @12
+ glClearIndex=glClearIndex @13
+ glClearColor=glClearColor @14
+ glClearDepth=glClearDepth @15
+ glClearStencil=glClearStencil @16
+ glClipPlane=glClipPlane @17
+ glColor3b=glColor3b @18
+ glColor3d=glColor3d @19
+ glColor3f=glColor3f @20
+ glColor3i=glColor3i @21
+ glColor3s=glColor3s @22
+ glColor3ub=glColor3ub @23
+ glColor3ui=glColor3ui @24
+ glColor3us=glColor3us @25
+ glColor4b=glColor4b @26
+ glColor4d=glColor4d @27
+ glColor4f=glColor4f @28
+ glColor4i=glColor4i @29
+ glColor4s=glColor4s @30
+ glColor4ub=glColor4ub @31
+ glColor4ui=glColor4ui @32
+ glColor4us=glColor4us @33
+ glColor3bv=glColor3bv @34
+ glColor3dv=glColor3dv @35
+ glColor3fv=glColor3fv @36
+ glColor3iv=glColor3iv @37
+ glColor3sv=glColor3sv @38
+ glColor3ubv=glColor3ubv @39
+ glColor3uiv=glColor3uiv @40
+ glColor3usv=glColor3usv @41
+ glColor4bv=glColor4bv @42
+ glColor4dv=glColor4dv @43
+ glColor4fv=glColor4fv @44
+ glColor4iv=glColor4iv @45
+ glColor4sv=glColor4sv @46
+ glColor4ubv=glColor4ubv @47
+ glColor4uiv=glColor4uiv @48
+ glColor4usv=glColor4usv @49
+ glColorMask=glColorMask @50
+ glColorMaterial=glColorMaterial @51
+ glColorPointer=glColorPointer @52
+ glColorTableEXT=glColorTableEXT @53
+ glColorSubTableEXT=glColorSubTableEXT @54
+ glCopyPixels=glCopyPixels @55
+ glCopyTexImage1D=glCopyTexImage1D @56
+ glCopyTexImage2D=glCopyTexImage2D @57
+ glCopyTexSubImage1D=glCopyTexSubImage1D @58
+ glCopyTexSubImage2D=glCopyTexSubImage2D @59
+ glCullFace=glCullFace @60
+ glDepthFunc=glDepthFunc @61
+ glDepthMask=glDepthMask @62
+ glDepthRange=glDepthRange @63
+ glDeleteLists=glDeleteLists @64
+ glDeleteTextures=glDeleteTextures @65
+ glDisable=glDisable @66
+ glDisableClientState=glDisableClientState @67
+ glDrawArrays=glDrawArrays @68
+ glDrawBuffer=glDrawBuffer @69
+ glDrawElements=glDrawElements @70
+ glDrawPixels=glDrawPixels @71
+ glEnable=glEnable @72
+ glEnableClientState=glEnableClientState @73
+ glEnd=glEnd @74
+ glEndList=glEndList @75
+ glEvalCoord1d=glEvalCoord1d @76
+ glEvalCoord1f=glEvalCoord1f @77
+ glEvalCoord1dv=glEvalCoord1dv @78
+ glEvalCoord1fv=glEvalCoord1fv @79
+ glEvalCoord2d=glEvalCoord2d @80
+ glEvalCoord2f=glEvalCoord2f @81
+ glEvalCoord2dv=glEvalCoord2dv @82
+ glEvalCoord2fv=glEvalCoord2fv @83
+ glEvalPoint1=glEvalPoint1 @84
+ glEvalPoint2=glEvalPoint2 @85
+ glEvalMesh1=glEvalMesh1 @86
+ glEdgeFlag=glEdgeFlag @87
+ glEdgeFlagv=glEdgeFlagv @88
+ glEdgeFlagPointer=glEdgeFlagPointer @89
+ glEvalMesh2=glEvalMesh2 @90
+ glFeedbackBuffer=glFeedbackBuffer @91
+ glFinish=glFinish @92
+ glFlush=glFlush @93
+ glFogf=glFogf @94
+ glFogi=glFogi @95
+ glFogfv=glFogfv @96
+ glFogiv=glFogiv @97
+ glFrontFace=glFrontFace @98
+ glFrustum=glFrustum @99
+ glGenLists=glGenLists @100
+ glGenTextures=glGenTextures @101
+ glGetBooleanv=glGetBooleanv @102
+ glGetClipPlane=glGetClipPlane @103
+ glGetColorTableEXT=glGetColorTableEXT @104
+ glGetColorTableParameterivEXT=glGetColorTableParameterivEXT @105
+ glGetColorTableParameterfvEXT=glGetColorTableParameterfvEXT @106
+ glGetDoublev=glGetDoublev @107
+ glGetError=glGetError @108
+ glGetFloatv=glGetFloatv @109
+ glGetIntegerv=glGetIntegerv @110
+ glGetLightfv=glGetLightfv @111
+ glGetLightiv=glGetLightiv @112
+ glGetMapdv=glGetMapdv @113
+ glGetMapfv=glGetMapfv @114
+ glGetMapiv=glGetMapiv @115
+ glGetMaterialfv=glGetMaterialfv @116
+ glGetMaterialiv=glGetMaterialiv @117
+ glGetPixelMapfv=glGetPixelMapfv @118
+ glGetPixelMapuiv=glGetPixelMapuiv @119
+ glGetPixelMapusv=glGetPixelMapusv @120
+ glGetPointerv=glGetPointerv @121
+ glGetPolygonStipple=glGetPolygonStipple @122
+ glGetString=glGetString @123
+ glGetTexEnvfv=glGetTexEnvfv @124
+ glGetTexEnviv=glGetTexEnviv @125
+ glGetTexGeniv=glGetTexGeniv @126
+ glGetTexGendv=glGetTexGendv @127
+ glGetTexGenfv=glGetTexGenfv @128
+ glGetTexImage=glGetTexImage @129
+ glGetTexLevelParameterfv=glGetTexLevelParameterfv @130
+ glGetTexLevelParameteriv=glGetTexLevelParameteriv @131
+ glGetTexParameterfv=glGetTexParameterfv @132
+ glGetTexParameteriv=glGetTexParameteriv @133
+ glHint=glHint @134
+ glIndexd=glIndexd @135
+ glIndexf=glIndexf @136
+ glIndexi=glIndexi @137
+ glIndexs=glIndexs @138
+ glIndexub=glIndexub @139
+ glIndexdv=glIndexdv @140
+ glIndexfv=glIndexfv @141
+ glIndexiv=glIndexiv @142
+ glIndexsv=glIndexsv @143
+ glIndexubv=glIndexubv @144
+ glIndexMask=glIndexMask @145
+ glIndexPointer=glIndexPointer @146
+ glInterleavedArrays=glInterleavedArrays @147
+ glInitNames=glInitNames @148
+ glIsList=glIsList @149
+ glIsTexture=glIsTexture @150
+ glLightf=glLightf @151
+ glLighti=glLighti @152
+ glLightfv=glLightfv @153
+ glLightiv=glLightiv @154
+ glLightModelf=glLightModelf @155
+ glLightModeli=glLightModeli @156
+ glLightModelfv=glLightModelfv @157
+ glLightModeliv=glLightModeliv @158
+ glLineWidth=glLineWidth @159
+ glLineStipple=glLineStipple @160
+ glListBase=glListBase @161
+ glLoadIdentity=glLoadIdentity @162
+ glLoadMatrixd=glLoadMatrixd @163
+ glLoadMatrixf=glLoadMatrixf @164
+ glLoadName=glLoadName @165
+ glLogicOp=glLogicOp @166
+ glMap1d=glMap1d @167
+ glMap1f=glMap1f @168
+ glMap2d=glMap2d @169
+ glMap2f=glMap2f @170
+ glMapGrid1d=glMapGrid1d @171
+ glMapGrid1f=glMapGrid1f @172
+ glMapGrid2d=glMapGrid2d @173
+ glMapGrid2f=glMapGrid2f @174
+ glMaterialf=glMaterialf @175
+ glMateriali=glMateriali @176
+ glMaterialfv=glMaterialfv @177
+ glMaterialiv=glMaterialiv @178
+ glMatrixMode=glMatrixMode @179
+ glMultMatrixd=glMultMatrixd @180
+ glMultMatrixf=glMultMatrixf @181
+ glNewList=glNewList @182
+ glNormal3b=glNormal3b @183
+ glNormal3d=glNormal3d @184
+ glNormal3f=glNormal3f @185
+ glNormal3i=glNormal3i @186
+ glNormal3s=glNormal3s @187
+ glNormal3bv=glNormal3bv @188
+ glNormal3dv=glNormal3dv @189
+ glNormal3fv=glNormal3fv @190
+ glNormal3iv=glNormal3iv @191
+ glNormal3sv=glNormal3sv @192
+ glNormalPointer=glNormalPointer @193
+ glOrtho=glOrtho @194
+ glPassThrough=glPassThrough @195
+ glPixelMapfv=glPixelMapfv @196
+ glPixelMapuiv=glPixelMapuiv @197
+ glPixelMapusv=glPixelMapusv @198
+ glPixelStoref=glPixelStoref @199
+ glPixelStorei=glPixelStorei @200
+ glPixelTransferf=glPixelTransferf @201
+ glPixelTransferi=glPixelTransferi @202
+ glPixelZoom=glPixelZoom @203
+ glPointSize=glPointSize @204
+ glPolygonMode=glPolygonMode @205
+ glPolygonOffset=glPolygonOffset @206
+ glPolygonOffsetEXT=glPolygonOffsetEXT @207
+ glPolygonStipple=glPolygonStipple @208
+ glPopAttrib=glPopAttrib @209
+ glPopClientAttrib=glPopClientAttrib @210
+ glPopMatrix=glPopMatrix @211
+ glPopName=glPopName @212
+ glPrioritizeTextures=glPrioritizeTextures @213
+ glPushMatrix=glPushMatrix @214
+ glRasterPos2d=glRasterPos2d @215
+ glRasterPos2f=glRasterPos2f @216
+ glRasterPos2i=glRasterPos2i @217
+ glRasterPos2s=glRasterPos2s @218
+ glRasterPos3d=glRasterPos3d @219
+ glRasterPos3f=glRasterPos3f @220
+ glRasterPos3i=glRasterPos3i @221
+ glRasterPos3s=glRasterPos3s @222
+ glRasterPos4d=glRasterPos4d @223
+ glRasterPos4f=glRasterPos4f @224
+ glRasterPos4i=glRasterPos4i @225
+ glRasterPos4s=glRasterPos4s @226
+ glRasterPos2dv=glRasterPos2dv @227
+ glRasterPos2fv=glRasterPos2fv @228
+ glRasterPos2iv=glRasterPos2iv @229
+ glRasterPos2sv=glRasterPos2sv @230
+ glRasterPos3dv=glRasterPos3dv @231
+ glRasterPos3fv=glRasterPos3fv @232
+ glRasterPos3iv=glRasterPos3iv @233
+ glRasterPos3sv=glRasterPos3sv @234
+ glRasterPos4dv=glRasterPos4dv @235
+ glRasterPos4fv=glRasterPos4fv @236
+ glRasterPos4iv=glRasterPos4iv @237
+ glRasterPos4sv=glRasterPos4sv @238
+ glReadBuffer=glReadBuffer @239
+ glReadPixels=glReadPixels @240
+ glRectd=glRectd @241
+ glRectf=glRectf @242
+ glRecti=glRecti @243
+ glRects=glRects @244
+ glRectdv=glRectdv @245
+ glRectfv=glRectfv @246
+ glRectiv=glRectiv @247
+ glRectsv=glRectsv @248
+ glScissor=glScissor @249
+ glIsEnabled=glIsEnabled @250
+ glPushAttrib=glPushAttrib @251
+ glPushClientAttrib=glPushClientAttrib @252
+ glPushName=glPushName @253
+ glRenderMode=glRenderMode @254
+ glRotated=glRotated @255
+ glRotatef=glRotatef @256
+ glSelectBuffer=glSelectBuffer @257
+ glScaled=glScaled @258
+ glScalef=glScalef @259
+ glShadeModel=glShadeModel @260
+ glStencilFunc=glStencilFunc @261
+ glStencilMask=glStencilMask @262
+ glStencilOp=glStencilOp @263
+ glTexCoord1d=glTexCoord1d @264
+ glTexCoord1f=glTexCoord1f @265
+ glTexCoord1i=glTexCoord1i @266
+ glTexCoord1s=glTexCoord1s @267
+ glTexCoord2d=glTexCoord2d @268
+ glTexCoord2f=glTexCoord2f @269
+ glTexCoord2i=glTexCoord2i @270
+ glTexCoord2s=glTexCoord2s @271
+ glTexCoord3d=glTexCoord3d @272
+ glTexCoord3f=glTexCoord3f @273
+ glTexCoord3i=glTexCoord3i @274
+ glTexCoord3s=glTexCoord3s @275
+ glTexCoord4d=glTexCoord4d @276
+ glTexCoord4f=glTexCoord4f @277
+ glTexCoord4i=glTexCoord4i @278
+ glTexCoord4s=glTexCoord4s @279
+ glTexCoord1dv=glTexCoord1dv @280
+ glTexCoord1fv=glTexCoord1fv @281
+ glTexCoord1iv=glTexCoord1iv @282
+ glTexCoord1sv=glTexCoord1sv @283
+ glTexCoord2dv=glTexCoord2dv @284
+ glTexCoord2fv=glTexCoord2fv @285
+ glTexCoord2iv=glTexCoord2iv @286
+ glTexCoord2sv=glTexCoord2sv @287
+ glTexCoord3dv=glTexCoord3dv @288
+ glTexCoord3fv=glTexCoord3fv @289
+ glTexCoord3iv=glTexCoord3iv @290
+ glTexCoord3sv=glTexCoord3sv @291
+ glTexCoord4dv=glTexCoord4dv @292
+ glTexCoord4fv=glTexCoord4fv @293
+ glTexCoord4iv=glTexCoord4iv @294
+ glTexCoord4sv=glTexCoord4sv @295
+ glTexCoordPointer=glTexCoordPointer @296
+ glTexGend=glTexGend @297
+ glTexGenf=glTexGenf @298
+ glTexGeni=glTexGeni @299
+ glTexGendv=glTexGendv @300
+ glTexGeniv=glTexGeniv @301
+ glTexGenfv=glTexGenfv @302
+ glTexEnvf=glTexEnvf @303
+ glTexEnvi=glTexEnvi @304
+ glTexEnvfv=glTexEnvfv @305
+ glTexEnviv=glTexEnviv @306
+ glTexImage1D=glTexImage1D @307
+ glTexImage2D=glTexImage2D @308
+ glTexParameterf=glTexParameterf @309
+ glTexParameteri=glTexParameteri @310
+ glTexParameterfv=glTexParameterfv @311
+ glTexParameteriv=glTexParameteriv @312
+ glTexSubImage1D=glTexSubImage1D @313
+ glTexSubImage2D=glTexSubImage2D @314
+ glTranslated=glTranslated @315
+ glTranslatef=glTranslatef @316
+ glVertex2d=glVertex2d @317
+ glVertex2f=glVertex2f @318
+ glVertex2i=glVertex2i @319
+ glVertex2s=glVertex2s @320
+ glVertex3d=glVertex3d @321
+ glVertex3f=glVertex3f @322
+ glVertex3i=glVertex3i @323
+ glVertex3s=glVertex3s @324
+ glVertex4d=glVertex4d @325
+ glVertex4f=glVertex4f @326
+ glVertex4i=glVertex4i @327
+ glVertex4s=glVertex4s @328
+ glVertex2dv=glVertex2dv @329
+ glVertex2fv=glVertex2fv @330
+ glVertex2iv=glVertex2iv @331
+ glVertex2sv=glVertex2sv @332
+ glVertex3dv=glVertex3dv @333
+ glVertex3fv=glVertex3fv @334
+ glVertex3iv=glVertex3iv @335
+ glVertex3sv=glVertex3sv @336
+ glVertex4dv=glVertex4dv @337
+ glVertex4fv=glVertex4fv @338
+ glVertex4iv=glVertex4iv @339
+ glVertex4sv=glVertex4sv @340
+ glVertexPointer=glVertexPointer @341
+ glViewport=glViewport @342
+ glBlendEquationEXT=glBlendEquationEXT @343
+ glBlendColorEXT=glBlendColorEXT @344
+ glVertexPointerEXT=glVertexPointerEXT @345
+ glNormalPointerEXT=glNormalPointerEXT @346
+ glColorPointerEXT=glColorPointerEXT @347
+ glIndexPointerEXT=glIndexPointerEXT @348
+ glTexCoordPointerEXT=glTexCoordPointerEXT @349
+ glEdgeFlagPointerEXT=glEdgeFlagPointerEXT @350
+ glGetPointervEXT=glGetPointervEXT @351
+ glArrayElementEXT=glArrayElementEXT @352
+ glDrawArraysEXT=glDrawArraysEXT @353
+ glBindTextureEXT=glBindTextureEXT @354
+ glDeleteTexturesEXT=glDeleteTexturesEXT @355
+ glGenTexturesEXT=glGenTexturesEXT @356
+ glPrioritizeTexturesEXT=glPrioritizeTexturesEXT @357
+ glCopyTexSubImage3DEXT=glCopyTexSubImage3DEXT @358
+ glTexImage3DEXT=glTexImage3DEXT @359
+ glTexSubImage3DEXT=glTexSubImage3DEXT @360
+ glWindowPos4fMESA=glWindowPos4fMESA @361
+ glWindowPos2iMESA=glWindowPos2iMESA @362
+ glWindowPos2sMESA=glWindowPos2sMESA @363
+ glWindowPos2fMESA=glWindowPos2fMESA @364
+ glWindowPos2dMESA=glWindowPos2dMESA @365
+ glWindowPos2ivMESA=glWindowPos2ivMESA @366
+ glWindowPos2svMESA=glWindowPos2svMESA @367
+ glWindowPos2fvMESA=glWindowPos2fvMESA @368
+ glWindowPos2dvMESA=glWindowPos2dvMESA @369
+ glWindowPos3iMESA=glWindowPos3iMESA @370
+ glWindowPos3sMESA=glWindowPos3sMESA @371
+ glWindowPos3fMESA=glWindowPos3fMESA @372
+ glWindowPos3dMESA=glWindowPos3dMESA @373
+ glWindowPos3ivMESA=glWindowPos3ivMESA @374
+ glWindowPos3svMESA=glWindowPos3svMESA @375
+ glWindowPos3fvMESA=glWindowPos3fvMESA @376
+ glWindowPos3dvMESA=glWindowPos3dvMESA @377
+ glWindowPos4iMESA=glWindowPos4iMESA @378
+ glWindowPos4sMESA=glWindowPos4sMESA @379
+ glWindowPos4dMESA=glWindowPos4dMESA @380
+ glWindowPos4ivMESA=glWindowPos4ivMESA @381
+ glWindowPos4svMESA=glWindowPos4svMESA @382
+ glWindowPos4fvMESA=glWindowPos4fvMESA @383
+ glWindowPos4dvMESA=glWindowPos4dvMESA @384
+ glResizeBuffersMESA=glResizeBuffersMESA @385
+ wglCopyContext=wglCopyContext @386
+ wglCreateContext=wglCreateContext @387
+ wglCreateLayerContext=wglCreateLayerContext @388
+ wglDeleteContext=wglDeleteContext @389
+ wglDescribeLayerPlane=wglDescribeLayerPlane @390
+ wglGetCurrentContext=wglGetCurrentContext @391
+ wglGetCurrentDC=wglGetCurrentDC @392
+ wglGetLayerPaletteEntries=wglGetLayerPaletteEntries @393
+ wglGetProcAddress=wglGetProcAddress @394
+ wglMakeCurrent=wglMakeCurrent @395
+ wglRealizeLayerPalette=wglRealizeLayerPalette @396
+ wglSetLayerPaletteEntries=wglSetLayerPaletteEntries @397
+ wglShareLists=wglShareLists @398
+ wglSwapLayerBuffers=wglSwapLayerBuffers @399
+ wglUseFontBitmapsA=wglUseFontBitmapsA @400
+ wglUseFontBitmapsW=wglUseFontBitmapsW @401
+ wglUseFontOutlinesA=wglUseFontOutlinesA @402
+ wglUseFontOutlinesW=wglUseFontOutlinesW @403
+ ChoosePixelFormat=ChoosePixelFormat @404
+ DescribePixelFormat=DescribePixelFormat @405
+ GetPixelFormat=GetPixelFormat @406
+ SetPixelFormat=SetPixelFormat @407
+ SwapBuffers=SwapBuffers @408
+ wglChoosePixelFormat=wglChoosePixelFormat @409
+ wglDescribePixelFormat=wglDescribePixelFormat @410
+ wglGetPixelFormat=wglGetPixelFormat @411
+ wglSetPixelFormat=wglSetPixelFormat @412
+ wglSwapBuffers=wglSwapBuffers @413
+ glActiveTextureARB=glActiveTextureARB @414
+ glClientActiveTextureARB=glClientActiveTextureARB @415
+ glMultiTexCoord1dARB=glMultiTexCoord1dARB @416
+ glMultiTexCoord1dvARB=glMultiTexCoord1dvARB @417
+ glMultiTexCoord1fARB=glMultiTexCoord1fARB @418
+ glMultiTexCoord1fvARB=glMultiTexCoord1fvARB @419
+ glMultiTexCoord1iARB=glMultiTexCoord1iARB @420
+ glMultiTexCoord1ivARB=glMultiTexCoord1ivARB @421
+ glMultiTexCoord1sARB=glMultiTexCoord1sARB @422
+ glMultiTexCoord1svARB=glMultiTexCoord1svARB @423
+ glMultiTexCoord2dARB=glMultiTexCoord2dARB @424
+ glMultiTexCoord2dvARB=glMultiTexCoord2dvARB @425
+ glMultiTexCoord2fARB=glMultiTexCoord2fARB @426
+ glMultiTexCoord2fvARB=glMultiTexCoord2fvARB @427
+ glMultiTexCoord2iARB=glMultiTexCoord2iARB @428
+ glMultiTexCoord2ivARB=glMultiTexCoord2ivARB @429
+ glMultiTexCoord2sARB=glMultiTexCoord2sARB @430
+ glMultiTexCoord2svARB=glMultiTexCoord2svARB @431
+ glMultiTexCoord3dARB=glMultiTexCoord3dARB @432
+ glMultiTexCoord3dvARB=glMultiTexCoord3dvARB @433
+ glMultiTexCoord3fARB=glMultiTexCoord3fARB @434
+ glMultiTexCoord3fvARB=glMultiTexCoord3fvARB @435
+ glMultiTexCoord3iARB=glMultiTexCoord3iARB @436
+ glMultiTexCoord3ivARB=glMultiTexCoord3ivARB @437
+ glMultiTexCoord3sARB=glMultiTexCoord3sARB @438
+ glMultiTexCoord3svARB=glMultiTexCoord3svARB @439
+ glMultiTexCoord4dARB=glMultiTexCoord4dARB @440
+ glMultiTexCoord4dvARB=glMultiTexCoord4dvARB @441
+ glMultiTexCoord4fARB=glMultiTexCoord4fARB @442
+ glMultiTexCoord4fvARB=glMultiTexCoord4fvARB @443
+ glMultiTexCoord4iARB=glMultiTexCoord4iARB @444
+ glMultiTexCoord4ivARB=glMultiTexCoord4ivARB @445
+ glMultiTexCoord4sARB=glMultiTexCoord4sARB @446
+ glMultiTexCoord4svARB=glMultiTexCoord4svARB @447
diff --git a/src/mesa/drivers/windows/gldirect/pixpack.h b/src/mesa/drivers/windows/gldirect/pixpack.h
new file mode 100644
index 0000000..ec848d4
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/pixpack.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+*
+* 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 (Win32)
+*
+* Description: Pixel packing functions.
+*
+****************************************************************************/
+
+#ifndef __PIXPACK_H
+#define __PIXPACK_H
+
+#include <GL\gl.h>
+#include <ddraw.h>
+
+#include "ddlog.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#define PXAPI
+
+// Typedef that can be used for pixel packing function pointers.
+#define PX_PACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packFunc)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel unpacking function pointers.
+#define PX_UNPACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_unpackFunc)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel span packing function pointers.
+#define PX_PACK_SPAN_FUNC(a) void PXAPI (a)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packSpanFunc)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Function that examines a pixel format and returns the relevent
+// pixel-packing function
+void PXAPI pxClassifyPixelFormat(const LPDDPIXELFORMAT lpddpf, PX_packFunc *lpPackFn ,PX_unpackFunc *lpUnpackFn, PX_packSpanFunc *lpPackSpanFn);
+
+// Packing functions
+PX_PACK_FUNC(pxPackGeneric);
+PX_PACK_FUNC(pxPackRGB555);
+PX_PACK_FUNC(pxPackARGB4444);
+PX_PACK_FUNC(pxPackARGB1555);
+PX_PACK_FUNC(pxPackRGB565);
+PX_PACK_FUNC(pxPackRGB332);
+PX_PACK_FUNC(pxPackRGB888);
+PX_PACK_FUNC(pxPackARGB8888);
+PX_PACK_FUNC(pxPackPAL8);
+
+// Unpacking functions
+PX_UNPACK_FUNC(pxUnpackGeneric);
+PX_UNPACK_FUNC(pxUnpackRGB555);
+PX_UNPACK_FUNC(pxUnpackARGB4444);
+PX_UNPACK_FUNC(pxUnpackARGB1555);
+PX_UNPACK_FUNC(pxUnpackRGB565);
+PX_UNPACK_FUNC(pxUnpackRGB332);
+PX_UNPACK_FUNC(pxUnpackRGB888);
+PX_UNPACK_FUNC(pxUnpackARGB8888);
+PX_UNPACK_FUNC(pxUnpackPAL8);
+
+// Span Packing functions
+PX_PACK_SPAN_FUNC(pxPackSpanGeneric);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB555);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB4444);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB1555);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB565);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB332);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB888);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB8888);
+PX_PACK_SPAN_FUNC(pxPackSpanPAL8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/icd/icd.c b/src/mesa/drivers/windows/icd/icd.c
new file mode 100644
index 0000000..969f530
--- /dev/null
+++ b/src/mesa/drivers/windows/icd/icd.c
@@ -0,0 +1,347 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+/*
+ * File name: icd.c
+ * Author: Gregor Anich
+ *
+ * ICD (Installable Client Driver) interface.
+ * Based on the windows GDI/WGL driver.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <stdio.h>
+#include <tchar.h>
+#include "../gdi/wmesadef.h"
+#include "GL/wmesa.h"
+#include "mtypes.h"
+#include "glapi.h"
+
+#define MAX_MESA_ATTRS 20
+
+
+typedef struct _icdTable {
+ DWORD size;
+ PROC table[336];
+} ICDTABLE, *PICDTABLE;
+
+#ifdef USE_MGL_NAMESPACE
+# define GL_FUNC(func) mgl##func
+#else
+# define GL_FUNC(func) gl##func
+#endif
+
+static ICDTABLE icdTable = { 336, {
+#define ICD_ENTRY(func) (PROC)GL_FUNC(func),
+#include "icdlist.h"
+#undef ICD_ENTRY
+} };
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLboolean doubleBuffered;
+};
+
+struct __pixelformat__ pix[] =
+{
+ /* Double Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ /* Single Buffer, alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL, /* | PFD_SUPPORT_GDI ? */
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_FALSE
+ },
+ /* Double Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ /* Single Buffer, no alpha */
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL, /* | PFD_SUPPORT_GDI ? */
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 0, 0,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_FALSE
+ },
+};
+
+int qt_pix = sizeof(pix) / sizeof(pix[0]);
+
+typedef struct {
+ WMesaContext ctx;
+ HDC hdc;
+} MesaWglCtx;
+
+#define MESAWGL_CTX_MAX_COUNT 20
+
+static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
+
+static unsigned ctx_count = 0;
+static int ctx_current = -1;
+static unsigned curPFD = 0;
+
+WGLAPI BOOL GLAPIENTRY DrvCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ (void) hglrcSrc; (void) hglrcDst; (void) mask;
+ return(FALSE);
+}
+
+WGLAPI HGLRC GLAPIENTRY DrvCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ int i = 0;
+
+ if(!(hWnd = WindowFromDC(hdc)))
+ {
+ SetLastError(0);
+ return(NULL);
+ }
+ if (!ctx_count)
+ {
+ for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++)
+ {
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ }
+ }
+ for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == NULL )
+ {
+ wgl_ctx[i].ctx = WMesaCreateContext( hWnd, NULL, GL_TRUE,
+ pix[curPFD-1].doubleBuffered,
+ pix[curPFD-1].pfd.cAlphaBits ? GL_TRUE : GL_FALSE);
+ if (wgl_ctx[i].ctx == NULL)
+ break;
+ wgl_ctx[i].hdc = hdc;
+ ctx_count++;
+ return ((HGLRC)wgl_ctx[i].ctx);
+ }
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvDeleteContext(HGLRC hglrc)
+{
+ int i;
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ WMesaMakeCurrent((PWMC) hglrc);
+ WMesaDestroyContext();
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ ctx_count--;
+ return(TRUE);
+ }
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI HGLRC GLAPIENTRY DrvCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ if (iLayerPlane == 0)
+ return DrvCreateContext(hdc);
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI PICDTABLE GLAPIENTRY DrvSetContext(HDC hdc,HGLRC hglrc,void *callback)
+{
+ int i;
+ (void) callback;
+
+ /* new code suggested by Andy Sy */
+ if (!hdc || !hglrc) {
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+ return NULL;
+ }
+
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ wgl_ctx[i].hdc = hdc;
+ WMesaMakeCurrent( (PWMC) hglrc );
+ ctx_current = i;
+ return &icdTable;
+ }
+ }
+ return NULL;
+}
+
+WGLAPI void GLAPIENTRY DrvReleaseContext(HGLRC hglrc)
+{
+ (void) hglrc;
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+}
+
+WGLAPI BOOL GLAPIENTRY DrvShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ (void) hglrc1; (void) hglrc2;
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvDescribeLayerPlane(HDC hdc,int iPixelFormat,
+ int iLayerPlane,UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ (void) hdc; (void) iPixelFormat; (void) iLayerPlane; (void) nBytes; (void) plpd;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY DrvSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ CONST COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI int GLAPIENTRY DrvGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ COLORREF *pcr)
+{
+ (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr;
+ SetLastError(0);
+ return(0);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
+{
+ (void) hdc; (void) iLayerPlane; (void) bRealize;
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ (void) fuPlanes;
+ if( !hdc )
+ {
+ WMesaSwapBuffers();
+ return(TRUE);
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+WGLAPI int GLAPIENTRY DrvDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(ppfd == NULL)
+ return(qt_valid_pix);
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || nBytes != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(0);
+ }
+ *ppfd = pix[iPixelFormat - 1].pfd;
+ return(qt_valid_pix);
+}
+
+/*
+* GetProcAddress - return the address of an appropriate extension
+*/
+WGLAPI PROC GLAPIENTRY DrvGetProcAddress(LPCSTR lpszProc)
+{
+ PROC p = (PROC) (int) _glapi_get_proc_address((const char *) lpszProc);
+ if (p)
+ return p;
+
+ SetLastError(0);
+ return(NULL);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSetPixelFormat(HDC hdc,int iPixelFormat)
+{
+ int qt_valid_pix;
+ (void) hdc;
+
+ qt_valid_pix = qt_pix;
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix)
+ {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvSwapBuffers(HDC hdc)
+{
+ (void) hdc;
+ if (ctx_current < 0)
+ return FALSE;
+
+ if(wgl_ctx[ctx_current].ctx == NULL) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ WMesaSwapBuffers();
+ return(TRUE);
+}
+
+WGLAPI BOOL GLAPIENTRY DrvValidateVersion(DWORD version)
+{
+ (void) version;
+ return TRUE;
+}
diff --git a/src/mesa/drivers/windows/icd/icdlist.h b/src/mesa/drivers/windows/icd/icdlist.h
new file mode 100644
index 0000000..1318804
--- /dev/null
+++ b/src/mesa/drivers/windows/icd/icdlist.h
@@ -0,0 +1,336 @@
+ICD_ENTRY(NewList) /* 0 */
+ICD_ENTRY(EndList) /* 1 */
+ICD_ENTRY(CallList) /* 2 */
+ICD_ENTRY(CallLists) /* 3 */
+ICD_ENTRY(DeleteLists) /* 4 */
+ICD_ENTRY(GenLists) /* 5 */
+ICD_ENTRY(ListBase) /* 6 */
+ICD_ENTRY(Begin) /* 7 */
+ICD_ENTRY(Bitmap) /* 8 */
+ICD_ENTRY(Color3b) /* 9 */
+ICD_ENTRY(Color3bv) /* 10 */
+ICD_ENTRY(Color3d) /* 11 */
+ICD_ENTRY(Color3dv) /* 12 */
+ICD_ENTRY(Color3f) /* 13 */
+ICD_ENTRY(Color3fv) /* 14 */
+ICD_ENTRY(Color3i) /* 15 */
+ICD_ENTRY(Color3iv) /* 16 */
+ICD_ENTRY(Color3s) /* 17 */
+ICD_ENTRY(Color3sv) /* 18 */
+ICD_ENTRY(Color3ub) /* 19 */
+ICD_ENTRY(Color3ubv) /* 20 */
+ICD_ENTRY(Color3ui) /* 21 */
+ICD_ENTRY(Color3uiv) /* 22 */
+ICD_ENTRY(Color3us) /* 23 */
+ICD_ENTRY(Color3usv) /* 24 */
+ICD_ENTRY(Color4b) /* 25 */
+ICD_ENTRY(Color4bv) /* 26 */
+ICD_ENTRY(Color4d) /* 27 */
+ICD_ENTRY(Color4dv) /* 28 */
+ICD_ENTRY(Color4f) /* 29 */
+ICD_ENTRY(Color4fv) /* 30 */
+ICD_ENTRY(Color4i) /* 31 */
+ICD_ENTRY(Color4iv) /* 32 */
+ICD_ENTRY(Color4s) /* 33 */
+ICD_ENTRY(Color4sv) /* 34 */
+ICD_ENTRY(Color4ub) /* 35 */
+ICD_ENTRY(Color4ubv) /* 36 */
+ICD_ENTRY(Color4ui) /* 37 */
+ICD_ENTRY(Color4uiv) /* 38 */
+ICD_ENTRY(Color4us) /* 39 */
+ICD_ENTRY(Color4usv) /* 40 */
+ICD_ENTRY(EdgeFlag) /* 41 */
+ICD_ENTRY(EdgeFlagv) /* 42 */
+ICD_ENTRY(End) /* 43 */
+ICD_ENTRY(Indexd) /* 44 */
+ICD_ENTRY(Indexdv) /* 45 */
+ICD_ENTRY(Indexf) /* 46 */
+ICD_ENTRY(Indexfv) /* 47 */
+ICD_ENTRY(Indexi) /* 48 */
+ICD_ENTRY(Indexiv) /* 49 */
+ICD_ENTRY(Indexs) /* 50 */
+ICD_ENTRY(Indexsv) /* 51 */
+ICD_ENTRY(Normal3b) /* 52 */
+ICD_ENTRY(Normal3bv) /* 53 */
+ICD_ENTRY(Normal3d) /* 54 */
+ICD_ENTRY(Normal3dv) /* 55 */
+ICD_ENTRY(Normal3f) /* 56 */
+ICD_ENTRY(Normal3fv) /* 57 */
+ICD_ENTRY(Normal3i) /* 58 */
+ICD_ENTRY(Normal3iv) /* 59 */
+ICD_ENTRY(Normal3s) /* 60 */
+ICD_ENTRY(Normal3sv) /* 61 */
+ICD_ENTRY(RasterPos2d) /* 62 */
+ICD_ENTRY(RasterPos2dv) /* 63 */
+ICD_ENTRY(RasterPos2f) /* 64 */
+ICD_ENTRY(RasterPos2fv) /* 65 */
+ICD_ENTRY(RasterPos2i) /* 66 */
+ICD_ENTRY(RasterPos2iv) /* 67 */
+ICD_ENTRY(RasterPos2s) /* 68 */
+ICD_ENTRY(RasterPos2sv) /* 69 */
+ICD_ENTRY(RasterPos3d) /* 70 */
+ICD_ENTRY(RasterPos3dv) /* 71 */
+ICD_ENTRY(RasterPos3f) /* 72 */
+ICD_ENTRY(RasterPos3fv) /* 73 */
+ICD_ENTRY(RasterPos3i) /* 74 */
+ICD_ENTRY(RasterPos3iv) /* 75 */
+ICD_ENTRY(RasterPos3s) /* 76 */
+ICD_ENTRY(RasterPos3sv) /* 77 */
+ICD_ENTRY(RasterPos4d) /* 78 */
+ICD_ENTRY(RasterPos4dv) /* 79 */
+ICD_ENTRY(RasterPos4f) /* 80 */
+ICD_ENTRY(RasterPos4fv) /* 81 */
+ICD_ENTRY(RasterPos4i) /* 82 */
+ICD_ENTRY(RasterPos4iv) /* 83 */
+ICD_ENTRY(RasterPos4s) /* 84 */
+ICD_ENTRY(RasterPos4sv) /* 85 */
+ICD_ENTRY(Rectd) /* 86 */
+ICD_ENTRY(Rectdv) /* 87 */
+ICD_ENTRY(Rectf) /* 88 */
+ICD_ENTRY(Rectfv) /* 89 */
+ICD_ENTRY(Recti) /* 90 */
+ICD_ENTRY(Rectiv) /* 91 */
+ICD_ENTRY(Rects) /* 92 */
+ICD_ENTRY(Rectsv) /* 93 */
+ICD_ENTRY(TexCoord1d) /* 94 */
+ICD_ENTRY(TexCoord1dv) /* 95 */
+ICD_ENTRY(TexCoord1f) /* 96 */
+ICD_ENTRY(TexCoord1fv) /* 97 */
+ICD_ENTRY(TexCoord1i) /* 98 */
+ICD_ENTRY(TexCoord1iv) /* 99 */
+ICD_ENTRY(TexCoord1s) /* 100 */
+ICD_ENTRY(TexCoord1sv) /* 101 */
+ICD_ENTRY(TexCoord2d) /* 102 */
+ICD_ENTRY(TexCoord2dv) /* 103 */
+ICD_ENTRY(TexCoord2f) /* 104 */
+ICD_ENTRY(TexCoord2fv) /* 105 */
+ICD_ENTRY(TexCoord2i) /* 106 */
+ICD_ENTRY(TexCoord2iv) /* 107 */
+ICD_ENTRY(TexCoord2s) /* 108 */
+ICD_ENTRY(TexCoord2sv) /* 109 */
+ICD_ENTRY(TexCoord3d) /* 110 */
+ICD_ENTRY(TexCoord3dv) /* 111 */
+ICD_ENTRY(TexCoord3f) /* 112 */
+ICD_ENTRY(TexCoord3fv) /* 113 */
+ICD_ENTRY(TexCoord3i) /* 114 */
+ICD_ENTRY(TexCoord3iv) /* 115 */
+ICD_ENTRY(TexCoord3s) /* 116 */
+ICD_ENTRY(TexCoord3sv) /* 117 */
+ICD_ENTRY(TexCoord4d) /* 118 */
+ICD_ENTRY(TexCoord4dv) /* 119 */
+ICD_ENTRY(TexCoord4f) /* 120 */
+ICD_ENTRY(TexCoord4fv) /* 121 */
+ICD_ENTRY(TexCoord4i) /* 122 */
+ICD_ENTRY(TexCoord4iv) /* 123 */
+ICD_ENTRY(TexCoord4s) /* 124 */
+ICD_ENTRY(TexCoord4sv) /* 125 */
+ICD_ENTRY(Vertex2d) /* 126 */
+ICD_ENTRY(Vertex2dv) /* 127 */
+ICD_ENTRY(Vertex2f) /* 128 */
+ICD_ENTRY(Vertex2fv) /* 129 */
+ICD_ENTRY(Vertex2i) /* 130 */
+ICD_ENTRY(Vertex2iv) /* 131 */
+ICD_ENTRY(Vertex2s) /* 132 */
+ICD_ENTRY(Vertex2sv) /* 133 */
+ICD_ENTRY(Vertex3d) /* 134 */
+ICD_ENTRY(Vertex3dv) /* 135 */
+ICD_ENTRY(Vertex3f) /* 136 */
+ICD_ENTRY(Vertex3fv) /* 137 */
+ICD_ENTRY(Vertex3i) /* 138 */
+ICD_ENTRY(Vertex3iv) /* 139 */
+ICD_ENTRY(Vertex3s) /* 140 */
+ICD_ENTRY(Vertex3sv) /* 141 */
+ICD_ENTRY(Vertex4d) /* 142 */
+ICD_ENTRY(Vertex4dv) /* 143 */
+ICD_ENTRY(Vertex4f) /* 144 */
+ICD_ENTRY(Vertex4fv) /* 145 */
+ICD_ENTRY(Vertex4i) /* 146 */
+ICD_ENTRY(Vertex4iv) /* 147 */
+ICD_ENTRY(Vertex4s) /* 148 */
+ICD_ENTRY(Vertex4sv) /* 149 */
+ICD_ENTRY(ClipPlane) /* 150 */
+ICD_ENTRY(ColorMaterial) /* 151 */
+ICD_ENTRY(CullFace) /* 152 */
+ICD_ENTRY(Fogf) /* 153 */
+ICD_ENTRY(Fogfv) /* 154 */
+ICD_ENTRY(Fogi) /* 155 */
+ICD_ENTRY(Fogiv) /* 156 */
+ICD_ENTRY(FrontFace) /* 157 */
+ICD_ENTRY(Hint) /* 158 */
+ICD_ENTRY(Lightf) /* 159 */
+ICD_ENTRY(Lightfv) /* 160 */
+ICD_ENTRY(Lighti) /* 161 */
+ICD_ENTRY(Lightiv) /* 162 */
+ICD_ENTRY(LightModelf) /* 163 */
+ICD_ENTRY(LightModelfv) /* 164 */
+ICD_ENTRY(LightModeli) /* 165 */
+ICD_ENTRY(LightModeliv) /* 166 */
+ICD_ENTRY(LineStipple) /* 167 */
+ICD_ENTRY(LineWidth) /* 168 */
+ICD_ENTRY(Materialf) /* 169 */
+ICD_ENTRY(Materialfv) /* 170 */
+ICD_ENTRY(Materiali) /* 171 */
+ICD_ENTRY(Materialiv) /* 172 */
+ICD_ENTRY(PointSize) /* 173 */
+ICD_ENTRY(PolygonMode) /* 174 */
+ICD_ENTRY(PolygonStipple) /* 175 */
+ICD_ENTRY(Scissor) /* 176 */
+ICD_ENTRY(ShadeModel) /* 177 */
+ICD_ENTRY(TexParameterf) /* 178 */
+ICD_ENTRY(TexParameterfv) /* 179 */
+ICD_ENTRY(TexParameteri) /* 180 */
+ICD_ENTRY(TexParameteriv) /* 181 */
+ICD_ENTRY(TexImage1D) /* 182 */
+ICD_ENTRY(TexImage2D) /* 183 */
+ICD_ENTRY(TexEnvf) /* 184 */
+ICD_ENTRY(TexEnvfv) /* 185 */
+ICD_ENTRY(TexEnvi) /* 186 */
+ICD_ENTRY(TexEnviv) /* 187 */
+ICD_ENTRY(TexGend) /* 188 */
+ICD_ENTRY(TexGendv) /* 189 */
+ICD_ENTRY(TexGenf) /* 190 */
+ICD_ENTRY(TexGenfv) /* 191 */
+ICD_ENTRY(TexGeni) /* 192 */
+ICD_ENTRY(TexGeniv) /* 193 */
+ICD_ENTRY(FeedbackBuffer) /* 194 */
+ICD_ENTRY(SelectBuffer) /* 195 */
+ICD_ENTRY(RenderMode) /* 196 */
+ICD_ENTRY(InitNames) /* 197 */
+ICD_ENTRY(LoadName) /* 198 */
+ICD_ENTRY(PassThrough) /* 199 */
+ICD_ENTRY(PopName) /* 200 */
+ICD_ENTRY(PushName) /* 201 */
+ICD_ENTRY(DrawBuffer) /* 202 */
+ICD_ENTRY(Clear) /* 203 */
+ICD_ENTRY(ClearAccum) /* 204 */
+ICD_ENTRY(ClearIndex) /* 205 */
+ICD_ENTRY(ClearColor) /* 206 */
+ICD_ENTRY(ClearStencil) /* 207 */
+ICD_ENTRY(ClearDepth) /* 208 */
+ICD_ENTRY(StencilMask) /* 209 */
+ICD_ENTRY(ColorMask) /* 210 */
+ICD_ENTRY(DepthMask) /* 211 */
+ICD_ENTRY(IndexMask) /* 212 */
+ICD_ENTRY(Accum) /* 213 */
+ICD_ENTRY(Disable) /* 214 */
+ICD_ENTRY(Enable) /* 215 */
+ICD_ENTRY(Finish) /* 216 */
+ICD_ENTRY(Flush) /* 217 */
+ICD_ENTRY(PopAttrib) /* 218 */
+ICD_ENTRY(PushAttrib) /* 219 */
+ICD_ENTRY(Map1d) /* 220 */
+ICD_ENTRY(Map1f) /* 221 */
+ICD_ENTRY(Map2d) /* 222 */
+ICD_ENTRY(Map2f) /* 223 */
+ICD_ENTRY(MapGrid1d) /* 224 */
+ICD_ENTRY(MapGrid1f) /* 225 */
+ICD_ENTRY(MapGrid2d) /* 226 */
+ICD_ENTRY(MapGrid2f) /* 227 */
+ICD_ENTRY(EvalCoord1d) /* 228 */
+ICD_ENTRY(EvalCoord1dv) /* 229 */
+ICD_ENTRY(EvalCoord1f) /* 230 */
+ICD_ENTRY(EvalCoord1fv) /* 231 */
+ICD_ENTRY(EvalCoord2d) /* 232 */
+ICD_ENTRY(EvalCoord2dv) /* 233 */
+ICD_ENTRY(EvalCoord2f) /* 234 */
+ICD_ENTRY(EvalCoord2fv) /* 235 */
+ICD_ENTRY(EvalMesh1) /* 236 */
+ICD_ENTRY(EvalPoint1) /* 237 */
+ICD_ENTRY(EvalMesh2) /* 238 */
+ICD_ENTRY(EvalPoint2) /* 239 */
+ICD_ENTRY(AlphaFunc) /* 240 */
+ICD_ENTRY(BlendFunc) /* 241 */
+ICD_ENTRY(LogicOp) /* 242 */
+ICD_ENTRY(StencilFunc) /* 243 */
+ICD_ENTRY(StencilOp) /* 244 */
+ICD_ENTRY(DepthFunc) /* 245 */
+ICD_ENTRY(PixelZoom) /* 246 */
+ICD_ENTRY(PixelTransferf) /* 247 */
+ICD_ENTRY(PixelTransferi) /* 248 */
+ICD_ENTRY(PixelStoref) /* 249 */
+ICD_ENTRY(PixelStorei) /* 250 */
+ICD_ENTRY(PixelMapfv) /* 251 */
+ICD_ENTRY(PixelMapuiv) /* 252 */
+ICD_ENTRY(PixelMapusv) /* 253 */
+ICD_ENTRY(ReadBuffer) /* 254 */
+ICD_ENTRY(CopyPixels) /* 255 */
+ICD_ENTRY(ReadPixels) /* 256 */
+ICD_ENTRY(DrawPixels) /* 257 */
+ICD_ENTRY(GetBooleanv) /* 258 */
+ICD_ENTRY(GetClipPlane) /* 259 */
+ICD_ENTRY(GetDoublev) /* 260 */
+ICD_ENTRY(GetError) /* 261 */
+ICD_ENTRY(GetFloatv) /* 262 */
+ICD_ENTRY(GetIntegerv) /* 263 */
+ICD_ENTRY(GetLightfv) /* 264 */
+ICD_ENTRY(GetLightiv) /* 265 */
+ICD_ENTRY(GetMapdv) /* 266 */
+ICD_ENTRY(GetMapfv) /* 267 */
+ICD_ENTRY(GetMapiv) /* 268 */
+ICD_ENTRY(GetMaterialfv) /* 269 */
+ICD_ENTRY(GetMaterialiv) /* 270 */
+ICD_ENTRY(GetPixelMapfv) /* 271 */
+ICD_ENTRY(GetPixelMapuiv) /* 272 */
+ICD_ENTRY(GetPixelMapusv) /* 273 */
+ICD_ENTRY(GetPolygonStipple) /* 274 */
+ICD_ENTRY(GetString) /* 275 */
+ICD_ENTRY(GetTexEnvfv) /* 276 */
+ICD_ENTRY(GetTexEnviv) /* 277 */
+ICD_ENTRY(GetTexGendv) /* 278 */
+ICD_ENTRY(GetTexGenfv) /* 279 */
+ICD_ENTRY(GetTexGeniv) /* 280 */
+ICD_ENTRY(GetTexImage) /* 281 */
+ICD_ENTRY(GetTexParameterfv) /* 282 */
+ICD_ENTRY(GetTexParameteriv) /* 283 */
+ICD_ENTRY(GetTexLevelParameterfv) /* 284 */
+ICD_ENTRY(GetTexLevelParameteriv) /* 285 */
+ICD_ENTRY(IsEnabled) /* 286 */
+ICD_ENTRY(IsList) /* 287 */
+ICD_ENTRY(DepthRange) /* 288 */
+ICD_ENTRY(Frustum) /* 289 */
+ICD_ENTRY(LoadIdentity) /* 290 */
+ICD_ENTRY(LoadMatrixf) /* 291 */
+ICD_ENTRY(LoadMatrixd) /* 292 */
+ICD_ENTRY(MatrixMode) /* 293 */
+ICD_ENTRY(MultMatrixf) /* 294 */
+ICD_ENTRY(MultMatrixd) /* 295 */
+ICD_ENTRY(Ortho) /* 296 */
+ICD_ENTRY(PopMatrix) /* 297 */
+ICD_ENTRY(PushMatrix) /* 298 */
+ICD_ENTRY(Rotated) /* 299 */
+ICD_ENTRY(Rotatef) /* 300 */
+ICD_ENTRY(Scaled) /* 301 */
+ICD_ENTRY(Scalef) /* 302 */
+ICD_ENTRY(Translated) /* 303 */
+ICD_ENTRY(Translatef) /* 304 */
+ICD_ENTRY(Viewport) /* 305 */
+ICD_ENTRY(ArrayElement) /* 306 */
+ICD_ENTRY(BindTexture) /* 307 */
+ICD_ENTRY(ColorPointer) /* 308 */
+ICD_ENTRY(DisableClientState) /* 309 */
+ICD_ENTRY(DrawArrays) /* 310 */
+ICD_ENTRY(DrawElements) /* 311 */
+ICD_ENTRY(EdgeFlagPointer) /* 312 */
+ICD_ENTRY(EnableClientState) /* 313 */
+ICD_ENTRY(IndexPointer) /* 314 */
+ICD_ENTRY(Indexub) /* 315 */
+ICD_ENTRY(Indexubv) /* 316 */
+ICD_ENTRY(InterleavedArrays) /* 317 */
+ICD_ENTRY(NormalPointer) /* 318 */
+ICD_ENTRY(PolygonOffset) /* 319 */
+ICD_ENTRY(TexCoordPointer) /* 320 */
+ICD_ENTRY(VertexPointer) /* 321 */
+ICD_ENTRY(AreTexturesResident) /* 322 */
+ICD_ENTRY(CopyTexImage1D) /* 323 */
+ICD_ENTRY(CopyTexImage2D) /* 324 */
+ICD_ENTRY(CopyTexSubImage1D) /* 325 */
+ICD_ENTRY(CopyTexSubImage2D) /* 326 */
+ICD_ENTRY(DeleteTextures) /* 327 */
+ICD_ENTRY(GenTextures) /* 328 */
+ICD_ENTRY(GetPointerv) /* 329 */
+ICD_ENTRY(IsTexture) /* 330 */
+ICD_ENTRY(PrioritizeTextures) /* 331 */
+ICD_ENTRY(TexSubImage1D) /* 332 */
+ICD_ENTRY(TexSubImage2D) /* 333 */
+ICD_ENTRY(PopClientAttrib) /* 334 */
+ICD_ENTRY(PushClientAttrib) /* 335 */
diff --git a/src/mesa/drivers/windows/icd/mesa.def b/src/mesa/drivers/windows/icd/mesa.def
new file mode 100644
index 0000000..263b9d4
--- /dev/null
+++ b/src/mesa/drivers/windows/icd/mesa.def
@@ -0,0 +1,110 @@
+DESCRIPTION 'Mesa (OpenGL driver) for Win32'
+VERSION 6.1
+
+EXPORTS
+;
+; ICD API
+ DrvCopyContext
+ DrvCreateContext
+ DrvCreateLayerContext
+ DrvDeleteContext
+ DrvDescribeLayerPlane
+ DrvDescribePixelFormat
+ DrvGetLayerPaletteEntries
+ DrvGetProcAddress
+ DrvReleaseContext
+ DrvRealizeLayerPalette
+ DrvSetContext
+ DrvSetLayerPaletteEntries
+ DrvSetPixelFormat
+ DrvShareLists
+ DrvSwapBuffers
+ DrvSwapLayerBuffers
+ DrvValidateVersion
+
+;
+; Mesa internals - mostly for OSMESA
+ _ac_CreateContext
+ _ac_DestroyContext
+ _ac_InvalidateState
+ _glapi_get_context
+ _glapi_get_proc_address
+ _mesa_buffer_data
+ _mesa_buffer_map
+ _mesa_buffer_subdata
+ _mesa_bzero
+ _mesa_calloc
+ _mesa_choose_tex_format
+ _mesa_compressed_texture_size
+ _mesa_create_framebuffer
+ _mesa_create_visual
+ _mesa_delete_buffer_object
+ _mesa_delete_texture_object
+ _mesa_destroy_framebuffer
+ _mesa_destroy_visual
+ _mesa_enable_1_3_extensions
+ _mesa_enable_1_4_extensions
+ _mesa_enable_1_5_extensions
+ _mesa_enable_sw_extensions
+ _mesa_error
+ _mesa_free
+ _mesa_free_context_data
+ _mesa_get_current_context
+ _mesa_init_default_imports
+ _mesa_init_driver_functions
+ _mesa_initialize_context
+ _mesa_make_current
+ _mesa_memcpy
+ _mesa_memset
+ _mesa_new_buffer_object
+ _mesa_new_texture_object
+ _mesa_problem
+ _mesa_ResizeBuffersMESA
+ _mesa_store_compressed_teximage1d
+ _mesa_store_compressed_teximage2d
+ _mesa_store_compressed_teximage3d
+ _mesa_store_compressed_texsubimage1d
+ _mesa_store_compressed_texsubimage2d
+ _mesa_store_compressed_texsubimage3d
+ _mesa_store_teximage1d
+ _mesa_store_teximage2d
+ _mesa_store_teximage3d
+ _mesa_store_texsubimage1d
+ _mesa_store_texsubimage2d
+ _mesa_store_texsubimage3d
+ _mesa_strcmp
+ _mesa_test_proxy_teximage
+ _mesa_Viewport
+ _swrast_Accum
+ _swrast_alloc_buffers
+ _swrast_Bitmap
+ _swrast_CopyPixels
+ _swrast_DrawBuffer
+ _swrast_DrawPixels
+ _swrast_GetDeviceDriverReference
+ _swrast_Clear
+ _swrast_choose_line
+ _swrast_choose_triangle
+ _swrast_CopyColorSubTable
+ _swrast_CopyColorTable
+ _swrast_CopyConvolutionFilter1D
+ _swrast_CopyConvolutionFilter2D
+ _swrast_copy_teximage1d
+ _swrast_copy_teximage2d
+ _swrast_copy_texsubimage1d
+ _swrast_copy_texsubimage2d
+ _swrast_copy_texsubimage3d
+ _swrast_CreateContext
+ _swrast_DestroyContext
+ _swrast_InvalidateState
+ _swrast_ReadPixels
+ _swrast_zbuffer_address
+ _swsetup_Wakeup
+ _swsetup_CreateContext
+ _swsetup_DestroyContext
+ _swsetup_InvalidateState
+ _tnl_CreateContext
+ _tnl_DestroyContext
+ _tnl_InvalidateState
+ _tnl_MakeCurrent
+ _tnl_run_pipeline
diff --git a/src/mesa/drivers/x11/descrip.mms b/src/mesa/drivers/x11/descrip.mms
new file mode 100644
index 0000000..ffac99f
--- /dev/null
+++ b/src/mesa/drivers/x11/descrip.mms
@@ -0,0 +1,50 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl
+# Last revision : 16 June 2003
+
+.first
+ define gl [----.include.gl]
+ define math [--.math]
+ define tnl [--.tnl]
+ define swrast [--.swrast]
+ define swrast_setup [--.swrast_setup]
+ define array_cache [--.array_cache]
+ define drivers [-]
+
+.include [----]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [----.include],[--.main],[--.glapi]
+LIBDIR = [----.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)
+
+SOURCES = fakeglx.c glxapi.c xfonts.c xm_api.c xm_dd.c xm_line.c xm_span.c\
+ xm_tri.c
+
+OBJECTS =fakeglx.obj,glxapi.obj,xfonts.obj,xm_api.obj,xm_dd.obj,xm_line.obj,\
+ xm_span.obj,xm_tri.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.4
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS)
+ @ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
+
+clean :
+ purge
+ delete *.obj;*
+
+fakeglx.obj : fakeglx.c
+glxapi.obj : glxapi.c
+xfonts.obj : xfonts.c
+xm_api.obj : xm_api.c
+xm_dd.obj : xm_dd.c
+xm_line.obj : xm_line.c
+xm_span.obj : xm_span.c
+xm_tri.obj : xm_tri.c
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c
new file mode 100644
index 0000000..fd7861f
--- /dev/null
+++ b/src/mesa/drivers/x11/fakeglx.c
@@ -0,0 +1,2929 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2.2
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+
+/*
+ * This is an emulation of the GLX API which allows Mesa/GLX-based programs
+ * to run on X servers which do not have the real GLX extension.
+ *
+ * Thanks to the contributors:
+ *
+ * Initial version: Philip Brown (phil@bolthole.com)
+ * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
+ * Further visual-handling refinements: Wolfram Gloger
+ * (wmglo@Dent.MED.Uni-Muenchen.DE).
+ *
+ * Notes:
+ * Don't be fooled, stereo isn't supported yet.
+ */
+
+
+
+#include "glxheader.h"
+#include "glxapi.h"
+#include "GL/xmesa.h"
+#include "context.h"
+#include "config.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "version.h"
+#include "xfonts.h"
+#include "xmesaP.h"
+
+
+/* This indicates the client-side GLX API and GLX encoder version. */
+#define CLIENT_MAJOR_VERSION 1
+#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */
+
+/* This indicates the server-side GLX decoder version.
+ * GLX 1.4 indicates OpenGL 1.3 support
+ */
+#define SERVER_MAJOR_VERSION 1
+#define SERVER_MINOR_VERSION 4
+
+/* This is appended onto the glXGetClient/ServerString version strings. */
+#define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING
+
+/* Who implemented this GLX? */
+#define VENDOR "Brian Paul"
+
+#define EXTENSIONS \
+ "GLX_MESA_set_3dfx_mode " \
+ "GLX_MESA_copy_sub_buffer " \
+ "GLX_MESA_pixmap_colormap " \
+ "GLX_MESA_release_buffers " \
+ "GLX_ARB_get_proc_address " \
+ "GLX_EXT_visual_info " \
+ "GLX_EXT_visual_rating " \
+ "GLX_SGI_video_sync " \
+ "GLX_SGIX_fbconfig " \
+ "GLX_SGIX_pbuffer "
+
+/*
+ * Our fake GLX context will contain a "real" GLX context and an XMesa context.
+ *
+ * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context,
+ * and vice versa.
+ *
+ * We really just need this structure in order to make the libGL functions
+ * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay()
+ * work correctly.
+ */
+struct fake_glx_context {
+ __GLXcontext glxContext; /* this MUST be first! */
+ XMesaContext xmesaContext;
+};
+
+
+
+/**********************************************************************/
+/*** GLX Visual Code ***/
+/**********************************************************************/
+
+#define DONT_CARE -1
+
+
+#define MAX_VISUALS 100
+static XMesaVisual VisualTable[MAX_VISUALS];
+static int NumVisuals = 0;
+
+
+/*
+ * This struct and some code fragments borrowed
+ * from Mark Kilgard's GLUT library.
+ */
+typedef struct _OverlayInfo {
+ /* Avoid 64-bit portability problems by being careful to use
+ longs due to the way XGetWindowProperty is specified. Note
+ that these parameters are passed as CARD32s over X
+ protocol. */
+ unsigned long overlay_visual;
+ long transparent_type;
+ long value;
+ long layer;
+} OverlayInfo;
+
+
+
+/* Macro to handle c_class vs class field name in XVisualInfo struct */
+#if defined(__cplusplus) || defined(c_plusplus)
+#define CLASS c_class
+#else
+#define CLASS class
+#endif
+
+
+
+
+/*
+ * Test if the given XVisualInfo is usable for Mesa rendering.
+ */
+static GLboolean
+is_usable_visual( XVisualInfo *vinfo )
+{
+ switch (vinfo->CLASS) {
+ case StaticGray:
+ case GrayScale:
+ /* Any StaticGray/GrayScale visual works in RGB or CI mode */
+ return GL_TRUE;
+ case StaticColor:
+ case PseudoColor:
+ /* Any StaticColor/PseudoColor visual of at least 4 bits */
+ if (vinfo->depth>=4) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ case TrueColor:
+ case DirectColor:
+ /* Any depth of TrueColor or DirectColor works in RGB mode */
+ return GL_TRUE;
+ default:
+ /* This should never happen */
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Return the level (overlay, normal, underlay) of a given XVisualInfo.
+ * Input: dpy - the X display
+ * vinfo - the XVisualInfo to test
+ * Return: level of the visual:
+ * 0 = normal planes
+ * >0 = overlay planes
+ * <0 = underlay planes
+ */
+static int
+level_of_visual( Display *dpy, XVisualInfo *vinfo )
+{
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info = NULL;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == None) {
+ return 0;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ XFree((void *) overlay_info);
+ return 0;
+ }
+
+ /* search the overlay visual list for the visual ID of interest */
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+ if (ov->overlay_visual==vinfo->visualid) {
+ /* found the visual */
+ if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
+ int level = ov->layer;
+ XFree((void *) overlay_info);
+ return level;
+ }
+ else {
+ XFree((void *) overlay_info);
+ return 0;
+ }
+ }
+ }
+
+ /* The visual ID was not found in the overlay list. */
+ XFree((void *) overlay_info);
+ return 0;
+}
+
+
+
+
+/*
+ * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
+ * configuration in our list of GLX visuals.
+ */
+static XMesaVisual
+save_glx_visual( Display *dpy, XVisualInfo *vinfo,
+ GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint depth_size, GLint stencil_size,
+ GLint accumRedSize, GLint accumGreenSize,
+ GLint accumBlueSize, GLint accumAlphaSize,
+ GLint level, GLint numAuxBuffers )
+{
+ GLboolean ximageFlag = GL_TRUE;
+ XMesaVisual xmvis;
+ GLint i;
+ GLboolean comparePointers;
+
+ if (dbFlag) {
+ /* Check if the MESA_BACK_BUFFER env var is set */
+ char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
+ if (backbuffer) {
+ if (backbuffer[0]=='p' || backbuffer[0]=='P') {
+ ximageFlag = GL_FALSE;
+ }
+ else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
+ ximageFlag = GL_TRUE;
+ }
+ else {
+ _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
+ }
+ }
+ }
+
+ /* Comparing IDs uses less memory but sometimes fails. */
+ /* XXX revisit this after 3.0 is finished. */
+ if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
+ comparePointers = GL_TRUE;
+ else
+ comparePointers = GL_FALSE;
+
+ /* Force the visual to have an alpha channel */
+ if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA"))
+ alphaFlag = GL_TRUE;
+
+ /* First check if a matching visual is already in the list */
+ for (i=0; i<NumVisuals; i++) {
+ XMesaVisual v = VisualTable[i];
+ if (v->display == dpy
+ && v->mesa_visual.level == level
+ && v->mesa_visual.numAuxBuffers == numAuxBuffers
+ && v->ximage_flag == ximageFlag
+ && v->mesa_visual.rgbMode == rgbFlag
+ && v->mesa_visual.doubleBufferMode == dbFlag
+ && v->mesa_visual.stereoMode == stereoFlag
+ && (v->mesa_visual.alphaBits > 0) == alphaFlag
+ && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
+ && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
+ && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
+ && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
+ && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
+ && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
+ /* now either compare XVisualInfo pointers or visual IDs */
+ if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
+ || (comparePointers && v->vishandle == vinfo)) {
+ return v;
+ }
+ }
+ }
+
+ /* Create a new visual and add it to the list. */
+
+ if (NumVisuals >= MAX_VISUALS) {
+ _mesa_problem(NULL, "GLX Error: maximum number of visuals exceeded");
+ return NULL;
+ }
+
+ xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
+ stereoFlag, ximageFlag,
+ depth_size, stencil_size,
+ accumRedSize, accumBlueSize,
+ accumBlueSize, accumAlphaSize, 0, level,
+ GLX_NONE_EXT );
+ if (xmvis) {
+ /* Save a copy of the pointer now so we can find this visual again
+ * if we need to search for it in find_glx_visual().
+ */
+ xmvis->vishandle = vinfo;
+ /* add xmvis to the list */
+ VisualTable[NumVisuals] = xmvis;
+ NumVisuals++;
+ /* XXX minor hack, because XMesaCreateVisual doesn't support an
+ * aux buffers parameter.
+ */
+ xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
+ }
+ return xmvis;
+}
+
+
+/**
+ * Return the default number of bits for the Z buffer.
+ * If defined, use the MESA_GLX_DEPTH_BITS env var value.
+ * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
+ * XXX probably do the same thing for stencil, accum, etc.
+ */
+static GLint
+default_depth_bits(void)
+{
+ int zBits;
+ const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
+ if (zEnv)
+ zBits = _mesa_atoi(zEnv);
+ else
+ zBits = DEFAULT_SOFTWARE_DEPTH_BITS;
+ return zBits;
+}
+
+
+
+/*
+ * Create a GLX visual from a regular XVisualInfo.
+ * This is called when Fake GLX is given an XVisualInfo which wasn't
+ * returned by glXChooseVisual. Since this is the first time we're
+ * considering this visual we'll take a guess at reasonable values
+ * for depth buffer size, stencil size, accum size, etc.
+ * This is the best we can do with a client-side emulation of GLX.
+ */
+static XMesaVisual
+create_glx_visual( Display *dpy, XVisualInfo *visinfo )
+{
+ int vislevel;
+ GLint zBits = default_depth_bits();
+
+ vislevel = level_of_visual( dpy, visinfo );
+ if (vislevel) {
+ /* Configure this visual as a CI, single-buffered overlay */
+ return save_glx_visual( dpy, visinfo,
+ GL_FALSE, /* rgb */
+ GL_FALSE, /* alpha */
+ GL_FALSE, /* double */
+ GL_FALSE, /* stereo */
+ 0, /* depth bits */
+ 0, /* stencil bits */
+ 0,0,0,0, /* accum bits */
+ vislevel, /* level */
+ 0 /* numAux */
+ );
+ }
+ else if (is_usable_visual( visinfo )) {
+ if (_mesa_getenv("MESA_GLX_FORCE_CI")) {
+ /* Configure this visual as a COLOR INDEX visual. */
+ return save_glx_visual( dpy, visinfo,
+ GL_FALSE, /* rgb */
+ GL_FALSE, /* alpha */
+ GL_TRUE, /* double */
+ GL_FALSE, /* stereo */
+ zBits,
+ 8 * sizeof(GLstencil),
+ 0 * sizeof(GLaccum), /* r */
+ 0 * sizeof(GLaccum), /* g */
+ 0 * sizeof(GLaccum), /* b */
+ 0 * sizeof(GLaccum), /* a */
+ 0, /* level */
+ 0 /* numAux */
+ );
+ }
+ else {
+ /* Configure this visual as RGB, double-buffered, depth-buffered. */
+ /* This is surely wrong for some people's needs but what else */
+ /* can be done? They should use glXChooseVisual(). */
+ return save_glx_visual( dpy, visinfo,
+ GL_TRUE, /* rgb */
+ GL_FALSE, /* alpha */
+ GL_TRUE, /* double */
+ GL_FALSE, /* stereo */
+ zBits,
+ 8 * sizeof(GLstencil),
+ 8 * sizeof(GLaccum), /* r */
+ 8 * sizeof(GLaccum), /* g */
+ 8 * sizeof(GLaccum), /* b */
+ 8 * sizeof(GLaccum), /* a */
+ 0, /* level */
+ 0 /* numAux */
+ );
+ }
+ }
+ else {
+ _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
+ return NULL;
+ }
+}
+
+
+
+/*
+ * Find the GLX visual associated with an XVisualInfo.
+ */
+static XMesaVisual
+find_glx_visual( Display *dpy, XVisualInfo *vinfo )
+{
+ int i;
+
+ /* try to match visual id */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy
+ && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
+ return VisualTable[i];
+ }
+ }
+
+ /* if that fails, try to match pointers */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
+ return VisualTable[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/*
+ * Return the transparent pixel value for a GLX visual.
+ * Input: glxvis - the glx_visual
+ * Return: a pixel value or -1 if no transparent pixel
+ */
+static int
+transparent_pixel( XMesaVisual glxvis )
+{
+ Display *dpy = glxvis->display;
+ XVisualInfo *vinfo = glxvis->visinfo;
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info = NULL;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == None) {
+ return -1;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ XFree((void *) overlay_info);
+ return -1;
+ }
+
+ /* search the overlay visual list for the visual ID of interest */
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+ if (ov->overlay_visual==vinfo->visualid) {
+ /* found it! */
+ if (ov->transparent_type==0) {
+ /* type 0 indicates no transparency */
+ XFree((void *) overlay_info);
+ return -1;
+ }
+ else {
+ /* ov->value is the transparent pixel */
+ XFree((void *) overlay_info);
+ return ov->value;
+ }
+ }
+ }
+
+ /* The visual ID was not found in the overlay list. */
+ XFree((void *) overlay_info);
+ return -1;
+}
+
+
+
+/*
+ * Try to get an X visual which matches the given arguments.
+ */
+static XVisualInfo *
+get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
+{
+ XVisualInfo temp, *vis;
+ long mask;
+ int n;
+ unsigned int default_depth;
+ int default_class;
+
+ mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+ temp.screen = scr;
+ temp.depth = depth;
+ temp.CLASS = xclass;
+
+ default_depth = DefaultDepth(dpy,scr);
+ default_class = DefaultVisual(dpy,scr)->CLASS;
+
+ if (depth==default_depth && xclass==default_class) {
+ /* try to get root window's visual */
+ temp.visualid = DefaultVisual(dpy,scr)->visualid;
+ mask |= VisualIDMask;
+ }
+
+ vis = XGetVisualInfo( dpy, mask, &temp, &n );
+
+ /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
+ * An SGI Infinite Reality system, for example, can have 30bpp pixels:
+ * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
+ */
+ if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
+ if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 &&
+ _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
+ _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
+ return vis;
+ }
+ else {
+ XFree((void *) vis);
+ return NULL;
+ }
+ }
+
+ return vis;
+}
+
+
+
+/*
+ * Retrieve the value of the given environment variable and find
+ * the X visual which matches it.
+ * Input: dpy - the display
+ * screen - the screen number
+ * varname - the name of the environment variable
+ * Return: an XVisualInfo pointer to NULL if error.
+ */
+static XVisualInfo *
+get_env_visual(Display *dpy, int scr, const char *varname)
+{
+ char value[100], type[100];
+ int depth, xclass = -1;
+ XVisualInfo *vis;
+
+ if (!_mesa_getenv( varname )) {
+ return NULL;
+ }
+
+ _mesa_strncpy( value, _mesa_getenv(varname), 100 );
+ value[99] = 0;
+
+ sscanf( value, "%s %d", type, &depth );
+
+ if (_mesa_strcmp(type,"TrueColor")==0) xclass = TrueColor;
+ else if (_mesa_strcmp(type,"DirectColor")==0) xclass = DirectColor;
+ else if (_mesa_strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
+ else if (_mesa_strcmp(type,"StaticColor")==0) xclass = StaticColor;
+ else if (_mesa_strcmp(type,"GrayScale")==0) xclass = GrayScale;
+ else if (_mesa_strcmp(type,"StaticGray")==0) xclass = StaticGray;
+
+ if (xclass>-1 && depth>0) {
+ vis = get_visual( dpy, scr, depth, xclass );
+ if (vis) {
+ return vis;
+ }
+ }
+
+ _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
+ type, depth);
+
+ return NULL;
+}
+
+
+
+/*
+ * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
+ * Input: dpy, screen - X display and screen number
+ * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
+ * min_depth - minimum visual depth
+ * preferred_class - preferred GLX visual class or DONT_CARE
+ * Return: pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *
+choose_x_visual( Display *dpy, int screen, GLboolean rgba, int min_depth,
+ int preferred_class )
+{
+ XVisualInfo *vis;
+ int xclass, visclass = 0;
+ int depth;
+
+ if (rgba) {
+ Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
+ /* First see if the MESA_RGB_VISUAL env var is defined */
+ vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
+ if (vis) {
+ return vis;
+ }
+ /* Otherwise, search for a suitable visual */
+ if (preferred_class==DONT_CARE) {
+ for (xclass=0;xclass<6;xclass++) {
+ switch (xclass) {
+ case 0: visclass = TrueColor; break;
+ case 1: visclass = DirectColor; break;
+ case 2: visclass = PseudoColor; break;
+ case 3: visclass = StaticColor; break;
+ case 4: visclass = GrayScale; break;
+ case 5: visclass = StaticGray; break;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* search for a specific visual class */
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
+ default: return NULL;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* First see if the MESA_CI_VISUAL env var is defined */
+ vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
+ if (vis) {
+ return vis;
+ }
+ /* Otherwise, search for a suitable visual, starting with shallowest */
+ if (preferred_class==DONT_CARE) {
+ for (xclass=0;xclass<4;xclass++) {
+ switch (xclass) {
+ case 0: visclass = PseudoColor; break;
+ case 1: visclass = StaticColor; break;
+ case 2: visclass = GrayScale; break;
+ case 3: visclass = StaticGray; break;
+ }
+ /* try 8-bit up through 16-bit */
+ for (depth=8;depth<=16;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ /* try min_depth up to 8-bit */
+ for (depth=min_depth;depth<8;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ else {
+ /* search for a specific visual class */
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
+ default: return NULL;
+ }
+ /* try 8-bit up through 16-bit */
+ for (depth=8;depth<=16;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ /* try min_depth up to 8-bit */
+ for (depth=min_depth;depth<8;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+
+ /* didn't find a visual */
+ return NULL;
+}
+
+
+
+/*
+ * Find the deepest X over/underlay visual of at least min_depth.
+ * Input: dpy, screen - X display and screen number
+ * level - the over/underlay level
+ * trans_type - transparent pixel type: GLX_NONE_EXT,
+ * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
+ * or DONT_CARE
+ * trans_value - transparent pixel value or DONT_CARE
+ * min_depth - minimum visual depth
+ * preferred_class - preferred GLX visual class or DONT_CARE
+ * Return: pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *
+choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
+ int level, int trans_type, int trans_value,
+ int min_depth, int preferred_class )
+{
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+ XVisualInfo *deepvis;
+ int deepest;
+
+ /*DEBUG int tt, tv; */
+
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: preferred_class = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: preferred_class = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: preferred_class = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: preferred_class = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: preferred_class = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: preferred_class = StaticGray; break;
+ default: preferred_class = DONT_CARE;
+ }
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == (Atom) None) {
+ return NULL;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ return NULL;
+ }
+
+ /* Search for the deepest overlay which satisifies all criteria. */
+ deepest = min_depth;
+ deepvis = NULL;
+
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ XVisualInfo *vislist, vistemplate;
+ int count;
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+
+ if (ov->layer!=level) {
+ /* failed overlay level criteria */
+ continue;
+ }
+ if (!(trans_type==DONT_CARE
+ || (trans_type==GLX_TRANSPARENT_INDEX_EXT
+ && ov->transparent_type>0)
+ || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
+ /* failed transparent pixel type criteria */
+ continue;
+ }
+ if (trans_value!=DONT_CARE && trans_value!=ov->value) {
+ /* failed transparent pixel value criteria */
+ continue;
+ }
+
+ /* get XVisualInfo and check the depth */
+ vistemplate.visualid = ov->overlay_visual;
+ vistemplate.screen = scr;
+ vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
+ &vistemplate, &count );
+
+ if (count!=1) {
+ /* something went wrong */
+ continue;
+ }
+ if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
+ /* wrong visual class */
+ continue;
+ }
+
+ /* if RGB was requested, make sure we have True/DirectColor */
+ if (rgbFlag && vislist->CLASS != TrueColor
+ && vislist->CLASS != DirectColor)
+ continue;
+
+ /* if CI was requested, make sure we have a color indexed visual */
+ if (!rgbFlag
+ && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor))
+ continue;
+
+ if (deepvis==NULL || vislist->depth > deepest) {
+ /* YES! found a satisfactory visual */
+ if (deepvis) {
+ XFree( deepvis );
+ }
+ deepest = vislist->depth;
+ deepvis = vislist;
+ /* DEBUG tt = ov->transparent_type;*/
+ /* DEBUG tv = ov->value; */
+ }
+ }
+
+/*DEBUG
+ if (deepvis) {
+ printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
+ deepvis->visualid, level, deepvis->depth, tt, tv );
+ }
+*/
+ return deepvis;
+}
+
+
+/**********************************************************************/
+/*** Begin Fake GLX API Functions ***/
+/**********************************************************************/
+
+
+static XMesaVisual
+choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
+{
+ const GLboolean rgbModeDefault = fbConfig;
+ const int *parselist;
+ XVisualInfo *vis;
+ int min_ci = 0;
+ int min_red=0, min_green=0, min_blue=0;
+ GLboolean rgb_flag = rgbModeDefault;
+ GLboolean alpha_flag = GL_FALSE;
+ GLboolean double_flag = GL_FALSE;
+ GLboolean stereo_flag = GL_FALSE;
+ GLint depth_size = 0;
+ GLint stencil_size = 0;
+ GLint accumRedSize = 0;
+ GLint accumGreenSize = 0;
+ GLint accumBlueSize = 0;
+ GLint accumAlphaSize = 0;
+ int level = 0;
+ int visual_type = DONT_CARE;
+ int trans_type = DONT_CARE;
+ int trans_value = DONT_CARE;
+ GLint caveat = DONT_CARE;
+ XMesaVisual xmvis = NULL;
+ int desiredVisualID = -1;
+ int numAux = 0;
+
+ parselist = list;
+
+ while (*parselist) {
+
+ switch (*parselist) {
+ case GLX_USE_GL:
+ if (fbConfig) {
+ /* invalid token */
+ return NULL;
+ }
+ else {
+ /* skip */
+ parselist++;
+ }
+ break;
+ case GLX_BUFFER_SIZE:
+ parselist++;
+ min_ci = *parselist++;
+ break;
+ case GLX_LEVEL:
+ parselist++;
+ level = *parselist++;
+ break;
+ case GLX_RGBA:
+ if (fbConfig) {
+ /* invalid token */
+ return NULL;
+ }
+ else {
+ rgb_flag = GL_TRUE;
+ parselist++;
+ }
+ break;
+ case GLX_DOUBLEBUFFER:
+ parselist++;
+ if (fbConfig) {
+ double_flag = *parselist++;
+ }
+ else {
+ double_flag = GL_TRUE;
+ }
+ break;
+ case GLX_STEREO:
+ parselist++;
+ if (fbConfig) {
+ stereo_flag = *parselist++;
+ }
+ else {
+ stereo_flag = GL_TRUE;
+ }
+ return NULL; /* stereo not supported */
+ case GLX_AUX_BUFFERS:
+ parselist++;
+ numAux = *parselist++;
+ if (numAux > MAX_AUX_BUFFERS)
+ return NULL;
+ break;
+ case GLX_RED_SIZE:
+ parselist++;
+ min_red = *parselist++;
+ break;
+ case GLX_GREEN_SIZE:
+ parselist++;
+ min_green = *parselist++;
+ break;
+ case GLX_BLUE_SIZE:
+ parselist++;
+ min_blue = *parselist++;
+ break;
+ case GLX_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ alpha_flag = size>0 ? 1 : 0;
+ }
+ break;
+ case GLX_DEPTH_SIZE:
+ parselist++;
+ depth_size = *parselist++;
+ break;
+ case GLX_STENCIL_SIZE:
+ parselist++;
+ stencil_size = *parselist++;
+ break;
+ case GLX_ACCUM_RED_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumRedSize = MAX2( accumRedSize, size );
+ }
+ break;
+ case GLX_ACCUM_GREEN_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumGreenSize = MAX2( accumGreenSize, size );
+ }
+ break;
+ case GLX_ACCUM_BLUE_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumBlueSize = MAX2( accumBlueSize, size );
+ }
+ break;
+ case GLX_ACCUM_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accumAlphaSize = MAX2( accumAlphaSize, size );
+ }
+ break;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ parselist++;
+ visual_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ parselist++;
+ trans_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ parselist++;
+ trans_value = *parselist++;
+ break;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* ignore */
+ parselist++;
+ parselist++;
+ break;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_VISUAL_CAVEAT_EXT:
+ parselist++;
+ caveat = *parselist++; /* ignored for now */
+ break;
+
+ /*
+ * GLX_ARB_multisample
+ */
+ case GLX_SAMPLE_BUFFERS_ARB:
+ /* ms not supported */
+ return NULL;
+ case GLX_SAMPLES_ARB:
+ /* ms not supported */
+ return NULL;
+
+ /*
+ * FBConfig attribs.
+ */
+ case GLX_RENDER_TYPE:
+ parselist++;
+ if (*parselist == GLX_RGBA_BIT) {
+ rgb_flag = GL_TRUE;
+ }
+ else if (*parselist == GLX_COLOR_INDEX_BIT) {
+ rgb_flag = GL_FALSE;
+ }
+ else if (*parselist == 0) {
+ rgb_flag = GL_TRUE;
+ }
+ parselist++;
+ break;
+ case GLX_DRAWABLE_TYPE:
+ parselist++;
+ if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
+ return NULL; /* bad bit */
+ }
+ parselist++;
+ break;
+ case GLX_FBCONFIG_ID:
+ parselist++;
+ desiredVisualID = *parselist;
+ break;
+
+ case None:
+ /* end of list */
+ break;
+
+ default:
+ /* undefined attribute */
+ _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
+ *parselist);
+ return NULL;
+ }
+ }
+
+ (void) caveat;
+
+ /*
+ * Since we're only simulating the GLX extension this function will never
+ * find any real GL visuals. Instead, all we can do is try to find an RGB
+ * or CI visual of appropriate depth. Other requested attributes such as
+ * double buffering, depth buffer, etc. will be associated with the X
+ * visual and stored in the VisualTable[].
+ */
+ if (desiredVisualID != -1) {
+ /* try to get a specific visual, by visualID */
+ XVisualInfo temp;
+ int n;
+ temp.visualid = desiredVisualID;
+ temp.screen = screen;
+ vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
+ if (vis) {
+ /* give the visual some useful GLX attributes */
+ double_flag = GL_TRUE;
+ if (vis->depth > 8)
+ rgb_flag = GL_TRUE;
+ depth_size = default_depth_bits();
+ stencil_size = STENCIL_BITS;
+ /* XXX accum??? */
+ }
+ }
+ else if (level==0) {
+ /* normal color planes */
+ if (rgb_flag) {
+ /* Get an RGB visual */
+ int min_rgb = min_red + min_green + min_blue;
+ if (min_rgb>1 && min_rgb<8) {
+ /* a special case to be sure we can get a monochrome visual */
+ min_rgb = 1;
+ }
+ vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
+ }
+ else {
+ /* Get a color index visual */
+ vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
+ accumRedSize = accumGreenSize = accumBlueSize = accumAlphaSize = 0;
+ }
+ }
+ else {
+ /* over/underlay planes */
+ if (rgb_flag) {
+ /* rgba overlay */
+ int min_rgb = min_red + min_green + min_blue;
+ if (min_rgb>1 && min_rgb<8) {
+ /* a special case to be sure we can get a monochrome visual */
+ min_rgb = 1;
+ }
+ vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
+ trans_type, trans_value, min_rgb, visual_type );
+ }
+ else {
+ /* color index overlay */
+ vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
+ trans_type, trans_value, min_ci, visual_type );
+ }
+ }
+
+ if (vis) {
+ /* Note: we're not exactly obeying the glXChooseVisual rules here.
+ * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
+ * largest depth buffer size, which is 32bits/value. Instead, we
+ * return 16 to maintain performance with earlier versions of Mesa.
+ */
+ if (depth_size > 24)
+ depth_size = 31; /* 32 causes int overflow problems */
+ else if (depth_size > 16)
+ depth_size = 24;
+ else if (depth_size > 0) {
+ depth_size = default_depth_bits();
+ }
+
+ /* we only support one size of stencil and accum buffers. */
+ if (stencil_size > 0)
+ stencil_size = STENCIL_BITS;
+ if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 ||
+ accumAlphaSize > 0) {
+ accumRedSize = ACCUM_BITS;
+ accumGreenSize = ACCUM_BITS;
+ accumBlueSize = ACCUM_BITS;
+ accumAlphaSize = alpha_flag ? ACCUM_BITS : 0;
+ }
+
+ xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
+ stereo_flag, depth_size, stencil_size,
+ accumRedSize, accumGreenSize,
+ accumBlueSize, accumAlphaSize, level, numAux );
+ }
+
+ return xmvis;
+}
+
+
+static XVisualInfo *
+Fake_glXChooseVisual( Display *dpy, int screen, int *list )
+{
+ XMesaVisual xmvis = choose_visual(dpy, screen, list, GL_FALSE);
+ if (xmvis) {
+#if 0
+ return xmvis->vishandle;
+#else
+ /* create a new vishandle - the cached one may be stale */
+ xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+ if (xmvis->vishandle) {
+ _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+ }
+ return xmvis->vishandle;
+#endif
+ }
+ else
+ return NULL;
+}
+
+
+static GLXContext
+Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext share_list, Bool direct )
+{
+ XMesaVisual xmvis;
+ struct fake_glx_context *glxCtx;
+ struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
+
+ if (!dpy || !visinfo)
+ return 0;
+
+ glxCtx = CALLOC_STRUCT(fake_glx_context);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ xmvis = find_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* This visual wasn't found with glXChooseVisual() */
+ xmvis = create_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* unusable visual */
+ FREE(glxCtx);
+ return NULL;
+ }
+ }
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ FREE(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->xmesaContext->direct = GL_FALSE;
+ glxCtx->glxContext.isDirect = GL_FALSE;
+ glxCtx->glxContext.currentDpy = dpy;
+ glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
+
+ assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+ return (GLXContext) glxCtx;
+}
+
+
+/* XXX these may have to be removed due to thread-safety issues. */
+static GLXContext MakeCurrent_PrevContext = 0;
+static GLXDrawable MakeCurrent_PrevDrawable = 0;
+static GLXDrawable MakeCurrent_PrevReadable = 0;
+static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
+static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
+
+
+/* GLX 1.3 and later */
+static Bool
+Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
+ GLXDrawable read, GLXContext ctx )
+{
+ struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+
+ if (ctx && draw && read) {
+ XMesaBuffer drawBuffer, readBuffer;
+ XMesaContext xmctx = glxCtx->xmesaContext;
+
+ /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
+ if (ctx == MakeCurrent_PrevContext
+ && draw == MakeCurrent_PrevDrawable) {
+ drawBuffer = MakeCurrent_PrevDrawBuffer;
+ }
+ else {
+ drawBuffer = XMesaFindBuffer( dpy, draw );
+ }
+ if (!drawBuffer) {
+ /* drawable must be a new window! */
+ drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, xmctx);
+ if (!drawBuffer) {
+ /* Out of memory, or context/drawable depth mismatch */
+ return False;
+ }
+ }
+
+ /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
+ if (ctx == MakeCurrent_PrevContext
+ && read == MakeCurrent_PrevReadable) {
+ readBuffer = MakeCurrent_PrevReadBuffer;
+ }
+ else {
+ readBuffer = XMesaFindBuffer( dpy, read );
+ }
+ if (!readBuffer) {
+ /* drawable must be a new window! */
+ readBuffer = XMesaCreateWindowBuffer2(glxCtx->xmesaContext->xm_visual,
+ read, xmctx);
+ if (!readBuffer) {
+ /* Out of memory, or context/drawable depth mismatch */
+ return False;
+ }
+ }
+
+ MakeCurrent_PrevContext = ctx;
+ MakeCurrent_PrevDrawable = draw;
+ MakeCurrent_PrevReadable = read;
+ MakeCurrent_PrevDrawBuffer = drawBuffer;
+ MakeCurrent_PrevReadBuffer = readBuffer;
+
+ /* Now make current! */
+ if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
+ ((__GLXcontext *) ctx)->currentDpy = dpy;
+ ((__GLXcontext *) ctx)->currentDrawable = draw;
+#ifndef GLX_BUILT_IN_XMESA
+ ((__GLXcontext *) ctx)->currentReadable = read;
+#else
+ __glXSetCurrentContext(ctx);
+#endif
+ return True;
+ }
+ else {
+ return False;
+ }
+ }
+ else if (!ctx && !draw && !read) {
+ /* release current context w/out assigning new one. */
+ XMesaMakeCurrent( NULL, NULL );
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevReadable = 0;
+ MakeCurrent_PrevDrawBuffer = 0;
+ MakeCurrent_PrevReadBuffer = 0;
+#ifdef GLX_BUILT_IN_XMESA
+ /* XXX bind dummy context with __glXSetCurrentContext(ctx); */
+#endif
+ return True;
+ }
+ else {
+ /* The args must either all be non-zero or all zero.
+ * This is an error.
+ */
+ return False;
+ }
+}
+
+
+static Bool
+Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+ return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx );
+}
+
+
+static GLXPixmap
+Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+ if (!b) {
+ return 0;
+ }
+ return b->frontbuffer;
+}
+
+
+/*** GLX_MESA_pixmap_colormap ***/
+
+static GLXPixmap
+Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap, Colormap cmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
+ if (!b) {
+ return 0;
+ }
+ return b->frontbuffer;
+}
+
+
+static void
+Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
+ }
+}
+
+
+static void
+Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ unsigned long mask )
+{
+ struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src;
+ struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst;
+ XMesaContext xm_src = fakeSrc->xmesaContext;
+ XMesaContext xm_dst = fakeDst->xmesaContext;
+ (void) dpy;
+ _mesa_copy_context( &(xm_src->mesa), &(xm_dst->mesa), (GLuint) mask );
+}
+
+
+static Bool
+Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+ /* Mesa's GLX isn't really an X extension but we try to act like one. */
+ (void) dpy;
+ (void) errorb;
+ (void) event;
+ return True;
+}
+
+
+extern void _kw_ungrab_all( Display *dpy );
+void _kw_ungrab_all( Display *dpy )
+{
+ XUngrabPointer( dpy, CurrentTime );
+ XUngrabKeyboard( dpy, CurrentTime );
+}
+
+
+static void
+Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+ struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+ (void) dpy;
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevReadable = 0;
+ MakeCurrent_PrevDrawBuffer = 0;
+ MakeCurrent_PrevReadBuffer = 0;
+ XMesaDestroyContext( glxCtx->xmesaContext );
+ XMesaGarbageCollect();
+}
+
+
+static Bool
+Fake_glXIsDirect( Display *dpy, GLXContext ctx )
+{
+ struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+ (void) dpy;
+ return glxCtx->xmesaContext->direct;
+}
+
+
+
+static void
+Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+
+ if (buffer) {
+ XMesaSwapBuffers(buffer);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "Mesa: glXSwapBuffers: invalid drawable\n");
+ }
+}
+
+
+
+/*** GLX_MESA_copy_sub_buffer ***/
+
+static void
+Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+ int x, int y, int width, int height )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+ if (buffer) {
+ XMesaCopySubBuffer(buffer, x, y, width, height);
+ }
+ else if (_mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
+ }
+}
+
+
+static Bool
+Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+ (void) dpy;
+ /* Return GLX version, not Mesa version */
+ assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
+ *maj = CLIENT_MAJOR_VERSION;
+ *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
+ return True;
+}
+
+
+/*
+ * Query the GLX attributes of the given XVisualInfo.
+ */
+static int
+get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
+{
+ ASSERT(xmvis);
+ switch(attrib) {
+ case GLX_USE_GL:
+ if (fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = (int) True;
+ return 0;
+ case GLX_BUFFER_SIZE:
+ *value = xmvis->visinfo->depth;
+ return 0;
+ case GLX_LEVEL:
+ *value = xmvis->mesa_visual.level;
+ return 0;
+ case GLX_RGBA:
+ if (fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ if (xmvis->mesa_visual.rgbMode) {
+ *value = True;
+ }
+ else {
+ *value = False;
+ }
+ return 0;
+ case GLX_DOUBLEBUFFER:
+ *value = (int) xmvis->mesa_visual.doubleBufferMode;
+ return 0;
+ case GLX_STEREO:
+ *value = (int) xmvis->mesa_visual.stereoMode;
+ return 0;
+ case GLX_AUX_BUFFERS:
+ *value = xmvis->mesa_visual.numAuxBuffers;
+ return 0;
+ case GLX_RED_SIZE:
+ *value = xmvis->mesa_visual.redBits;
+ return 0;
+ case GLX_GREEN_SIZE:
+ *value = xmvis->mesa_visual.greenBits;
+ return 0;
+ case GLX_BLUE_SIZE:
+ *value = xmvis->mesa_visual.blueBits;
+ return 0;
+ case GLX_ALPHA_SIZE:
+ *value = xmvis->mesa_visual.alphaBits;
+ return 0;
+ case GLX_DEPTH_SIZE:
+ *value = xmvis->mesa_visual.depthBits;
+ return 0;
+ case GLX_STENCIL_SIZE:
+ *value = xmvis->mesa_visual.stencilBits;
+ return 0;
+ case GLX_ACCUM_RED_SIZE:
+ *value = xmvis->mesa_visual.accumRedBits;
+ return 0;
+ case GLX_ACCUM_GREEN_SIZE:
+ *value = xmvis->mesa_visual.accumGreenBits;
+ return 0;
+ case GLX_ACCUM_BLUE_SIZE:
+ *value = xmvis->mesa_visual.accumBlueBits;
+ return 0;
+ case GLX_ACCUM_ALPHA_SIZE:
+ *value = xmvis->mesa_visual.accumAlphaBits;
+ return 0;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ switch (xmvis->visinfo->CLASS) {
+ case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
+ case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
+ case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
+ case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
+ }
+ return 0;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ if (xmvis->mesa_visual.level==0) {
+ /* normal planes */
+ *value = GLX_NONE_EXT;
+ }
+ else if (xmvis->mesa_visual.level>0) {
+ /* overlay */
+ if (xmvis->mesa_visual.rgbMode) {
+ *value = GLX_TRANSPARENT_RGB_EXT;
+ }
+ else {
+ *value = GLX_TRANSPARENT_INDEX_EXT;
+ }
+ }
+ else if (xmvis->mesa_visual.level<0) {
+ /* underlay */
+ *value = GLX_NONE_EXT;
+ }
+ return 0;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ {
+ int pixel = transparent_pixel( xmvis );
+ if (pixel>=0) {
+ *value = pixel;
+ }
+ /* else undefined */
+ }
+ return 0;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* undefined */
+ return 0;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_VISUAL_CAVEAT_EXT:
+ /* test for zero, just in case */
+ if (xmvis->mesa_visual.visualRating > 0)
+ *value = xmvis->mesa_visual.visualRating;
+ else
+ *value = GLX_NONE_EXT;
+ return 0;
+
+ /*
+ * GLX_ARB_multisample
+ */
+ case GLX_SAMPLE_BUFFERS_ARB:
+ *value = 0;
+ return 0;
+ case GLX_SAMPLES_ARB:
+ *value = 0;
+ return 0;
+
+ /*
+ * For FBConfigs:
+ */
+ case GLX_SCREEN_EXT:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->screen;
+ break;
+ case GLX_DRAWABLE_TYPE: /*SGIX too */
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
+ break;
+ case GLX_RENDER_TYPE_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ if (xmvis->mesa_visual.rgbMode)
+ *value = GLX_RGBA_BIT;
+ else
+ *value = GLX_COLOR_INDEX_BIT;
+ break;
+ case GLX_X_RENDERABLE_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = True; /* XXX really? */
+ break;
+ case GLX_FBCONFIG_ID_SGIX:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->visualid;
+ break;
+ case GLX_MAX_PBUFFER_WIDTH:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ /* XXX or MAX_WIDTH? */
+ *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_MAX_PBUFFER_PIXELS:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
+ DisplayHeight(xmvis->display, xmvis->visinfo->screen);
+ break;
+ case GLX_VISUAL_ID:
+ if (!fbconfig)
+ return GLX_BAD_ATTRIBUTE;
+ *value = xmvis->visinfo->visualid;
+ break;
+
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+ return Success;
+}
+
+
+static int
+Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value )
+{
+ XMesaVisual xmvis;
+
+ if (!dpy || !visinfo)
+ return GLX_BAD_ATTRIBUTE;
+
+ xmvis = find_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* this visual wasn't obtained with glXChooseVisual */
+ xmvis = create_glx_visual( dpy, visinfo );
+ if (!xmvis) {
+ /* this visual can't be used for GL rendering */
+ if (attrib==GLX_USE_GL) {
+ *value = (int) False;
+ return 0;
+ }
+ else {
+ return GLX_BAD_VISUAL;
+ }
+ }
+ }
+
+ return get_config(xmvis, attrib, value, GL_FALSE);
+}
+
+
+static void
+Fake_glXWaitGL( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+
+static void
+Fake_glXWaitX( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+static const char *
+get_extensions( void )
+{
+#ifdef FX
+ const char *fx = _mesa_getenv("MESA_GLX_FX");
+ if (fx && fx[0] != 'd') {
+ return EXTENSIONS;
+ }
+#endif
+ return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXQueryExtensionsString( Display *dpy, int screen )
+{
+ (void) dpy;
+ (void) screen;
+ return get_extensions();
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXQueryServerString( Display *dpy, int screen, int name )
+{
+ static char version[1000];
+ _mesa_sprintf(version, "%d.%d %s",
+ SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION);
+
+ (void) dpy;
+ (void) screen;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return get_extensions();
+ case GLX_VENDOR:
+ return VENDOR;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/* GLX 1.1 and later */
+static const char *
+Fake_glXGetClientString( Display *dpy, int name )
+{
+ static char version[1000];
+ _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
+ CLIENT_MINOR_VERSION, MESA_GLX_VERSION);
+
+ (void) dpy;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return get_extensions();
+ case GLX_VENDOR:
+ return VENDOR;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/*
+ * GLX 1.3 and later
+ */
+
+
+static int
+Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
+ int attribute, int *value )
+{
+ XMesaVisual v = (XMesaVisual) config;
+ (void) dpy;
+ (void) config;
+
+ if (!dpy || !config || !value)
+ return -1;
+
+ return get_config(v, attribute, value, GL_TRUE);
+}
+
+
+static GLXFBConfig *
+Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
+{
+ XVisualInfo *visuals, visTemplate;
+ const long visMask = VisualScreenMask;
+ int i;
+
+ /* Get list of all X visuals */
+ visTemplate.screen = screen;
+ visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
+ if (*nelements > 0) {
+ XMesaVisual *results;
+ results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual));
+ if (!results) {
+ *nelements = 0;
+ return NULL;
+ }
+ for (i = 0; i < *nelements; i++) {
+ results[i] = create_glx_visual(dpy, visuals + i);
+ }
+ return (GLXFBConfig *) results;
+ }
+ return NULL;
+}
+
+
+static GLXFBConfig *
+Fake_glXChooseFBConfig( Display *dpy, int screen,
+ const int *attribList, int *nitems )
+{
+ XMesaVisual xmvis;
+
+ if (!attribList || !attribList[0]) {
+ /* return list of all configs (per GLX_SGIX_fbconfig spec) */
+ return Fake_glXGetFBConfigs(dpy, screen, nitems);
+ }
+
+ xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
+ if (xmvis) {
+ GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual));
+ if (!config) {
+ *nitems = 0;
+ return NULL;
+ }
+ *nitems = 1;
+ config[0] = (GLXFBConfig) xmvis;
+ return (GLXFBConfig *) config;
+ }
+ else {
+ *nitems = 0;
+ return NULL;
+ }
+}
+
+
+static XVisualInfo *
+Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
+{
+ if (dpy && config) {
+ XMesaVisual xmvis = (XMesaVisual) config;
+#if 0
+ return xmvis->vishandle;
+#else
+ /* create a new vishandle - the cached one may be stale */
+ xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
+ if (xmvis->vishandle) {
+ _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
+ }
+ return xmvis->vishandle;
+#endif
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+static GLXWindow
+Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
+ const int *attribList )
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ if (!xmvis)
+ return 0;
+
+ xmbuf = XMesaCreateWindowBuffer2(xmvis, win, NULL);
+ if (!xmbuf)
+ return 0;
+
+ (void) dpy;
+ (void) attribList; /* Ignored in GLX 1.3 */
+
+ return win; /* A hack for now */
+}
+
+
+static void
+Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window);
+ if (b)
+ XMesaDestroyBuffer(b);
+ /* don't destroy X window */
+}
+
+
+/* XXX untested */
+static GLXPixmap
+Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
+ const int *attribList )
+{
+ XMesaVisual v = (XMesaVisual) config;
+ XMesaBuffer b;
+
+ (void) dpy;
+ (void) config;
+ (void) pixmap;
+ (void) attribList; /* Ignored in GLX 1.3 */
+
+ if (!dpy || !config || !pixmap)
+ return 0;
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+ if (!b) {
+ return 0;
+ }
+
+ return pixmap;
+}
+
+
+static void
+Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap);
+ if (b)
+ XMesaDestroyBuffer(b);
+ /* don't destroy X pixmap */
+}
+
+
+static GLXPbuffer
+Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+ const int *attribList )
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ const int *attrib;
+ int width = 0, height = 0;
+ GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+ (void) dpy;
+
+ for (attrib = attribList; *attrib; attrib++) {
+ switch (*attrib) {
+ case GLX_PBUFFER_WIDTH:
+ attrib++;
+ width = *attrib;
+ break;
+ case GLX_PBUFFER_HEIGHT:
+ attrib++;
+ height = *attrib;
+ break;
+ case GLX_PRESERVED_CONTENTS:
+ attrib++;
+ preserveContents = *attrib; /* ignored */
+ break;
+ case GLX_LARGEST_PBUFFER:
+ attrib++;
+ useLargest = *attrib; /* ignored */
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* not used at this time */
+ (void) useLargest;
+ (void) preserveContents;
+
+ if (width == 0 || height == 0)
+ return 0;
+
+ xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+ /* A GLXPbuffer handle must be an X Drawable because that's what
+ * glXMakeCurrent takes.
+ */
+ return (GLXPbuffer) xmbuf->frontbuffer;
+}
+
+
+static void
+Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ }
+}
+
+
+static void
+Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
+ unsigned int *value )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
+ if (!xmbuf)
+ return;
+
+ switch (attribute) {
+ case GLX_WIDTH:
+ *value = xmbuf->width;
+ break;
+ case GLX_HEIGHT:
+ *value = xmbuf->height;
+ break;
+ case GLX_PRESERVED_CONTENTS:
+ *value = True;
+ break;
+ case GLX_LARGEST_PBUFFER:
+ *value = xmbuf->width * xmbuf->height;
+ break;
+ case GLX_FBCONFIG_ID:
+ *value = xmbuf->xm_visual->visinfo->visualid;
+ return;
+ default:
+ return; /* GLX_BAD_ATTRIBUTE? */
+ }
+}
+
+
+static GLXContext
+Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
+ int renderType, GLXContext shareList, Bool direct )
+{
+ struct fake_glx_context *glxCtx;
+ struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList;
+ XMesaVisual xmvis = (XMesaVisual) config;
+
+ if (!dpy || !config ||
+ (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
+ return 0;
+
+ glxCtx = CALLOC_STRUCT(fake_glx_context);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ FREE(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->xmesaContext->direct = GL_FALSE;
+ glxCtx->glxContext.isDirect = GL_FALSE;
+ glxCtx->glxContext.currentDpy = dpy;
+ glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
+
+ assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+ return (GLXContext) glxCtx;
+}
+
+
+static int
+Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
+{
+ struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
+ XMesaContext xmctx = glxCtx->xmesaContext;
+
+ (void) dpy;
+ (void) ctx;
+
+ switch (attribute) {
+ case GLX_FBCONFIG_ID:
+ *value = xmctx->xm_visual->visinfo->visualid;
+ break;
+ case GLX_RENDER_TYPE:
+ if (xmctx->xm_visual->mesa_visual.rgbMode)
+ *value = GLX_RGBA_BIT;
+ else
+ *value = GLX_COLOR_INDEX_BIT;
+ break;
+ case GLX_SCREEN:
+ *value = 0;
+ return Success;
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+ return 0;
+}
+
+
+static void
+Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf)
+ xmbuf->selectedEvents = mask;
+}
+
+
+static void
+Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
+ unsigned long *mask )
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf)
+ *mask = xmbuf->selectedEvents;
+ else
+ *mask = 0;
+}
+
+
+
+/*** GLX_SGI_swap_control ***/
+
+static int
+Fake_glXSwapIntervalSGI(int interval)
+{
+ (void) interval;
+ return 0;
+}
+
+
+
+/*** GLX_SGI_video_sync ***/
+
+static int
+Fake_glXGetVideoSyncSGI(unsigned int *count)
+{
+ (void) count;
+ return 0;
+}
+
+static int
+Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+ (void) divisor;
+ (void) remainder;
+ (void) count;
+ return 0;
+}
+
+
+
+/*** GLX_SGI_make_current_read ***/
+
+static Bool
+Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+ return Fake_glXMakeContextCurrent( dpy, draw, read, ctx );
+}
+
+/* not used
+static GLXDrawable
+Fake_glXGetCurrentReadDrawableSGI(void)
+{
+ return 0;
+}
+*/
+
+
+/*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+
+static GLXVideoSourceSGIX
+Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
+{
+ (void) dpy;
+ (void) screen;
+ (void) server;
+ (void) path;
+ (void) nodeClass;
+ (void) drainNode;
+ return 0;
+}
+
+static void
+Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
+{
+ (void) dpy;
+ (void) src;
+}
+
+#endif
+
+
+/*** GLX_EXT_import_context ***/
+
+static void
+Fake_glXFreeContextEXT(Display *dpy, GLXContext context)
+{
+ (void) dpy;
+ (void) context;
+}
+
+static GLXContextID
+Fake_glXGetContextIDEXT(const GLXContext context)
+{
+ (void) context;
+ return 0;
+}
+
+static GLXContext
+Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID)
+{
+ (void) dpy;
+ (void) contextID;
+ return 0;
+}
+
+static int
+Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value)
+{
+ (void) dpy;
+ (void) context;
+ (void) attribute;
+ (void) value;
+ return 0;
+}
+
+
+
+/*** GLX_SGIX_fbconfig ***/
+
+static int
+Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
+{
+ return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value);
+}
+
+static GLXFBConfigSGIX *
+Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
+{
+ return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements);
+}
+
+
+static GLXPixmap
+Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
+ return xmbuf->frontbuffer; /* need to return an X ID */
+}
+
+
+static GLXContext
+Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ struct fake_glx_context *glxCtx;
+ struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
+
+ glxCtx = CALLOC_STRUCT(fake_glx_context);
+ if (!glxCtx)
+ return 0;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ glxCtx->xmesaContext = XMesaCreateContext(xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL);
+ if (!glxCtx->xmesaContext) {
+ FREE(glxCtx);
+ return NULL;
+ }
+
+ glxCtx->xmesaContext->direct = GL_FALSE;
+ glxCtx->glxContext.isDirect = GL_FALSE;
+ glxCtx->glxContext.currentDpy = dpy;
+ glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */
+
+ assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+
+ return (GLXContext) glxCtx;
+}
+
+
+static XVisualInfo *
+Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
+{
+ return Fake_glXGetVisualFromFBConfig(dpy, config);
+}
+
+
+static GLXFBConfigSGIX
+Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
+{
+ XMesaVisual xmvis = find_glx_visual(dpy, vis);
+ if (!xmvis) {
+ /* This visual wasn't found with glXChooseVisual() */
+ xmvis = create_glx_visual(dpy, vis);
+ }
+
+ return (GLXFBConfigSGIX) xmvis;
+}
+
+
+
+/*** GLX_SGIX_pbuffer ***/
+
+static GLXPbufferSGIX
+Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
+ unsigned int width, unsigned int height,
+ int *attribList)
+{
+ XMesaVisual xmvis = (XMesaVisual) config;
+ XMesaBuffer xmbuf;
+ const int *attrib;
+ GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
+ (void) dpy;
+
+ for (attrib = attribList; attrib && *attrib; attrib++) {
+ switch (*attrib) {
+ case GLX_PRESERVED_CONTENTS_SGIX:
+ attrib++;
+ preserveContents = *attrib; /* ignored */
+ break;
+ case GLX_LARGEST_PBUFFER_SGIX:
+ attrib++;
+ useLargest = *attrib; /* ignored */
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ /* not used at this time */
+ (void) useLargest;
+ (void) preserveContents;
+
+ xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
+ /* A GLXPbuffer handle must be an X Drawable because that's what
+ * glXMakeCurrent takes.
+ */
+ return (GLXPbuffer) xmbuf->frontbuffer;
+}
+
+
+static void
+Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+ if (xmbuf) {
+ XMesaDestroyBuffer(xmbuf);
+ }
+}
+
+
+static int
+Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
+{
+ const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
+
+ if (!xmbuf) {
+ /* Generate GLXBadPbufferSGIX for bad pbuffer */
+ return 0;
+ }
+
+ switch (attribute) {
+ case GLX_PRESERVED_CONTENTS_SGIX:
+ *value = True;
+ break;
+ case GLX_LARGEST_PBUFFER_SGIX:
+ *value = xmbuf->width * xmbuf->height;
+ break;
+ case GLX_WIDTH_SGIX:
+ *value = xmbuf->width;
+ break;
+ case GLX_HEIGHT_SGIX:
+ *value = xmbuf->height;
+ break;
+ case GLX_EVENT_MASK_SGIX:
+ *value = 0; /* XXX might be wrong */
+ break;
+ default:
+ *value = 0;
+ }
+ return 0;
+}
+
+
+static void
+Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf) {
+ /* Note: we'll never generate clobber events */
+ xmbuf->selectedEvents = mask;
+ }
+}
+
+
+static void
+Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+ XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
+ if (xmbuf) {
+ *mask = xmbuf->selectedEvents;
+ }
+ else {
+ *mask = 0;
+ }
+}
+
+
+
+/*** GLX_SGI_cushion ***/
+
+static void
+Fake_glXCushionSGI(Display *dpy, Window win, float cushion)
+{
+ (void) dpy;
+ (void) win;
+ (void) cushion;
+}
+
+
+
+/*** GLX_SGIX_video_resize ***/
+
+static int
+Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) window;
+ return 0;
+}
+
+static int
+Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
+ return 0;
+}
+
+static int
+Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
+ return 0;
+}
+
+static int
+Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) dx;
+ (void) dy;
+ (void) dw;
+ (void) dh;
+ return 0;
+}
+
+static int
+Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
+{
+ (void) dpy;
+ (void) screen;
+ (void) channel;
+ (void) synctype;
+ return 0;
+}
+
+
+
+/*** GLX_SGIX_dmbuffer **/
+
+#if defined(_DM_BUFFER_H_)
+static Bool
+Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
+{
+ (void) dpy;
+ (void) pbuffer;
+ (void) params;
+ (void) dmbuffer;
+ return False;
+}
+#endif
+
+
+/*** GLX_SGIX_swap_group ***/
+
+static void
+Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
+{
+ (void) dpy;
+ (void) drawable;
+ (void) member;
+}
+
+
+
+/*** GLX_SGIX_swap_barrier ***/
+
+static void
+Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
+{
+ (void) dpy;
+ (void) drawable;
+ (void) barrier;
+}
+
+static Bool
+Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+{
+ (void) dpy;
+ (void) screen;
+ (void) max;
+ return False;
+}
+
+
+
+/*** GLX_SUN_get_transparent_index ***/
+
+static Status
+Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
+{
+ (void) dpy;
+ (void) overlay;
+ (void) underlay;
+ (void) pTransparent;
+ return 0;
+}
+
+
+
+/*** GLX_MESA_release_buffers ***/
+
+/*
+ * Release the depth, stencil, accum buffers attached to a GLXDrawable
+ * (a window or pixmap) prior to destroying the GLXDrawable.
+ */
+static Bool
+Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, d);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ return True;
+ }
+ return False;
+}
+
+
+
+/*** GLX_MESA_set_3dfx_mode ***/
+
+static Bool
+Fake_glXSet3DfxModeMESA( int mode )
+{
+ return XMesaSetFXmode( mode );
+}
+
+
+
+/*** GLX_NV_vertex_array range ***/
+static void *
+Fake_glXAllocateMemoryNV( GLsizei size,
+ GLfloat readFrequency,
+ GLfloat writeFrequency,
+ GLfloat priority )
+{
+ (void) size;
+ (void) readFrequency;
+ (void) writeFrequency;
+ (void) priority;
+ return NULL;
+}
+
+
+static void
+Fake_glXFreeMemoryNV( GLvoid *pointer )
+{
+ (void) pointer;
+}
+
+
+/*** GLX_MESA_agp_offset ***/
+
+static GLuint
+Fake_glXGetAGPOffsetMESA( const GLvoid *pointer )
+{
+ (void) pointer;
+ return ~0;
+}
+
+
+/*** GLX_ARB_render_texture ***/
+
+static Bool
+Fake_glXBindTexImageARB( Display *dpy, GLXPbuffer pbuffer, int buffer )
+{
+ return False;
+}
+
+
+static Bool
+Fake_glXReleaseTexImageARB(Display *dpy, GLXPbuffer pbuffer, int buffer )
+{
+ return False;
+}
+
+
+static Bool
+Fake_glXDrawableAttribARB( Display *dpy, GLXDrawable draw, const int *attribList )
+{
+ return False;
+}
+
+
+/* silence warning */
+extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
+
+
+/**
+ * Create a new GLX API dispatch table with its function pointers
+ * initialized to point to Mesa's "fake" GLX API functions.
+ * Note: there's a similar function (_real_GetGLXDispatchTable) that
+ * returns a new dispatch table with all pointers initalized to point
+ * to "real" GLX functions (which understand GLX wire protocol, etc).
+ */
+struct _glxapi_table *
+_mesa_GetGLXDispatchTable(void)
+{
+ static struct _glxapi_table glx;
+
+ /* be sure our dispatch table size <= libGL's table */
+ {
+ GLuint size = sizeof(struct _glxapi_table) / sizeof(void *);
+ (void) size;
+ assert(_glxapi_get_dispatch_table_size() >= size);
+ }
+
+ /* initialize the whole table to no-ops */
+ _glxapi_set_no_op_table(&glx);
+
+ /* now initialize the table with the functions I implement */
+ glx.ChooseVisual = Fake_glXChooseVisual;
+ glx.CopyContext = Fake_glXCopyContext;
+ glx.CreateContext = Fake_glXCreateContext;
+ glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap;
+ glx.DestroyContext = Fake_glXDestroyContext;
+ glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap;
+ glx.GetConfig = Fake_glXGetConfig;
+ /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
+ /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
+ glx.IsDirect = Fake_glXIsDirect;
+ glx.MakeCurrent = Fake_glXMakeCurrent;
+ glx.QueryExtension = Fake_glXQueryExtension;
+ glx.QueryVersion = Fake_glXQueryVersion;
+ glx.SwapBuffers = Fake_glXSwapBuffers;
+ glx.UseXFont = Fake_glXUseXFont;
+ glx.WaitGL = Fake_glXWaitGL;
+ glx.WaitX = Fake_glXWaitX;
+
+ /*** GLX_VERSION_1_1 ***/
+ glx.GetClientString = Fake_glXGetClientString;
+ glx.QueryExtensionsString = Fake_glXQueryExtensionsString;
+ glx.QueryServerString = Fake_glXQueryServerString;
+
+ /*** GLX_VERSION_1_2 ***/
+ /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
+
+ /*** GLX_VERSION_1_3 ***/
+ glx.ChooseFBConfig = Fake_glXChooseFBConfig;
+ glx.CreateNewContext = Fake_glXCreateNewContext;
+ glx.CreatePbuffer = Fake_glXCreatePbuffer;
+ glx.CreatePixmap = Fake_glXCreatePixmap;
+ glx.CreateWindow = Fake_glXCreateWindow;
+ glx.DestroyPbuffer = Fake_glXDestroyPbuffer;
+ glx.DestroyPixmap = Fake_glXDestroyPixmap;
+ glx.DestroyWindow = Fake_glXDestroyWindow;
+ /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
+ glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib;
+ glx.GetFBConfigs = Fake_glXGetFBConfigs;
+ glx.GetSelectedEvent = Fake_glXGetSelectedEvent;
+ glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig;
+ glx.MakeContextCurrent = Fake_glXMakeContextCurrent;
+ glx.QueryContext = Fake_glXQueryContext;
+ glx.QueryDrawable = Fake_glXQueryDrawable;
+ glx.SelectEvent = Fake_glXSelectEvent;
+
+ /*** GLX_SGI_swap_control ***/
+ glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI;
+
+ /*** GLX_SGI_video_sync ***/
+ glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI;
+ glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI;
+
+ /*** GLX_SGI_make_current_read ***/
+ glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI;
+ /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/
+
+/*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+ glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX;
+ glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX;
+#endif
+
+ /*** GLX_EXT_import_context ***/
+ glx.FreeContextEXT = Fake_glXFreeContextEXT;
+ glx.GetContextIDEXT = Fake_glXGetContextIDEXT;
+ /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/
+ glx.ImportContextEXT = Fake_glXImportContextEXT;
+ glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT;
+
+ /*** GLX_SGIX_fbconfig ***/
+ glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX;
+ glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX;
+ glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX;
+ glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX;
+ glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX;
+ glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX;
+
+ /*** GLX_SGIX_pbuffer ***/
+ glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX;
+ glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX;
+ glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX;
+ glx.SelectEventSGIX = Fake_glXSelectEventSGIX;
+ glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX;
+
+ /*** GLX_SGI_cushion ***/
+ glx.CushionSGI = Fake_glXCushionSGI;
+
+ /*** GLX_SGIX_video_resize ***/
+ glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX;
+ glx.ChannelRectSGIX = Fake_glXChannelRectSGIX;
+ glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX;
+ glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX;
+ glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX;
+
+ /*** GLX_SGIX_dmbuffer **/
+#if defined(_DM_BUFFER_H_)
+ glx.AssociateDMPbufferSGIX = NULL;
+#endif
+
+ /*** GLX_SGIX_swap_group ***/
+ glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX;
+
+ /*** GLX_SGIX_swap_barrier ***/
+ glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX;
+ glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX;
+
+ /*** GLX_SUN_get_transparent_index ***/
+ glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN;
+
+ /*** GLX_MESA_copy_sub_buffer ***/
+ glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA;
+
+ /*** GLX_MESA_release_buffers ***/
+ glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA;
+
+ /*** GLX_MESA_pixmap_colormap ***/
+ glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA;
+
+ /*** GLX_MESA_set_3dfx_mode ***/
+ glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA;
+
+ /*** GLX_NV_vertex_array_range ***/
+ glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV;
+ glx.FreeMemoryNV = Fake_glXFreeMemoryNV;
+
+ /*** GLX_MESA_agp_offset ***/
+ glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA;
+
+ /*** GLX_ARB_render_texture ***/
+ glx.BindTexImageARB = Fake_glXBindTexImageARB;
+ glx.ReleaseTexImageARB = Fake_glXReleaseTexImageARB;
+ glx.DrawableAttribARB = Fake_glXDrawableAttribARB;
+
+ return &glx;
+}
diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c
new file mode 100644
index 0000000..99fc4e2
--- /dev/null
+++ b/src/mesa/drivers/x11/glxapi.c
@@ -0,0 +1,1343 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2.1
+ *
+ * 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.
+ */
+
+
+/*
+ * This is the GLX API dispatcher. Calls to the glX* functions are
+ * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions.
+ * See the glxapi.h file for more details.
+ */
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "glapi.h"
+#include "glxapi.h"
+
+
+extern struct _glxapi_table *_real_GetGLXDispatchTable(void);
+extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
+
+
+struct display_dispatch {
+ Display *Dpy;
+ struct _glxapi_table *Table;
+ struct display_dispatch *Next;
+};
+
+static struct display_dispatch *DispatchList = NULL;
+
+
+/* Display -> Dispatch caching */
+static Display *prevDisplay = NULL;
+static struct _glxapi_table *prevTable = NULL;
+
+
+static struct _glxapi_table *
+get_dispatch(Display *dpy)
+{
+ if (!dpy)
+ return NULL;
+
+ /* search list of display/dispatch pairs for this display */
+ {
+ const struct display_dispatch *d = DispatchList;
+ while (d) {
+ if (d->Dpy == dpy) {
+ prevDisplay = dpy;
+ prevTable = d->Table;
+ return d->Table; /* done! */
+ }
+ d = d->Next;
+ }
+ }
+
+ /* A new display, determine if we should use real GLX
+ * or Mesa's pseudo-GLX.
+ */
+ {
+ struct _glxapi_table *t = NULL;
+
+#ifdef GLX_BUILT_IN_XMESA
+ if (!getenv("LIBGL_FORCE_XMESA")) {
+ int ignore;
+ if (XQueryExtension( dpy, "GLX", &ignore, &ignore, &ignore )) {
+ /* the X server has the GLX extension */
+ t = _real_GetGLXDispatchTable();
+ }
+ }
+#endif
+
+ if (!t) {
+ /* Fallback to Mesa with Xlib driver */
+#ifdef GLX_BUILT_IN_XMESA
+ if (getenv("LIBGL_DEBUG")) {
+ fprintf(stderr,
+ "libGL: server %s lacks the GLX extension.",
+ dpy->display_name);
+ fprintf(stderr, " Using Mesa Xlib renderer.\n");
+ }
+#endif
+ t = _mesa_GetGLXDispatchTable();
+ assert(t); /* this has to work */
+ }
+
+ if (t) {
+ struct display_dispatch *d;
+ d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch));
+ if (d) {
+ d->Dpy = dpy;
+ d->Table = t;
+ /* insert at head of list */
+ d->Next = DispatchList;
+ DispatchList = d;
+ /* update cache */
+ prevDisplay = dpy;
+ prevTable = t;
+ return t;
+ }
+ }
+ }
+
+ /* If we get here that means we can't use real GLX on this display
+ * and the Mesa pseudo-GLX software renderer wasn't compiled in.
+ * Or, we ran out of memory!
+ */
+ return NULL;
+}
+
+
+#define GET_DISPATCH(DPY, TABLE) \
+ if (DPY == prevDisplay) { \
+ TABLE = prevTable; \
+ } \
+ else if (!DPY) { \
+ TABLE = NULL; \
+ } \
+ else { \
+ TABLE = get_dispatch(DPY); \
+ }
+
+
+
+
+/* Set by glXMakeCurrent() and glXMakeContextCurrent() only */
+#ifndef GLX_BUILT_IN_XMESA
+static GLXContext CurrentContext = 0;
+#define __glXGetCurrentContext() CurrentContext;
+#endif
+
+
+/*
+ * GLX API entrypoints
+ */
+
+/*** GLX_VERSION_1_0 ***/
+
+XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *list)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->ChooseVisual)(dpy, screen, list);
+}
+
+
+void glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->CopyContext)(dpy, src, dst, mask);
+}
+
+
+GLXContext glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateContext)(dpy, visinfo, shareList, direct);
+}
+
+
+GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateGLXPixmap)(dpy, visinfo, pixmap);
+}
+
+
+void glXDestroyContext(Display *dpy, GLXContext ctx)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyContext)(dpy, ctx);
+}
+
+
+void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyGLXPixmap)(dpy, pixmap);
+}
+
+
+int glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return GLX_NO_EXTENSION;
+ return (t->GetConfig)(dpy, visinfo, attrib, value);
+}
+
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use real libGL's glXGetCurrentContext() function */
+#else
+/* stand-alone Mesa */
+GLXContext glXGetCurrentContext(void)
+{
+ return CurrentContext;
+}
+#endif
+
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use real libGL's glXGetCurrentContext() function */
+#else
+/* stand-alone Mesa */
+GLXDrawable glXGetCurrentDrawable(void)
+{
+ __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+ return gc ? gc->currentDrawable : 0;
+}
+#endif
+
+
+Bool glXIsDirect(Display *dpy, GLXContext ctx)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->IsDirect)(dpy, ctx);
+}
+
+
+Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{
+ Bool b;
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t) {
+ return False;
+ }
+ b = (*t->MakeCurrent)(dpy, drawable, ctx);
+#ifndef GLX_BUILT_IN_XMESA
+ if (b) {
+ CurrentContext = ctx;
+ }
+#endif
+ return b;
+}
+
+
+Bool glXQueryExtension(Display *dpy, int *errorb, int *event)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->QueryExtension)(dpy, errorb, event);
+}
+
+
+Bool glXQueryVersion(Display *dpy, int *maj, int *min)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->QueryVersion)(dpy, maj, min);
+}
+
+
+void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->SwapBuffers)(dpy, drawable);
+}
+
+
+void glXUseXFont(Font font, int first, int count, int listBase)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->UseXFont)(font, first, count, listBase);
+}
+
+
+void glXWaitGL(void)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->WaitGL)();
+}
+
+
+void glXWaitX(void)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->WaitX)();
+}
+
+
+
+/*** GLX_VERSION_1_1 ***/
+
+const char *glXGetClientString(Display *dpy, int name)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->GetClientString)(dpy, name);
+}
+
+
+const char *glXQueryExtensionsString(Display *dpy, int screen)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->QueryExtensionsString)(dpy, screen);
+}
+
+
+const char *glXQueryServerString(Display *dpy, int screen, int name)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->QueryServerString)(dpy, screen, name);
+}
+
+
+/*** GLX_VERSION_1_2 ***/
+
+#if !defined(GLX_BUILT_IN_XMESA)
+Display *glXGetCurrentDisplay(void)
+{
+ /* Same code as in libGL's glxext.c */
+ __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+ if (NULL == gc) return NULL;
+ return gc->currentDpy;
+}
+#endif
+
+
+
+/*** GLX_VERSION_1_3 ***/
+
+GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->ChooseFBConfig)(dpy, screen, attribList, nitems);
+}
+
+
+GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateNewContext)(dpy, config, renderType, shareList, direct);
+}
+
+
+GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreatePbuffer)(dpy, config, attribList);
+}
+
+
+GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreatePixmap)(dpy, config, pixmap, attribList);
+}
+
+
+GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateWindow)(dpy, config, win, attribList);
+}
+
+
+void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyPbuffer)(dpy, pbuf);
+}
+
+
+void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyPixmap)(dpy, pixmap);
+}
+
+
+void glXDestroyWindow(Display *dpy, GLXWindow window)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyWindow)(dpy, window);
+}
+
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use the glXGetCurrentReadDrawable() function from libGL */
+#else
+GLXDrawable glXGetCurrentReadDrawable(void)
+{
+ __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext();
+ return gc ? gc->currentReadable : 0;
+}
+#endif
+
+
+int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return GLX_NO_EXTENSION;
+ return (t->GetFBConfigAttrib)(dpy, config, attribute, value);
+}
+
+
+GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->GetFBConfigs)(dpy, screen, nelements);
+}
+
+void glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->GetSelectedEvent)(dpy, drawable, mask);
+}
+
+
+XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->GetVisualFromFBConfig)(dpy, config);
+}
+
+
+Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+ Bool b;
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ b = (t->MakeContextCurrent)(dpy, draw, read, ctx);
+#ifndef GLX_BUILT_IN_XMESA
+ if (b) {
+ CurrentContext = ctx;
+ }
+#endif
+ return b;
+}
+
+
+int glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ assert(t);
+ if (!t)
+ return 0; /* XXX correct? */
+ return (t->QueryContext)(dpy, ctx, attribute, value);
+}
+
+
+void glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->QueryDrawable)(dpy, draw, attribute, value);
+}
+
+
+void glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->SelectEvent)(dpy, drawable, mask);
+}
+
+
+
+/*** GLX_SGI_swap_control ***/
+
+int glXSwapIntervalSGI(int interval)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->SwapIntervalSGI)(interval);
+}
+
+
+
+/*** GLX_SGI_video_sync ***/
+
+int glXGetVideoSyncSGI(unsigned int *count)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->GetVideoSyncSGI)(count);
+}
+
+int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->WaitVideoSyncSGI)(divisor, remainder, count);
+}
+
+
+
+/*** GLX_SGI_make_current_read ***/
+
+Bool glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx);
+}
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use glXGetCurrentReadDrawableSGI() from libGL */
+#else
+/* stand-alone Mesa */
+GLXDrawable glXGetCurrentReadDrawableSGI(void)
+{
+ return glXGetCurrentReadDrawable();
+}
+#endif
+
+
+#if defined(_VL_H)
+
+GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode);
+}
+
+void glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->DestroyGLXVideoSourceSGIX)(dpy, src);
+}
+
+#endif
+
+
+/*** GLX_EXT_import_context ***/
+
+void glXFreeContextEXT(Display *dpy, GLXContext context)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->FreeContextEXT)(dpy, context);
+}
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use real libGL's glXGetContextIDEXT() function */
+#else
+/* stand-alone Mesa */
+GLXContextID glXGetContextIDEXT(const GLXContext context)
+{
+ return ((__GLXcontext *) context)->xid;
+}
+#endif
+
+#ifdef GLX_BUILT_IN_XMESA
+/* Use real libGL's glXGetCurrentDisplayEXT() function */
+#else
+/* stand-alone Mesa */
+Display *glXGetCurrentDisplayEXT(void)
+{
+ return glXGetCurrentDisplay();
+}
+#endif
+
+GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->ImportContextEXT)(dpy, contextID);
+}
+
+int glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0; /* XXX ok? */
+ return (t->QueryContextInfoEXT)(dpy, context, attribute, value);
+}
+
+
+
+/*** GLX_SGIX_fbconfig ***/
+
+int glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value);
+}
+
+GLXFBConfigSGIX *glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements);
+}
+
+GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap);
+}
+
+GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct);
+}
+
+XVisualInfo * glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->GetVisualFromFBConfigSGIX)(dpy, config);
+}
+
+GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->GetFBConfigFromVisualSGIX)(dpy, vis);
+}
+
+
+
+/*** GLX_SGIX_pbuffer ***/
+
+GLXPbufferSGIX glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list);
+}
+
+void glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->DestroyGLXPbufferSGIX)(dpy, pbuf);
+}
+
+int glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value);
+}
+
+void glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->SelectEventSGIX)(dpy, drawable, mask);
+}
+
+void glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->GetSelectedEventSGIX)(dpy, drawable, mask);
+}
+
+
+
+/*** GLX_SGI_cushion ***/
+
+void glXCushionSGI(Display *dpy, Window win, float cushion)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->CushionSGI)(dpy, win, cushion);
+}
+
+
+
+/*** GLX_SGIX_video_resize ***/
+
+int glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window);
+}
+
+int glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
+}
+
+int glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h);
+}
+
+int glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh);
+}
+
+int glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype);
+}
+
+
+
+#if defined(_DM_BUFFER_H_)
+
+Bool glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer);
+}
+
+#endif
+
+
+/*** GLX_SGIX_swap_group ***/
+
+void glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (*t->JoinSwapGroupSGIX)(dpy, drawable, member);
+}
+
+
+/*** GLX_SGIX_swap_barrier ***/
+
+void glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier);
+}
+
+Bool glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max);
+}
+
+
+
+/*** GLX_SUN_get_transparent_index ***/
+
+Status glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent);
+}
+
+
+
+/*** GLX_MESA_copy_sub_buffer ***/
+
+void glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height);
+}
+
+
+
+/*** GLX_MESA_release_buffers ***/
+
+Bool glXReleaseBuffersMESA(Display *dpy, Window w)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->ReleaseBuffersMESA)(dpy, w);
+}
+
+
+
+/*** GLX_MESA_pixmap_colormap ***/
+
+GLXPixmap glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap)
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return 0;
+ return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap);
+}
+
+
+
+/*** GLX_MESA_set_3dfx_mode ***/
+
+Bool glXSet3DfxModeMESA(int mode)
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->Set3DfxModeMESA)(mode);
+}
+
+
+
+/*** GLX_NV_vertex_array_range ***/
+
+void *
+glXAllocateMemoryNV( GLsizei size,
+ GLfloat readFrequency,
+ GLfloat writeFrequency,
+ GLfloat priority )
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return NULL;
+ return (t->AllocateMemoryNV)(size, readFrequency, writeFrequency, priority);
+}
+
+
+void
+glXFreeMemoryNV( GLvoid *pointer )
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return;
+ (t->FreeMemoryNV)(pointer);
+}
+
+
+/*** GLX_MESA_agp_offset */
+
+GLuint
+glXGetAGPOffsetMESA( const GLvoid *pointer )
+{
+ struct _glxapi_table *t;
+ Display *dpy = glXGetCurrentDisplay();
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return ~0;
+ return (t->GetAGPOffsetMESA)(pointer);
+}
+
+
+/*** GLX_ARB_render_Texture ***/
+
+Bool
+glXBindTexImageARB( Display *dpy, GLXPbuffer pbuffer, int buffer )
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->BindTexImageARB)(dpy, pbuffer, buffer);
+}
+
+
+Bool
+glXReleaseTexImageARB(Display *dpy, GLXPbuffer pbuffer, int buffer )
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->ReleaseTexImageARB)(dpy, pbuffer, buffer);
+}
+
+
+Bool
+glXDrawableAttribARB( Display *dpy, GLXDrawable draw, const int *attribList )
+{
+ struct _glxapi_table *t;
+ GET_DISPATCH(dpy, t);
+ if (!t)
+ return False;
+ return (t->DrawableAttribARB)(dpy, draw, attribList);
+}
+
+
+
+/**********************************************************************/
+/* GLX API management functions */
+/**********************************************************************/
+
+
+const char *
+_glxapi_get_version(void)
+{
+ return "1.3";
+}
+
+
+/*
+ * Return array of extension strings.
+ */
+const char **
+_glxapi_get_extensions(void)
+{
+ static const char *extensions[] = {
+#ifdef GLX_EXT_import_context
+ "GLX_EXT_import_context",
+#endif
+#ifdef GLX_SGI_video_sync
+ "GLX_SGI_video_sync",
+#endif
+#ifdef GLX_MESA_copy_sub_buffer
+ "GLX_MESA_copy_sub_buffer",
+#endif
+#ifdef GLX_MESA_release_buffers
+ "GLX_MESA_release_buffers",
+#endif
+#ifdef GLX_MESA_pixmap_colormap
+ "GLX_MESA_pixmap_colormap",
+#endif
+#ifdef GLX_MESA_set_3dfx_mode
+ "GLX_MESA_set_3dfx_mode",
+#endif
+#ifdef GLX_SGIX_fbconfig
+ "GLX_SGIX_fbconfig",
+#endif
+#ifdef GLX_SGIX_pbuffer
+ "GLX_SGIX_pbuffer",
+#endif
+#ifdef GLX_ARB_render_texture
+ "GLX_ARB_render_texture",
+#endif
+ NULL
+ };
+ return extensions;
+}
+
+
+/*
+ * Return size of the GLX dispatch table, in entries, not bytes.
+ */
+GLuint
+_glxapi_get_dispatch_table_size(void)
+{
+ return sizeof(struct _glxapi_table) / sizeof(void *);
+}
+
+
+static int
+generic_no_op_func(void)
+{
+ return 0;
+}
+
+
+/*
+ * Initialize all functions in given dispatch table to be no-ops
+ */
+void
+_glxapi_set_no_op_table(struct _glxapi_table *t)
+{
+ typedef int (*nop_func)(void);
+ nop_func *dispatch = (nop_func *) t;
+ GLuint n = _glxapi_get_dispatch_table_size();
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ dispatch[i] = generic_no_op_func;
+ }
+}
+
+
+struct name_address_pair {
+ const char *Name;
+ __GLXextFuncPtr Address;
+};
+
+static struct name_address_pair GLX_functions[] = {
+ /*** GLX_VERSION_1_0 ***/
+ { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual },
+ { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext },
+ { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext },
+ { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap },
+ { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext },
+ { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap },
+ { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig },
+ { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext },
+ { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable },
+ { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect },
+ { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent },
+ { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension },
+ { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion },
+ { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers },
+ { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont },
+ { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL },
+ { "glXWaitX", (__GLXextFuncPtr) glXWaitX },
+
+ /*** GLX_VERSION_1_1 ***/
+ { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString },
+ { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString },
+ { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString },
+
+ /*** GLX_VERSION_1_2 ***/
+ { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay },
+
+ /*** GLX_VERSION_1_3 ***/
+ { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig },
+ { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext },
+ { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer },
+ { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap },
+ { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow },
+ { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer },
+ { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap },
+ { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow },
+ { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable },
+ { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib },
+ { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs },
+ { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent },
+ { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig },
+ { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent },
+ { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext },
+ { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable },
+ { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent },
+
+ /*** GLX_VERSION_1_4 ***/
+ { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress },
+
+ /*** GLX_SGI_swap_control ***/
+ { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI },
+
+ /*** GLX_SGI_video_sync ***/
+ { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI },
+ { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI },
+
+ /*** GLX_SGI_make_current_read ***/
+ { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI },
+ { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI },
+
+ /*** GLX_SGIX_video_source ***/
+#if defined(_VL_H)
+ { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX },
+ { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX },
+#endif
+
+ /*** GLX_EXT_import_context ***/
+ { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT },
+ { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT },
+ { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT },
+ { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT },
+ { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT },
+
+ /*** GLX_SGIX_fbconfig ***/
+ { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX },
+ { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX },
+ { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX },
+ { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX },
+ { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX },
+ { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX },
+
+ /*** GLX_SGIX_pbuffer ***/
+ { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX },
+ { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX },
+ { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX },
+ { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX },
+ { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX },
+
+ /*** GLX_SGI_cushion ***/
+ { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI },
+
+ /*** GLX_SGIX_video_resize ***/
+ { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX },
+ { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX },
+ { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX },
+ { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX },
+ { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX },
+
+ /*** GLX_SGIX_dmbuffer **/
+#if defined(_DM_BUFFER_H_)
+ { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX },
+#endif
+
+ /*** GLX_SGIX_swap_group ***/
+ { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX },
+
+ /*** GLX_SGIX_swap_barrier ***/
+ { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX },
+ { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX },
+
+ /*** GLX_SUN_get_transparent_index ***/
+ { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN },
+
+ /*** GLX_MESA_copy_sub_buffer ***/
+ { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA },
+
+ /*** GLX_MESA_pixmap_colormap ***/
+ { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA },
+
+ /*** GLX_MESA_release_buffers ***/
+ { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA },
+
+ /*** GLX_MESA_set_3dfx_mode ***/
+ { "glXSet3DfxModeMESA", (__GLXextFuncPtr) glXSet3DfxModeMESA },
+
+ /*** GLX_ARB_get_proc_address ***/
+ { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB },
+
+ /*** GLX_NV_vertex_array_range ***/
+ { "glXAllocateMemoryNV", (__GLXextFuncPtr) glXAllocateMemoryNV },
+ { "glXFreeMemoryNV", (__GLXextFuncPtr) glXFreeMemoryNV },
+
+ /*** GLX_MESA_agp_offset ***/
+ { "glXGetAGPOffsetMESA", (__GLXextFuncPtr) glXGetAGPOffsetMESA },
+
+ /*** GLX_ARB_render_texture ***/
+ { "glXBindTexImageARB", (__GLXextFuncPtr) glXBindTexImageARB },
+ { "glXReleaseTexImageARB", (__GLXextFuncPtr) glXReleaseTexImageARB },
+ { "glXDrawableAttribARB", (__GLXextFuncPtr) glXDrawableAttribARB },
+
+ { NULL, NULL } /* end of list */
+};
+
+
+
+/*
+ * Return address of named glX function, or NULL if not found.
+ */
+__GLXextFuncPtr
+_glxapi_get_proc_address(const char *funcName)
+{
+ GLuint i;
+ for (i = 0; GLX_functions[i].Name; i++) {
+ if (strcmp(GLX_functions[i].Name, funcName) == 0)
+ return GLX_functions[i].Address;
+ }
+ return NULL;
+}
+
+
+
+/*
+ * This function does not get dispatched through the dispatch table
+ * since it's really a "meta" function.
+ */
+__GLXextFuncPtr
+glXGetProcAddressARB(const GLubyte *procName)
+{
+ __GLXextFuncPtr f;
+
+ f = _glxapi_get_proc_address((const char *) procName);
+ if (f) {
+ return f;
+ }
+
+ f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName);
+ return f;
+}
+
+
+/* GLX 1.4 */
+void (*glXGetProcAddress(const GLubyte *procName))()
+{
+ return glXGetProcAddressARB(procName);
+}
diff --git a/src/mesa/drivers/x11/glxapi.h b/src/mesa/drivers/x11/glxapi.h
new file mode 100644
index 0000000..d6bc157
--- /dev/null
+++ b/src/mesa/drivers/x11/glxapi.h
@@ -0,0 +1,236 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2002 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.
+ */
+
+
+#ifndef _glxapi_h_
+#define _glxapi_h_
+
+
+#define GLX_GLXEXT_PROTOTYPES
+#include "GL/glx.h"
+
+
+#ifdef GLX_BUILT_IN_XMESA
+/* The GLX API dispatcher (i.e. this code) is being built into XFree86's
+ * libGL so we'll use the __GLXContextRec defined in xc/lib/GL/glx/glxclient.h
+*/
+#include "glxclient.h"
+#else
+/* The GLX API dispatcher (i.e. this code) is being built into stand-alone
+ * Mesa. We don't know anything about XFree86 or real GLX so we define a
+ * minimal __GLXContextRec here so some of the functions in this file can
+ * work properly.
+ */
+typedef struct __GLXcontextRec {
+ Display *currentDpy;
+ GLboolean isDirect;
+ GLXDrawable currentDrawable;
+ GLXDrawable currentReadable;
+ XID xid;
+} __GLXcontext;
+#endif
+
+
+/*
+ * Almost all the GLX API functions get routed through this dispatch table.
+ * The exceptions are the glXGetCurrentXXX() functions.
+ *
+ * This dispatch table allows multiple GLX client-side modules to coexist.
+ * Specifically, a real GLX library (like SGI's or the Utah GLX) and Mesa's
+ * pseudo-GLX can be present at the same time. The former being used on
+ * GLX-enabled X servers and the later on non-GLX X servers.
+ *
+ * Red Hat has been using this since Red Hat Linux 7.0 (I think).
+ * This'll be a standard feature in XFree86 4.3. It basically allows one
+ * libGL to do both DRI-rendering and "fake GLX" rendering to X displays
+ * that lack the GLX extension.
+ */
+struct _glxapi_table {
+ /*** GLX_VERSION_1_0 ***/
+ XVisualInfo *(*ChooseVisual)(Display *dpy, int screen, int *list);
+ void (*CopyContext)(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
+ GLXContext (*CreateContext)(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct);
+ GLXPixmap (*CreateGLXPixmap)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap);
+ void (*DestroyContext)(Display *dpy, GLXContext ctx);
+ void (*DestroyGLXPixmap)(Display *dpy, GLXPixmap pixmap);
+ int (*GetConfig)(Display *dpy, XVisualInfo *visinfo, int attrib, int *value);
+ /*GLXContext (*GetCurrentContext)(void);*/
+ /*GLXDrawable (*GetCurrentDrawable)(void);*/
+ Bool (*IsDirect)(Display *dpy, GLXContext ctx);
+ Bool (*MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+ Bool (*QueryExtension)(Display *dpy, int *errorb, int *event);
+ Bool (*QueryVersion)(Display *dpy, int *maj, int *min);
+ void (*SwapBuffers)(Display *dpy, GLXDrawable drawable);
+ void (*UseXFont)(Font font, int first, int count, int listBase);
+ void (*WaitGL)(void);
+ void (*WaitX)(void);
+
+ /*** GLX_VERSION_1_1 ***/
+ const char *(*GetClientString)(Display *dpy, int name);
+ const char *(*QueryExtensionsString)(Display *dpy, int screen);
+ const char *(*QueryServerString)(Display *dpy, int screen, int name);
+
+ /*** GLX_VERSION_1_2 ***/
+ /*Display *(*GetCurrentDisplay)(void);*/
+
+ /*** GLX_VERSION_1_3 ***/
+ GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems);
+ GLXContext (*CreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct);
+ GLXPbuffer (*CreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attribList);
+ GLXPixmap (*CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList);
+ GLXWindow (*CreateWindow)(Display *dpy, GLXFBConfig config, Window win, const int *attribList);
+ void (*DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf);
+ void (*DestroyPixmap)(Display *dpy, GLXPixmap pixmap);
+ void (*DestroyWindow)(Display *dpy, GLXWindow window);
+ /*GLXDrawable (*GetCurrentReadDrawable)(void);*/
+ int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value);
+ GLXFBConfig *(*GetFBConfigs)(Display *dpy, int screen, int *nelements);
+ void (*GetSelectedEvent)(Display *dpy, GLXDrawable drawable, unsigned long *mask);
+ XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config);
+ Bool (*MakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+ int (*QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value);
+ void (*QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+ void (*SelectEvent)(Display *dpy, GLXDrawable drawable, unsigned long mask);
+
+ /*** GLX_SGI_swap_control ***/
+ int (*SwapIntervalSGI)(int);
+
+ /*** GLX_SGI_video_sync ***/
+ int (*GetVideoSyncSGI)(unsigned int *count);
+ int (*WaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count);
+
+ /*** GLX_SGI_make_current_read ***/
+ Bool (*MakeCurrentReadSGI)(Display *, GLXDrawable, GLXDrawable, GLXContext);
+ /*GLXDrawable (*GetCurrentReadDrawableSGI)(void);*/
+
+ /*** GLX_SGIX_video_source (needs video library) ***/
+#if defined(_VL_H_)
+ GLXVideoSourceSGIX (*CreateGLXVideoSourceSGIX)(Display *, int, VLServer, VLPath, int, VLNode);
+ void (*DestroyGLXVideoSourceSGIX)(Display *, GLXVideoSourceSGIX);
+#else
+ void *CreateGLXVideoSourceSGIX;
+ void *DestroyGLXVideoSourceSGIX;
+#endif
+
+ /*** GLX_EXT_import_context ***/
+ void (*FreeContextEXT)(Display *dpy, GLXContext context);
+ GLXContextID (*GetContextIDEXT)(const GLXContext context);
+ /*Display *(*GetCurrentDisplayEXT)(void);*/
+ GLXContext (*ImportContextEXT)(Display *dpy, GLXContextID contextID);
+ int (*QueryContextInfoEXT)(Display *dpy, GLXContext context, int attribute,int *value);
+
+ /*** GLX_SGIX_fbconfig ***/
+ int (*GetFBConfigAttribSGIX)(Display *, GLXFBConfigSGIX, int, int *);
+ GLXFBConfigSGIX * (*ChooseFBConfigSGIX)(Display *, int, int *, int *);
+ GLXPixmap (*CreateGLXPixmapWithConfigSGIX)(Display *, GLXFBConfigSGIX, Pixmap);
+ GLXContext (*CreateContextWithConfigSGIX)(Display *, GLXFBConfigSGIX, int, GLXContext, Bool);
+ XVisualInfo * (*GetVisualFromFBConfigSGIX)(Display *, GLXFBConfigSGIX);
+ GLXFBConfigSGIX (*GetFBConfigFromVisualSGIX)(Display *, XVisualInfo *);
+
+ /*** GLX_SGIX_pbuffer ***/
+ GLXPbufferSGIX (*CreateGLXPbufferSGIX)(Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *);
+ void (*DestroyGLXPbufferSGIX)(Display *, GLXPbufferSGIX);
+ int (*QueryGLXPbufferSGIX)(Display *, GLXPbufferSGIX, int, unsigned int *);
+ void (*SelectEventSGIX)(Display *, GLXDrawable, unsigned long);
+ void (*GetSelectedEventSGIX)(Display *, GLXDrawable, unsigned long *);
+
+ /*** GLX_SGI_cushion ***/
+ void (*CushionSGI)(Display *, Window, float);
+
+ /*** GLX_SGIX_video_resize ***/
+ int (*BindChannelToWindowSGIX)(Display *, int, int, Window);
+ int (*ChannelRectSGIX)(Display *, int, int, int, int, int, int);
+ int (*QueryChannelRectSGIX)(Display *, int, int, int *, int *, int *, int *);
+ int (*QueryChannelDeltasSGIX)(Display *, int, int, int *, int *, int *, int *);
+ int (*ChannelRectSyncSGIX)(Display *, int, int, GLenum);
+
+ /*** GLX_SGIX_dmbuffer (needs dmedia library) ***/
+#if defined (_DM_BUFFER_H_)
+ Bool (*AssociateDMPbufferSGIX)(Display *, GLXPbufferSGIX, DMparams *, DMbuffer);
+#else
+ void *AssociciateDMPbufferSGIX;
+#endif
+
+ /*** GLX_SGIX_swap_group ***/
+ void (*JoinSwapGroupSGIX)(Display *, GLXDrawable, GLXDrawable);
+
+ /*** GLX_SGIX_swap_barrier ***/
+ void (*BindSwapBarrierSGIX)(Display *, GLXDrawable, int);
+ Bool (*QueryMaxSwapBarriersSGIX)(Display *, int, int *);
+
+ /*** GLX_SUN_get_transparent_index ***/
+ Status (*GetTransparentIndexSUN)(Display *, Window, Window, long *);
+
+ /*** GLX_MESA_copy_sub_buffer ***/
+ void (*CopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height);
+
+ /*** GLX_MESA_release_buffers ***/
+ Bool (*ReleaseBuffersMESA)(Display *dpy, Window w);
+
+ /*** GLX_MESA_pixmap_colormap ***/
+ GLXPixmap (*CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap);
+
+ /*** GLX_MESA_set_3dfx_mode ***/
+ Bool (*Set3DfxModeMESA)(int mode);
+
+ /*** GLX_NV_vertex_array_range ***/
+ void * (*AllocateMemoryNV)( GLsizei size,
+ GLfloat readFrequency,
+ GLfloat writeFrequency,
+ GLfloat priority );
+ void (*FreeMemoryNV)( GLvoid *pointer );
+
+ /*** GLX_MESA_agp_offset ***/
+ GLuint (*GetAGPOffsetMESA)( const GLvoid *pointer );
+
+ /*** GLX_ARB_render_texture ***/
+ Bool (*BindTexImageARB)(Display *dpy, GLXPbuffer pbuffer, int buffer);
+ Bool (*ReleaseTexImageARB)(Display *dpy, GLXPbuffer pbuffer, int buffer);
+ Bool (*DrawableAttribARB)(Display *dpy, GLXDrawable draw, const int *attribList);
+};
+
+
+
+extern const char *
+_glxapi_get_version(void);
+
+
+extern const char **
+_glxapi_get_extensions(void);
+
+
+extern GLuint
+_glxapi_get_dispatch_table_size(void);
+
+
+extern void
+_glxapi_set_no_op_table(struct _glxapi_table *t);
+
+
+extern __GLXextFuncPtr
+_glxapi_get_proc_address(const char *funcName);
+
+
+#endif
diff --git a/src/mesa/drivers/x11/glxheader.h b/src/mesa/drivers/x11/glxheader.h
new file mode 100644
index 0000000..b583400
--- /dev/null
+++ b/src/mesa/drivers/x11/glxheader.h
@@ -0,0 +1,71 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 4.1
+ *
+ * Copyright (C) 1999-2002 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.
+ */
+
+
+#ifndef GLX_HEADER_H
+#define GLX_HEADER_H
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+
+#include "glheader.h"
+
+
+#ifdef XFree86Server
+
+# include "resource.h"
+# include "windowstr.h"
+# include "gcstruct.h"
+# include "GL/xf86glx.h"
+# include "xf86glx_util.h"
+
+#else
+
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
+# ifdef USE_XSHM /* was SHM */
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <X11/extensions/XShm.h>
+# endif
+# include <GL/glx.h>
+
+#endif
+
+
+
+/* this silences a compiler warning on several systems */
+struct timespec;
+struct itimerspec;
+
+
+
+#endif /*GLX_HEADER*/
diff --git a/src/mesa/drivers/x11/realglx.c b/src/mesa/drivers/x11/realglx.c
new file mode 100644
index 0000000..520f0f1
--- /dev/null
+++ b/src/mesa/drivers/x11/realglx.c
@@ -0,0 +1,185 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2002 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.
+ */
+
+
+#include <assert.h>
+#include <GL/glx.h>
+#include "realglx.h"
+#include "glxapi.h"
+
+
+struct _glxapi_table *
+_real_GetGLXDispatchTable(void)
+{
+ static struct _glxapi_table glx;
+
+ /* be sure our dispatch table size <= libGL's table */
+ {
+ GLuint size = sizeof(struct _glxapi_table) / sizeof(void *);
+ (void) size;
+ assert(_glxapi_get_dispatch_table_size() >= size);
+ }
+
+ /* initialize the whole table to no-ops */
+ _glxapi_set_no_op_table(&glx);
+
+ /* now initialize the table with the functions I implement */
+
+ /*** GLX_VERSION_1_0 ***/
+ glx.ChooseVisual = _real_glXChooseVisual;
+ glx.CopyContext = _real_glXCopyContext;
+ glx.CreateContext = _real_glXCreateContext;
+ glx.CreateGLXPixmap = _real_glXCreateGLXPixmap;
+ glx.DestroyContext = _real_glXDestroyContext;
+ glx.DestroyGLXPixmap = _real_glXDestroyGLXPixmap;
+ glx.GetConfig = _real_glXGetConfig;
+ /*glx.GetCurrentContext = _real_glXGetCurrentContext;*/
+ /*glx.GetCurrentDrawable = _real_glXGetCurrentDrawable;*/
+ glx.IsDirect = _real_glXIsDirect;
+ glx.MakeCurrent = _real_glXMakeCurrent;
+ glx.QueryExtension = _real_glXQueryExtension;
+ glx.QueryVersion = _real_glXQueryVersion;
+ glx.SwapBuffers = _real_glXSwapBuffers;
+ glx.UseXFont = _real_glXUseXFont;
+ glx.WaitGL = _real_glXWaitGL;
+ glx.WaitX = _real_glXWaitX;
+
+ /*** GLX_VERSION_1_1 ***/
+ glx.GetClientString = _real_glXGetClientString;
+ glx.QueryExtensionsString = _real_glXQueryExtensionsString;
+ glx.QueryServerString = _real_glXQueryServerString;
+
+ /*** GLX_VERSION_1_2 ***/
+ /*glx.GetCurrentDisplay = _real_glXGetCurrentDisplay;*/
+
+ /*** GLX_VERSION_1_3 ***/
+ glx.ChooseFBConfig = _real_glXChooseFBConfig;
+ glx.CreateNewContext = _real_glXCreateNewContext;
+ glx.CreatePbuffer = _real_glXCreatePbuffer;
+ glx.CreatePixmap = _real_glXCreatePixmap;
+ glx.CreateWindow = _real_glXCreateWindow;
+ glx.DestroyPbuffer = _real_glXDestroyPbuffer;
+ glx.DestroyPixmap = _real_glXDestroyPixmap;
+ glx.DestroyWindow = _real_glXDestroyWindow;
+ /*glx.GetCurrentReadDrawable = _real_glXGetCurrentReadDrawable;*/
+ glx.GetFBConfigAttrib = _real_glXGetFBConfigAttrib;
+ glx.GetFBConfigs = _real_glXGetFBConfigs;
+ glx.GetSelectedEvent = _real_glXGetSelectedEvent;
+ glx.GetVisualFromFBConfig = _real_glXGetVisualFromFBConfig;
+ glx.MakeContextCurrent = _real_glXMakeContextCurrent;
+ glx.QueryContext = _real_glXQueryContext;
+ glx.QueryDrawable = _real_glXQueryDrawable;
+ glx.SelectEvent = _real_glXSelectEvent;
+
+ /*** GLX_SGI_swap_control ***/
+ glx.SwapIntervalSGI = _real_glXSwapIntervalSGI;
+
+ /*** GLX_SGI_video_sync ***/
+ glx.GetVideoSyncSGI = _real_glXGetVideoSyncSGI;
+ glx.WaitVideoSyncSGI = _real_glXWaitVideoSyncSGI;
+
+ /*** GLX_SGI_make_current_read ***/
+ glx.MakeCurrentReadSGI = _real_glXMakeCurrentReadSGI;
+ /*glx.GetCurrentReadDrawableSGI = _real_glXGetCurrentReadDrawableSGI;*/
+
+#if defined(_VL_H)
+ /*** GLX_SGIX_video_source ***/
+ glx.CreateGLXVideoSourceSGIX = _real_glXCreateGLXVideoSourceSGIX;
+ glx.DestroyGLXVideoSourceSGIX = _real_glXDestroyGLXVideoSourceSGIX;
+#endif
+
+ /*** GLX_EXT_import_context ***/
+ glx.FreeContextEXT = _real_glXFreeContextEXT;
+ /*glx.GetContextIDEXT = _real_glXGetContextIDEXT;*/
+ /*glx.GetCurrentDisplayEXT = _real_glXGetCurrentDisplayEXT;*/
+ glx.ImportContextEXT = _real_glXImportContextEXT;
+ glx.QueryContextInfoEXT = _real_glXQueryContextInfoEXT;
+
+ /*** GLX_SGIX_fbconfig ***/
+ glx.GetFBConfigAttribSGIX = _real_glXGetFBConfigAttribSGIX;
+ glx.ChooseFBConfigSGIX = _real_glXChooseFBConfigSGIX;
+ glx.CreateGLXPixmapWithConfigSGIX = _real_glXCreateGLXPixmapWithConfigSGIX;
+ glx.CreateContextWithConfigSGIX = _real_glXCreateContextWithConfigSGIX;
+ glx.GetVisualFromFBConfigSGIX = _real_glXGetVisualFromFBConfigSGIX;
+ glx.GetFBConfigFromVisualSGIX = _real_glXGetFBConfigFromVisualSGIX;
+
+ /*** GLX_SGIX_pbuffer ***/
+ glx.CreateGLXPbufferSGIX = _real_glXCreateGLXPbufferSGIX;
+ glx.DestroyGLXPbufferSGIX = _real_glXDestroyGLXPbufferSGIX;
+ glx.QueryGLXPbufferSGIX = _real_glXQueryGLXPbufferSGIX;
+ glx.SelectEventSGIX = _real_glXSelectEventSGIX;
+ glx.GetSelectedEventSGIX = _real_glXGetSelectedEventSGIX;
+
+ /*** GLX_SGI_cushion ***/
+ glx.CushionSGI = _real_glXCushionSGI;
+
+ /*** GLX_SGIX_video_resize ***/
+ glx.BindChannelToWindowSGIX = _real_glXBindChannelToWindowSGIX;
+ glx.ChannelRectSGIX = _real_glXChannelRectSGIX;
+ glx.QueryChannelRectSGIX = _real_glXQueryChannelRectSGIX;
+ glx.QueryChannelDeltasSGIX = _real_glXQueryChannelDeltasSGIX;
+ glx.ChannelRectSyncSGIX = _real_glXChannelRectSyncSGIX;
+
+#if defined(_DM_BUFFER_H_)
+ /*** (GLX_SGIX_dmbuffer ***/
+ glx.AssociateDMPbufferSGIX = NULL;
+#endif
+
+ /*** GLX_SGIX_swap_group ***/
+ glx.JoinSwapGroupSGIX = _real_glXJoinSwapGroupSGIX;
+
+ /*** GLX_SGIX_swap_barrier ***/
+ glx.BindSwapBarrierSGIX = _real_glXBindSwapBarrierSGIX;
+ glx.QueryMaxSwapBarriersSGIX = _real_glXQueryMaxSwapBarriersSGIX;
+
+ /*** GLX_SUN_get_transparent_index ***/
+ glx.GetTransparentIndexSUN = _real_glXGetTransparentIndexSUN;
+
+ /*** GLX_MESA_copy_sub_buffer ***/
+ glx.CopySubBufferMESA = _real_glXCopySubBufferMESA;
+
+ /*** GLX_MESA_release_buffers ***/
+ glx.ReleaseBuffersMESA = _real_glXReleaseBuffersMESA;
+
+ /*** GLX_MESA_pixmap_colormap ***/
+ glx.CreateGLXPixmapMESA = _real_glXCreateGLXPixmapMESA;
+
+ /*** GLX_MESA_set_3dfx_mode ***/
+ glx.Set3DfxModeMESA = _real_glXSet3DfxModeMESA;
+
+ /*** GLX_NV_vertex_array_range ***/
+ glx.AllocateMemoryNV = _real_glXAllocateMemoryNV;
+ glx.FreeMemoryNV = _real_glXFreeMemoryNV;
+
+ /*** GLX_MESA_agp_offset ***/
+ glx.GetAGPOffsetMESA = _real_glXGetAGPOffsetMESA;
+
+ /*** GLX_ARB_render_texture ***/
+ glx.BindTexImageARB = _real_glXBindTexImageARB;
+ glx.ReleaseTexImageARB = _real_glXReleaseTexImageARB;
+ glx.DrawableAttribARB = _real_glXDrawableAttribARB;
+
+ return &glx;
+}
diff --git a/src/mesa/drivers/x11/realglx.h b/src/mesa/drivers/x11/realglx.h
new file mode 100644
index 0000000..150129d
--- /dev/null
+++ b/src/mesa/drivers/x11/realglx.h
@@ -0,0 +1,326 @@
+
+/*
+ * 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.
+ */
+
+
+#ifndef REALGLX_H
+#define REALGLX_H
+
+
+extern struct _glxapi_table *
+_real_GetGLXDispatchTable(void);
+
+
+/*
+ * Basically just need these to prevent compiler warnings.
+ */
+
+
+extern XVisualInfo *
+_real_glXChooseVisual( Display *dpy, int screen, int *list );
+
+extern GLXContext
+_real_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext share_list, Bool direct );
+
+extern GLXPixmap
+_real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap );
+
+extern GLXPixmap
+_real_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap, Colormap cmap );
+
+extern void
+_real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap );
+
+extern void
+_real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ unsigned long mask );
+
+extern Bool
+_real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx );
+
+extern Bool
+_real_glXQueryExtension( Display *dpy, int *errorb, int *event );
+
+extern void
+_real_glXDestroyContext( Display *dpy, GLXContext ctx );
+
+extern Bool
+_real_glXIsDirect( Display *dpy, GLXContext ctx );
+
+extern void
+_real_glXSwapBuffers( Display *dpy, GLXDrawable drawable );
+
+extern void
+_real_glXUseXFont( Font font, int first, int count, int listbase );
+
+extern Bool
+_real_glXQueryVersion( Display *dpy, int *maj, int *min );
+
+extern int
+_real_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value );
+
+extern void
+_real_glXWaitGL( void );
+
+
+extern void
+_real_glXWaitX( void );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXQueryExtensionsString( Display *dpy, int screen );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXQueryServerString( Display *dpy, int screen, int name );
+
+/* GLX 1.1 and later */
+extern const char *
+_real_glXGetClientString( Display *dpy, int name );
+
+
+/*
+ * GLX 1.3 and later
+ */
+
+extern GLXFBConfig *
+_real_glXChooseFBConfig( Display *dpy, int screen,
+ const int *attribList, int *nitems );
+
+extern int
+_real_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
+ int attribute, int *value );
+
+extern GLXFBConfig *
+_real_glXGetFBConfigs( Display *dpy, int screen, int *nelements );
+
+extern XVisualInfo *
+_real_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config );
+
+extern GLXWindow
+_real_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
+ const int *attribList );
+
+extern void
+_real_glXDestroyWindow( Display *dpy, GLXWindow window );
+
+extern GLXPixmap
+_real_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
+ const int *attribList );
+
+extern void
+_real_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap );
+
+extern GLXPbuffer
+_real_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
+ const int *attribList );
+
+extern void
+_real_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf );
+
+extern void
+_real_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
+ unsigned int *value );
+
+extern GLXContext
+_real_glXCreateNewContext( Display *dpy, GLXFBConfig config,
+ int renderType, GLXContext shareList, Bool direct );
+
+
+extern Bool
+_real_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
+ GLXDrawable read, GLXContext ctx );
+
+extern int
+_real_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value );
+
+extern void
+_real_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask );
+
+extern void
+_real_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
+ unsigned long *mask );
+
+#ifdef GLX_SGI_swap_control
+extern int
+_real_glXSwapIntervalSGI(int interval);
+#endif
+
+
+#ifdef GLX_SGI_video_sync
+extern int
+_real_glXGetVideoSyncSGI(unsigned int *count);
+
+extern int
+_real_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count);
+#endif
+
+
+#ifdef GLX_SGI_make_current_read
+extern Bool
+_real_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+
+extern GLXDrawable
+_real_glXGetCurrentReadDrawableSGI(void);
+#endif
+
+#if defined(_VL_H) && defined(GLX_SGIX_video_source)
+extern GLXVideoSourceSGIX
+_real_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode);
+
+extern void
+_real_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src);
+#endif
+
+#ifdef GLX_EXT_import_context
+extern void
+_real_glXFreeContextEXT(Display *dpy, GLXContext context);
+
+extern GLXContextID
+_real_glXGetContextIDEXT(const GLXContext context);
+
+extern Display *
+_real_glXGetCurrentDisplayEXT(void);
+
+extern GLXContext
+_real_glXImportContextEXT(Display *dpy, GLXContextID contextID);
+
+extern int
+_real_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value);
+#endif
+
+#ifdef GLX_SGIX_fbconfig
+extern int
+_real_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+
+extern GLXFBConfigSGIX *
+_real_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements);
+
+extern GLXPixmap
+_real_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap);
+
+extern GLXContext
+_real_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+
+extern XVisualInfo *
+_real_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config);
+
+extern GLXFBConfigSGIX
+_real_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis);
+#endif
+
+#ifdef GLX_SGIX_pbuffer
+extern GLXPbufferSGIX
+_real_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list);
+
+extern void
+_real_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf);
+
+extern int
+_real_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value);
+
+extern void
+_real_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask);
+
+extern void
+_real_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask);
+#endif
+
+#ifdef GLX_SGI_cushion
+extern void
+_real_glXCushionSGI(Display *dpy, Window win, float cushion);
+#endif
+
+#ifdef GLX_SGIX_video_resize
+extern int
+_real_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window);
+
+extern int
+_real_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h);
+
+extern int
+_real_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h);
+
+extern int
+_real_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh);
+
+extern int
+_real_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype);
+#endif
+
+#if defined(_DM_BUFFER_H_) && defined(GLX_SGIX_dmbuffer)
+extern Bool
+_real_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer);
+#endif
+
+#ifdef GLX_SGIX_swap_group
+extern void
+_real_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member);
+#endif
+
+#ifdef GLX_SGIX_swap_barrier
+extern void
+_real_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier);
+
+extern Bool
+_real_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max);
+#endif
+
+#ifdef GLX_SUN_get_transparent_index
+extern Status
+_real_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent);
+#endif
+
+#ifdef GLX_MESA_release_buffers
+extern Bool
+_real_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d );
+#endif
+
+#ifdef GLX_MESA_set_3dfx_mode
+extern Bool
+_real_glXSet3DfxModeMESA( int mode );
+#endif
+
+#ifdef GLX_NV_vertex_array_range
+extern void *
+_real_glXAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
+extern void
+_real_glXFreeMemoryNV(GLvoid *pointer);
+#endif
+
+#ifdef GLX_MESA_agp_offset
+extern GLuint
+_real_glXGetAGPOffsetMESA(const GLvoid *pointer);
+#endif
+
+#ifdef GLX_MESA_copy_sub_buffer
+extern void
+_real_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+ int x, int y, int width, int height );
+#endif
+
+#endif /* REALGLX_H */
diff --git a/src/mesa/drivers/x11/xfonts.c b/src/mesa/drivers/x11/xfonts.c
new file mode 100644
index 0000000..d72c600
--- /dev/null
+++ b/src/mesa/drivers/x11/xfonts.c
@@ -0,0 +1,377 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2000 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.
+ */
+
+
+/* xfonts.c -- glXUseXFont() for Mesa written by
+ * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
+ */
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include "glxheader.h"
+#include "context.h"
+#include "imports.h"
+#include "xfonts.h"
+
+
+/* Some debugging info. */
+
+#ifdef DEBUG
+#undef _R
+#undef _G
+#undef _B
+#include <ctype.h>
+
+int debug_xfonts = 0;
+
+static void
+dump_char_struct(XCharStruct * ch, char *prefix)
+{
+ printf("%slbearing = %d, rbearing = %d, width = %d\n",
+ prefix, ch->lbearing, ch->rbearing, ch->width);
+ printf("%sascent = %d, descent = %d, attributes = %u\n",
+ prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
+}
+
+static void
+dump_font_struct(XFontStruct * font)
+{
+ printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
+ printf("char_or_byte2 = (%u,%u)\n",
+ font->min_char_or_byte2, font->max_char_or_byte2);
+ printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
+ printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
+ printf("default_char = %c (\\%03o)\n",
+ (char) (isprint(font->default_char) ? font->default_char : ' '),
+ font->default_char);
+ dump_char_struct(&font->min_bounds, "min> ");
+ dump_char_struct(&font->max_bounds, "max> ");
+#if 0
+ for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
+ char prefix[8];
+ sprintf(prefix, "%d> ", c);
+ dump_char_struct(&font->per_char[c], prefix);
+ }
+#endif
+}
+
+static void
+dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
+{
+ unsigned int x, y;
+
+ printf(" ");
+ for (x = 0; x < 8 * width; x++)
+ printf("%o", 7 - (x % 8));
+ putchar('\n');
+ for (y = 0; y < height; y++) {
+ printf("%3o:", y);
+ for (x = 0; x < 8 * width; x++)
+ putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
+ 8))))
+ ? '*' : '.');
+ printf(" ");
+ for (x = 0; x < width; x++)
+ printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
+ putchar('\n');
+ }
+}
+#endif /* DEBUG */
+
+
+/* Implementation. */
+
+/* Fill a BITMAP with a character C from thew current font
+ in the graphics context GC. WIDTH is the width in bytes
+ and HEIGHT is the height in bits.
+
+ Note that the generated bitmaps must be used with
+
+ glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+
+ Possible optimizations:
+
+ * use only one reusable pixmap with the maximum dimensions.
+ * draw the entire font into a single pixmap (careful with
+ proportional fonts!).
+*/
+
+
+/*
+ * Generate OpenGL-compatible bitmap.
+ */
+static void
+fill_bitmap(Display * dpy, Window win, GC gc,
+ unsigned int width, unsigned int height,
+ int x0, int y0, unsigned int c, GLubyte * bitmap)
+{
+ XImage *image;
+ unsigned int x, y;
+ Pixmap pixmap;
+ XChar2b char2b;
+
+ pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
+ XSetForeground(dpy, gc, 0);
+ XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
+ XSetForeground(dpy, gc, 1);
+
+ char2b.byte1 = (c >> 8) & 0xff;
+ char2b.byte2 = (c & 0xff);
+
+ XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
+
+ image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
+ if (image) {
+ /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
+ for (y = 0; y < height; y++)
+ for (x = 0; x < 8 * width; x++)
+ if (XGetPixel(image, x, y))
+ bitmap[width * (height - y - 1) + x / 8] |=
+ (1 << (7 - (x % 8)));
+ XDestroyImage(image);
+ }
+
+ XFreePixmap(dpy, pixmap);
+}
+
+/*
+ * determine if a given glyph is valid and return the
+ * corresponding XCharStruct.
+ */
+static XCharStruct *
+isvalid(XFontStruct * fs, unsigned int which)
+{
+ unsigned int rows, pages;
+ unsigned int byte1 = 0, byte2 = 0;
+ int i, valid = 1;
+
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+
+ if (rows == 1) {
+ /* "linear" fonts */
+ if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
+ valid = 0;
+ }
+ else {
+ /* "matrix" fonts */
+ byte2 = which & 0xff;
+ byte1 = which >> 8;
+ if ((fs->min_char_or_byte2 > byte2) ||
+ (fs->max_char_or_byte2 < byte2) ||
+ (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
+ valid = 0;
+ }
+
+ if (valid) {
+ if (fs->per_char) {
+ if (rows == 1) {
+ /* "linear" fonts */
+ return (fs->per_char + (which - fs->min_char_or_byte2));
+ }
+ else {
+ /* "matrix" fonts */
+ i = ((byte1 - fs->min_byte1) * pages) +
+ (byte2 - fs->min_char_or_byte2);
+ return (fs->per_char + i);
+ }
+ }
+ else {
+ return (&fs->min_bounds);
+ }
+ }
+ return (NULL);
+}
+
+
+void
+Fake_glXUseXFont(Font font, int first, int count, int listbase)
+{
+ Display *dpy;
+ Window win;
+ Pixmap pixmap;
+ GC gc;
+ XGCValues values;
+ unsigned long valuemask;
+ XFontStruct *fs;
+ GLint swapbytes, lsbfirst, rowlength;
+ GLint skiprows, skippixels, alignment;
+ unsigned int max_width, max_height, max_bm_width, max_bm_height;
+ GLubyte *bm;
+ int i;
+
+ dpy = glXGetCurrentDisplay();
+ if (!dpy)
+ return; /* I guess glXMakeCurrent wasn't called */
+ win = RootWindow(dpy, DefaultScreen(dpy));
+
+ fs = XQueryFont(dpy, font);
+ if (!fs) {
+ _mesa_error(NULL, GL_INVALID_VALUE,
+ "Couldn't get font structure information");
+ return;
+ }
+
+ /* Allocate a bitmap that can fit all characters. */
+ max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+ max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
+ max_bm_width = (max_width + 7) / 8;
+ max_bm_height = max_height;
+
+ bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte));
+ if (!bm) {
+ XFreeFontInfo(NULL, fs, 1);
+ _mesa_error(NULL, GL_OUT_OF_MEMORY,
+ "Couldn't allocate bitmap in glXUseXFont()");
+ return;
+ }
+
+#if 0
+ /* get the page info */
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+ firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
+ lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ unsigned int first_char, last_char, pages, rows;
+#endif
+
+ /* Save the current packing mode for bitmaps. */
+ glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
+ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
+ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
+ /* Enforce a standard packing mode which is compatible with
+ fill_bitmap() from above. This is actually the default mode,
+ except for the (non)alignment. */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
+ values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
+ values.background = WhitePixel(dpy, DefaultScreen(dpy));
+ values.font = fs->fid;
+ valuemask = GCForeground | GCBackground | GCFont;
+ gc = XCreateGC(dpy, pixmap, valuemask, &values);
+ XFreePixmap(dpy, pixmap);
+
+#ifdef DEBUG
+ if (debug_xfonts)
+ dump_font_struct(fs);
+#endif
+
+ for (i = 0; i < count; i++) {
+ unsigned int width, height, bm_width, bm_height;
+ GLfloat x0, y0, dx, dy;
+ XCharStruct *ch;
+ int x, y;
+ unsigned int c = first + i;
+ int list = listbase + i;
+ int valid;
+
+ /* check on index validity and get the bounds */
+ ch = isvalid(fs, c);
+ if (!ch) {
+ ch = &fs->max_bounds;
+ valid = 0;
+ }
+ else {
+ valid = 1;
+ }
+
+#ifdef DEBUG
+ if (debug_xfonts) {
+ char s[7];
+ sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
+ dump_char_struct(ch, s);
+ }
+#endif
+
+ /* glBitmap()' parameters:
+ straight from the glXUseXFont(3) manpage. */
+ width = ch->rbearing - ch->lbearing;
+ height = ch->ascent + ch->descent;
+ x0 = -ch->lbearing;
+ y0 = ch->descent - 0; /* XXX used to subtract 1 here */
+ /* but that caused a conformace failure */
+ dx = ch->width;
+ dy = 0;
+
+ /* X11's starting point. */
+ x = -ch->lbearing;
+ y = ch->ascent;
+
+ /* Round the width to a multiple of eight. We will use this also
+ for the pixmap for capturing the X11 font. This is slightly
+ inefficient, but it makes the OpenGL part real easy. */
+ bm_width = (width + 7) / 8;
+ bm_height = height;
+
+ glNewList(list, GL_COMPILE);
+ if (valid && (bm_width > 0) && (bm_height > 0)) {
+
+ MEMSET(bm, '\0', bm_width * bm_height);
+ fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
+
+ glBitmap(width, height, x0, y0, dx, dy, bm);
+#ifdef DEBUG
+ if (debug_xfonts) {
+ printf("width/height = %u/%u\n", width, height);
+ printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
+ dump_bitmap(bm_width, bm_height, bm);
+ }
+#endif
+ }
+ else {
+ glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
+ }
+ glEndList();
+ }
+
+ FREE(bm);
+ XFreeFontInfo(NULL, fs, 1);
+ XFreeGC(dpy, gc);
+
+ /* Restore saved packing modes. */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
diff --git a/src/mesa/drivers/x11/xfonts.h b/src/mesa/drivers/x11/xfonts.h
new file mode 100644
index 0000000..e36f42f
--- /dev/null
+++ b/src/mesa/drivers/x11/xfonts.h
@@ -0,0 +1,41 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2000 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.
+ */
+
+
+#ifndef XFONTS_H
+#define XFONTS_H
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include <X11/Xlib.h>
+
+
+extern void Fake_glXUseXFont( Font font, int first, int count, int listbase );
+
+
+#endif
+
diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c
new file mode 100644
index 0000000..d714b55
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_api.c
@@ -0,0 +1,2676 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2.2
+ *
+ * Copyright (C) 1999-2005 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.
+ */
+
+/*
+ * This file contains the implementations of all the XMesa* functions.
+ *
+ *
+ * NOTES:
+ *
+ * The window coordinate system origin (0,0) is in the lower-left corner
+ * of the window. X11's window coordinate origin is in the upper-left
+ * corner of the window. Therefore, most drawing functions in this
+ * file have to flip Y coordinates.
+ *
+ * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
+ * in support for the MIT Shared Memory extension. If enabled, when you
+ * use an Ximage for the back buffer in double buffered mode, the "swap"
+ * operation will be faster. You must also link with -lXext.
+ *
+ * Byte swapping: If the Mesa host and the X display use a different
+ * byte order then there's some trickiness to be aware of when using
+ * XImages. The byte ordering used for the XImage is that of the X
+ * display, not the Mesa host.
+ * The color-to-pixel encoding for True/DirectColor must be done
+ * according to the display's visual red_mask, green_mask, and blue_mask.
+ * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
+ * do byte swapping if needed. If one wants to directly "poke" the pixel
+ * into the XImage's buffer then the pixel must be byte swapped first. In
+ * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
+ * and use XPutPixel everywhere except in the implementation of
+ * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so
+ * instead of using XPutPixel we "poke" our values after byte-swapping
+ * the clear pixel value if needed.
+ *
+ */
+
+#ifdef __CYGWIN__
+#undef WIN32
+#undef __WIN32__
+#endif
+
+#include "glxheader.h"
+#include "GL/xmesa.h"
+#include "xmesaP.h"
+#include "context.h"
+#include "extensions.h"
+#include "glthread.h"
+#include "imports.h"
+#include "matrix.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "texformat.h"
+#include "texobj.h"
+#include "texstore.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "drivers/common/driverfuncs.h"
+
+#ifdef XFree86Server
+#include <GL/glxtokens.h>
+#endif
+
+/*
+ * Global X driver lock
+ */
+_glthread_Mutex _xmesa_lock;
+
+
+
+/*
+ * Lookup tables for HPCR pixel format:
+ */
+static short hpcr_rgbTbl[3][256] = {
+{
+ 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
+ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 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, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
+},
+{
+ 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
+ 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 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, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
+},
+{
+ 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39,
+ 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
+ 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
+ 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
+ 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
+ 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79,
+ 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
+}
+};
+
+
+
+/**********************************************************************/
+/***** X Utility Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Return the host's byte order as LSBFirst or MSBFirst ala X.
+ */
+#ifndef XFree86Server
+static int host_byte_order( void )
+{
+ int i = 1;
+ char *cptr = (char *) &i;
+ return (*cptr==1) ? LSBFirst : MSBFirst;
+}
+#endif
+
+
+/*
+ * Error handling.
+ */
+#ifndef XFree86Server
+static volatile int mesaXErrorFlag = 0;
+
+static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event )
+{
+ (void) dpy;
+ (void) event;
+ mesaXErrorFlag = 1;
+ return 0;
+}
+#endif
+
+
+/*
+ * Check if the X Shared Memory extension is available.
+ * Return: 0 = not available
+ * 1 = shared XImage support available
+ * 2 = shared Pixmap support available also
+ */
+#ifndef XFree86Server
+static int check_for_xshm( XMesaDisplay *display )
+{
+#ifdef USE_XSHM
+ int major, minor, ignore;
+ Bool pixmaps;
+
+ if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
+ if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
+ return (pixmaps==True) ? 2 : 1;
+ }
+ else {
+ return 0;
+ }
+ }
+ else {
+ return 0;
+ }
+#else
+ /* Can't compile XSHM support */
+ return 0;
+#endif
+}
+#endif
+
+
+/*
+ * Return the width and height of the given drawable.
+ */
+static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d,
+ unsigned int *width, unsigned int *height)
+{
+#ifdef XFree86Server
+ (void) dpy;
+ *width = d->width;
+ *height = d->height;
+#else
+ Window root;
+ int x, y;
+ unsigned int bw, depth;
+
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+#endif
+}
+
+
+/*
+ * Apply gamma correction to an intensity value in [0..max]. Return the
+ * new intensity value.
+ */
+static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max )
+{
+ if (gamma == 1.0) {
+ return value;
+ }
+ else {
+ double x = (double) value / (double) max;
+ return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma));
+ }
+}
+
+
+
+/*
+ * Return the true number of bits per pixel for XImages.
+ * For example, if we request a 24-bit deep visual we may actually need/get
+ * 32bpp XImages. This function returns the appropriate bpp.
+ * Input: dpy - the X display
+ * visinfo - desribes the visual to be used for XImages
+ * Return: true number of bits per pixel for XImages
+ */
+#ifdef XFree86Server
+
+static int bits_per_pixel( XMesaVisual xmv )
+{
+ const int depth = xmv->nplanes;
+ int i;
+ for (i = 0; i < screenInfo.numPixmapFormats; i++) {
+ if (screenInfo.formats[i].depth == depth)
+ return screenInfo.formats[i].bitsPerPixel;
+ }
+ return depth; /* should never get here, but this should be safe */
+}
+
+#else
+
+static int bits_per_pixel( XMesaVisual xmv )
+{
+ XMesaDisplay *dpy = xmv->display;
+ XMesaVisualInfo visinfo = xmv->visinfo;
+ XMesaImage *img;
+ int bitsPerPixel;
+ /* Create a temporary XImage */
+ img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
+ ZPixmap, 0, /*format, offset*/
+ (char*) MALLOC(8), /*data*/
+ 1, 1, /*width, height*/
+ 32, /*bitmap_pad*/
+ 0 /*bytes_per_line*/
+ );
+ assert(img);
+ /* grab the bits/pixel value */
+ bitsPerPixel = img->bits_per_pixel;
+ /* free the XImage */
+ FREE( img->data );
+ img->data = NULL;
+ XMesaDestroyImage( img );
+ return bitsPerPixel;
+}
+#endif
+
+
+
+/*
+ * Determine if a given X window ID is valid (window exists).
+ * Do this by calling XGetWindowAttributes() for the window and
+ * checking if we catch an X error.
+ * Input: dpy - the display
+ * win - the window to check for existance
+ * Return: GL_TRUE - window exists
+ * GL_FALSE - window doesn't exist
+ */
+#ifndef XFree86Server
+static GLboolean WindowExistsFlag;
+
+static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
+{
+ (void) dpy;
+ if (xerr->error_code == BadWindow) {
+ WindowExistsFlag = GL_FALSE;
+ }
+ return 0;
+}
+
+static GLboolean window_exists( XMesaDisplay *dpy, Window win )
+{
+ XWindowAttributes wa;
+ int (*old_handler)( XMesaDisplay*, XErrorEvent* );
+ WindowExistsFlag = GL_TRUE;
+ old_handler = XSetErrorHandler(window_exists_err_handler);
+ XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
+ XSetErrorHandler(old_handler);
+ return WindowExistsFlag;
+}
+#endif
+
+
+
+/**********************************************************************/
+/***** Linked list of XMesaBuffers *****/
+/**********************************************************************/
+
+static XMesaBuffer XMesaBufferList = NULL;
+
+
+/* Allocate a new XMesaBuffer, add to linked list */
+static XMesaBuffer alloc_xmesa_buffer(void)
+{
+ XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
+ if (b) {
+ b->Next = XMesaBufferList;
+ XMesaBufferList = b;
+ }
+ return b;
+}
+
+
+/*
+ * Find an XMesaBuffer by matching X display and colormap but NOT matching
+ * the notThis buffer.
+ */
+static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy,
+ XMesaColormap cmap,
+ XMesaBuffer notThis)
+{
+ XMesaBuffer b;
+ for (b=XMesaBufferList; b; b=b->Next) {
+ if (b->display==dpy && b->cmap==cmap && b!=notThis) {
+ return b;
+ }
+ }
+ return NULL;
+}
+
+
+/*
+ * Free an XMesaBuffer, remove from linked list, perhaps free X colormap
+ * entries.
+ */
+static void free_xmesa_buffer(int client, XMesaBuffer buffer)
+{
+ XMesaBuffer prev = NULL, b;
+ (void) client;
+ for (b=XMesaBufferList; b; b=b->Next) {
+ if (b==buffer) {
+ /* unlink bufer from list */
+ if (prev)
+ prev->Next = buffer->Next;
+ else
+ XMesaBufferList = buffer->Next;
+ /* Check to free X colors */
+ if (buffer->num_alloced>0) {
+ /* If no other buffer uses this X colormap then free the colors. */
+ if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) {
+#ifdef XFree86Server
+ (void)FreeColors(buffer->cmap, client,
+ buffer->num_alloced, buffer->alloced_colors,
+ 0);
+#else
+ XFreeColors(buffer->display, buffer->cmap,
+ buffer->alloced_colors, buffer->num_alloced, 0);
+#endif
+ }
+ }
+
+ _mesa_free_framebuffer_data(&buffer->mesa_buffer);
+ FREE(buffer);
+
+ return;
+ }
+ /* continue search */
+ prev = b;
+ }
+ /* buffer not found in XMesaBufferList */
+ _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n");
+}
+
+
+/* Copy X color table stuff from one XMesaBuffer to another. */
+static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src)
+{
+ MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table));
+ MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r));
+ MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g));
+ MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b));
+ dst->num_alloced = src->num_alloced;
+ MEMCPY(dst->alloced_colors, src->alloced_colors,
+ sizeof(src->alloced_colors));
+}
+
+
+
+/**********************************************************************/
+/***** Misc Private Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Return number of bits set in n.
+ */
+static int bitcount( unsigned long n )
+{
+ int bits;
+ for (bits=0; n>0; n=n>>1) {
+ if (n&1) {
+ bits++;
+ }
+ }
+ return bits;
+}
+
+
+
+/*
+ * Allocate a shared memory XImage back buffer for the given XMesaBuffer.
+ * Return: GL_TRUE if success, GL_FALSE if error
+ */
+#ifndef XFree86Server
+static GLboolean alloc_shm_back_buffer( XMesaBuffer b )
+{
+#ifdef USE_XSHM
+ /*
+ * We have to do a _lot_ of error checking here to be sure we can
+ * really use the XSHM extension. It seems different servers trigger
+ * errors at different points if the extension won't work. Therefore
+ * we have to be very careful...
+ */
+ GC gc;
+ int (*old_handler)( XMesaDisplay *, XErrorEvent * );
+
+ b->backimage = XShmCreateImage( b->xm_visual->display,
+ b->xm_visual->visinfo->visual,
+ b->xm_visual->visinfo->depth,
+ ZPixmap, NULL, &b->shminfo,
+ b->width, b->height );
+ if (b->backimage == NULL) {
+ _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.");
+ b->shm = 0;
+ return GL_FALSE;
+ }
+
+ b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line
+ * b->backimage->height, IPC_CREAT|0777 );
+ if (b->shminfo.shmid < 0) {
+ _mesa_warning(NULL, "shmget failed while allocating back buffer");
+ XDestroyImage( b->backimage );
+ b->backimage = NULL;
+ _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.");
+ b->shm = 0;
+ return GL_FALSE;
+ }
+
+ b->shminfo.shmaddr = b->backimage->data
+ = (char*)shmat( b->shminfo.shmid, 0, 0 );
+ if (b->shminfo.shmaddr == (char *) -1) {
+ _mesa_warning(NULL, "shmat() failed while allocating back buffer");
+ XDestroyImage( b->backimage );
+ shmctl( b->shminfo.shmid, IPC_RMID, 0 );
+ b->backimage = NULL;
+ _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.");
+ b->shm = 0;
+ return GL_FALSE;
+ }
+
+ b->shminfo.readOnly = False;
+ mesaXErrorFlag = 0;
+ old_handler = XSetErrorHandler( mesaHandleXError );
+ /* This may trigger the X protocol error we're ready to catch: */
+ XShmAttach( b->xm_visual->display, &b->shminfo );
+ XSync( b->xm_visual->display, False );
+
+ if (mesaXErrorFlag) {
+ /* we are on a remote display, this error is normal, don't print it */
+ XFlush( b->xm_visual->display );
+ mesaXErrorFlag = 0;
+ XDestroyImage( b->backimage );
+ shmdt( b->shminfo.shmaddr );
+ shmctl( b->shminfo.shmid, IPC_RMID, 0 );
+ b->backimage = NULL;
+ b->shm = 0;
+ (void) XSetErrorHandler( old_handler );
+ return GL_FALSE;
+ }
+
+ shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */
+
+ /* Finally, try an XShmPutImage to be really sure the extension works */
+ gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL );
+ XShmPutImage( b->xm_visual->display, b->frontbuffer, gc,
+ b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False );
+ XSync( b->xm_visual->display, False );
+ XFreeGC( b->xm_visual->display, gc );
+ (void) XSetErrorHandler( old_handler );
+ if (mesaXErrorFlag) {
+ XFlush( b->xm_visual->display );
+ mesaXErrorFlag = 0;
+ XDestroyImage( b->backimage );
+ shmdt( b->shminfo.shmaddr );
+ shmctl( b->shminfo.shmid, IPC_RMID, 0 );
+ b->backimage = NULL;
+ b->shm = 0;
+ return GL_FALSE;
+ }
+
+ if (b->backimage) {
+ int height = b->backimage->height;
+ /* Needed by PIXELADDR1 macro */
+ b->ximage_width1 = b->backimage->bytes_per_line;
+ b->ximage_origin1 = (GLubyte *) b->backimage->data
+ + b->ximage_width1 * (height-1);
+ /* Needed by PIXELADDR2 macro */
+ b->ximage_width2 = b->backimage->bytes_per_line / 2;
+ b->ximage_origin2 = (GLushort *) b->backimage->data
+ + b->ximage_width2 * (height-1);
+ /* Needed by PIXELADDR3 macro */
+ b->ximage_width3 = b->backimage->bytes_per_line;
+ b->ximage_origin3 = (GLubyte *) b->backimage->data
+ + b->ximage_width3 * (height-1);
+ /* Needed by PIXELADDR4 macro */
+ b->ximage_width4 = b->backimage->width;
+ b->ximage_origin4 = (GLuint *) b->backimage->data
+ + b->ximage_width4 * (height-1);
+ }
+
+ return GL_TRUE;
+#else
+ /* Can't compile XSHM support */
+ return GL_FALSE;
+#endif
+}
+#endif
+
+
+
+/*
+ * Setup an off-screen pixmap or Ximage to use as the back buffer.
+ * Input: b - the X/Mesa buffer
+ */
+void xmesa_alloc_back_buffer( XMesaBuffer b )
+{
+ if (b->db_state==BACK_XIMAGE) {
+ /* Deallocate the old backimage, if any */
+ if (b->backimage) {
+#if defined(USE_XSHM) && !defined(XFree86Server)
+ if (b->shm) {
+ XShmDetach( b->xm_visual->display, &b->shminfo );
+ XDestroyImage( b->backimage );
+ shmdt( b->shminfo.shmaddr );
+ }
+ else
+#endif
+ XMesaDestroyImage( b->backimage );
+ b->backimage = NULL;
+ }
+
+ /* Allocate new back buffer */
+#ifdef XFree86Server
+ {
+ /* Allocate a regular XImage for the back buffer. */
+ b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel,
+ b->width, b->height, NULL);
+#else
+ if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) {
+ /* Allocate a regular XImage for the back buffer. */
+ b->backimage = XCreateImage( b->xm_visual->display,
+ b->xm_visual->visinfo->visual,
+ GET_VISUAL_DEPTH(b->xm_visual),
+ ZPixmap, 0, /* format, offset */
+ NULL, b->width, b->height,
+ 8, 0 ); /* pad, bytes_per_line */
+#endif
+ if (!b->backimage) {
+ _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.");
+ }
+ b->backimage->data = (char *) MALLOC( b->backimage->height
+ * b->backimage->bytes_per_line );
+ if (!b->backimage->data) {
+ _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.");
+ XMesaDestroyImage( b->backimage );
+ b->backimage = NULL;
+ }
+ }
+ b->backpixmap = None;
+ }
+ else if (b->db_state==BACK_PIXMAP) {
+ XMesaPixmap old_pixmap = b->backpixmap;
+ /* Free the old back pixmap */
+ if (b->backpixmap) {
+ XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
+ }
+ /* Allocate new back pixmap */
+ b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer,
+ b->width, b->height,
+ GET_VISUAL_DEPTH(b->xm_visual) );
+ b->backimage = NULL;
+ /* update other references to backpixmap */
+ if (b->buffer==(XMesaDrawable)old_pixmap) {
+ b->buffer = (XMesaDrawable)b->backpixmap;
+ }
+ }
+}
+
+
+
+/*
+ * A replacement for XAllocColor. This function should never
+ * fail to allocate a color. When XAllocColor fails, we return
+ * the nearest matching color. If we have to allocate many colors
+ * this function isn't too efficient; the XQueryColors() could be
+ * done just once.
+ * Written by Michael Pichler, Brian Paul, Mark Kilgard
+ * Input: dpy - X display
+ * cmap - X colormap
+ * cmapSize - size of colormap
+ * In/Out: color - the XColor struct
+ * Output: exact - 1=exact color match, 0=closest match
+ * alloced - 1=XAlloc worked, 0=XAlloc failed
+ */
+static void
+noFaultXAllocColor( int client,
+ XMesaDisplay *dpy,
+ XMesaColormap cmap,
+ int cmapSize,
+ XMesaColor *color,
+ int *exact, int *alloced )
+{
+#ifdef XFree86Server
+ Pixel *ppixIn;
+ xrgb *ctable;
+#else
+ /* we'll try to cache ctable for better remote display performance */
+ static Display *prevDisplay = NULL;
+ static XMesaColormap prevCmap = 0;
+ static int prevCmapSize = 0;
+ static XMesaColor *ctable = NULL;
+#endif
+ XMesaColor subColor;
+ int i, bestmatch;
+ double mindist; /* 3*2^16^2 exceeds long int precision. */
+
+ (void) client;
+
+ /* First try just using XAllocColor. */
+#ifdef XFree86Server
+ if (AllocColor(cmap,
+ &color->red, &color->green, &color->blue,
+ &color->pixel,
+ client) == Success) {
+#else
+ if (XAllocColor(dpy, cmap, color)) {
+#endif
+ *exact = 1;
+ *alloced = 1;
+ return;
+ }
+
+ /* Alloc failed, search for closest match */
+
+ /* Retrieve color table entries. */
+ /* XXX alloca candidate. */
+#ifdef XFree86Server
+ ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel));
+ ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb));
+ for (i = 0; i < cmapSize; i++) {
+ ppixIn[i] = i;
+ }
+ QueryColors(cmap, cmapSize, ppixIn, ctable);
+#else
+ if (prevDisplay != dpy || prevCmap != cmap
+ || prevCmapSize != cmapSize || !ctable) {
+ /* free previously cached color table */
+ if (ctable)
+ FREE(ctable);
+ /* Get the color table from X */
+ ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor));
+ assert(ctable);
+ for (i = 0; i < cmapSize; i++) {
+ ctable[i].pixel = i;
+ }
+ XQueryColors(dpy, cmap, ctable, cmapSize);
+ prevDisplay = dpy;
+ prevCmap = cmap;
+ prevCmapSize = cmapSize;
+ }
+#endif
+
+ /* Find best match. */
+ bestmatch = -1;
+ mindist = 0.0;
+ for (i = 0; i < cmapSize; i++) {
+ double dr = 0.30 * ((double) color->red - (double) ctable[i].red);
+ double dg = 0.59 * ((double) color->green - (double) ctable[i].green);
+ double db = 0.11 * ((double) color->blue - (double) ctable[i].blue);
+ double dist = dr * dr + dg * dg + db * db;
+ if (bestmatch < 0 || dist < mindist) {
+ bestmatch = i;
+ mindist = dist;
+ }
+ }
+
+ /* Return result. */
+ subColor.red = ctable[bestmatch].red;
+ subColor.green = ctable[bestmatch].green;
+ subColor.blue = ctable[bestmatch].blue;
+ /* Try to allocate the closest match color. This should only
+ * fail if the cell is read/write. Otherwise, we're incrementing
+ * the cell's reference count.
+ */
+#ifdef XFree86Server
+ if (AllocColor(cmap,
+ &subColor.red, &subColor.green, &subColor.blue,
+ &subColor.pixel,
+ client) == Success) {
+#else
+ if (XAllocColor(dpy, cmap, &subColor)) {
+#endif
+ *alloced = 1;
+ }
+ else {
+ /* do this to work around a problem reported by Frank Ortega */
+ subColor.pixel = (unsigned long) bestmatch;
+ subColor.red = ctable[bestmatch].red;
+ subColor.green = ctable[bestmatch].green;
+ subColor.blue = ctable[bestmatch].blue;
+ subColor.flags = DoRed | DoGreen | DoBlue;
+ *alloced = 0;
+ }
+#ifdef XFree86Server
+ FREE(ppixIn);
+ FREE(ctable);
+#else
+ /* don't free table, save it for next time */
+#endif
+
+ *color = subColor;
+ *exact = 0;
+}
+
+
+
+
+/*
+ * Do setup for PF_GRAYSCALE pixel format.
+ * Note that buffer may be NULL.
+ */
+static GLboolean setup_grayscale( int client, XMesaVisual v,
+ XMesaBuffer buffer, XMesaColormap cmap )
+{
+ if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
+ return GL_FALSE;
+ }
+
+ if (buffer) {
+ XMesaBuffer prevBuffer;
+
+ if (!cmap) {
+ return GL_FALSE;
+ }
+
+ prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
+ if (prevBuffer &&
+ (buffer->xm_visual->mesa_visual.rgbMode ==
+ prevBuffer->xm_visual->mesa_visual.rgbMode)) {
+ /* Copy colormap stuff from previous XMesaBuffer which uses same
+ * X colormap. Do this to avoid time spent in noFaultXAllocColor.
+ */
+ copy_colortable_info(buffer, prevBuffer);
+ }
+ else {
+ /* Allocate 256 shades of gray */
+ int gray;
+ int colorsfailed = 0;
+ for (gray=0;gray<256;gray++) {
+ GLint r = gamma_adjust( v->RedGamma, gray, 255 );
+ GLint g = gamma_adjust( v->GreenGamma, gray, 255 );
+ GLint b = gamma_adjust( v->BlueGamma, gray, 255 );
+ int exact, alloced;
+ XMesaColor xcol;
+ xcol.red = (r << 8) | r;
+ xcol.green = (g << 8) | g;
+ xcol.blue = (b << 8) | b;
+ noFaultXAllocColor( client, v->display,
+ cmap, GET_COLORMAP_SIZE(v),
+ &xcol, &exact, &alloced );
+ if (!exact) {
+ colorsfailed++;
+ }
+ if (alloced) {
+ assert(buffer->num_alloced<256);
+ buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
+ buffer->num_alloced++;
+ }
+
+ /*OLD
+ assert(gray < 576);
+ buffer->color_table[gray*3+0] = xcol.pixel;
+ buffer->color_table[gray*3+1] = xcol.pixel;
+ buffer->color_table[gray*3+2] = xcol.pixel;
+ assert(xcol.pixel < 65536);
+ buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100;
+ buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100;
+ buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100;
+ */
+ buffer->color_table[gray] = xcol.pixel;
+ assert(xcol.pixel < 65536);
+ buffer->pixel_to_r[xcol.pixel] = gray;
+ buffer->pixel_to_g[xcol.pixel] = gray;
+ buffer->pixel_to_b[xcol.pixel] = gray;
+ }
+
+ if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL,
+ "Note: %d out of 256 needed colors do not match exactly.\n",
+ colorsfailed );
+ }
+ }
+ }
+
+ v->dithered_pf = PF_Grayscale;
+ v->undithered_pf = PF_Grayscale;
+ return GL_TRUE;
+}
+
+
+
+/*
+ * Setup RGB rendering for a window with a PseudoColor, StaticColor,
+ * or 8-bit TrueColor visual visual. We try to allocate a palette of 225
+ * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB
+ * color. While this function was originally designed just for 8-bit
+ * visuals, it has also proven to work from 4-bit up to 16-bit visuals.
+ * Dithering code contributed by Bob Mercier.
+ */
+static GLboolean setup_dithered_color( int client, XMesaVisual v,
+ XMesaBuffer buffer, XMesaColormap cmap )
+{
+ if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) {
+ return GL_FALSE;
+ }
+
+ if (buffer) {
+ XMesaBuffer prevBuffer;
+
+ if (!cmap) {
+ return GL_FALSE;
+ }
+
+ prevBuffer = find_xmesa_buffer(v->display, cmap, buffer);
+ if (prevBuffer &&
+ (buffer->xm_visual->mesa_visual.rgbMode ==
+ prevBuffer->xm_visual->mesa_visual.rgbMode)) {
+ /* Copy colormap stuff from previous, matching XMesaBuffer.
+ * Do this to avoid time spent in noFaultXAllocColor.
+ */
+ copy_colortable_info(buffer, prevBuffer);
+ }
+ else {
+ /* Allocate X colors and initialize color_table[], red_table[], etc */
+ int r, g, b, i;
+ int colorsfailed = 0;
+ for (r = 0; r < DITH_R; r++) {
+ for (g = 0; g < DITH_G; g++) {
+ for (b = 0; b < DITH_B; b++) {
+ XMesaColor xcol;
+ int exact, alloced;
+ xcol.red =gamma_adjust(v->RedGamma, r*65535/(DITH_R-1),65535);
+ xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535);
+ xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(DITH_B-1),65535);
+ noFaultXAllocColor( client, v->display,
+ cmap, GET_COLORMAP_SIZE(v),
+ &xcol, &exact, &alloced );
+ if (!exact) {
+ colorsfailed++;
+ }
+ if (alloced) {
+ assert(buffer->num_alloced<256);
+ buffer->alloced_colors[buffer->num_alloced] = xcol.pixel;
+ buffer->num_alloced++;
+ }
+ i = DITH_MIX( r, g, b );
+ assert(i < 576);
+ buffer->color_table[i] = xcol.pixel;
+ assert(xcol.pixel < 65536);
+ buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1);
+ buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1);
+ buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1);
+ }
+ }
+ }
+
+ if (colorsfailed && _mesa_getenv("MESA_DEBUG")) {
+ _mesa_warning(NULL,
+ "Note: %d out of %d needed colors do not match exactly.\n",
+ colorsfailed, DITH_R * DITH_G * DITH_B );
+ }
+ }
+ }
+
+ v->dithered_pf = PF_Dither;
+ v->undithered_pf = PF_Lookup;
+ return GL_TRUE;
+}
+
+
+/*
+ * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode.
+ * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer.
+ * Special dithering tables have to be initialized.
+ */
+static void setup_8bit_hpcr( XMesaVisual v )
+{
+ /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be)
+ * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined
+ * on the root window AND the colormap obtainable by XGetRGBColormaps
+ * for that atom must be set on the window. (see also tkInitWindow)
+ * If that colormap is not set, the output will look stripy.
+ */
+
+ /* Setup color tables with gamma correction */
+ int i;
+ double g;
+
+ g = 1.0 / v->RedGamma;
+ for (i=0; i<256; i++) {
+ GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g ));
+ v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 );
+ }
+
+ g = 1.0 / v->GreenGamma;
+ for (i=0; i<256; i++) {
+ GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g ));
+ v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 );
+ }
+
+ g = 1.0 / v->BlueGamma;
+ for (i=0; i<256; i++) {
+ GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g ));
+ v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 );
+ }
+ v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */
+ v->dithered_pf = PF_HPCR;
+
+ /* which method should I use to clear */
+ /* GL_FALSE: keep the ordinary method */
+ /* GL_TRUE : clear with dither pattern */
+ v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE;
+
+ if (v->hpcr_clear_flag) {
+ v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display,
+ DefaultRootWindow(v->display),
+ 16, 2, 8);
+#ifndef XFree86Server
+ v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap,
+ 0, 0, 16, 2, AllPlanes, ZPixmap);
+#endif
+ }
+}
+
+
+/*
+ * Setup RGB rendering for a window with a True/DirectColor visual.
+ */
+static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer,
+ XMesaColormap cmap )
+{
+ unsigned long rmask, gmask, bmask;
+ (void) buffer;
+ (void) cmap;
+
+ /* Compute red multiplier (mask) and bit shift */
+ v->rshift = 0;
+ rmask = GET_REDMASK(v);
+ while ((rmask & 1)==0) {
+ v->rshift++;
+ rmask = rmask >> 1;
+ }
+
+ /* Compute green multiplier (mask) and bit shift */
+ v->gshift = 0;
+ gmask = GET_GREENMASK(v);
+ while ((gmask & 1)==0) {
+ v->gshift++;
+ gmask = gmask >> 1;
+ }
+
+ /* Compute blue multiplier (mask) and bit shift */
+ v->bshift = 0;
+ bmask = GET_BLUEMASK(v);
+ while ((bmask & 1)==0) {
+ v->bshift++;
+ bmask = bmask >> 1;
+ }
+
+ /*
+ * Compute component-to-pixel lookup tables and dithering kernel
+ */
+ {
+ static GLubyte kernel[16] = {
+ 0*16, 8*16, 2*16, 10*16,
+ 12*16, 4*16, 14*16, 6*16,
+ 3*16, 11*16, 1*16, 9*16,
+ 15*16, 7*16, 13*16, 5*16,
+ };
+ GLint rBits = bitcount(rmask);
+ GLint gBits = bitcount(gmask);
+ GLint bBits = bitcount(bmask);
+ GLint maxBits;
+ GLuint i;
+
+ /* convert pixel components in [0,_mask] to RGB values in [0,255] */
+ for (i=0; i<=rmask; i++)
+ v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
+ for (i=0; i<=gmask; i++)
+ v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
+ for (i=0; i<=bmask; i++)
+ v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
+
+ /* convert RGB values from [0,255] to pixel components */
+
+ for (i=0;i<256;i++) {
+ GLint r = gamma_adjust(v->RedGamma, i, 255);
+ GLint g = gamma_adjust(v->GreenGamma, i, 255);
+ GLint b = gamma_adjust(v->BlueGamma, i, 255);
+ v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
+ v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
+ v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
+ }
+ /* overflow protection */
+ for (i=256;i<512;i++) {
+ v->RtoPixel[i] = v->RtoPixel[255];
+ v->GtoPixel[i] = v->GtoPixel[255];
+ v->BtoPixel[i] = v->BtoPixel[255];
+ }
+
+ /* setup dithering kernel */
+ maxBits = rBits;
+ if (gBits > maxBits) maxBits = gBits;
+ if (bBits > maxBits) maxBits = bBits;
+ for (i=0;i<16;i++) {
+ v->Kernel[i] = kernel[i] >> maxBits;
+ }
+
+ v->undithered_pf = PF_Truecolor;
+ v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
+ }
+
+ /*
+ * Now check for TrueColor visuals which we can optimize.
+ */
+ if ( GET_REDMASK(v) ==0x0000ff
+ && GET_GREENMASK(v)==0x00ff00
+ && GET_BLUEMASK(v) ==0xff0000
+ && CHECK_BYTE_ORDER(v)
+ && v->BitsPerPixel==32
+ && sizeof(GLuint)==4
+ && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+ /* common 32 bpp config used on SGI, Sun */
+ v->undithered_pf = v->dithered_pf = PF_8A8B8G8R;
+ }
+ else if (GET_REDMASK(v) ==0xff0000
+ && GET_GREENMASK(v)==0x00ff00
+ && GET_BLUEMASK(v) ==0x0000ff
+ && CHECK_BYTE_ORDER(v)
+ && v->BitsPerPixel==32
+ && sizeof(GLuint)==4
+ && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+ /* common 32 bpp config used on Linux, HP, IBM */
+ if (GET_VISUAL_DEPTH(v)==32)
+ v->undithered_pf = v->dithered_pf = PF_8A8R8G8B;
+ else
+ v->undithered_pf = v->dithered_pf = PF_8R8G8B;
+ }
+ else if (GET_REDMASK(v) ==0xff0000
+ && GET_GREENMASK(v)==0x00ff00
+ && GET_BLUEMASK(v) ==0x0000ff
+ && CHECK_BYTE_ORDER(v)
+ && v->BitsPerPixel==24
+ && sizeof(GLuint)==4
+ && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+ /* common packed 24 bpp config used on Linux */
+ v->undithered_pf = v->dithered_pf = PF_8R8G8B24;
+ }
+ else if (GET_REDMASK(v) ==0xf800
+ && GET_GREENMASK(v)==0x07e0
+ && GET_BLUEMASK(v) ==0x001f
+ && CHECK_BYTE_ORDER(v)
+ && v->BitsPerPixel==16
+ && sizeof(GLushort)==2
+ && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
+ /* 5-6-5 color weight on common PC VGA boards */
+ v->undithered_pf = PF_5R6G5B;
+ v->dithered_pf = PF_Dither_5R6G5B;
+ }
+ else if (GET_REDMASK(v) ==0xe0
+ && GET_GREENMASK(v)==0x1c
+ && GET_BLUEMASK(v) ==0x03
+ && CHECK_FOR_HPCR(v)) {
+ setup_8bit_hpcr( v );
+ }
+}
+
+
+
+/*
+ * Setup RGB rendering for a window with a monochrome visual.
+ */
+static void setup_monochrome( XMesaVisual v, XMesaBuffer b )
+{
+ (void) b;
+ v->dithered_pf = v->undithered_pf = PF_1Bit;
+ /* if black=1 then we must flip pixel values */
+ v->bitFlip = (GET_BLACK_PIXEL(v) != 0);
+}
+
+
+
+/*
+ * When a context is "made current" for the first time, we can finally
+ * finish initializing the context's visual and buffer information.
+ * Input: v - the XMesaVisual to initialize
+ * b - the XMesaBuffer to initialize (may be NULL)
+ * rgb_flag - TRUE = RGBA mode, FALSE = color index mode
+ * window - the window/pixmap we're rendering into
+ * cmap - the colormap associated with the window/pixmap
+ * Return: GL_TRUE=success, GL_FALSE=failure
+ */
+static GLboolean initialize_visual_and_buffer( int client,
+ XMesaVisual v,
+ XMesaBuffer b,
+ GLboolean rgb_flag,
+ XMesaDrawable window,
+ XMesaColormap cmap )
+{
+#ifndef XFree86Server
+ XGCValues gcvalues;
+#endif
+
+ if (b) {
+ assert(b->xm_visual == v);
+ }
+
+ /* Save true bits/pixel */
+ v->BitsPerPixel = bits_per_pixel(v);
+ assert(v->BitsPerPixel > 0);
+
+
+ if (rgb_flag==GL_FALSE) {
+ /* COLOR-INDEXED WINDOW:
+ * Even if the visual is TrueColor or DirectColor we treat it as
+ * being color indexed. This is weird but might be useful to someone.
+ */
+ v->dithered_pf = v->undithered_pf = PF_Index;
+ v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v);
+ }
+ else {
+ /* RGB WINDOW:
+ * We support RGB rendering into almost any kind of visual.
+ */
+ const int xclass = v->mesa_visual.visualType;
+ if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
+ setup_truecolor( v, b, cmap );
+ }
+ else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) {
+ setup_monochrome( v, b );
+ }
+ else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) {
+ if (!setup_grayscale( client, v, b, cmap )) {
+ return GL_FALSE;
+ }
+ }
+ else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR)
+ && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) {
+ if (!setup_dithered_color( client, v, b, cmap )) {
+ return GL_FALSE;
+ }
+ }
+ else {
+ _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.");
+ return GL_FALSE;
+ }
+ v->mesa_visual.indexBits = 0;
+
+ if (_mesa_getenv("MESA_NO_DITHER")) {
+ v->dithered_pf = v->undithered_pf;
+ }
+ }
+
+
+ /*
+ * If MESA_INFO env var is set print out some debugging info
+ * which can help Brian figure out what's going on when a user
+ * reports bugs.
+ */
+ if (_mesa_getenv("MESA_INFO")) {
+ _mesa_printf("X/Mesa visual = %p\n", (void *) v);
+ _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
+ _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
+ _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
+ _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
+ _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
+ }
+
+ if (b && window) {
+ /* Do window-specific initializations */
+
+ /* Window dimensions */
+ unsigned int w, h;
+ get_drawable_size( v->display, window, &w, &h );
+ b->width = w;
+ b->height = h;
+
+ b->frontbuffer = window;
+
+ /* Setup for single/double buffering */
+ if (v->mesa_visual.doubleBufferMode) {
+ /* Double buffered */
+#ifndef XFree86Server
+ b->shm = check_for_xshm( v->display );
+#endif
+ xmesa_alloc_back_buffer( b );
+ if (b->db_state==BACK_PIXMAP) {
+ b->buffer = (XMesaDrawable)b->backpixmap;
+ }
+ else {
+ b->buffer = XIMAGE;
+ }
+ }
+ else {
+ /* Single Buffered */
+ b->buffer = b->frontbuffer;
+ }
+
+ /* X11 graphics contexts */
+#ifdef XFree86Server
+ b->gc = CreateScratchGC(v->display, window->depth);
+#else
+ b->gc = XCreateGC( v->display, window, 0, NULL );
+#endif
+ XMesaSetFunction( v->display, b->gc, GXcopy );
+
+ /* cleargc - for glClear() */
+#ifdef XFree86Server
+ b->cleargc = CreateScratchGC(v->display, window->depth);
+#else
+ b->cleargc = XCreateGC( v->display, window, 0, NULL );
+#endif
+ XMesaSetFunction( v->display, b->cleargc, GXcopy );
+
+ /*
+ * Don't generate Graphics Expose/NoExpose events in swapbuffers().
+ * Patch contributed by Michael Pichler May 15, 1995.
+ */
+#ifdef XFree86Server
+ b->swapgc = CreateScratchGC(v->display, window->depth);
+ {
+ CARD32 v[1];
+ v[0] = FALSE;
+ dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL);
+ }
+#else
+ gcvalues.graphics_exposures = False;
+ b->swapgc = XCreateGC( v->display, window,
+ GCGraphicsExposures, &gcvalues);
+#endif
+ XMesaSetFunction( v->display, b->swapgc, GXcopy );
+ /*
+ * Set fill style and tile pixmap once for all for HPCR stuff
+ * (instead of doing it each time in clear_color_HPCR_pixmap())
+ * Initialize whole stuff
+ * Patch contributed by Jacques Leroy March 8, 1998.
+ */
+ if (v->hpcr_clear_flag && b->buffer!=XIMAGE) {
+ int i;
+ for (i=0; i<16; i++)
+ {
+ XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0);
+ XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0);
+ }
+ XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap,
+ b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
+ XMesaSetFillStyle( v->display, b->cleargc, FillTiled);
+ XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap );
+ }
+
+ /* Initialize the row buffer XImage for use in write_color_span() */
+#ifdef XFree86Server
+ b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1,
+ (char *)MALLOC(MAX_WIDTH*4));
+#else
+ b->rowimage = XCreateImage( v->display,
+ v->visinfo->visual,
+ v->visinfo->depth,
+ ZPixmap, 0, /*format, offset*/
+ (char*) MALLOC(MAX_WIDTH*4), /*data*/
+ MAX_WIDTH, 1, /*width, height*/
+ 32, /*bitmap_pad*/
+ 0 /*bytes_per_line*/ );
+#endif
+ if (!b->rowimage)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+/*
+ * Convert an RGBA color to a pixel value.
+ */
+unsigned long
+xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a,
+ GLuint pixelFormat)
+{
+ switch (pixelFormat) {
+ case PF_Index:
+ return 0;
+ case PF_Truecolor:
+ {
+ unsigned long p;
+ PACK_TRUECOLOR( p, r, g, b );
+ return p;
+ }
+ case PF_8A8B8G8R:
+ return PACK_8A8B8G8R( r, g, b, a );
+ case PF_8A8R8G8B:
+ return PACK_8A8R8G8B( r, g, b, a );
+ case PF_8R8G8B:
+ /* fall through */
+ case PF_8R8G8B24:
+ return PACK_8R8G8B( r, g, b );
+ case PF_5R6G5B:
+ return PACK_5R6G5B( r, g, b );
+ case PF_Dither:
+ {
+ DITHER_SETUP;
+ return DITHER( 1, 0, r, g, b );
+ }
+ case PF_1Bit:
+ /* 382 = (3*255)/2 */
+ return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
+ case PF_HPCR:
+ return DITHER_HPCR(1, 1, r, g, b);
+ case PF_Lookup:
+ {
+ LOOKUP_SETUP;
+ return LOOKUP( r, g, b );
+ }
+ case PF_Grayscale:
+ return GRAY_RGB( r, g, b );
+ case PF_Dither_True:
+ /* fall through */
+ case PF_Dither_5R6G5B:
+ {
+ unsigned long p;
+ PACK_TRUEDITHER(p, 1, 0, r, g, b);
+ return p;
+ }
+ default:
+ _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel");
+ }
+ return 0;
+}
+
+
+#define NUM_VISUAL_TYPES 6
+
+/**
+ * Convert an X visual type to a GLX visual type.
+ *
+ * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
+ * to be converted.
+ * \return If \c visualType is a valid X visual type, a GLX visual type will
+ * be returned. Otherwise \c GLX_NONE will be returned.
+ *
+ * \note
+ * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
+ * DRI CVS tree.
+ */
+static GLint
+xmesa_convert_from_x_visual_type( int visualType )
+{
+ static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ( (unsigned) visualType < NUM_VISUAL_TYPES )
+ ? glx_visual_types[ visualType ] : GLX_NONE;
+}
+
+
+/**********************************************************************/
+/***** Public Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Create a new X/Mesa visual.
+ * Input: display - X11 display
+ * visinfo - an XVisualInfo pointer
+ * rgb_flag - GL_TRUE = RGB mode,
+ * GL_FALSE = color index mode
+ * alpha_flag - alpha buffer requested?
+ * db_flag - GL_TRUE = double-buffered,
+ * GL_FALSE = single buffered
+ * stereo_flag - stereo visual?
+ * ximage_flag - GL_TRUE = use an XImage for back buffer,
+ * GL_FALSE = use an off-screen pixmap for back buffer
+ * depth_size - requested bits/depth values, or zero
+ * stencil_size - requested bits/stencil values, or zero
+ * accum_red_size - requested bits/red accum values, or zero
+ * accum_green_size - requested bits/green accum values, or zero
+ * accum_blue_size - requested bits/blue accum values, or zero
+ * accum_alpha_size - requested bits/alpha accum values, or zero
+ * num_samples - number of samples/pixel if multisampling, or zero
+ * level - visual level, usually 0
+ * visualCaveat - ala the GLX extension, usually GLX_NONE
+ * Return; a new XMesaVisual or 0 if error.
+ */
+XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
+ XMesaVisualInfo visinfo,
+ GLboolean rgb_flag,
+ GLboolean alpha_flag,
+ GLboolean db_flag,
+ GLboolean stereo_flag,
+ GLboolean ximage_flag,
+ GLint depth_size,
+ GLint stencil_size,
+ GLint accum_red_size,
+ GLint accum_green_size,
+ GLint accum_blue_size,
+ GLint accum_alpha_size,
+ GLint num_samples,
+ GLint level,
+ GLint visualCaveat )
+{
+ char *gamma;
+ XMesaVisual v;
+ GLint red_bits, green_bits, blue_bits, alpha_bits;
+
+ /* For debugging only */
+ if (_mesa_getenv("MESA_XSYNC")) {
+ /* This makes debugging X easier.
+ * In your debugger, set a breakpoint on _XError to stop when an
+ * X protocol error is generated.
+ */
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ XSynchronize( display, 1 );
+#endif
+ }
+
+ v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
+ if (!v) {
+ return NULL;
+ }
+
+ /*
+ * In the X server, NULL is passed in for the display. It will have
+ * to be set before using this visual. See XMesaSetVisualDisplay()
+ * below.
+ */
+ v->display = display;
+
+ /* Save a copy of the XVisualInfo struct because the user may XFREE()
+ * the struct but we may need some of the information contained in it
+ * at a later time.
+ */
+#ifndef XFree86Server
+ v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
+ if(!v->visinfo) {
+ FREE(v);
+ return NULL;
+ }
+ MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
+#endif
+
+ /* check for MESA_GAMMA environment variable */
+ gamma = _mesa_getenv("MESA_GAMMA");
+ if (gamma) {
+ v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
+ sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
+ if (v->RedGamma<=0.0) v->RedGamma = 1.0;
+ if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma;
+ if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma;
+ }
+ else {
+ v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
+ }
+
+ v->ximage_flag = ximage_flag;
+
+#ifdef XFree86Server
+ /* We could calculate these values by ourselves. nplanes is either the sum
+ * of the red, green, and blue bits or the number index bits.
+ * ColormapEntries is either (1U << index_bits) or
+ * (1U << max(redBits, greenBits, blueBits)).
+ */
+ v->nplanes = visinfo->nplanes;
+ v->ColormapEntries = visinfo->ColormapEntries;
+
+ v->mesa_visual.redMask = visinfo->redMask;
+ v->mesa_visual.greenMask = visinfo->greenMask;
+ v->mesa_visual.blueMask = visinfo->blueMask;
+ v->mesa_visual.visualID = visinfo->vid;
+ v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
+#else
+ v->mesa_visual.redMask = visinfo->red_mask;
+ v->mesa_visual.greenMask = visinfo->green_mask;
+ v->mesa_visual.blueMask = visinfo->blue_mask;
+ v->mesa_visual.visualID = visinfo->visualid;
+ v->mesa_visual.screen = visinfo->screen;
+#endif
+
+#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
+ v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
+#else
+ v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
+#endif
+
+ v->mesa_visual.visualRating = visualCaveat;
+
+ (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 );
+
+ {
+ const int xclass = v->mesa_visual.visualType;
+ if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) {
+ red_bits = bitcount(GET_REDMASK(v));
+ green_bits = bitcount(GET_GREENMASK(v));
+ blue_bits = bitcount(GET_BLUEMASK(v));
+ alpha_bits = 0;
+ }
+ else {
+ /* this is an approximation */
+ int depth;
+ depth = GET_VISUAL_DEPTH(v);
+ red_bits = depth / 3;
+ depth -= red_bits;
+ green_bits = depth / 2;
+ depth -= green_bits;
+ blue_bits = depth;
+ alpha_bits = 0;
+ assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
+ }
+ }
+
+ if (alpha_flag && alpha_bits == 0)
+ alpha_bits = 8;
+
+ _mesa_initialize_visual( &v->mesa_visual,
+ rgb_flag, db_flag, stereo_flag,
+ red_bits, green_bits,
+ blue_bits, alpha_bits,
+ v->mesa_visual.indexBits,
+ depth_size,
+ stencil_size,
+ accum_red_size, accum_green_size,
+ accum_blue_size, accum_alpha_size,
+ 0 );
+
+ /* XXX minor hack */
+ v->mesa_visual.level = level;
+ return v;
+}
+
+
+void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v )
+{
+ v->display = dpy;
+}
+
+
+void XMesaDestroyVisual( XMesaVisual v )
+{
+#ifndef XFree86Server
+ FREE(v->visinfo);
+#endif
+ FREE(v);
+}
+
+
+
+/**
+ * Create a new XMesaContext.
+ * \param v the XMesaVisual
+ * \param share_list another XMesaContext with which to share display
+ * lists or NULL if no sharing is wanted.
+ * \return an XMesaContext or NULL if error.
+ */
+XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
+{
+ static GLboolean firstTime = GL_TRUE;
+ XMesaContext c;
+ GLcontext *mesaCtx;
+ struct dd_function_table functions;
+ TNLcontext *tnl;
+
+ if (firstTime) {
+ _glthread_INIT_MUTEX(_xmesa_lock);
+ firstTime = GL_FALSE;
+ }
+
+ /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
+ c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
+ if (!c)
+ return NULL;
+
+ mesaCtx = &(c->mesa);
+
+ /* initialize with default driver functions, then plug in XMesa funcs */
+ _mesa_init_driver_functions(&functions);
+ xmesa_init_driver_functions(v, &functions);
+ if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual,
+ share_list ? &(share_list->mesa) : (GLcontext *) NULL,
+ &functions, (void *) c)) {
+ FREE(c);
+ return NULL;
+ }
+
+ _mesa_enable_sw_extensions(mesaCtx);
+ _mesa_enable_1_3_extensions(mesaCtx);
+ _mesa_enable_1_4_extensions(mesaCtx);
+ _mesa_enable_1_5_extensions(mesaCtx);
+
+ /* finish up xmesa context initializations */
+ c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
+ c->xm_visual = v;
+ c->xm_draw_buffer = NULL; /* set later by XMesaMakeCurrent */
+ c->xm_read_buffer = NULL; /* set later by XMesaMakeCurrent */
+ c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
+ c->display = v->display;
+ c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ if (!_swrast_CreateContext( mesaCtx ) ||
+ !_ac_CreateContext( mesaCtx ) ||
+ !_tnl_CreateContext( mesaCtx ) ||
+ !_swsetup_CreateContext( mesaCtx )) {
+ _mesa_free_context_data(&c->mesa);
+ _mesa_free(c);
+ return NULL;
+ }
+
+ /* tnl setup */
+ tnl = TNL_CONTEXT(mesaCtx);
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ /* swrast setup */
+ xmesa_register_swrast_functions( mesaCtx );
+ _swsetup_Wakeup(mesaCtx);
+
+ return c;
+}
+
+
+
+void XMesaDestroyContext( XMesaContext c )
+{
+ GLcontext *mesaCtx = &c->mesa;
+#ifdef FX
+ if (c->xm_draw_buffer && c->xm_buffer->FXctx)
+ fxMesaDestroyContext(c->xm_draw_buffer->FXctx);
+#endif
+ _swsetup_DestroyContext( mesaCtx );
+ _swrast_DestroyContext( mesaCtx );
+ _tnl_DestroyContext( mesaCtx );
+ _ac_DestroyContext( mesaCtx );
+ _mesa_free_context_data( mesaCtx );
+ _mesa_free( c );
+}
+
+
+
+/*
+ * XXX this isn't a public function! It's a hack for the 3Dfx driver.
+ * Create a new XMesaBuffer from an X window.
+ * Input: v - the XMesaVisual
+ * w - the window
+ * c - the context
+ * Return: new XMesaBuffer or NULL if error
+ */
+XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w,
+ XMesaContext c )
+{
+#ifndef XFree86Server
+ XWindowAttributes attr;
+#endif
+#ifdef FX
+ char *fxEnvVar;
+#endif
+ int client = 0;
+
+ XMesaBuffer b = alloc_xmesa_buffer();
+ if (!b) {
+ return NULL;
+ }
+
+ (void) c;
+
+#ifdef XFree86Server
+ client = CLIENT_ID(((XMesaDrawable)w)->id);
+#endif
+
+ assert(v);
+
+#ifdef XFree86Server
+ if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) {
+#else
+ XGetWindowAttributes( v->display, w, &attr );
+
+ if (GET_VISUAL_DEPTH(v) != attr.depth) {
+#endif
+ _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n");
+ return NULL;
+ }
+
+ b->xm_visual = v;
+ b->type = WINDOW;
+ b->display = v->display;
+#ifdef XFree86Server
+ b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
+#else
+ if (attr.colormap) {
+ b->cmap = attr.colormap;
+ }
+ else {
+ _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
+ /* this is weird, a window w/out a colormap!? */
+ /* OK, let's just allocate a new one and hope for the best */
+ b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
+ }
+#endif
+
+ /* determine back buffer implementation */
+ if (v->mesa_visual.doubleBufferMode) {
+ if (v->ximage_flag) {
+ b->db_state = BACK_XIMAGE;
+ }
+ else {
+ b->db_state = BACK_PIXMAP;
+ }
+ }
+ else {
+ b->db_state = 0;
+ }
+
+ _mesa_initialize_framebuffer(&b->mesa_buffer,
+ &v->mesa_visual,
+ v->mesa_visual.depthBits > 0,
+ v->mesa_visual.stencilBits > 0,
+ v->mesa_visual.accumRedBits > 0,
+ v->mesa_visual.alphaBits > 0 );
+ /* XXX hack */
+ b->mesa_buffer.UseSoftwareAuxBuffers = GL_TRUE;
+
+ if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode,
+ (XMesaDrawable)w, b->cmap )) {
+ free_xmesa_buffer(client, b);
+ return NULL;
+ }
+
+#ifdef FX
+ fxEnvVar = _mesa_getenv("MESA_GLX_FX");
+ if (fxEnvVar) {
+ if (fxEnvVar[0]!='d') {
+ int attribs[100];
+ int numAttribs = 0;
+ int hw;
+ if (v->mesa_visual.depthBits > 0) {
+ attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
+ attribs[numAttribs++] = v->mesa_visual.depthBits;
+ }
+ if (v->mesa_visual.doubleBufferMode) {
+ attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
+ }
+ if (v->mesa_visual.accumRedBits > 0) {
+ attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
+ attribs[numAttribs++] = v->mesa_visual.accumRedBits;
+ }
+ if (v->mesa_visual.stencilBits > 0) {
+ attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
+ attribs[numAttribs++] = v->mesa_visual.stencilBits;
+ }
+ if (v->mesa_visual.alphaBits > 0) {
+ attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
+ attribs[numAttribs++] = v->mesa_visual.alphaBits;
+ }
+ if (1) {
+ attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
+ attribs[numAttribs++] = (int) &(c->mesa);
+ }
+ attribs[numAttribs++] = FXMESA_NONE;
+
+ /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
+ hw = fxMesaSelectCurrentBoard(0);
+ if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
+ b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
+ if ((v->undithered_pf!=PF_Index) && (b->backimage)) {
+ b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
+ if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
+ b->FXwindowHack = GL_TRUE;
+ FX_grSstControl(GR_CONTROL_DEACTIVATE);
+ }
+ else {
+ b->FXwindowHack = GL_FALSE;
+ }
+ }
+ }
+ else {
+ if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
+ b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
+ GR_REFRESH_75Hz, attribs);
+ else
+ b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs);
+ b->FXisHackUsable = GL_FALSE;
+ b->FXwindowHack = GL_FALSE;
+ }
+ /*
+ fprintf(stderr,
+ "voodoo %d, wid %d height %d hack: usable %d active %d\n",
+ hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack);
+ */
+ }
+ }
+ else {
+ _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
+ _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n");
+ _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n");
+ _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
+ }
+#endif
+
+ return b;
+}
+
+
+XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w )
+{
+ return XMesaCreateWindowBuffer2( v, w, NULL );
+}
+
+
+/**
+ * Create a new XMesaBuffer from an X pixmap.
+ *
+ * \param v the XMesaVisual
+ * \param p the pixmap
+ * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR visual for the pixmap
+ * \returns new XMesaBuffer or NULL if error
+ */
+XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v,
+ XMesaPixmap p, XMesaColormap cmap )
+{
+ int client = 0;
+ XMesaBuffer b = alloc_xmesa_buffer();
+ if (!b) {
+ return NULL;
+ }
+
+
+#ifdef XFree86Server
+ client = CLIENT_ID(((XMesaDrawable)p)->id);
+#endif
+
+ assert(v);
+
+ b->xm_visual = v;
+ b->type = PIXMAP;
+ b->display = v->display;
+ b->cmap = cmap;
+
+ /* determine back buffer implementation */
+ if (v->mesa_visual.doubleBufferMode) {
+ if (v->ximage_flag) {
+ b->db_state = BACK_XIMAGE;
+ }
+ else {
+ b->db_state = BACK_PIXMAP;
+ }
+ }
+ else {
+ b->db_state = 0;
+ }
+
+ _mesa_initialize_framebuffer(&b->mesa_buffer,
+ &v->mesa_visual,
+ v->mesa_visual.depthBits > 0,
+ v->mesa_visual.stencilBits > 0,
+ v->mesa_visual.accumRedBits +
+ v->mesa_visual.accumGreenBits +
+ v->mesa_visual.accumBlueBits > 0,
+ v->mesa_visual.alphaBits > 0 );
+
+ if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
+ (XMesaDrawable)p, cmap)) {
+ free_xmesa_buffer(client, b);
+ return NULL;
+ }
+
+ return b;
+}
+
+
+
+XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap,
+ unsigned int width, unsigned int height )
+{
+#ifdef XFree86Server
+ return 0;
+#else
+ int client = 0;
+ XMesaWindow root;
+ XMesaDrawable drawable; /* X Pixmap Drawable */
+ XMesaBuffer b = alloc_xmesa_buffer();
+ if (!b) {
+ return NULL;
+ }
+
+ b->xm_visual = v;
+ b->type = PBUFFER;
+ b->display = v->display;
+ b->cmap = cmap;
+
+ /* allocate pixmap for front buffer */
+ root = RootWindow( v->display, v->visinfo->screen );
+ drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth );
+
+ /* determine back buffer implementation */
+ if (v->mesa_visual.doubleBufferMode) {
+ if (v->ximage_flag) {
+ b->db_state = BACK_XIMAGE;
+ }
+ else {
+ b->db_state = BACK_PIXMAP;
+ }
+ }
+ else {
+ b->db_state = 0;
+ }
+
+ _mesa_initialize_framebuffer(&b->mesa_buffer,
+ &v->mesa_visual,
+ v->mesa_visual.depthBits > 0,
+ v->mesa_visual.stencilBits > 0,
+ v->mesa_visual.accumRedBits +
+ v->mesa_visual.accumGreenBits +
+ v->mesa_visual.accumBlueBits > 0,
+ v->mesa_visual.alphaBits > 0 );
+
+ if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode,
+ drawable, cmap)) {
+ free_xmesa_buffer(client, b);
+ return NULL;
+ }
+
+ return b;
+#endif
+}
+
+
+
+/*
+ * Deallocate an XMesaBuffer structure and all related info.
+ */
+void XMesaDestroyBuffer( XMesaBuffer b )
+{
+ int client = 0;
+
+#ifdef XFree86Server
+ if (b->frontbuffer)
+ client = CLIENT_ID(b->frontbuffer->id);
+#endif
+
+ if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc );
+ if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc );
+ if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc );
+
+ if (b->backimage) {
+#if defined(USE_XSHM) && !defined(XFree86Server)
+ if (b->shm) {
+ XShmDetach( b->xm_visual->display, &b->shminfo );
+ XDestroyImage( b->backimage );
+ shmdt( b->shminfo.shmaddr );
+ }
+ else
+#endif
+ XMesaDestroyImage( b->backimage );
+ }
+ if (b->backpixmap) {
+ XMesaFreePixmap( b->xm_visual->display, b->backpixmap );
+ if (b->xm_visual->hpcr_clear_flag) {
+ XMesaFreePixmap( b->xm_visual->display,
+ b->xm_visual->hpcr_clear_pixmap );
+ XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage );
+ }
+ }
+ if (b->rowimage) {
+ FREE( b->rowimage->data );
+ b->rowimage->data = NULL;
+ XMesaDestroyImage( b->rowimage );
+ }
+
+ free_xmesa_buffer(client, b);
+}
+
+
+
+/*
+ * Bind buffer b to context c and make c the current rendering context.
+ */
+GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
+{
+ return XMesaMakeCurrent2( c, b, b );
+}
+
+
+/*
+ * Bind buffer b to context c and make c the current rendering context.
+ */
+GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
+ XMesaBuffer readBuffer )
+{
+ if (c) {
+ if (!drawBuffer || !readBuffer)
+ return GL_FALSE; /* must specify buffers! */
+
+#ifdef FX
+ if (drawBuffer->FXctx) {
+ fxMesaMakeCurrent(drawBuffer->FXctx);
+
+ c->xm_draw_buffer = drawBuffer;
+ c->xm_read_buffer = readBuffer;
+ c->xm_buffer = drawBuffer;
+
+ return GL_TRUE;
+ }
+#endif
+ if (&(c->mesa) == _mesa_get_current_context()
+ && c->xm_draw_buffer == drawBuffer
+ && c->xm_read_buffer == readBuffer
+ && c->xm_draw_buffer->wasCurrent) {
+ /* same context and buffer, do nothing */
+ return GL_TRUE;
+ }
+
+ c->xm_draw_buffer = drawBuffer;
+ c->xm_read_buffer = readBuffer;
+ c->xm_buffer = drawBuffer;
+
+ _mesa_make_current2(&(c->mesa),
+ &drawBuffer->mesa_buffer,
+ &readBuffer->mesa_buffer);
+
+ if (c->mesa.Viewport.Width == 0) {
+ /* initialize viewport to window size */
+ _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height );
+ c->mesa.Scissor.Width = drawBuffer->width;
+ c->mesa.Scissor.Height = drawBuffer->height;
+ }
+
+ if (c->xm_visual->mesa_visual.rgbMode) {
+ /*
+ * Must recompute and set these pixel values because colormap
+ * can be different for different windows.
+ */
+ c->clearpixel = xmesa_color_to_pixel( c,
+ c->clearcolor[0],
+ c->clearcolor[1],
+ c->clearcolor[2],
+ c->clearcolor[3],
+ c->xm_visual->undithered_pf);
+ XMesaSetForeground(c->display, c->xm_draw_buffer->cleargc, c->clearpixel);
+ }
+
+ /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
+ c->xm_draw_buffer->wasCurrent = GL_TRUE;
+ }
+ else {
+ /* Detach */
+ _mesa_make_current2( NULL, NULL, NULL );
+ }
+ return GL_TRUE;
+}
+
+
+/*
+ * Unbind the context c from its buffer.
+ */
+GLboolean XMesaUnbindContext( XMesaContext c )
+{
+ /* A no-op for XFree86 integration purposes */
+ return GL_TRUE;
+}
+
+
+XMesaContext XMesaGetCurrentContext( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ return xmesa;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+XMesaBuffer XMesaGetCurrentBuffer( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ return xmesa->xm_draw_buffer;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+/* New in Mesa 3.1 */
+XMesaBuffer XMesaGetCurrentReadBuffer( void )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ if (ctx) {
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ return xmesa->xm_read_buffer;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+GLboolean XMesaForceCurrent(XMesaContext c)
+{
+ if (c) {
+ if (&(c->mesa) != _mesa_get_current_context()) {
+ _mesa_make_current(&(c->mesa), &c->xm_draw_buffer->mesa_buffer);
+ }
+ }
+ else {
+ _mesa_make_current(NULL, NULL);
+ }
+ return GL_TRUE;
+}
+
+
+GLboolean XMesaLoseCurrent(XMesaContext c)
+{
+ (void) c;
+ _mesa_make_current(NULL, NULL);
+ return GL_TRUE;
+}
+
+
+/*
+ * Switch 3Dfx support hack between window and full-screen mode.
+ */
+GLboolean XMesaSetFXmode( GLint mode )
+{
+#ifdef FX
+ const char *fx = _mesa_getenv("MESA_GLX_FX");
+ if (fx && fx[0] != 'd') {
+ GET_CURRENT_CONTEXT(ctx);
+ GrHwConfiguration hw;
+ if (!FX_grSstQueryHardware(&hw)) {
+ /*fprintf(stderr, "!grSstQueryHardware\n");*/
+ return GL_FALSE;
+ }
+ if (hw.num_sst < 1) {
+ /*fprintf(stderr, "hw.num_sst < 1\n");*/
+ return GL_FALSE;
+ }
+ if (ctx) {
+ /* [dBorca] Hack alert:
+ * oh, this is sooo wrong: ctx above is
+ * really an fxMesaContext, not an XMesaContext
+ */
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (mode == XMESA_FX_WINDOW) {
+ if (xmesa->xm_draw_buffer->FXisHackUsable) {
+ FX_grSstControl(GR_CONTROL_DEACTIVATE);
+ xmesa->xm_draw_buffer->FXwindowHack = GL_TRUE;
+ return GL_TRUE;
+ }
+ }
+ else if (mode == XMESA_FX_FULLSCREEN) {
+ FX_grSstControl(GR_CONTROL_ACTIVATE);
+ xmesa->xm_draw_buffer->FXwindowHack = GL_FALSE;
+ return GL_TRUE;
+ }
+ else {
+ /* Error: Bad mode value */
+ }
+ }
+ }
+ /*fprintf(stderr, "fallthrough\n");*/
+#else
+ (void) mode;
+#endif
+ return GL_FALSE;
+}
+
+
+
+#ifdef FX
+/*
+ * Read image from VooDoo frame buffer into X/Mesa's back XImage.
+ */
+static void FXgetImage( XMesaBuffer b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ static unsigned short pixbuf[MAX_WIDTH];
+ GLuint x, y;
+ int xpos, ypos;
+ XMesaWindow root;
+ unsigned int bw, depth, width, height;
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+#ifdef XFree86Server
+ x = b->frontbuffer->x;
+ y = b->frontbuffer->y;
+ width = b->frontbuffer->width;
+ height = b->frontbuffer->height;
+ depth = b->frontbuffer->depth;
+#else
+ XGetGeometry( b->xm_visual->display, b->frontbuffer,
+ &root, &xpos, &ypos, &width, &height, &bw, &depth);
+#endif
+ if (b->width != width || b->height != height) {
+ b->width = MIN2((int)width, b->FXctx->width);
+ b->height = MIN2((int)height, b->FXctx->height);
+ if (b->width & 1)
+ b->width--; /* prevent odd width */
+ xmesa_alloc_back_buffer( b );
+ }
+
+ /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
+ /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
+ if (b->xm_visual->undithered_pf==PF_5R6G5B) {
+ /* Special case: 16bpp RGB */
+ grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */
+ 0, b->FXctx->height - b->height, /*pos*/
+ b->width, b->height, /* size */
+ b->width * sizeof(GLushort), /* stride */
+ b->backimage->data); /* dest buffer */
+ }
+ else if (b->xm_visual->dithered_pf==PF_Dither
+ && GET_VISUAL_DEPTH(b->xm_visual)==8) {
+ /* Special case: 8bpp RGB */
+ for (y=0;y<b->height;y++) {
+ GLubyte *ptr = (GLubyte*) b->backimage->data
+ + b->backimage->bytes_per_line * y;
+ XDITHER_SETUP(y);
+
+ /* read row from 3Dfx frame buffer */
+ grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
+ 0, b->FXctx->height-(b->height-y),
+ b->width, 1,
+ 0,
+ pixbuf );
+
+ /* write to XImage back buffer */
+ for (x=0;x<b->width;x++) {
+ GLubyte r = (pixbuf[x] & 0xf800) >> 8;
+ GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
+ GLubyte b = (pixbuf[x] & 0x001f) << 3;
+ *ptr++ = XDITHER( x, r, g, b);
+ }
+ }
+ }
+ else {
+ /* General case: slow! */
+ for (y=0;y<b->height;y++) {
+ /* read row from 3Dfx frame buffer */
+ grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
+ 0, b->FXctx->height-(b->height-y),
+ b->width, 1,
+ 0,
+ pixbuf );
+
+ /* write to XImage back buffer */
+ for (x=0;x<b->width;x++) {
+ XMesaPutPixel(b->backimage,x,y,
+ xmesa_color_to_pixel(xmesa,
+ (pixbuf[x] & 0xf800) >> 8,
+ (pixbuf[x] & 0x07e0) >> 3,
+ (pixbuf[x] & 0x001f) << 3,
+ 0xff,
+ b->xm_visual->undithered_pf));
+ }
+ }
+ }
+ /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
+}
+#endif
+
+
+/*
+ * Copy the back buffer to the front buffer. If there's no back buffer
+ * this is a no-op.
+ */
+void XMesaSwapBuffers( XMesaBuffer b )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
+ _mesa_notifySwapBuffers(ctx);
+
+ if (b->db_state) {
+#ifdef FX
+ if (b->FXctx) {
+ fxMesaSwapBuffers();
+
+ if (b->FXwindowHack)
+ FXgetImage(b);
+ else
+ return;
+ }
+#endif
+ if (b->backimage) {
+ /* Copy Ximage from host's memory to server's window */
+#if defined(USE_XSHM) && !defined(XFree86Server)
+ if (b->shm) {
+ /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+ XShmPutImage( b->xm_visual->display, b->frontbuffer,
+ b->swapgc,
+ b->backimage, 0, 0,
+ 0, 0, b->width, b->height, False );
+ /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+ }
+ else
+#endif
+ {
+ /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+ XMesaPutImage( b->xm_visual->display, b->frontbuffer,
+ b->swapgc,
+ b->backimage, 0, 0,
+ 0, 0, b->width, b->height );
+ /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+ }
+ }
+ else {
+ /* Copy pixmap to window on server */
+ /*_glthread_LOCK_MUTEX(_xmesa_lock);*/
+ XMesaCopyArea( b->xm_visual->display,
+ b->backpixmap, /* source drawable */
+ b->frontbuffer, /* dest. drawable */
+ b->swapgc,
+ 0, 0, b->width, b->height, /* source region */
+ 0, 0 /* dest region */
+ );
+ /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/
+ }
+ }
+#if !defined(XFree86Server)
+ XSync( b->xm_visual->display, False );
+#endif
+}
+
+
+
+/*
+ * Copy sub-region of back buffer to front buffer
+ */
+void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+ if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
+ _mesa_notifySwapBuffers(ctx);
+
+ if (b->db_state) {
+ int yTop = b->height - y - height;
+#ifdef FX
+ if (b->FXctx) {
+ fxMesaSwapBuffers();
+ if (b->FXwindowHack)
+ FXgetImage(b);
+ else
+ return;
+ }
+#endif
+ if (b->backimage) {
+ /* Copy Ximage from host's memory to server's window */
+#if defined(USE_XSHM) && !defined(XFree86Server)
+ if (b->shm) {
+ /* XXX assuming width and height aren't too large! */
+ XShmPutImage( b->xm_visual->display, b->frontbuffer,
+ b->swapgc,
+ b->backimage, x, yTop,
+ x, yTop, width, height, False );
+ /* wait for finished event??? */
+ }
+ else
+#endif
+ {
+ /* XXX assuming width and height aren't too large! */
+ XMesaPutImage( b->xm_visual->display, b->frontbuffer,
+ b->swapgc,
+ b->backimage, x, yTop,
+ x, yTop, width, height );
+ }
+ }
+ else {
+ /* Copy pixmap to window on server */
+ XMesaCopyArea( b->xm_visual->display,
+ b->backpixmap, /* source drawable */
+ b->frontbuffer, /* dest. drawable */
+ b->swapgc,
+ x, yTop, width, height, /* source region */
+ x, yTop /* dest region */
+ );
+ }
+ }
+}
+
+
+/*
+ * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function
+ * is a way to get "under the hood" of X/Mesa so one can manipulate the
+ * back buffer directly.
+ * Output: pixmap - pointer to back buffer's Pixmap, or 0
+ * ximage - pointer to back buffer's XImage, or NULL
+ * Return: GL_TRUE = context is double buffered
+ * GL_FALSE = context is single buffered
+ */
+GLboolean XMesaGetBackBuffer( XMesaBuffer b,
+ XMesaPixmap *pixmap,
+ XMesaImage **ximage )
+{
+ if (b->db_state) {
+ if (pixmap) *pixmap = b->backpixmap;
+ if (ximage) *ximage = b->backimage;
+ return GL_TRUE;
+ }
+ else {
+ *pixmap = 0;
+ *ximage = NULL;
+ return GL_FALSE;
+ }
+}
+
+
+/*
+ * Return the depth buffer associated with an XMesaBuffer.
+ * Input: b - the XMesa buffer handle
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
+ GLint *bytesPerValue, void **buffer )
+{
+ if (!b->mesa_buffer.DepthBuffer) {
+ *width = 0;
+ *height = 0;
+ *bytesPerValue = 0;
+ *buffer = 0;
+ return GL_FALSE;
+ }
+ else {
+ *width = b->mesa_buffer.Width;
+ *height = b->mesa_buffer.Height;
+ *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
+ ? sizeof(GLushort) : sizeof(GLuint);
+ *buffer = b->mesa_buffer.DepthBuffer;
+ return GL_TRUE;
+ }
+}
+
+
+void XMesaFlush( XMesaContext c )
+{
+ if (c && c->xm_visual) {
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ XSync( c->xm_visual->display, False );
+#endif
+ }
+}
+
+
+
+const char *XMesaGetString( XMesaContext c, int name )
+{
+ (void) c;
+ if (name==XMESA_VERSION) {
+ return "5.0";
+ }
+ else if (name==XMESA_EXTENSIONS) {
+ return "";
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+
+XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
+{
+ XMesaBuffer b;
+ for (b=XMesaBufferList; b; b=b->Next) {
+ if (b->frontbuffer==d && b->display==dpy) {
+ return b;
+ }
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Look for XMesaBuffers whose X window has been destroyed.
+ * Deallocate any such XMesaBuffers.
+ */
+void XMesaGarbageCollect( void )
+{
+ XMesaBuffer b, next;
+ for (b=XMesaBufferList; b; b=next) {
+ next = b->Next;
+ if (b->display && b->frontbuffer && b->type == WINDOW) {
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ XSync(b->display, False);
+ if (!window_exists( b->display, b->frontbuffer )) {
+ /* found a dead window, free the ancillary info */
+ XMesaDestroyBuffer( b );
+ }
+#endif
+ }
+ }
+}
+
+
+void XMesaReset( void )
+{
+ while (XMesaBufferList)
+ XMesaDestroyBuffer(XMesaBufferList);
+
+ XMesaBufferList = NULL;
+}
+
+
+unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
+ GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha )
+{
+ GLint r = (GLint) (red * 255.0F);
+ GLint g = (GLint) (green * 255.0F);
+ GLint b = (GLint) (blue * 255.0F);
+ GLint a = (GLint) (alpha * 255.0F);
+
+ switch (xmesa->pixelformat) {
+ case PF_Index:
+ return 0;
+ case PF_Truecolor:
+ {
+ unsigned long p;
+ PACK_TRUECOLOR( p, r, g, b );
+ return p;
+ }
+ case PF_8A8B8G8R:
+ return PACK_8A8B8G8R( r, g, b, a );
+ case PF_8A8R8G8B:
+ return PACK_8A8R8G8B( r, g, b, a );
+ case PF_8R8G8B:
+ return PACK_8R8G8B( r, g, b );
+ case PF_5R6G5B:
+ return PACK_5R6G5B( r, g, b );
+ case PF_Dither:
+ {
+ DITHER_SETUP;
+ return DITHER( x, y, r, g, b );
+ }
+ case PF_1Bit:
+ /* 382 = (3*255)/2 */
+ return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip;
+ case PF_HPCR:
+ return DITHER_HPCR(x, y, r, g, b);
+ case PF_Lookup:
+ {
+ LOOKUP_SETUP;
+ return LOOKUP( r, g, b );
+ }
+ case PF_Grayscale:
+ return GRAY_RGB( r, g, b );
+ case PF_Dither_5R6G5B:
+ /* fall through */
+ case PF_Dither_True:
+ {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, r, g, b);
+ return p;
+ }
+ default:
+ _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
+ }
+ return 0;
+}
+
+
+/*
+ * This is typically called when the window size changes and we need
+ * to reallocate the buffer's back/depth/stencil/accum buffers.
+ */
+void XMesaResizeBuffers( XMesaBuffer b )
+{
+ xmesa_resize_buffers( &(b->mesa_buffer) );
+
+}
+
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
new file mode 100644
index 0000000..ebd75cd
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -0,0 +1,1220 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+#include "glxheader.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "drawpix.h"
+#include "extensions.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "xmesaP.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast/s_auxbuffer.h"
+#include "swrast/s_context.h"
+#include "swrast/s_drawpix.h"
+#include "swrast/s_alphabuf.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#ifdef XFree86Server
+#include <GL/glxtokens.h>
+#endif
+
+
+
+/*
+ * Dithering kernels and lookup tables.
+ */
+
+const int xmesa_kernel8[DITH_DY * DITH_DX] = {
+ 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC,
+ 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC,
+ 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC,
+ 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC,
+};
+
+const short xmesa_HPCR_DRGB[3][2][16] = {
+ {
+ { 16, -4, 1,-11, 14, -6, 3, -9, 15, -5, 2,-10, 13, -7, 4, -8},
+ {-15, 5, 0, 12,-13, 7, -2, 10,-14, 6, -1, 11,-12, 8, -3, 9}
+ },
+ {
+ {-11, 15, -7, 3, -8, 14, -4, 2,-10, 16, -6, 4, -9, 13, -5, 1},
+ { 12,-14, 8, -2, 9,-13, 5, -1, 11,-15, 7, -3, 10,-12, 6, 0}
+ },
+ {
+ { 6,-18, 26,-14, 2,-22, 30,-10, 8,-16, 28,-12, 4,-20, 32, -8},
+ { -4, 20,-24, 16, 0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
+ }
+};
+
+const int xmesa_kernel1[16] = {
+ 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */
+ 6*47, 2*47, 14*47, 8*47,
+ 10*47, 1*47, 5*47, 11*47,
+ 7*47, 13*47, 3*47, 15*47
+};
+
+
+/*
+ * Return the size (width, height) of the X window for the given GLframebuffer.
+ * Output: width - width of buffer in pixels.
+ * height - height of buffer in pixels.
+ */
+static void
+get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+ /* We can do this cast because the first field in the XMesaBuffer
+ * struct is a GLframebuffer struct. If this weren't true, we'd
+ * need a pointer from the GLframebuffer to the XMesaBuffer.
+ */
+ const XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
+ unsigned int winwidth, winheight;
+#ifdef XFree86Server
+ /* XFree86 GLX renderer */
+ winwidth = MIN2(xmBuffer->frontbuffer->width, MAX_WIDTH);
+ winheight = MIN2(xmBuffer->frontbuffer->height, MAX_HEIGHT);
+#else
+ Window root;
+ int winx, winy;
+ unsigned int bw, d;
+
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XSync(xmBuffer->xm_visual->display, 0); /* added for Chromium */
+ XGetGeometry( xmBuffer->xm_visual->display, xmBuffer->frontbuffer, &root,
+ &winx, &winy, &winwidth, &winheight, &bw, &d );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+#endif
+
+ *width = winwidth;
+ *height = winheight;
+}
+
+
+static void
+finish_or_flush( GLcontext *ctx )
+{
+#ifdef XFree86Server
+ /* NOT_NEEDED */
+#else
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (xmesa) {
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XSync( xmesa->display, False );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+ }
+#endif
+}
+
+
+
+/*
+ * This chooses the color buffer for reading and writing spans, points,
+ * lines, and triangles.
+ */
+void
+xmesa_set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
+{
+ /* We can make this cast since the XMesaBuffer wraps GLframebuffer.
+ * GLframebuffer is the first member in a XMesaBuffer struct.
+ */
+ XMesaBuffer target = (XMesaBuffer) buffer;
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+ /* This assignment tells the span/point/line/triangle functions
+ * which XMesaBuffer to use.
+ */
+ xmesa->xm_buffer = target;
+
+ /*
+ * Now determine front vs back color buffer.
+ */
+ if (bufferBit == DD_FRONT_LEFT_BIT) {
+ target->buffer = target->frontbuffer;
+ xmesa_update_span_funcs(ctx);
+ }
+ else if (bufferBit == DD_BACK_LEFT_BIT) {
+ ASSERT(target->db_state);
+ if (target->backpixmap) {
+ /* back buffer is a pixmap */
+ target->buffer = (XMesaDrawable) target->backpixmap;
+ }
+ else if (target->backimage) {
+ /* back buffer is an XImage */
+ target->buffer = None;
+ }
+ else {
+ /* No back buffer!!!! Must be out of memory, use front buffer */
+ target->buffer = target->frontbuffer;
+ }
+ xmesa_update_span_funcs(ctx);
+ }
+ else if (bufferBit & (DD_AUX0_BIT | DD_AUX1_BIT | DD_AUX2_BIT | DD_AUX3_BIT)) {
+ _swrast_use_aux_buffer(ctx, buffer, bufferBit);
+ }
+ else {
+ _mesa_problem(ctx, "invalid buffer 0x%x in set_buffer() in xm_dd.c");
+ return;
+ }
+}
+
+
+
+static void
+clear_index( GLcontext *ctx, GLuint index )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ xmesa->clearpixel = (unsigned long) index;
+ XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
+ (unsigned long) index );
+}
+
+
+static void
+clear_color( GLcontext *ctx, const GLfloat color[4] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+ xmesa->clearpixel = xmesa_color_to_pixel( xmesa,
+ xmesa->clearcolor[0],
+ xmesa->clearcolor[1],
+ xmesa->clearcolor[2],
+ xmesa->clearcolor[3],
+ xmesa->xm_visual->undithered_pf );
+ _glthread_LOCK_MUTEX(_xmesa_lock);
+ XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc,
+ xmesa->clearpixel );
+ _glthread_UNLOCK_MUTEX(_xmesa_lock);
+}
+
+
+
+/* Set index mask ala glIndexMask */
+static void
+index_mask( GLcontext *ctx, GLuint mask )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (xmesa->xm_draw_buffer->buffer != XIMAGE) {
+ unsigned long m;
+ if (mask==0xffffffff) {
+ m = ((unsigned long)~0L);
+ }
+ else {
+ m = (unsigned long) mask;
+ }
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m );
+ }
+}
+
+
+/* Implements glColorMask() */
+static void
+color_mask(GLcontext *ctx,
+ GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const int xclass = xmesa->xm_visual->mesa_visual.visualType;
+ (void) amask;
+
+ if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
+ unsigned long m;
+ if (rmask && gmask && bmask) {
+ m = ((unsigned long)~0L);
+ }
+ else {
+ m = 0;
+ if (rmask) m |= GET_REDMASK(xmesa->xm_visual);
+ if (gmask) m |= GET_GREENMASK(xmesa->xm_visual);
+ if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual);
+ }
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m );
+ XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m );
+ }
+}
+
+
+
+/**********************************************************************/
+/*** glClear implementations ***/
+/**********************************************************************/
+
+
+static void
+clear_front_pixmap( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (all) {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
+ xmesa->xm_draw_buffer->cleargc,
+ 0, 0,
+ xmesa->xm_draw_buffer->width+1,
+ xmesa->xm_draw_buffer->height+1 );
+ }
+ else {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer,
+ xmesa->xm_draw_buffer->cleargc,
+ x, xmesa->xm_draw_buffer->height - y - height,
+ width, height );
+ }
+}
+
+
+static void
+clear_back_pixmap( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (all) {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
+ xmesa->xm_draw_buffer->cleargc,
+ 0, 0,
+ xmesa->xm_draw_buffer->width+1,
+ xmesa->xm_draw_buffer->height+1 );
+ }
+ else {
+ XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap,
+ xmesa->xm_draw_buffer->cleargc,
+ x, xmesa->xm_draw_buffer->height - y - height,
+ width, height );
+ }
+}
+
+
+static void
+clear_8bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (all) {
+ size_t n = xmesa->xm_draw_buffer->backimage->bytes_per_line
+ * xmesa->xm_draw_buffer->backimage->height;
+ MEMSET( xmesa->xm_draw_buffer->backimage->data, xmesa->clearpixel, n );
+ }
+ else {
+ GLint i;
+ for (i=0;i<height;i++) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, y+i );
+ MEMSET( ptr, xmesa->clearpixel, width );
+ }
+ }
+}
+
+
+static void
+clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (all) {
+ GLint i, c16 = (xmesa->xm_draw_buffer->backimage->bytes_per_line>>4)<<4;
+ GLubyte *ptr = (GLubyte *)xmesa->xm_draw_buffer->backimage->data;
+ for (i=0; i<xmesa->xm_draw_buffer->backimage->height; i++) {
+ GLint j;
+ GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+ if (i&1) {
+ sptr += 16;
+ }
+ for (j=0; j<c16; j+=16) {
+ ptr[0] = sptr[0];
+ ptr[1] = sptr[1];
+ ptr[2] = sptr[2];
+ ptr[3] = sptr[3];
+ ptr[4] = sptr[4];
+ ptr[5] = sptr[5];
+ ptr[6] = sptr[6];
+ ptr[7] = sptr[7];
+ ptr[8] = sptr[8];
+ ptr[9] = sptr[9];
+ ptr[10] = sptr[10];
+ ptr[11] = sptr[11];
+ ptr[12] = sptr[12];
+ ptr[13] = sptr[13];
+ ptr[14] = sptr[14];
+ ptr[15] = sptr[15];
+ ptr += 16;
+ }
+ for (; j<xmesa->xm_draw_buffer->backimage->bytes_per_line; j++) {
+ *ptr = sptr[j&15];
+ ptr++;
+ }
+ }
+ }
+ else {
+ GLint i;
+ for (i=y; i<y+height; i++) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_draw_buffer, x, i );
+ int j;
+ GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+ if (i&1) {
+ sptr += 16;
+ }
+ for (j=x; j<x+width; j++) {
+ *ptr = sptr[j&15];
+ ptr++;
+ }
+ }
+ }
+}
+
+
+static void
+clear_16bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint pixel = (GLuint) xmesa->clearpixel;
+ if (xmesa->swapbytes) {
+ pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
+ }
+ if (all) {
+ register GLuint n;
+ register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
+ if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
+ /* low and high bytes are equal so use memset() */
+ n = xmesa->xm_draw_buffer->backimage->bytes_per_line
+ * xmesa->xm_draw_buffer->height;
+ MEMSET( ptr4, pixel & 0xff, n );
+ }
+ else {
+ pixel = pixel | (pixel<<16);
+ n = xmesa->xm_draw_buffer->backimage->bytes_per_line
+ * xmesa->xm_draw_buffer->height / 4;
+ do {
+ *ptr4++ = pixel;
+ n--;
+ } while (n!=0);
+
+ if ((xmesa->xm_draw_buffer->backimage->bytes_per_line *
+ xmesa->xm_draw_buffer->height) & 0x2)
+ *(GLushort *)ptr4 = pixel & 0xffff;
+ }
+ }
+ else {
+ register int i, j;
+ for (j=0;j<height;j++) {
+ register GLushort *ptr2 = PIXELADDR2( xmesa->xm_draw_buffer, x, y+j );
+ for (i=0;i<width;i++) {
+ *ptr2++ = pixel;
+ }
+ }
+ }
+}
+
+
+/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
+static void
+clear_24bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = xmesa->clearcolor[0];
+ const GLubyte g = xmesa->clearcolor[1];
+ const GLubyte b = xmesa->clearcolor[2];
+#if 0 /* See below */
+ register GLuint clearPixel;
+ if (xmesa->swapbytes) {
+ clearPixel = (b << 16) | (g << 8) | r;
+ }
+ else {
+ clearPixel = (r << 16) | (g << 8) | b;
+ }
+#endif
+
+ if (all) {
+ if (r==g && g==b) {
+ /* same value for all three components (gray) */
+ const GLint w3 = xmesa->xm_draw_buffer->width * 3;
+ const GLint h = xmesa->xm_draw_buffer->height;
+ GLint i;
+ for (i = 0; i < h; i++) {
+ bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
+ MEMSET(ptr3, r, w3);
+ }
+ }
+ else {
+ /* the usual case */
+ const GLint w = xmesa->xm_draw_buffer->width;
+ const GLint h = xmesa->xm_draw_buffer->height;
+ GLint i, j;
+ for (i = 0; i < h; i++) {
+ bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i);
+ for (j = 0; j < w; j++) {
+ ptr3->r = r;
+ ptr3->g = g;
+ ptr3->b = b;
+ ptr3++;
+ }
+ }
+#if 0 /* this code doesn't work for all window widths */
+ register GLuint *ptr4 = (GLuint *) ptr3;
+ register GLuint px;
+ GLuint pixel4[3];
+ register GLuint *p = pixel4;
+ pixel4[0] = clearPixel | (clearPixel << 24);
+ pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
+ pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
+ switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
+ case 0:
+ break;
+ case 1:
+ px = *ptr4 & 0x00ffffff;
+ px |= pixel4[0] & 0xff000000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffff0000;
+ px |= pixel4[2] & 0x0000ffff;
+ *ptr4 = px;
+ if (0 == --n)
+ break;
+ case 2:
+ px = *ptr4 & 0x0000fffff;
+ px |= pixel4[1] & 0xffff0000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffffff00;
+ px |= pixel4[2] & 0x000000ff;
+ *ptr4 = px;
+ if (0 == --n)
+ break;
+ case 3:
+ px = *ptr4 & 0x000000ff;
+ px |= pixel4[2] & 0xffffff00;
+ *ptr4++ = px;
+ --n;
+ break;
+ }
+ while (n > 3) {
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ n -= 4;
+ }
+ switch (n) {
+ case 3:
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffffff00;
+ px |= clearPixel & 0xff;
+ *ptr4 = px;
+ break;
+ case 2:
+ p = pixel4;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffff0000;
+ px |= *p & 0xffff;
+ *ptr4 = px;
+ break;
+ case 1:
+ px = *ptr4 & 0xff000000;
+ px |= *p & 0xffffff;
+ *ptr4 = px;
+ break;
+ case 0:
+ break;
+ }
+#endif
+ }
+ }
+ else {
+ /* only clear subrect of color buffer */
+ if (r==g && g==b) {
+ /* same value for all three components (gray) */
+ GLint j;
+ for (j=0;j<height;j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
+ MEMSET(ptr3, r, 3 * width);
+ }
+ }
+ else {
+ /* non-gray clear color */
+ GLint i, j;
+ for (j = 0; j < height; j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
+ for (i = 0; i < width; i++) {
+ ptr3->r = r;
+ ptr3->g = g;
+ ptr3->b = b;
+ ptr3++;
+ }
+ }
+#if 0 /* this code might not always (seems ptr3 always == ptr4) */
+ GLint j;
+ GLuint pixel4[3];
+ pixel4[0] = clearPixel | (clearPixel << 24);
+ pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
+ pixel4[2] = (clearPixel << 8) | (clearPixel >> 16);
+ for (j=0;j<height;j++) {
+ bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j );
+ register GLuint *ptr4 = (GLuint *)ptr3;
+ register GLuint *p, px;
+ GLuint w = width;
+ switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
+ case 0:
+ break;
+ case 1:
+ px = *ptr4 & 0x00ffffff;
+ px |= pixel4[0] & 0xff000000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffff0000;
+ px |= pixel4[2] & 0x0000ffff;
+ *ptr4 = px;
+ if (0 == --w)
+ break;
+ case 2:
+ px = *ptr4 & 0x0000fffff;
+ px |= pixel4[1] & 0xffff0000;
+ *ptr4++ = px;
+ px = *ptr4 & 0xffffff00;
+ px |= pixel4[2] & 0x000000ff;
+ *ptr4 = px;
+ if (0 == --w)
+ break;
+ case 3:
+ px = *ptr4 & 0x000000ff;
+ px |= pixel4[2] & 0xffffff00;
+ *ptr4++ = px;
+ --w;
+ break;
+ }
+ while (w > 3){
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ w -= 4;
+ }
+ switch (w) {
+ case 3:
+ p = pixel4;
+ *ptr4++ = *p++;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffffff00;
+ px |= *p & 0xff;
+ *ptr4 = px;
+ break;
+ case 2:
+ p = pixel4;
+ *ptr4++ = *p++;
+ px = *ptr4 & 0xffff0000;
+ px |= *p & 0xffff;
+ *ptr4 = px;
+ break;
+ case 1:
+ px = *ptr4 & 0xff000000;
+ px |= pixel4[0] & 0xffffff;
+ *ptr4 = px;
+ break;
+ case 0:
+ break;
+ }
+ }
+#endif
+ }
+ }
+}
+
+
+static void
+clear_32bit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint pixel = (GLuint) xmesa->clearpixel;
+ if (xmesa->swapbytes) {
+ pixel = ((pixel >> 24) & 0x000000ff)
+ | ((pixel >> 8) & 0x0000ff00)
+ | ((pixel << 8) & 0x00ff0000)
+ | ((pixel << 24) & 0xff000000);
+ }
+ if (all) {
+ register GLint n = xmesa->xm_draw_buffer->width * xmesa->xm_draw_buffer->height;
+ register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data;
+ if (pixel==0) {
+ MEMSET( ptr4, pixel, 4*n );
+ }
+ else {
+ do {
+ *ptr4++ = pixel;
+ n--;
+ } while (n!=0);
+ }
+ }
+ else {
+ register int i, j;
+ for (j=0;j<height;j++) {
+ register GLuint *ptr4 = PIXELADDR4( xmesa->xm_draw_buffer, x, y+j );
+ for (i=0;i<width;i++) {
+ *ptr4++ = pixel;
+ }
+ }
+ }
+}
+
+
+static void
+clear_nbit_ximage( GLcontext *ctx, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_draw_buffer->backimage;
+ if (all) {
+ register int i, j;
+ width = xmesa->xm_draw_buffer->width;
+ height = xmesa->xm_draw_buffer->height;
+ for (j=0;j<height;j++) {
+ for (i=0;i<width;i++) {
+ XMesaPutPixel( img, i, j, xmesa->clearpixel );
+ }
+ }
+ }
+ else {
+ /* TODO: optimize this */
+ register int i, j;
+ y = FLIP(xmesa->xm_draw_buffer, y);
+ for (j=0;j<height;j++) {
+ for (i=0;i<width;i++) {
+ XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
+ }
+ }
+ }
+}
+
+
+
+static void
+clear_buffers( GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) &&
+ xmesa->xm_draw_buffer->mesa_buffer.UseSoftwareAlphaBuffers &&
+ ctx->Color.ColorMask[ACOMP]) {
+ _swrast_clear_alpha_buffers(ctx);
+ }
+
+ /* we can't handle color or index masking */
+ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+ if (mask & DD_FRONT_LEFT_BIT) {
+ ASSERT(xmesa->xm_draw_buffer->front_clear_func);
+ (*xmesa->xm_draw_buffer->front_clear_func)( ctx, all, x, y, width, height );
+ mask &= ~DD_FRONT_LEFT_BIT;
+ }
+ if (mask & DD_BACK_LEFT_BIT) {
+ ASSERT(xmesa->xm_draw_buffer->back_clear_func);
+ (*xmesa->xm_draw_buffer->back_clear_func)( ctx, all, x, y, width, height );
+ mask &= ~DD_BACK_LEFT_BIT;
+ }
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+
+/*
+ * When we detect that the user has resized the window this function will
+ * get called. Here we'll reallocate the back buffer, depth buffer,
+ * stencil buffer etc. to match the new window size.
+ */
+void
+xmesa_resize_buffers( GLframebuffer *buffer )
+{
+ int height = (int) buffer->Height;
+ /* We can do this cast because the first field in the XMesaBuffer
+ * struct is a GLframebuffer struct. If this weren't true, we'd
+ * need a pointer from the GLframebuffer to the XMesaBuffer.
+ */
+ XMesaBuffer xmBuffer = (XMesaBuffer) buffer;
+
+ xmBuffer->width = buffer->Width;
+ xmBuffer->height = buffer->Height;
+ xmesa_alloc_back_buffer( xmBuffer );
+
+ /* Needed by FLIP macro */
+ xmBuffer->bottom = height - 1;
+
+ if (xmBuffer->backimage) {
+ /* Needed by PIXELADDR1 macro */
+ xmBuffer->ximage_width1 = xmBuffer->backimage->bytes_per_line;
+ xmBuffer->ximage_origin1 = (GLubyte *) xmBuffer->backimage->data
+ + xmBuffer->ximage_width1 * (height-1);
+
+ /* Needed by PIXELADDR2 macro */
+ xmBuffer->ximage_width2 = xmBuffer->backimage->bytes_per_line / 2;
+ xmBuffer->ximage_origin2 = (GLushort *) xmBuffer->backimage->data
+ + xmBuffer->ximage_width2 * (height-1);
+
+ /* Needed by PIXELADDR3 macro */
+ xmBuffer->ximage_width3 = xmBuffer->backimage->bytes_per_line;
+ xmBuffer->ximage_origin3 = (GLubyte *) xmBuffer->backimage->data
+ + xmBuffer->ximage_width3 * (height-1);
+
+ /* Needed by PIXELADDR4 macro */
+ xmBuffer->ximage_width4 = xmBuffer->backimage->width;
+ xmBuffer->ximage_origin4 = (GLuint *) xmBuffer->backimage->data
+ + xmBuffer->ximage_width4 * (height-1);
+ }
+
+ _swrast_alloc_buffers( buffer );
+}
+
+
+#ifndef XFree86Server
+/* XXX this was never tested in the Xserver environment */
+
+/**
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable).
+ * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
+ */
+static void
+xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+ ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B);
+ ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ if (buffer && /* buffer != 0 means it's a Window or Pixmap */
+ format == GL_BGRA &&
+ type == GL_UNSIGNED_BYTE &&
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
+ int dstX = x;
+ int dstY = y;
+ int w = width;
+ int h = height;
+ int srcX = unpack->SkipPixels;
+ int srcY = unpack->SkipRows;
+ int rowLength = unpack->RowLength ? unpack->RowLength : width;
+
+ pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
+ format, type, (GLvoid *) pixels);
+ if (!pixels)
+ return;
+
+ if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ /* This is a little tricky since all coordinates up to now have
+ * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
+ * so we have to carefully compute the Y coordinates/addresses here.
+ */
+ XMesaImage ximage;
+ MEMSET(&ximage, 0, sizeof(XMesaImage));
+ ximage.width = width;
+ ximage.height = height;
+ ximage.format = ZPixmap;
+ ximage.data = (char *) pixels
+ + ((srcY + h - 1) * rowLength + srcX) * 4;
+ ximage.byte_order = LSBFirst;
+ ximage.bitmap_unit = 32;
+ ximage.bitmap_bit_order = LSBFirst;
+ ximage.bitmap_pad = 32;
+ ximage.depth = 24;
+ ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */
+ ximage.bits_per_pixel = 32;
+ /* it seems we don't need to set the ximage.red/green/blue_mask fields */
+ /* flip Y axis for dest position */
+ dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
+ XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
+ }
+ }
+ else {
+ /* software fallback */
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ }
+}
+
+
+
+/**
+ * This function implements glDrawPixels() with an XPutImage call when
+ * drawing to the front buffer (X Window drawable). The image format
+ * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to
+ * match the PF_5R6G5B pixel format.
+ */
+static void
+xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+ ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ if (buffer && /* buffer != 0 means it's a Window or Pixmap */
+ format == GL_RGB &&
+ type == GL_UNSIGNED_SHORT_5_6_5 &&
+ !ctx->Color.DitherFlag && /* no dithering */
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
+ int dstX = x;
+ int dstY = y;
+ int w = width;
+ int h = height;
+ int srcX = unpack->SkipPixels;
+ int srcY = unpack->SkipRows;
+ int rowLength = unpack->RowLength ? unpack->RowLength : width;
+
+ pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
+ format, type, (GLvoid *) pixels);
+ if (!pixels)
+ return;
+
+ if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
+ /* This is a little tricky since all coordinates up to now have
+ * been in the OpenGL bottom-to-top orientation. X is top-to-bottom
+ * so we have to carefully compute the Y coordinates/addresses here.
+ */
+ XMesaImage ximage;
+ MEMSET(&ximage, 0, sizeof(XMesaImage));
+ ximage.width = width;
+ ximage.height = height;
+ ximage.format = ZPixmap;
+ ximage.data = (char *) pixels
+ + ((srcY + h - 1) * rowLength + srcX) * 2;
+ ximage.byte_order = LSBFirst;
+ ximage.bitmap_unit = 16;
+ ximage.bitmap_bit_order = LSBFirst;
+ ximage.bitmap_pad = 16;
+ ximage.depth = 16;
+ ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */
+ ximage.bits_per_pixel = 16;
+ /* it seems we don't need to set the ximage.red/green/blue_mask fields */
+ /* flip Y axis for dest position */
+ dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1;
+ XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h);
+ }
+ }
+ else {
+ /* software fallback */
+ _swrast_DrawPixels(ctx, x, y, width, height,
+ format, type, unpack, pixels);
+ }
+}
+
+
+
+/**
+ * Implement glCopyPixels for the front color buffer (or back buffer Pixmap)
+ * for the color buffer. Don't support zooming, pixel transfer, etc.
+ * We do support copying from one window to another, ala glXMakeCurrentRead.
+ */
+static void
+xmesa_CopyPixels( GLcontext *ctx,
+ GLint srcx, GLint srcy, GLsizei width, GLsizei height,
+ GLint destx, GLint desty, GLenum type )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer;
+ const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer;
+ const XMesaGC gc = xmesa->xm_draw_buffer->gc;
+
+ ASSERT(dpy);
+ ASSERT(gc);
+
+ if (swrast->NewState)
+ _swrast_validate_derived( ctx );
+
+ if (ctx->Color.DrawBuffer == GL_FRONT &&
+ ctx->Pixel.ReadBuffer == GL_FRONT &&
+ drawBuffer && /* buffer != 0 means it's a Window or Pixmap */
+ readBuffer &&
+ type == GL_COLOR &&
+ (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */
+ ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */
+ ctx->Pixel.ZoomX == 1.0 && /* no zooming */
+ ctx->Pixel.ZoomY == 1.0) {
+ /* Note: we don't do any special clipping work here. We could,
+ * but X will do it for us.
+ */
+ srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1;
+ desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1;
+ XCopyArea(dpy, readBuffer, drawBuffer, gc,
+ srcx, srcy, width, height, destx, desty);
+ }
+ else {
+ _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type );
+ }
+}
+#endif /* XFree86Server */
+
+
+
+/*
+ * Every driver should implement a GetString function in order to
+ * return a meaningful GL_RENDERER string.
+ */
+static const GLubyte *
+get_string( GLcontext *ctx, GLenum name )
+{
+ (void) ctx;
+ switch (name) {
+ case GL_RENDERER:
+#ifdef XFree86Server
+ return (const GLubyte *) "Mesa GLX Indirect";
+#else
+ return (const GLubyte *) "Mesa X11";
+#endif
+ case GL_VENDOR:
+#ifdef XFree86Server
+ return (const GLubyte *) "Mesa project: www.mesa3d.org";
+#else
+ return NULL;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+
+/*
+ * We implement the glEnable function only because we care about
+ * dither enable/disable.
+ */
+static void
+enable( GLcontext *ctx, GLenum pname, GLboolean state )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+ switch (pname) {
+ case GL_DITHER:
+ if (state)
+ xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
+ else
+ xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
+ break;
+ default:
+ ; /* silence compiler warning */
+ }
+}
+
+
+void xmesa_update_state( GLcontext *ctx, GLuint new_state )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+ /* Propogate statechange information to swrast and swrast_setup
+ * modules. The X11 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 );
+
+
+ /* setup pointers to front and back buffer clear functions */
+ xmesa->xm_draw_buffer->front_clear_func = clear_front_pixmap;
+ if (xmesa->xm_draw_buffer->backpixmap != XIMAGE) {
+ xmesa->xm_draw_buffer->back_clear_func = clear_back_pixmap;
+ }
+ else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
+ xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
+ }
+ else switch (xmesa->xm_visual->BitsPerPixel) {
+ case 8:
+ if (xmesa->xm_visual->hpcr_clear_flag) {
+ xmesa->xm_draw_buffer->back_clear_func = clear_HPCR_ximage;
+ }
+ else {
+ xmesa->xm_draw_buffer->back_clear_func = clear_8bit_ximage;
+ }
+ break;
+ case 16:
+ xmesa->xm_draw_buffer->back_clear_func = clear_16bit_ximage;
+ break;
+ case 24:
+ xmesa->xm_draw_buffer->back_clear_func = clear_24bit_ximage;
+ break;
+ case 32:
+ xmesa->xm_draw_buffer->back_clear_func = clear_32bit_ximage;
+ break;
+ default:
+ xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage;
+ break;
+ }
+
+ if (ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ xmesa_update_span_funcs(ctx);
+ }
+}
+
+
+
+/**
+ * Called via ctx->Driver.TestProxyTeximage(). Normally, we'd just use
+ * the _mesa_test_proxy_teximage() fallback function, but we're going to
+ * special-case the 3D texture case to allow textures up to 512x512x32
+ * texels.
+ */
+static GLboolean
+test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat, GLenum format, GLenum type,
+ GLint width, GLint height, GLint depth, GLint border)
+{
+ if (target == GL_PROXY_TEXTURE_3D) {
+ /* special case for 3D textures */
+ if (width * height * depth > 512 * 512 * 64 ||
+ width < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(width - 2 * border) != 1) ||
+ height < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(height - 2 * border) != 1) ||
+ depth < 2 * border ||
+ (!ctx->Extensions.ARB_texture_non_power_of_two &&
+ _mesa_bitcount(depth - 2 * border) != 1)) {
+ /* Bad size, or too many texels */
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+ }
+ else {
+ /* use the fallback routine for 1D, 2D, cube and rect targets */
+ return _mesa_test_proxy_teximage(ctx, target, level, internalFormat,
+ format, type, width, height, depth,
+ border);
+ }
+}
+
+
+/**
+ * Initialize the device driver function table with the functions
+ * we implement in this driver.
+ */
+void xmesa_init_driver_functions( XMesaVisual xmvisual,
+ struct dd_function_table *driver )
+{
+ driver->GetString = get_string;
+ driver->UpdateState = xmesa_update_state;
+ driver->GetBufferSize = get_buffer_size;
+ driver->Flush = finish_or_flush;
+ driver->Finish = finish_or_flush;
+ driver->ClearIndex = clear_index;
+ driver->ClearColor = clear_color;
+ driver->IndexMask = index_mask;
+ driver->ColorMask = color_mask;
+ driver->Enable = enable;
+ driver->Clear = clear_buffers;
+ driver->ResizeBuffers = xmesa_resize_buffers;
+#ifndef XFree86Server
+ driver->CopyPixels = /*_swrast_CopyPixels;*/xmesa_CopyPixels;
+ if (xmvisual->undithered_pf == PF_8R8G8B &&
+ xmvisual->dithered_pf == PF_8R8G8B) {
+ driver->DrawPixels = xmesa_DrawPixels_8R8G8B;
+ }
+ else if (xmvisual->undithered_pf == PF_5R6G5B) {
+ driver->DrawPixels = xmesa_DrawPixels_5R6G5B;
+ }
+#endif
+ driver->TestProxyTexImage = test_proxy_teximage;
+}
+
+
+#define XMESA_NEW_POINT (_NEW_POINT | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_LINE (_NEW_LINE | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \
+ _NEW_TEXTURE | \
+ _NEW_LIGHT | \
+ _NEW_DEPTH | \
+ _NEW_RENDERMODE | \
+ _SWRAST_NEW_RASTERMASK)
+
+
+/* Extend the software rasterizer with our line/point/triangle
+ * functions.
+ */
+void xmesa_register_swrast_functions( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT( ctx );
+ struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference(ctx);
+
+ dd->SetBuffer = xmesa_set_buffer;
+
+ swrast->choose_point = xmesa_choose_point;
+ swrast->choose_line = xmesa_choose_line;
+ swrast->choose_triangle = xmesa_choose_triangle;
+
+ swrast->invalidate_point |= XMESA_NEW_POINT;
+ swrast->invalidate_line |= XMESA_NEW_LINE;
+ swrast->invalidate_triangle |= XMESA_NEW_TRIANGLE;
+}
diff --git a/src/mesa/drivers/x11/xm_line.c b/src/mesa/drivers/x11/xm_line.c
new file mode 100644
index 0000000..5cd5cf7
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_line.c
@@ -0,0 +1,617 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2002 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.
+ */
+
+
+/*
+ * This file contains "accelerated" point, line, and triangle functions.
+ * It should be fairly easy to write new special-purpose point, line or
+ * triangle functions and hook them into this module.
+ */
+
+
+#include "glxheader.h"
+#include "depth.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "xmesaP.h"
+
+/* Internal swrast includes:
+ */
+#include "swrast/s_depth.h"
+#include "swrast/s_points.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_context.h"
+
+
+/**********************************************************************/
+/*** Point rendering ***/
+/**********************************************************************/
+
+
+/*
+ * Render an array of points into a pixmap, any pixel format.
+ */
+#if 000
+/* XXX don't use this, it doesn't dither correctly */
+static void draw_points_ANY_pixmap( GLcontext *ctx, const SWvertex *vert )
+{
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+
+ if (xmesa->xm_visual->mesa_visual.RGBAflag) {
+ register int x, y;
+ const GLubyte *color = vert->color;
+ unsigned long pixel = xmesa_color_to_pixel( xmesa,
+ color[0], color[1],
+ color[2], color[3],
+ xmesa->pixelformat);
+ XMesaSetForeground( dpy, gc, pixel );
+ x = (GLint) vert->win[0];
+ y = FLIP( xmesa->xm_buffer, (GLint) vert->win[1] );
+ XMesaDrawPoint( dpy, buffer, gc, x, y);
+ }
+ else {
+ /* Color index mode */
+ register int x, y;
+ XMesaSetForeground( dpy, gc, vert->index );
+ x = (GLint) vert->win[0];
+ y = FLIP( xmesa->xm_buffer, (GLint) vert->win[1] );
+ XMesaDrawPoint( dpy, buffer, gc, x, y);
+ }
+}
+#endif
+
+
+/* Override the swrast point-selection function. Try to use one of
+ * our internal point functions, otherwise fall back to the standard
+ * swrast functions.
+ */
+void xmesa_choose_point( GLcontext *ctx )
+{
+#if 0
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (ctx->RenderMode == GL_RENDER
+ && ctx->Point.Size == 1.0F && !ctx->Point.SmoothFlag
+ && swrast->_RasterMask == 0
+ && !ctx->Texture._EnabledUnits
+ && xmesa->xm_buffer->buffer != XIMAGE) {
+ swrast->Point = draw_points_ANY_pixmap;
+ }
+ else {
+ _swrast_choose_point( ctx );
+ }
+#else
+ _swrast_choose_point( ctx );
+#endif
+}
+
+
+
+/**********************************************************************/
+/*** Line rendering ***/
+/**********************************************************************/
+
+
+/*
+ * Draw a flat-shaded, PF_TRUECOLOR line into an XImage.
+ */
+#define NAME flat_TRUECOLOR_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ unsigned long pixel; \
+ PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
+#define CLIP_HACK 1
+#define PLOT(X,Y) XMesaPutPixel( img, X, FLIP(xmesa->xm_buffer, Y), pixel );
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8A8B8G8R line into an XImage.
+ */
+#define NAME flat_8A8B8G8R_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8B8G8R( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8A8R8G8B line into an XImage.
+ */
+#define NAME flat_8A8R8G8B_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8R8G8B line into an XImage.
+ */
+#define NAME flat_8R8G8B_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_8R8G8B24 line into an XImage.
+ */
+#define NAME flat_8R8G8B24_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color;
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) { \
+ pixelPtr->r = color[RCOMP]; \
+ pixelPtr->g = color[GCOMP]; \
+ pixelPtr->b = color[BCOMP]; \
+}
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_5R6G5B line into an XImage.
+ */
+#define NAME flat_5R6G5B_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_DITHER_5R6G5B line into an XImage.
+ */
+#define NAME flat_DITHER_5R6G5B_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color;
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) PACK_TRUEDITHER( *pixelPtr, X, Y, color[0], color[1], color[2] );
+#include "swrast/s_linetemp.h"
+
+
+
+
+/*
+ * Draw a flat-shaded, PF_DITHER 8-bit line into an XImage.
+ */
+#define NAME flat_DITHER8_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLint r = color[0], g = color[1], b = color[2]; \
+ DITHER_SETUP;
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = DITHER(X,Y,r,g,b);
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_LOOKUP 8-bit line into an XImage.
+ */
+#define NAME flat_LOOKUP8_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLubyte pixel; \
+ LOOKUP_SETUP; \
+ pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] );
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = pixel;
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, PF_HPCR line into an XImage.
+ */
+#define NAME flat_HPCR_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLint r = color[0], g = color[1], b = color[2];
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) *pixelPtr = (GLubyte) DITHER_HPCR(X,Y,r,g,b);
+#include "swrast/s_linetemp.h"
+
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_TRUECOLOR line into an XImage.
+ */
+#define NAME flat_TRUECOLOR_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ unsigned long pixel; \
+ PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ XMesaPutPixel( img, X, FLIP(xmesa->xm_buffer, Y), pixel ); \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8A8B8G8R line into an XImage.
+ */
+#define NAME flat_8A8B8G8R_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8B8G8R( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = pixel; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8A8R8G8B line into an XImage.
+ */
+#define NAME flat_8A8R8G8B_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = pixel; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8R8G8B line into an XImage.
+ */
+#define NAME flat_8R8G8B_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = pixel; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_8R8G8B24 line into an XImage.
+ */
+#define NAME flat_8R8G8B24_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ pixelPtr->r = color[RCOMP]; \
+ pixelPtr->g = color[GCOMP]; \
+ pixelPtr->b = color[BCOMP]; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_5R6G5B line into an XImage.
+ */
+#define NAME flat_5R6G5B_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = pixel; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_DITHER_5R6G5B line into an XImage.
+ */
+#define NAME flat_DITHER_5R6G5B_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ PACK_TRUEDITHER(*pixelPtr, X, Y, color[0], color[1], color[2]); \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_DITHER 8-bit line into an XImage.
+ */
+#define NAME flat_DITHER8_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLint r = color[0], g = color[1], b = color[2]; \
+ DITHER_SETUP;
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = (GLubyte) DITHER( X, Y, r, g, b); \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_LOOKUP 8-bit line into an XImage.
+ */
+#define NAME flat_LOOKUP8_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLubyte pixel; \
+ LOOKUP_SETUP; \
+ pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] );
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = pixel; \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+/*
+ * Draw a flat-shaded, Z-less, PF_HPCR line into an XImage.
+ */
+#define NAME flat_HPCR_z_line
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = vert1->color; \
+ GLint r = color[0], g = color[1], b = color[2];
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ *zPtr = Z; \
+ *pixelPtr = (GLubyte) DITHER_HPCR( X, Y, r, g, b); \
+ }
+#include "swrast/s_linetemp.h"
+
+
+
+static swrast_line_func get_line_func( GLcontext *ctx )
+{
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ int depth = GET_VISUAL_DEPTH(xmesa->xm_visual);
+
+ if ((ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) ==0)
+ return (swrast_line_func) NULL;
+ if (ctx->RenderMode != GL_RENDER) return (swrast_line_func) NULL;
+ if (ctx->Line.SmoothFlag) return (swrast_line_func) NULL;
+ if (ctx->Texture._EnabledUnits) return (swrast_line_func) NULL;
+ if (ctx->Light.ShadeModel != GL_FLAT) return (swrast_line_func) NULL;
+ if (ctx->Line.StippleFlag) return (swrast_line_func) NULL;
+ if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL;
+
+ if (xmesa->xm_buffer->buffer==XIMAGE
+ && swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+ && ctx->Line.Width==1.0F) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ return flat_TRUECOLOR_z_line;
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_z_line;
+ case PF_8A8R8G8B:
+ return flat_8A8R8G8B_z_line;
+ case PF_8R8G8B:
+ return flat_8R8G8B_z_line;
+ case PF_8R8G8B24:
+ return flat_8R8G8B24_z_line;
+ case PF_5R6G5B:
+ return flat_5R6G5B_z_line;
+ case PF_Dither_5R6G5B:
+ return flat_DITHER_5R6G5B_z_line;
+ case PF_Dither:
+ return (depth==8) ? flat_DITHER8_z_line : (swrast_line_func) NULL;
+ case PF_Lookup:
+ return (depth==8) ? flat_LOOKUP8_z_line : (swrast_line_func) NULL;
+ case PF_HPCR:
+ return flat_HPCR_z_line;
+ default:
+ return (swrast_line_func)NULL;
+ }
+ }
+ if (xmesa->xm_buffer->buffer==XIMAGE
+ && swrast->_RasterMask==0
+ && ctx->Line.Width==1.0F) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ return flat_TRUECOLOR_line;
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_line;
+ case PF_8A8R8G8B:
+ return flat_8A8R8G8B_line;
+ case PF_8R8G8B:
+ return flat_8R8G8B_line;
+ case PF_8R8G8B24:
+ return flat_8R8G8B24_line;
+ case PF_5R6G5B:
+ return flat_5R6G5B_line;
+ case PF_Dither_5R6G5B:
+ return flat_DITHER_5R6G5B_line;
+ case PF_Dither:
+ return (depth==8) ? flat_DITHER8_line : (swrast_line_func) NULL;
+ case PF_Lookup:
+ return (depth==8) ? flat_LOOKUP8_line : (swrast_line_func) NULL;
+ case PF_HPCR:
+ return flat_HPCR_line;
+ default:
+ return (swrast_line_func)NULL;
+ }
+ }
+
+ 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.
+ */
+void xmesa_choose_line( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (!(swrast->Line = get_line_func( ctx )))
+ _swrast_choose_line( ctx );
+}
diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c
new file mode 100644
index 0000000..807be39
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_span.c
@@ -0,0 +1,4777 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.2.1
+ *
+ * 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.
+ */
+/* $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"
+#include "context.h"
+#include "depth.h"
+#include "drawpix.h"
+#include "extensions.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "state.h"
+#include "xmesaP.h"
+
+#include "swrast/swrast.h"
+
+
+/*
+ * The following functions are used to trap XGetImage() calls which
+ * generate BadMatch errors if the drawable isn't mapped.
+ */
+
+#ifndef XFree86Server
+static int caught_xgetimage_error = 0;
+static int (*old_xerror_handler)( XMesaDisplay *dpy, XErrorEvent *ev );
+static unsigned long xgetimage_serial;
+
+/*
+ * This is the error handler which will be called if XGetImage fails.
+ */
+static int xgetimage_error_handler( XMesaDisplay *dpy, XErrorEvent *ev )
+{
+ if (ev->serial==xgetimage_serial && ev->error_code==BadMatch) {
+ /* caught the expected error */
+ caught_xgetimage_error = 0;
+ }
+ else {
+ /* call the original X error handler, if any. otherwise ignore */
+ if (old_xerror_handler) {
+ (*old_xerror_handler)( dpy, ev );
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Call this right before XGetImage to setup error trap.
+ */
+static void catch_xgetimage_errors( XMesaDisplay *dpy )
+{
+ xgetimage_serial = NextRequest( dpy );
+ old_xerror_handler = XSetErrorHandler( xgetimage_error_handler );
+ caught_xgetimage_error = 0;
+}
+
+
+/*
+ * Call this right after XGetImage to check if an error occured.
+ */
+static int check_xgetimage_errors( void )
+{
+ /* restore old handler */
+ (void) XSetErrorHandler( old_xerror_handler );
+ /* return 0=no error, 1=error caught */
+ return caught_xgetimage_error;
+}
+#endif
+
+
+/*
+ * Read a pixel from an X drawable.
+ */
+static unsigned long read_pixel( XMesaDisplay *dpy,
+ XMesaDrawable d, int x, int y )
+{
+ unsigned long p;
+#ifndef XFree86Server
+ XMesaImage *pixel = NULL;
+ int error;
+
+ catch_xgetimage_errors( dpy );
+ pixel = XGetImage( dpy, d, x, y, 1, 1, AllPlanes, ZPixmap );
+ error = check_xgetimage_errors();
+ if (pixel && !error) {
+ p = XMesaGetPixel( pixel, 0, 0 );
+ }
+ else {
+ p = 0;
+ }
+ if (pixel) {
+ XMesaDestroyImage( pixel );
+ }
+#else
+ (*dpy->GetImage)(d, x, y, 1, 1, ZPixmap, ~0L, (pointer)&p);
+#endif
+ return p;
+}
+
+
+
+/*
+ * The Mesa library needs to be able to draw pixels in a number of ways:
+ * 1. RGB vs Color Index
+ * 2. as horizontal spans (polygons, images) vs random locations (points,
+ * lines)
+ * 3. different color per-pixel or same color for all pixels
+ *
+ * Furthermore, the X driver needs to support rendering to 3 possible
+ * "buffers", usually one, but sometimes two at a time:
+ * 1. The front buffer as an X window
+ * 2. The back buffer as a Pixmap
+ * 3. The back buffer as an XImage
+ *
+ * Finally, if the back buffer is an XImage, we can avoid using XPutPixel and
+ * optimize common cases such as 24-bit and 8-bit modes.
+ *
+ * By multiplication, there's at least 48 possible combinations of the above.
+ *
+ * Below are implementations of the most commonly used combinations. They are
+ * accessed through function pointers which get initialized here and are used
+ * directly from the Mesa library. The 8 function pointers directly correspond
+ * to the first 3 cases listed above.
+ *
+ *
+ * The function naming convention is:
+ *
+ * write_[span|pixels]_[mono]_[format]_[pixmap|ximage]
+ *
+ * New functions optimized for specific cases can be added without too much
+ * trouble. An example might be the 24-bit TrueColor mode 8A8R8G8B which is
+ * found on IBM RS/6000 X servers.
+ */
+
+
+
+
+/**********************************************************************/
+/*** Write COLOR SPAN functions ***/
+/**********************************************************************/
+
+
+#define RGBA_SPAN_ARGS const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ CONST GLubyte rgba[][4], const GLubyte mask[]
+
+#define RGB_SPAN_ARGS const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ CONST GLubyte rgb[][3], const GLubyte mask[]
+
+
+/* NOTE: if mask==NULL, draw all pixels */
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void write_span_TRUECOLOR_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaPutPixel( rowimg, i, 0, p );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void write_span_rgb_TRUECOLOR_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ XMesaPutPixel( rowimg, i, 0, p );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void write_span_TRUEDITHER_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaPutPixel( rowimg, i, 0, p );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_TRUEDITHER_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ XMesaPutPixel( rowimg, i, 0, p );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+
+/*
+ * Write a span of PF_8A8B8G8R pixels to a pixmap.
+ */
+static void write_span_8A8B8G8R_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8A8B8G8R(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_8A8B8G8R_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8B8G8R(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+/*
+ * Write a span of PF_8A8R8G8B pixels to a pixmap.
+ */
+static void write_span_8A8R8G8B_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8A8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8A8R8G8B pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_8A8R8G8B_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B pixels to a pixmap.
+ */
+static void write_span_8R8G8B_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24 pixels to a pixmap.
+ */
+static void write_span_8R8G8B24_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ register GLuint i;
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ register GLuint pixel;
+ static const GLuint shift[4] = {0, 8, 16, 24};
+ register GLuint i = 0;
+ int w = n;
+ while (w > 3) {
+ pixel = rgba[i][BCOMP] /* << shift[0]*/;
+ pixel |= rgba[i][GCOMP] << shift[1];
+ pixel |= rgba[i++][RCOMP] << shift[2];
+ pixel |= rgba[i][BCOMP] << shift[3];
+ *ptr4++ = pixel;
+
+ pixel = rgba[i][GCOMP] /* << shift[0]*/;
+ pixel |= rgba[i++][RCOMP] << shift[1];
+ pixel |= rgba[i][BCOMP] << shift[2];
+ pixel |= rgba[i][GCOMP] << shift[3];
+ *ptr4++ = pixel;
+
+ pixel = rgba[i++][RCOMP]/* << shift[0]*/;
+ pixel |= rgba[i][BCOMP] << shift[1];
+ pixel |= rgba[i][GCOMP] << shift[2];
+ pixel |= rgba[i++][RCOMP] << shift[3];
+ *ptr4++ = pixel;
+
+ w -= 4;
+ }
+ switch (w) {
+ case 3:
+ pixel = 0;
+ pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+ pixel |= rgba[i][GCOMP] << shift[1];
+ pixel |= rgba[i++][RCOMP] << shift[2];
+ pixel |= rgba[i][BCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = 0;
+ pixel |= rgba[i][GCOMP] /*<< shift[0]*/;
+ pixel |= rgba[i++][RCOMP] << shift[1];
+ pixel |= rgba[i][BCOMP] << shift[2];
+ pixel |= rgba[i][GCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = 0xffffff00 & *ptr4;
+ pixel |= rgba[i][RCOMP] /*<< shift[0]*/;
+ *ptr4 = pixel;
+ break;
+ case 2:
+ pixel = 0;
+ pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+ pixel |= rgba[i][GCOMP] << shift[1];
+ pixel |= rgba[i++][RCOMP] << shift[2];
+ pixel |= rgba[i][BCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = 0xffff0000 & *ptr4;
+ pixel |= rgba[i][GCOMP] /*<< shift[0]*/;
+ pixel |= rgba[i][RCOMP] << shift[1];
+ *ptr4 = pixel;
+ break;
+ case 1:
+ pixel = 0xff000000 & *ptr4;
+ pixel |= rgba[i][BCOMP] /*<< shift[0]*/;
+ pixel |= rgba[i][GCOMP] << shift[1];
+ pixel |= rgba[i][RCOMP] << shift[2];
+ *ptr4 = pixel;
+ break;
+ case 0:
+ break;
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ for (i=0;i<n;i++) {
+ *ptr4++ = PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24 pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_8R8G8B24_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ register GLuint i;
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLuint *ptr4 = (GLuint *) rowimg->data;
+ register GLuint pixel;
+ static const GLuint shift[4] = {0, 8, 16, 24};
+ unsigned w = n;
+ register GLuint i = 0;
+ while (w > 3) {
+ pixel = 0;
+ pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+ pixel |= rgb[i][GCOMP] << shift[1];
+ pixel |= rgb[i++][RCOMP] << shift[2];
+ pixel |= rgb[i][BCOMP] <<shift[3];
+ *ptr4++ = pixel;
+
+ pixel = 0;
+ pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+ pixel |= rgb[i++][RCOMP] << shift[1];
+ pixel |= rgb[i][BCOMP] << shift[2];
+ pixel |= rgb[i][GCOMP] << shift[3];
+ *ptr4++ = pixel;
+
+ pixel = 0;
+ pixel |= rgb[i++][RCOMP]/* << shift[0]*/;
+ pixel |= rgb[i][BCOMP] << shift[1];
+ pixel |= rgb[i][GCOMP] << shift[2];
+ pixel |= rgb[i++][RCOMP] << shift[3];
+ *ptr4++ = pixel;
+ w -= 4;
+ }
+ switch (w) {
+ case 3:
+ pixel = 0;
+ pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+ pixel |= rgb[i][GCOMP] << shift[1];
+ pixel |= rgb[i++][RCOMP] << shift[2];
+ pixel |= rgb[i][BCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = 0;
+ pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+ pixel |= rgb[i++][RCOMP] << shift[1];
+ pixel |= rgb[i][BCOMP] << shift[2];
+ pixel |= rgb[i][GCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = *ptr4;
+ pixel &= 0xffffff00;
+ pixel |= rgb[i++][RCOMP]/* << shift[0]*/;
+ *ptr4++ = pixel;
+ break;
+ case 2:
+ pixel = 0;
+ pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+ pixel |= rgb[i][GCOMP] << shift[1];
+ pixel |= rgb[i++][RCOMP] << shift[2];
+ pixel |= rgb[i][BCOMP] << shift[3];
+ *ptr4++ = pixel;
+ pixel = *ptr4;
+ pixel &= 0xffff0000;
+ pixel |= rgb[i][GCOMP]/* << shift[0]*/;
+ pixel |= rgb[i++][RCOMP] << shift[1];
+ *ptr4++ = pixel;
+ break;
+ case 1:
+ pixel = *ptr4;
+ pixel &= 0xff000000;
+ pixel |= rgb[i][BCOMP]/* << shift[0]*/;
+ pixel |= rgb[i][GCOMP] << shift[1];
+ pixel |= rgb[i++][RCOMP] << shift[2];
+ *ptr4++ = pixel;
+ break;
+ case 0:
+ break;
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B pixels to a pixmap.
+ */
+static void write_span_5R6G5B_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLushort *ptr2 = (GLushort *) rowimg->data;
+ for (i=0;i<n;i++) {
+ ptr2[i] = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B pixels to a pixmap.
+ */
+static void write_span_DITHER_5R6G5B_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLushort *ptr2 = (GLushort *) rowimg->data;
+ for (i=0;i<n;i++) {
+ PACK_TRUEDITHER( ptr2[i], x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_5R6G5B_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLushort *ptr2 = (GLushort *) rowimg->data;
+ for (i=0;i<n;i++) {
+ ptr2[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_DITHER_5R6G5B_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLushort *ptr2 = (GLushort *) rowimg->data;
+ for (i=0;i<n;i++) {
+ PACK_TRUEDITHER( ptr2[i], x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap.
+ */
+static void write_span_DITHER_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ XDITHER_SETUP(y);
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, XDITHER(x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, XDITHER(x+i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_DITHER_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ XDITHER_SETUP(y);
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, XDITHER(x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, XDITHER(x+i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap.
+ */
+static void write_span_1BIT_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_1BIT( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0,
+ DITHER_1BIT( x+i, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_1BIT_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0,
+ DITHER_1BIT(x+i, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to a pixmap.
+ */
+static void write_span_HPCR_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLubyte *ptr = (GLubyte *) xmesa->xm_buffer->rowimage->data;
+ for (i=0;i<n;i++) {
+ ptr[i] = DITHER_HPCR( (x+i), y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_HPCR_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_HPCR(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ register GLubyte *ptr = (GLubyte *) xmesa->xm_buffer->rowimage->data;
+ for (i=0;i<n;i++) {
+ ptr[i] = DITHER_HPCR( (x+i), y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to a pixmap.
+ */
+static void write_span_LOOKUP_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ LOOKUP_SETUP;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, LOOKUP(rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_LOOKUP_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ LOOKUP_SETUP;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, LOOKUP(rgb[i][RCOMP],rgb[i][GCOMP],rgb[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to a pixmap.
+ */
+static void write_span_GRAYSCALE_pixmap( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, GRAY_RGB(rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to a pixmap (no alpha).
+ */
+static void write_span_rgb_GRAYSCALE_pixmap( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ XMesaImage *rowimg = xmesa->xm_buffer->rowimage;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel( rowimg, i, 0, GRAY_RGB(rgb[i][RCOMP],rgb[i][GCOMP],rgb[i][BCOMP]) );
+ }
+ XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 );
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to an XImage.
+ */
+static void write_span_TRUECOLOR_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUECOLOR pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_TRUECOLOR_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to an XImage.
+ */
+static void write_span_TRUEDITHER_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ XMesaPutPixel( img, x, y, p );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R-format pixels to an ximage.
+ */
+static void write_span_8A8B8G8R_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8A8B8G8R-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8A8B8G8R( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8A8B8G8R( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+ }
+ }
+}
+
+/*
+ * Write a span of PF_8A8R8G8B-format pixels to an ximage.
+ */
+static void write_span_8A8R8G8B_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8A8R8G8B-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8A8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8A8R8G8B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B-format pixels to an ximage.
+ */
+static void write_span_8R8G8B_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8R8G8B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24-format pixels to an ximage.
+ */
+static void write_span_8R8G8B24_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = (GLubyte *) PIXELADDR3( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = (GLuint *) ptr;
+ register GLuint pixel = *ptr4;
+ switch (3 & (int)(ptr - (GLubyte*)ptr4)) {
+ case 0:
+ pixel &= 0xff000000;
+ pixel |= rgba[i][BCOMP];
+ pixel |= rgba[i][GCOMP] << 8;
+ pixel |= rgba[i][RCOMP] << 16;
+ *ptr4 = pixel;
+ break;
+ case 3:
+ pixel &= 0x00ffffff;
+ pixel |= rgba[i][BCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 && 0xffff0000;
+ pixel |= rgba[i][GCOMP];
+ pixel |= rgba[i][RCOMP] << 8;
+ *ptr4 = pixel;
+ break;
+ case 2:
+ pixel &= 0x0000ffff;
+ pixel |= rgba[i][BCOMP] << 16;
+ pixel |= rgba[i][GCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 && 0xffffff00;
+ pixel |= rgba[i][RCOMP];
+ *ptr4 = pixel;
+ break;
+ case 1:
+ pixel &= 0x000000ff;
+ pixel |= rgba[i][BCOMP] << 8;
+ pixel |= rgba[i][GCOMP] << 16;
+ pixel |= rgba[i][RCOMP] << 24;
+ *ptr4 = pixel;
+ break;
+ }
+ }
+ ptr += 3;
+ }
+ }
+ else {
+ /* write all pixels */
+ int w = n;
+ GLuint *ptr4 = (GLuint *) ptr;
+ register GLuint pixel = *ptr4;
+ int index = (int)(ptr - (GLubyte *)ptr4);
+ register GLuint i = 0;
+ switch (index) {
+ case 0:
+ break;
+ case 1:
+ pixel &= 0x00ffffff;
+ pixel |= rgba[i][BCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 && 0xffff0000;
+ pixel |= rgba[i][GCOMP];
+ pixel |= rgba[i++][RCOMP] << 8;
+ *ptr4 = pixel;
+ if (0 == --w)
+ break;
+ case 2:
+ pixel &= 0x0000ffff;
+ pixel |= rgba[i][BCOMP] << 16;
+ pixel |= rgba[i][GCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 && 0xffffff00;
+ pixel |= rgba[i++][RCOMP];
+ *ptr4 = pixel;
+ if (0 == --w)
+ break;
+ case 3:
+ pixel &= 0x000000ff;
+ pixel |= rgba[i][BCOMP] << 8;
+ pixel |= rgba[i][GCOMP] << 16;
+ pixel |= rgba[i++][RCOMP] << 24;
+ *ptr4++ = pixel;
+ if (0 == --w)
+ break;
+ break;
+ }
+ while (w > 3) {
+ pixel = rgba[i][BCOMP];
+ pixel |= rgba[i][GCOMP] << 8;
+ pixel |= rgba[i++][RCOMP] << 16;
+ pixel |= rgba[i][BCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = rgba[i][GCOMP];
+ pixel |= rgba[i++][RCOMP] << 8;
+ pixel |= rgba[i][BCOMP] << 16;
+ pixel |= rgba[i][GCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = rgba[i++][RCOMP];
+ pixel |= rgba[i][BCOMP] << 8;
+ pixel |= rgba[i][GCOMP] << 16;
+ pixel |= rgba[i++][RCOMP] << 24;
+ *ptr4++ = pixel;
+ w -= 4;
+ }
+ switch (w) {
+ case 0:
+ break;
+ case 1:
+ pixel = *ptr4 & 0xff000000;
+ pixel |= rgba[i][BCOMP];
+ pixel |= rgba[i][GCOMP] << 8;
+ pixel |= rgba[i][RCOMP] << 16;
+ *ptr4 = pixel;
+ break;
+ case 2:
+ pixel = rgba[i][BCOMP];
+ pixel |= rgba[i][GCOMP] << 8;
+ pixel |= rgba[i++][RCOMP] << 16;
+ pixel |= rgba[i][BCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 & 0xffff0000;
+ pixel |= rgba[i][GCOMP];
+ pixel |= rgba[i][RCOMP] << 8;
+ *ptr4 = pixel;
+ break;
+ case 3:
+ pixel = rgba[i][BCOMP];
+ pixel |= rgba[i][GCOMP] << 8;
+ pixel |= rgba[i++][RCOMP] << 16;
+ pixel |= rgba[i][BCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = rgba[i][GCOMP];
+ pixel |= rgba[i++][RCOMP] << 8;
+ pixel |= rgba[i][BCOMP] << 16;
+ pixel |= rgba[i][GCOMP] << 24;
+ *ptr4++ = pixel;
+ pixel = *ptr4 & 0xffffff00;
+ pixel |= rgba[i][RCOMP];
+ *ptr4 = pixel;
+ break;
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_8R8G8B_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_8R8G8B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_8R8G8B24-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = (GLubyte *) PIXELADDR3( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ *ptr++ = rgb[i][BCOMP];
+ *ptr++ = rgb[i][GCOMP];
+ *ptr++ = rgb[i][RCOMP];
+ }
+ else {
+ ptr += 3;
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ *ptr++ = rgb[i][BCOMP];
+ *ptr++ = rgb[i][GCOMP];
+ *ptr++ = rgb[i][RCOMP];
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B-format pixels to an ximage.
+ */
+static void write_span_5R6G5B_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+ GLuint *ptr32 = (GLuint *) ptr;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+ for (i = 0; i < n; i += 2) {
+ GLuint p0, p1;
+ p0 = PACK_5R6G5B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ p1 = PACK_5R6G5B(rgba[i+1][RCOMP], rgba[i+1][GCOMP], rgba[i+1][BCOMP]);
+ *ptr32++ = (p1 << 16) | p0;
+ }
+ if (extraPixel) {
+ ptr[n] = PACK_5R6G5B(rgba[n][RCOMP], rgba[n][GCOMP], rgba[n][BCOMP]);
+ }
+#else
+ for (i = 0; i < n; i++) {
+ ptr[i] = PACK_5R6G5B(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+#endif
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B-format pixels to an ximage.
+ */
+static void write_span_DITHER_5R6G5B_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x, y );
+ const GLint y2 = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ PACK_TRUEDITHER( ptr[i], x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+ GLuint *ptr32 = (GLuint *) ptr;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+ for (i = 0; i < n; i += 2, x += 2) {
+ GLuint p0, p1;
+ PACK_TRUEDITHER( p0, x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ PACK_TRUEDITHER( p1, x+1, y2, rgba[i+1][RCOMP], rgba[i+1][GCOMP], rgba[i+1][BCOMP] );
+ *ptr32++ = (p1 << 16) | p0;
+ }
+ if (extraPixel) {
+ PACK_TRUEDITHER( ptr[n], x+n, y2, rgba[n][RCOMP], rgba[n][GCOMP], rgba[n][BCOMP]);
+ }
+#else
+ for (i = 0; i < n; i++, x++) {
+ PACK_TRUEDITHER( ptr[i], x, y2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+#endif
+ }
+}
+
+
+/*
+ * Write a span of PF_5R6G5B-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_5R6G5B_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+ GLuint *ptr32 = (GLuint *) ptr;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+ for (i = 0; i < n; i += 2) {
+ GLuint p0, p1;
+ p0 = PACK_5R6G5B(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ p1 = PACK_5R6G5B(rgb[i+1][RCOMP], rgb[i+1][GCOMP], rgb[i+1][BCOMP]);
+ *ptr32++ = (p1 << 16) | p0;
+ }
+ if (extraPixel) {
+ ptr[n] = PACK_5R6G5B(rgb[n][RCOMP], rgb[n][GCOMP], rgb[n][BCOMP]);
+ }
+#else
+ for (i=0;i<n;i++) {
+ ptr[i] = PACK_5R6G5B( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+#endif
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER_5R6G5B-format pixels to an ximage (no alpha).
+ */
+static void write_span_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ PACK_TRUEDITHER( ptr[i], x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+ GLuint *ptr32 = (GLuint *) ptr;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+ for (i = 0; i < n; i += 2, x += 2) {
+ GLuint p0, p1;
+ PACK_TRUEDITHER( p0, x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ PACK_TRUEDITHER( p1, x+1, y, rgb[i+1][RCOMP], rgb[i+1][GCOMP], rgb[i+1][BCOMP] );
+ *ptr32++ = (p1 << 16) | p0;
+ }
+ if (extraPixel) {
+ PACK_TRUEDITHER( ptr[n], x+n, y, rgb[n][RCOMP], rgb[n][GCOMP], rgb[n][BCOMP]);
+ }
+#else
+ for (i=0;i<n;i++,x++) {
+ PACK_TRUEDITHER( ptr[i], x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+#endif
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to an XImage.
+ */
+static void write_span_DITHER_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ int yy = FLIP(xmesa->xm_buffer, y);
+ XDITHER_SETUP(yy);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, yy, XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, yy, XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_DITHER_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ int yy = FLIP(xmesa->xm_buffer, y);
+ XDITHER_SETUP(yy);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, yy, XDITHER( x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, yy, XDITHER( x, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+}
+
+
+
+/*
+ * Write a span of 8-bit PF_DITHER pixels to an XImage.
+ */
+static void write_span_DITHER8_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ XDITHER_SETUP(y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ ptr[i] = (GLubyte) XDITHER( x, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+static void write_span_rgb_DITHER8_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ XDITHER_SETUP(y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) XDITHER( x, rgb[i][0], rgb[i][1], rgb[i][2] );
+ }
+ }
+ }
+ else {
+ const GLubyte *data = (GLubyte *) rgb;
+ for (i=0;i<n;i++,x++) {
+ /*ptr[i] = XDITHER( x, rgb[i][0], rgb[i][1], rgb[i][2] );*/
+ ptr[i] = (GLubyte) XDITHER( x, data[i+i+i], data[i+i+i+1], data[i+i+i+2] );
+ }
+ }
+}
+
+
+
+/*
+ * Write a span of PF_1BIT pixels to an XImage.
+ */
+static void write_span_1BIT_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel(img, x, y, DITHER_1BIT(x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, DITHER_1BIT(x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_1BIT_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel(img, x, y, DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, DITHER_1BIT(x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to an XImage.
+ */
+static void write_span_HPCR_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ ptr[i] = DITHER_HPCR( x, y, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_HPCR pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_HPCR_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = DITHER_HPCR( x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ ptr[i] = DITHER_HPCR( x, y, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to an XImage.
+ */
+static void write_span_LOOKUP_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ LOOKUP_SETUP;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_LOOKUP pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_LOOKUP_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ LOOKUP_SETUP;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, LOOKUP( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void write_span_LOOKUP8_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ LOOKUP_SETUP;
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ ptr[i] = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+static void write_rgb_LOOKUP8_ximage( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgb[][3],
+ const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ LOOKUP_SETUP;
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) LOOKUP( rgb[i][0], rgb[i][1], rgb[i][2] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ const GLubyte *data = (GLubyte *) rgb;
+ for (i=0;i<n;i++,x++) {
+ /*ptr[i] = LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );*/
+ ptr[i] = (GLubyte) LOOKUP( data[i+i+i], data[i+i+i+1], data[i+i+i+2] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to an XImage.
+ */
+static void write_span_GRAYSCALE_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_GRAYSCALE pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void write_span_GRAYSCALE8_ximage( RGBA_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of 8-bit PF_GRAYSCALE pixels to an XImage (no alpha).
+ */
+static void write_span_rgb_GRAYSCALE8_ximage( RGB_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y );
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0;i<n;i++) {
+ ptr[i] = (GLubyte) GRAY_RGB( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/*** Write COLOR PIXEL functions ***/
+/**********************************************************************/
+
+
+#define RGBA_PIXEL_ARGS const GLcontext *ctx, \
+ GLuint n, const GLint x[], const GLint y[], \
+ CONST GLubyte rgba[][4], const GLubyte mask[]
+
+
+/*
+ * Write an array of PF_TRUECOLOR pixels to a pixmap.
+ */
+static void write_pixels_TRUECOLOR_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void write_pixels_TRUEDITHER_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_8A8B8G8R pixels to a pixmap.
+ */
+static void write_pixels_8A8B8G8R_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+/*
+ * Write an array of PF_8A8R8G8B pixels to a pixmap.
+ */
+static void write_pixels_8A8R8G8B_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+/*
+ * Write an array of PF_8R8G8B pixels to a pixmap.
+ */
+static void write_pixels_8R8G8B_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B24 pixels to a pixmap.
+ */
+static void write_pixels_8R8G8B24_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_5R6G5B pixels to a pixmap.
+ */
+static void write_pixels_5R6G5B_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_DITHER_5R6G5B pixels to a pixmap.
+ */
+static void write_pixels_DITHER_5R6G5B_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to a pixmap.
+ */
+static void write_pixels_DITHER_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER(x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to a pixmap.
+ */
+static void write_pixels_1BIT_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ SETUP_1BIT;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_1BIT( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_HPCR pixels to a pixmap.
+ */
+static void write_pixels_HPCR_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc,
+ DITHER_HPCR( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_LOOKUP pixels to a pixmap.
+ */
+static void write_pixels_LOOKUP_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ LOOKUP_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_GRAYSCALE pixels to a pixmap.
+ */
+static void write_pixels_GRAYSCALE_pixmap( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_TRUECOLOR pixels to an ximage.
+ */
+static void write_pixels_TRUECOLOR_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUECOLOR( p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), p );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to an XImage.
+ */
+static void write_pixels_TRUEDITHER_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), p );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_8A8B8G8R pixels to an ximage.
+ */
+static void write_pixels_8A8B8G8R_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+/*
+ * Write an array of PF_8A8R8G8B pixels to an ximage.
+ */
+static void write_pixels_8A8R8G8B_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B pixels to an ximage.
+ */
+static void write_pixels_8R8G8B_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_8R8G8B24 pixels to an ximage.
+ */
+static void write_pixels_8R8G8B24_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ bgr_t *ptr = PIXELADDR3( xmesa->xm_buffer, x[i], y[i] );
+ ptr->r = rgba[i][RCOMP];
+ ptr->g = rgba[i][GCOMP];
+ ptr->b = rgba[i][BCOMP];
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_5R6G5B pixels to an ximage.
+ */
+static void write_pixels_5R6G5B_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_DITHER_5R6G5B pixels to an ximage.
+ */
+static void write_pixels_DITHER_5R6G5B_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x[i], y[i] );
+ PACK_TRUEDITHER( *ptr, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to an XImage.
+ */
+static void write_pixels_DITHER_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]),
+ DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of 8-bit PF_DITHER pixels to an XImage.
+ */
+static void write_pixels_DITHER8_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = (GLubyte) DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to an XImage.
+ */
+static void write_pixels_1BIT_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ SETUP_1BIT;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]),
+ DITHER_1BIT( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ));
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_HPCR pixels to an XImage.
+ */
+static void write_pixels_HPCR_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = (GLubyte) DITHER_HPCR( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_LOOKUP pixels to an XImage.
+ */
+static void write_pixels_LOOKUP_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ LOOKUP_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), LOOKUP(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void write_pixels_LOOKUP8_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ LOOKUP_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_GRAYSCALE pixels to an XImage.
+ */
+static void write_pixels_GRAYSCALE_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]),
+ GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void write_pixels_GRAYSCALE8_ximage( RGBA_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/*** Write MONO COLOR SPAN functions ***/
+/**********************************************************************/
+
+#define MONO_SPAN_ARGS const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, const GLchan color[4], \
+ const GLubyte mask[]
+
+
+/*
+ * Write a span of identical pixels to a pixmap.
+ */
+static void write_span_mono_pixmap( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ register GLuint i;
+ XMesaSetForeground( xmesa->display, gc, pixel );
+ y = FLIP(xmesa->xm_buffer, y);
+
+ /* New code contributed by Jeff Epler and cleaned up by Keith
+ * Whitwell.
+ */
+ for (i = 0; i < n; ) {
+ GLuint start = i;
+
+ /* Identify and emit contiguous rendered pixels
+ */
+ while (i < n && (!mask || mask[i]))
+ i++;
+
+ if (start < i)
+ XMesaFillRectangle( dpy, buffer, gc,
+ (int)(x+start), (int) y,
+ (int)(i-start), 1);
+
+ /* Eat up non-rendered pixels
+ */
+ while (i < n && !mask[i])
+ i++;
+ }
+}
+
+
+
+static void write_span_mono_index_pixmap( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLuint colorIndex,
+ const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ XMesaSetForeground( xmesa->display, gc, colorIndex );
+ y = FLIP(xmesa->xm_buffer, y);
+
+ for (i = 0 ; i < n ;) {
+ GLuint start = i;
+
+ /* Identify and emit contiguous rendered pixels
+ */
+ while (i < n && mask[i])
+ i++;
+
+ if (start < i)
+ XMesaFillRectangle( dpy, buffer, gc,
+ (int)(x+start), (int) y,
+ (int)(i-start), 1);
+
+ /* Eat up non-rendered pixels
+ */
+ while (i < n && !mask[i])
+ i++;
+ }
+}
+
+
+
+/*
+ * Write a span of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void write_span_mono_TRUEDITHER_pixmap( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ int yy = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x, yy, r, g, b);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) yy );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_DITHER pixels to a pixmap.
+ */
+static void write_span_mono_DITHER_pixmap( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ int yy = FLIP(xmesa->xm_buffer, y);
+ XDITHER_SETUP(yy);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, XDITHER( x, r, g, b ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) yy );
+ }
+ }
+}
+
+
+/*
+ * Write a span of PF_1BIT pixels to a pixmap.
+ */
+static void write_span_mono_1BIT_pixmap( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, DITHER_1BIT( x, y, r, g, b ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical pixels to an XImage.
+ */
+static void write_span_mono_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, pixel );
+ }
+ }
+}
+
+
+static void write_span_mono_index_ximage( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLuint colorIndex,
+ const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, colorIndex );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical PF_TRUEDITHER pixels to an XImage.
+ */
+static void write_span_mono_TRUEDITHER_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER( p, x+i, y, r, g, b);
+ XMesaPutPixel( img, x+i, y, p );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8A8B8G8R pixels to an XImage.
+ */
+static void write_span_mono_8A8B8G8R_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ GLuint i, *ptr;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = pixel;
+ }
+ }
+}
+
+/*
+ * Write a span of identical 8A8R8G8B pixels to an XImage.
+ */
+static void write_span_mono_8A8R8G8B_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ GLuint i, *ptr;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = pixel;
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8R8G8B pixels to an XImage.
+ */
+static void write_span_mono_8R8G8B_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLuint pixel = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (!mask || mask[i]) {
+ ptr[i] = pixel;
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8R8G8B pixels to an XImage.
+ */
+static void write_span_mono_8R8G8B24_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP];
+ const GLubyte g = color[GCOMP];
+ const GLubyte b = color[BCOMP];
+ GLuint i;
+ bgr_t *ptr = PIXELADDR3( xmesa->xm_buffer, x, y );
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i].r = r;
+ ptr[i].g = g;
+ ptr[i].b = b;
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical DITHER pixels to an XImage.
+ */
+static void write_span_mono_DITHER_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ int yy = FLIP(xmesa->xm_buffer, y);
+ register GLuint i;
+ XDITHER_SETUP(yy);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, yy, XDITHER( x, r, g, b ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8-bit DITHER pixels to an XImage.
+ */
+static void write_span_mono_DITHER8_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x,y);
+ register GLuint i;
+ XDITHER_SETUP(y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = (GLubyte) XDITHER( x, r, g, b );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8-bit LOOKUP pixels to an XImage.
+ */
+static void write_span_mono_LOOKUP8_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x,y);
+ GLubyte pixel;
+ LOOKUP_SETUP;
+ pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = pixel;
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical PF_1BIT pixels to an XImage.
+ */
+static void write_span_mono_1BIT_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ SETUP_1BIT;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, DITHER_1BIT( x, y, r, g, b ) );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical HPCR pixels to an XImage.
+ */
+static void write_span_mono_HPCR_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x,y);
+ register GLuint i;
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ ptr[i] = DITHER_HPCR( x, y, r, g, b );
+ }
+ }
+}
+
+
+/*
+ * Write a span of identical 8-bit GRAYSCALE pixels to an XImage.
+ */
+static void write_span_mono_GRAYSCALE8_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ GLubyte *ptr = (GLubyte *) PIXELADDR1( xmesa->xm_buffer,x,y);
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr[i] = p;
+ }
+ }
+}
+
+
+
+/*
+ * Write a span of identical PF_DITHER_5R6G5B pixels to an XImage.
+ */
+static void write_span_mono_DITHER_5R6G5B_ximage( MONO_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x, y );
+ const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ PACK_TRUEDITHER(ptr[i], x+i, y, r, g, b);
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/*** Write MONO COLOR PIXELS functions ***/
+/**********************************************************************/
+
+#define MONO_PIXEL_ARGS const GLcontext *ctx, \
+ GLuint n, const GLint x[], const GLint y[], \
+ const GLchan color[4], const GLubyte mask[]
+
+/*
+ * Write an array of identical pixels to a pixmap.
+ */
+static void write_pixels_mono_pixmap( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ XMesaSetForeground( xmesa->display, gc, pixel );
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaDrawPoint( dpy, buffer, gc,
+ (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+static void write_pixels_mono_index_pixmap(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex,
+ const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ XMesaSetForeground( xmesa->display, gc, colorIndex );
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaDrawPoint( dpy, buffer, gc,
+ (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_TRUEDITHER pixels to a pixmap.
+ */
+static void write_pixels_mono_TRUEDITHER_pixmap( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x[i], y[i], r, g, b);
+ XMesaSetForeground( dpy, gc, p );
+ XMesaDrawPoint( dpy, buffer, gc,
+ (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_DITHER pixels to a pixmap.
+ */
+static void write_pixels_mono_DITHER_pixmap( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, DITHER( x[i], y[i], r, g, b ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of PF_1BIT pixels to a pixmap.
+ */
+static void write_pixels_mono_1BIT_pixmap( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ SETUP_1BIT;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, DITHER_1BIT( x[i], y[i], r, g, b ) );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical pixels to an XImage.
+ */
+static void write_pixels_mono_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP],
+ color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), pixel );
+ }
+ }
+}
+
+
+static void write_pixels_mono_index_ximage( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex,
+ const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), colorIndex );
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical TRUEDITHER pixels to an XImage.
+ */
+static void write_pixels_mono_TRUEDITHER_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ PACK_TRUEDITHER(p, x[i], FLIP(xmesa->xm_buffer, y[i]), r, g, b);
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), p );
+ }
+ }
+}
+
+
+
+/*
+ * Write an array of identical 8A8B8G8R pixels to an XImage
+ */
+static void write_pixels_mono_8A8B8G8R_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLuint p = PACK_8A8B8G8R(color[RCOMP], color[GCOMP],
+ color[BCOMP], color[ACOMP]);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = p;
+ }
+ }
+}
+
+/*
+ * Write an array of identical 8A8R8G8B pixels to an XImage
+ */
+static void write_pixels_mono_8A8R8G8B_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLuint p = PACK_8A8R8G8B(color[RCOMP], color[GCOMP],
+ color[BCOMP], color[ACOMP]);
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = p;
+ }
+ }
+}
+
+/*
+ * Write an array of identical 8R8G8B pixels to an XImage.
+ */
+static void write_pixels_mono_8R8G8B_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ const GLuint p = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x[i], y[i] );
+ *ptr = p;
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical 8R8G8B pixels to an XImage.
+ */
+static void write_pixels_mono_8R8G8B24_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ bgr_t *ptr = PIXELADDR3( xmesa->xm_buffer, x[i], y[i] );
+ ptr->r = r;
+ ptr->g = g;
+ ptr->b = b;
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical PF_DITHER pixels to an XImage.
+ */
+static void write_pixels_mono_DITHER_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), DITHER( x[i], y[i], r, g, b ) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_DITHER pixels to an XImage.
+ */
+static void write_pixels_mono_DITHER8_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ DITHER_SETUP;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = (GLubyte) DITHER( x[i], y[i], r, g, b );
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_LOOKUP pixels to an XImage.
+ */
+static void write_pixels_mono_LOOKUP8_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ GLubyte pixel;
+ LOOKUP_SETUP;
+ pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = pixel;
+ }
+ }
+}
+
+
+
+/*
+ * Write an array of identical PF_1BIT pixels to an XImage.
+ */
+static void write_pixels_mono_1BIT_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ SETUP_1BIT;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]),
+ DITHER_1BIT( x[i], y[i], r, g, b ));
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical PF_HPCR pixels to an XImage.
+ */
+static void write_pixels_mono_HPCR_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = DITHER_HPCR( x[i], y[i], r, g, b );
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical 8-bit PF_GRAYSCALE pixels to an XImage.
+ */
+static void write_pixels_mono_GRAYSCALE8_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ register GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer,x[i],y[i]);
+ *ptr = p;
+ }
+ }
+}
+
+
+/*
+ * Write an array of identical PF_DITHER_5R6G5B pixels to an XImage.
+ */
+static void write_pixels_mono_DITHER_5R6G5B_ximage( MONO_PIXEL_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLushort *ptr = PIXELADDR2( xmesa->xm_buffer, x[i], y[i] );
+ PACK_TRUEDITHER(*ptr, x[i], y[i], r, g, b);
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/*** Write INDEX SPAN functions ***/
+/**********************************************************************/
+
+#define INDEX_SPAN_ARGS const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, const GLuint index[], \
+ const GLubyte mask[]
+
+#define INDEX8_SPAN_ARGS const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, const GLubyte index[], \
+ const GLubyte mask[]
+
+
+/*
+ * Write a span of CI pixels to a Pixmap.
+ */
+static void write_span_index_pixmap( INDEX_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+}
+
+
+/*
+ * Write a span of 8-bit CI pixels to a Pixmap.
+ */
+static void write_span_index8_pixmap( INDEX8_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x, (int) y );
+ }
+ }
+}
+
+
+/*
+ * Write a span of CI pixels to an XImage.
+ */
+static void write_span_index_ximage( INDEX_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ y = FLIP(xmesa->xm_buffer, y);
+ if (mask) {
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x, y, (unsigned long) index[i] );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,x++) {
+ XMesaPutPixel( img, x, y, (unsigned long) index[i] );
+ }
+ }
+}
+
+
+/*
+ * Write a span of 8-bit CI pixels to a non 8-bit XImage.
+ */
+static void write_span_index8_ximage( INDEX8_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ if (mask) {
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel(xmesa->xm_buffer->backimage, x+i, y, index[i]);
+ }
+ }
+ }
+ else {
+ GLuint i;
+ for (i=0;i<n;i++) {
+ XMesaPutPixel(xmesa->xm_buffer->backimage, x+i, y, index[i]);
+ }
+ }
+}
+
+/*
+ * Write a span of 8-bit CI pixels to an 8-bit XImage.
+ */
+static void write_span_index8_ximage8( INDEX8_SPAN_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ GLubyte *dst = PIXELADDR1( xmesa->xm_buffer,x,y);
+ if (mask) {
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ dst[i] = index[i];
+ }
+ }
+ }
+ else {
+ MEMCPY( dst, index, n );
+ }
+}
+
+
+
+/**********************************************************************/
+/*** Write INDEX PIXELS functions ***/
+/**********************************************************************/
+
+#define INDEX_PIXELS_ARGS const GLcontext *ctx, \
+ GLuint n, const GLint x[], const GLint y[], \
+ const GLuint index[], const GLubyte mask[]
+
+
+/*
+ * Write an array of CI pixels to a Pixmap.
+ */
+static void write_pixels_index_pixmap( INDEX_PIXELS_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ XMesaDrawable buffer = xmesa->xm_buffer->buffer;
+ XMesaGC gc = xmesa->xm_buffer->gc;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaSetForeground( dpy, gc, (unsigned long) index[i] );
+ XMesaDrawPoint( dpy, buffer, gc, (int) x[i], (int) FLIP(xmesa->xm_buffer, y[i]) );
+ }
+ }
+}
+
+
+/*
+ * Write an array of CI pixels to an XImage.
+ */
+static void write_pixels_index_ximage( INDEX_PIXELS_ARGS )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+ register GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), (unsigned long) index[i] );
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Pixel reading *****/
+/**********************************************************************/
+
+#ifndef XFree86Server
+/**
+ * Do clip testing prior to calling XGetImage. If any of the region lies
+ * outside the screen's bounds, XGetImage will return NULL.
+ * We use XTranslateCoordinates() to check if that's the case and
+ * adjust the x, y and length parameters accordingly.
+ * \return -1 if span is totally clipped away,
+ * else return number of pixels to skip in the destination array.
+ */
+static int
+clip_for_xgetimage(XMesaContext xmesa, GLuint *n, GLint *x, GLint *y)
+{
+ XMesaBuffer source = xmesa->xm_buffer;
+ Window rootWin = RootWindow(xmesa->display, 0);
+ Window child;
+ int screenWidth = WidthOfScreen(DefaultScreenOfDisplay(xmesa->display));
+ int dx, dy;
+ if (source->type == PBUFFER || source->type == PIXMAP)
+ return 0;
+ XTranslateCoordinates(xmesa->display, source->buffer, rootWin,
+ *x, *y, &dx, &dy, &child);
+ if (dx >= screenWidth) {
+ /* totally clipped on right */
+ return -1;
+ }
+ if (dx < 0) {
+ /* clipped on left */
+ int clip = -dx;
+ if (clip >= *n)
+ return -1; /* totally clipped on left */
+ *x += clip;
+ *n -= clip;
+ dx = 0;
+ return clip;
+ }
+ if (dx + *n > screenWidth) {
+ /* clipped on right */
+ int clip = dx + *n - screenWidth;
+ *n -= clip;
+ }
+ return 0;
+}
+#endif
+
+
+/*
+ * Read a horizontal span of color-index pixels.
+ */
+static void read_index_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaBuffer source = xmesa->xm_buffer;
+ GLuint i;
+
+ y = FLIP(source, y);
+
+ if (source->buffer) {
+#ifndef XFree86Server
+ XMesaImage *span = NULL;
+ int error;
+ int k = clip_for_xgetimage(xmesa, &n, &x, &y);
+ if (k < 0)
+ return;
+ index += k;
+
+ catch_xgetimage_errors( xmesa->display );
+ span = XGetImage( xmesa->display, source->buffer,
+ x, y, n, 1, AllPlanes, ZPixmap );
+ error = check_xgetimage_errors();
+ if (span && !error) {
+ for (i=0;i<n;i++) {
+ index[i] = (GLuint) XMesaGetPixel( span, i, 0 );
+ }
+ }
+ else {
+ /* return 0 pixels */
+ for (i=0;i<n;i++) {
+ index[i] = 0;
+ }
+ }
+ if (span) {
+ XMesaDestroyImage( span );
+ }
+#else
+ (*xmesa->display->GetImage)(source->buffer,
+ x, y, n, 1, ZPixmap,
+ ~0L, (pointer)index);
+#endif
+ }
+ else if (source->backimage) {
+ XMesaImage *img = source->backimage;
+ for (i=0;i<n;i++,x++) {
+ index[i] = (GLuint) XMesaGetPixel( img, x, y );
+ }
+ }
+}
+
+
+
+/*
+ * Read a horizontal span of color pixels.
+ */
+static void read_color_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaBuffer source = xmesa->xm_buffer;
+
+ if (source->buffer) {
+ /* Read from Pixmap or Window */
+ XMesaImage *span = NULL;
+ int error;
+#ifdef XFree86Server
+ span = XMesaCreateImage(xmesa->xm_visual->BitsPerPixel, n, 1, NULL);
+ span->data = (char *)MALLOC(span->height * span->bytes_per_line);
+ error = (!span->data);
+ (*xmesa->display->GetImage)(source->buffer,
+ x, FLIP(source, y), n, 1, ZPixmap,
+ ~0L, (pointer)span->data);
+#else
+ int k;
+ y = FLIP(source, y);
+ k = clip_for_xgetimage(xmesa, &n, &x, &y);
+ if (k < 0)
+ return;
+ rgba += k;
+ catch_xgetimage_errors( xmesa->display );
+ span = XGetImage( xmesa->display, source->buffer,
+ x, y, n, 1, AllPlanes, ZPixmap );
+ error = check_xgetimage_errors();
+#endif
+ if (span && !error) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ case PF_Dither_True:
+ {
+ const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+ unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+ unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+ GLint rShift = xmesa->xm_visual->rshift;
+ GLint gShift = xmesa->xm_visual->gshift;
+ GLint bShift = xmesa->xm_visual->bshift;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ p = XMesaGetPixel( span, i, 0 );
+ rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+ rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+ rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_5R6G5B:
+ case PF_Dither_5R6G5B:
+ {
+ const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p = XMesaGetPixel( span, i, 0 );
+ /* fast, but not quite accurate
+ rgba[i][RCOMP] = ((p >> 8) & 0xf8);
+ rgba[i][GCOMP] = ((p >> 3) & 0xfc);
+ rgba[i][BCOMP] = ((p << 3) & 0xff);
+ */
+ rgba[i][RCOMP] = pixelToR[p >> 11];
+ rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+ rgba[i][BCOMP] = pixelToB[p & 0x1f];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_8A8B8G8R:
+ {
+ const GLuint *ptr4 = (GLuint *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8A8R8G8B:
+ {
+ const GLuint *ptr4 = (GLuint *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8R8G8B:
+ {
+ const GLuint *ptr4 = (GLuint *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_8R8G8B24:
+ {
+ const bgr_t *ptr3 = (bgr_t *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP] = ptr3[i].r;
+ rgba[i][GCOMP] = ptr3[i].g;
+ rgba[i][BCOMP] = ptr3[i].b;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_HPCR:
+ {
+ GLubyte *ptr1 = (GLubyte *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLubyte p = *ptr1++;
+ rgba[i][RCOMP] = p & 0xE0;
+ rgba[i][GCOMP] = (p & 0x1C) << 3;
+ rgba[i][BCOMP] = (p & 0x03) << 6;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_Dither:
+ case PF_Lookup:
+ case PF_Grayscale:
+ {
+ GLubyte *rTable = source->pixel_to_r;
+ GLubyte *gTable = source->pixel_to_g;
+ GLubyte *bTable = source->pixel_to_b;
+ if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
+ const GLubyte *ptr1 = (GLubyte *) span->data;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p = *ptr1++;
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ else {
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p = XMesaGetPixel( span, i, 0 );
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_1Bit:
+ {
+ int bitFlip = xmesa->xm_visual->bitFlip;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ p = XMesaGetPixel( span, i, 0 ) ^ bitFlip;
+ rgba[i][RCOMP] = (GLubyte) (p * 255);
+ rgba[i][GCOMP] = (GLubyte) (p * 255);
+ rgba[i][BCOMP] = (GLubyte) (p * 255);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL,"Problem in DD.read_color_span (1)");
+ return;
+ }
+ }
+ else {
+ /* return black pixels */
+ GLuint i;
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP] = rgba[i][GCOMP] = rgba[i][BCOMP] = rgba[i][ACOMP] = 0;
+ }
+ }
+ if (span) {
+ XMesaDestroyImage( span );
+ }
+ }
+ else if (source->backimage) {
+ /* Read from XImage back buffer */
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ case PF_Dither_True:
+ {
+ const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+ unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+ unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+ GLint rShift = xmesa->xm_visual->rshift;
+ GLint gShift = xmesa->xm_visual->gshift;
+ GLint bShift = xmesa->xm_visual->bshift;
+ XMesaImage *img = source->backimage;
+ GLuint i;
+ y = FLIP(source, y);
+ for (i=0;i<n;i++) {
+ unsigned long p;
+ p = XMesaGetPixel( img, x+i, y );
+ rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+ rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+ rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_5R6G5B:
+ case PF_Dither_5R6G5B:
+ {
+ const GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ const GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ const GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ const GLushort *ptr2 = PIXELADDR2( source, x, y );
+ GLuint i;
+#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */
+ const GLuint *ptr4 = (const GLuint *) ptr2;
+ GLuint extraPixel = (n & 1);
+ n -= extraPixel;
+ for (i = 0; i < n; i += 2) {
+ const GLuint p = *ptr4++;
+ const GLuint p0 = p & 0xffff;
+ const GLuint p1 = p >> 16;
+ /* fast, but not quite accurate
+ rgba[i][RCOMP] = ((p >> 8) & 0xf8);
+ rgba[i][GCOMP] = ((p >> 3) & 0xfc);
+ rgba[i][BCOMP] = ((p << 3) & 0xff);
+ */
+ rgba[i][RCOMP] = pixelToR[p0 >> 11];
+ rgba[i][GCOMP] = pixelToG[(p0 >> 5) & 0x3f];
+ rgba[i][BCOMP] = pixelToB[p0 & 0x1f];
+ rgba[i][ACOMP] = 255;
+ rgba[i+1][RCOMP] = pixelToR[p1 >> 11];
+ rgba[i+1][GCOMP] = pixelToG[(p1 >> 5) & 0x3f];
+ rgba[i+1][BCOMP] = pixelToB[p1 & 0x1f];
+ rgba[i+1][ACOMP] = 255;
+ }
+ if (extraPixel) {
+ GLushort p = ptr2[n];
+ rgba[n][RCOMP] = pixelToR[p >> 11];
+ rgba[n][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+ rgba[n][BCOMP] = pixelToB[p & 0x1f];
+ rgba[n][ACOMP] = 255;
+ }
+#else
+ for (i = 0; i < n; i++) {
+ const GLushort p = ptr2[i];
+ rgba[i][RCOMP] = pixelToR[p >> 11];
+ rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f];
+ rgba[i][BCOMP] = pixelToB[p & 0x1f];
+ rgba[i][ACOMP] = 255;
+ }
+#endif
+ }
+ break;
+ case PF_8A8B8G8R:
+ {
+ const GLuint *ptr4 = PIXELADDR4( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8A8R8G8B:
+ {
+ const GLuint *ptr4 = PIXELADDR4( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8R8G8B:
+ {
+ const GLuint *ptr4 = PIXELADDR4( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLuint p4 = *ptr4++;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_8R8G8B24:
+ {
+ const bgr_t *ptr3 = PIXELADDR3( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP] = ptr3[i].r;
+ rgba[i][GCOMP] = ptr3[i].g;
+ rgba[i][BCOMP] = ptr3[i].b;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_HPCR:
+ {
+ const GLubyte *ptr1 = PIXELADDR1( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLubyte p = *ptr1++;
+ rgba[i][RCOMP] = p & 0xE0;
+ rgba[i][GCOMP] = (p & 0x1C) << 3;
+ rgba[i][BCOMP] = (p & 0x03) << 6;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_Dither:
+ case PF_Lookup:
+ case PF_Grayscale:
+ {
+ const GLubyte *rTable = source->pixel_to_r;
+ const GLubyte *gTable = source->pixel_to_g;
+ const GLubyte *bTable = source->pixel_to_b;
+ if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) {
+ GLubyte *ptr1 = PIXELADDR1( source, x, y );
+ GLuint i;
+ for (i=0;i<n;i++) {
+ unsigned long p = *ptr1++;
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ else {
+ XMesaImage *img = source->backimage;
+ GLuint i;
+ y = FLIP(source, y);
+ for (i=0;i<n;i++,x++) {
+ unsigned long p = XMesaGetPixel( img, x, y );
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_1Bit:
+ {
+ XMesaImage *img = source->backimage;
+ int bitFlip = xmesa->xm_visual->bitFlip;
+ GLuint i;
+ y = FLIP(source, y);
+ for (i=0;i<n;i++,x++) {
+ unsigned long p;
+ p = XMesaGetPixel( img, x, y ) ^ bitFlip;
+ rgba[i][RCOMP] = (GLubyte) (p * 255);
+ rgba[i][GCOMP] = (GLubyte) (p * 255);
+ rgba[i][BCOMP] = (GLubyte) (p * 255);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL,"Problem in DD.read_color_span (2)");
+ return;
+ }
+ }
+}
+
+
+
+/*
+ * Read an array of color index pixels.
+ */
+static void read_index_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ register GLuint i;
+ XMesaBuffer source = xmesa->xm_buffer;
+
+ if (source->buffer) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ indx[i] = (GLuint) read_pixel( xmesa->display,
+ source->buffer,
+ x[i], FLIP(source, y[i]) );
+ }
+ }
+ }
+ else if (source->backimage) {
+ XMesaImage *img = source->backimage;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ indx[i] = (GLuint) XMesaGetPixel( img, x[i], FLIP(source, y[i]) );
+ }
+ }
+ }
+}
+
+
+
+static void read_color_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ XMesaDisplay *dpy = xmesa->xm_visual->display;
+ register GLuint i;
+ XMesaBuffer source = xmesa->xm_buffer;
+ XMesaDrawable buffer = source->buffer; /* the X drawable */
+
+ if (source->buffer) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ case PF_Dither_True:
+ case PF_5R6G5B:
+ case PF_Dither_5R6G5B:
+ {
+ unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+ unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+ unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+ GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ GLint rShift = xmesa->xm_visual->rshift;
+ GLint gShift = xmesa->xm_visual->gshift;
+ GLint bShift = xmesa->xm_visual->bshift;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+ rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+ rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_8A8B8G8R:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = (GLubyte) ( p & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ((p >> 16) & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8A8R8G8B:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8R8G8B:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p & 0xff);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_8R8G8B24:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = (GLubyte) ((p >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p & 0xff);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_HPCR:
+ {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = (GLubyte) ( p & 0xE0 );
+ rgba[i][GCOMP] = (GLubyte) ((p & 0x1C) << 3);
+ rgba[i][BCOMP] = (GLubyte) ((p & 0x03) << 6);
+ rgba[i][ACOMP] = (GLubyte) 255;
+ }
+ }
+ }
+ break;
+ case PF_Dither:
+ case PF_Lookup:
+ case PF_Grayscale:
+ {
+ GLubyte *rTable = source->pixel_to_r;
+ GLubyte *gTable = source->pixel_to_g;
+ GLubyte *bTable = source->pixel_to_b;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_1Bit:
+ {
+ int bitFlip = xmesa->xm_visual->bitFlip;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p = read_pixel( dpy, buffer,
+ x[i], FLIP(source, y[i])) ^ bitFlip;
+ rgba[i][RCOMP] = (GLubyte) (p * 255);
+ rgba[i][GCOMP] = (GLubyte) (p * 255);
+ rgba[i][BCOMP] = (GLubyte) (p * 255);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)");
+ return;
+ }
+ }
+ else if (source->backimage) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ case PF_Dither_True:
+ case PF_5R6G5B:
+ case PF_Dither_5R6G5B:
+ {
+ unsigned long rMask = GET_REDMASK(xmesa->xm_visual);
+ unsigned long gMask = GET_GREENMASK(xmesa->xm_visual);
+ unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual);
+ GLubyte *pixelToR = xmesa->xm_visual->PixelToR;
+ GLubyte *pixelToG = xmesa->xm_visual->PixelToG;
+ GLubyte *pixelToB = xmesa->xm_visual->PixelToB;
+ GLint rShift = xmesa->xm_visual->rshift;
+ GLint gShift = xmesa->xm_visual->gshift;
+ GLint bShift = xmesa->xm_visual->bshift;
+ XMesaImage *img = source->backimage;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ p = XMesaGetPixel( img, x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = pixelToR[(p & rMask) >> rShift];
+ rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift];
+ rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_8A8B8G8R:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4( source, x[i], y[i] );
+ GLuint p4 = *ptr4;
+ rgba[i][RCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8A8R8G8B:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4( source, x[i], y[i] );
+ GLuint p4 = *ptr4;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff);
+ }
+ }
+ break;
+ case PF_8R8G8B:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4( source, x[i], y[i] );
+ GLuint p4 = *ptr4;
+ rgba[i][RCOMP] = (GLubyte) ((p4 >> 16) & 0xff);
+ rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff);
+ rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_8R8G8B24:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ bgr_t *ptr3 = PIXELADDR3( source, x[i], y[i] );
+ rgba[i][RCOMP] = ptr3->r;
+ rgba[i][GCOMP] = ptr3->g;
+ rgba[i][BCOMP] = ptr3->b;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_HPCR:
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr1 = PIXELADDR1( source, x[i], y[i] );
+ GLubyte p = *ptr1;
+ rgba[i][RCOMP] = p & 0xE0;
+ rgba[i][GCOMP] = (p & 0x1C) << 3;
+ rgba[i][BCOMP] = (p & 0x03) << 6;
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ break;
+ case PF_Dither:
+ case PF_Lookup:
+ case PF_Grayscale:
+ {
+ GLubyte *rTable = source->pixel_to_r;
+ GLubyte *gTable = source->pixel_to_g;
+ GLubyte *bTable = source->pixel_to_b;
+ XMesaImage *img = source->backimage;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ p = XMesaGetPixel( img, x[i], FLIP(source, y[i]) );
+ rgba[i][RCOMP] = rTable[p];
+ rgba[i][GCOMP] = gTable[p];
+ rgba[i][BCOMP] = bTable[p];
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ case PF_1Bit:
+ {
+ XMesaImage *img = source->backimage;
+ int bitFlip = xmesa->xm_visual->bitFlip;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ unsigned long p;
+ p = XMesaGetPixel( img, x[i], FLIP(source, y[i]) ) ^ bitFlip;
+ rgba[i][RCOMP] = (GLubyte) (p * 255);
+ rgba[i][GCOMP] = (GLubyte) (p * 255);
+ rgba[i][BCOMP] = (GLubyte) (p * 255);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ }
+ break;
+ default:
+ _mesa_problem(NULL,"Problem in DD.read_color_pixels (1)");
+ return;
+ }
+ }
+}
+
+
+static void
+clear_color_HPCR_ximage( GLcontext *ctx, const GLfloat color[4] )
+{
+ int i;
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+
+ if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
+ /* black is black */
+ MEMSET( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 ,
+ sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern));
+ }
+ else {
+ /* build clear pattern */
+ for (i=0; i<16; i++) {
+ xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] =
+ DITHER_HPCR(i, 0,
+ xmesa->clearcolor[0],
+ xmesa->clearcolor[1],
+ xmesa->clearcolor[2]);
+ xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i] =
+ DITHER_HPCR(i, 1,
+ xmesa->clearcolor[0],
+ xmesa->clearcolor[1],
+ xmesa->clearcolor[2]);
+ }
+ }
+}
+
+
+static void
+clear_color_HPCR_pixmap( GLcontext *ctx, const GLfloat color[4] )
+{
+ int i;
+ const XMesaContext xmesa = XMESA_CONTEXT(ctx);
+
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]);
+
+ if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) {
+ /* black is black */
+ for (i=0; i<16; i++) {
+ XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0);
+ XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0);
+ }
+ }
+ else {
+ for (i=0; i<16; i++) {
+ XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0,
+ DITHER_HPCR(i, 0,
+ xmesa->clearcolor[0],
+ xmesa->clearcolor[1],
+ xmesa->clearcolor[2]));
+ XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1,
+ DITHER_HPCR(i, 1,
+ xmesa->clearcolor[0],
+ xmesa->clearcolor[1],
+ xmesa->clearcolor[2]));
+ }
+ }
+ /* change tile pixmap content */
+ XMesaPutImage(xmesa->display,
+ (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap,
+ xmesa->xm_buffer->cleargc,
+ xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2);
+}
+
+
+
+void xmesa_update_span_funcs( GLcontext *ctx )
+{
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ int depth=GET_VISUAL_DEPTH(xmesa->xm_visual);
+ struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference( ctx );
+
+ /*
+ * These drawing functions depend on color buffer config:
+ */
+ if (xmesa->xm_buffer->buffer!=XIMAGE) {
+ /* Writing to window or back pixmap */
+ switch (xmesa->pixelformat) {
+ case PF_Index:
+ dd->WriteCI32Span = write_span_index_pixmap;
+ dd->WriteCI8Span = write_span_index8_pixmap;
+ dd->WriteMonoCISpan = write_span_mono_index_pixmap;
+ dd->WriteCI32Pixels = write_pixels_index_pixmap;
+ dd->WriteMonoCIPixels = write_pixels_mono_index_pixmap;
+ break;
+ case PF_Truecolor:
+ dd->WriteRGBASpan = write_span_TRUECOLOR_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_TRUECOLOR_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_TRUECOLOR_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_Dither_True:
+ dd->WriteRGBASpan = write_span_TRUEDITHER_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_TRUEDITHER_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_pixmap;
+ dd->WriteRGBAPixels = write_pixels_TRUEDITHER_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_pixmap;
+ break;
+ case PF_8A8B8G8R:
+ dd->WriteRGBASpan = write_span_8A8B8G8R_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_8A8B8G8R_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_8A8B8G8R_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_8A8R8G8B:
+ dd->WriteRGBASpan = write_span_8A8R8G8B_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_8A8R8G8B_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_8A8R8G8B_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_8R8G8B:
+ dd->WriteRGBASpan = write_span_8R8G8B_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_8R8G8B_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_8R8G8B_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_8R8G8B24:
+ dd->WriteRGBASpan = write_span_8R8G8B24_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_8R8G8B24_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_8R8G8B24_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_5R6G5B:
+ dd->WriteRGBASpan = write_span_5R6G5B_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_5R6G5B_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_5R6G5B_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_Dither_5R6G5B:
+ dd->WriteRGBASpan = write_span_DITHER_5R6G5B_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_DITHER_5R6G5B_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_pixmap;
+ dd->WriteRGBAPixels = write_pixels_DITHER_5R6G5B_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_pixmap;
+ break;
+ case PF_Dither:
+ dd->WriteRGBASpan = write_span_DITHER_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_DITHER_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_DITHER_pixmap;
+ dd->WriteRGBAPixels = write_pixels_DITHER_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_pixmap;
+ break;
+ case PF_1Bit:
+ dd->WriteRGBASpan = write_span_1BIT_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_1BIT_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_1BIT_pixmap;
+ dd->WriteRGBAPixels = write_pixels_1BIT_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_1BIT_pixmap;
+ break;
+ case PF_HPCR:
+ dd->WriteRGBASpan = write_span_HPCR_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_HPCR_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_HPCR_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ if (xmesa->xm_visual->hpcr_clear_flag) {
+ ctx->Driver.ClearColor = clear_color_HPCR_pixmap;
+ }
+ break;
+ case PF_Lookup:
+ dd->WriteRGBASpan = write_span_LOOKUP_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_LOOKUP_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_LOOKUP_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ case PF_Grayscale:
+ dd->WriteRGBASpan = write_span_GRAYSCALE_pixmap;
+ dd->WriteRGBSpan = write_span_rgb_GRAYSCALE_pixmap;
+ dd->WriteMonoRGBASpan = write_span_mono_pixmap;
+ dd->WriteRGBAPixels = write_pixels_GRAYSCALE_pixmap;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap;
+ break;
+ default:
+ _mesa_problem(NULL,"Bad pixel format in xmesa_update_state (1)");
+ return;
+ }
+ }
+ else if (xmesa->xm_buffer->buffer==XIMAGE) {
+ /* Writing to back XImage */
+ switch (xmesa->pixelformat) {
+ case PF_Index:
+ dd->WriteCI32Span = write_span_index_ximage;
+ if (depth==8)
+ dd->WriteCI8Span = write_span_index8_ximage8;
+ else
+ dd->WriteCI8Span = write_span_index8_ximage;
+ dd->WriteMonoCISpan = write_span_mono_index_ximage;
+ dd->WriteCI32Pixels = write_pixels_index_ximage;
+ dd->WriteMonoCIPixels = write_pixels_mono_index_ximage;
+ break;
+ case PF_Truecolor:
+ /* Generic RGB */
+ dd->WriteRGBASpan = write_span_TRUECOLOR_ximage;
+ dd->WriteRGBSpan = write_span_rgb_TRUECOLOR_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_ximage;
+ dd->WriteRGBAPixels = write_pixels_TRUECOLOR_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_ximage;
+ break;
+ case PF_Dither_True:
+ dd->WriteRGBASpan = write_span_TRUEDITHER_ximage;
+ dd->WriteRGBSpan = write_span_rgb_TRUEDITHER_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_ximage;
+ dd->WriteRGBAPixels = write_pixels_TRUEDITHER_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_ximage;
+ break;
+ case PF_8A8B8G8R:
+ dd->WriteRGBASpan = write_span_8A8B8G8R_ximage;
+ dd->WriteRGBSpan = write_span_rgb_8A8B8G8R_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_8A8B8G8R_ximage;
+ dd->WriteRGBAPixels = write_pixels_8A8B8G8R_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_8A8B8G8R_ximage;
+ break;
+ case PF_8A8R8G8B:
+ dd->WriteRGBASpan = write_span_8A8R8G8B_ximage;
+ dd->WriteRGBSpan = write_span_rgb_8A8R8G8B_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_8A8R8G8B_ximage;
+ dd->WriteRGBAPixels = write_pixels_8A8R8G8B_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_8A8R8G8B_ximage;
+ break;
+ case PF_8R8G8B:
+ dd->WriteRGBASpan = write_span_8R8G8B_ximage;
+ dd->WriteRGBSpan = write_span_rgb_8R8G8B_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_8R8G8B_ximage;
+ dd->WriteRGBAPixels = write_pixels_8R8G8B_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_8R8G8B_ximage;
+ break;
+ case PF_8R8G8B24:
+ dd->WriteRGBASpan = write_span_8R8G8B24_ximage;
+ dd->WriteRGBSpan = write_span_rgb_8R8G8B24_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_8R8G8B24_ximage;
+ dd->WriteRGBAPixels = write_pixels_8R8G8B24_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_8R8G8B24_ximage;
+ break;
+ case PF_5R6G5B:
+ dd->WriteRGBASpan = write_span_5R6G5B_ximage;
+ dd->WriteRGBSpan = write_span_rgb_5R6G5B_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_ximage;
+ dd->WriteRGBAPixels = write_pixels_5R6G5B_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_ximage;
+ break;
+ case PF_Dither_5R6G5B:
+ dd->WriteRGBASpan = write_span_DITHER_5R6G5B_ximage;
+ dd->WriteRGBSpan = write_span_rgb_DITHER_5R6G5B_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_DITHER_5R6G5B_ximage;
+ dd->WriteRGBAPixels = write_pixels_DITHER_5R6G5B_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_5R6G5B_ximage;
+ break;
+ case PF_Dither:
+ if (depth==8) {
+ dd->WriteRGBASpan = write_span_DITHER8_ximage;
+ dd->WriteRGBSpan = write_span_rgb_DITHER8_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_DITHER8_ximage;
+ dd->WriteRGBAPixels = write_pixels_DITHER8_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER8_ximage;
+ }
+ else {
+ dd->WriteRGBASpan = write_span_DITHER_ximage;
+ dd->WriteRGBSpan = write_span_rgb_DITHER_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_DITHER_ximage;
+ dd->WriteRGBAPixels = write_pixels_DITHER_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_ximage;
+ }
+ break;
+ case PF_1Bit:
+ dd->WriteRGBASpan = write_span_1BIT_ximage;
+ dd->WriteRGBSpan = write_span_rgb_1BIT_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_1BIT_ximage;
+ dd->WriteRGBAPixels = write_pixels_1BIT_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_1BIT_ximage;
+ break;
+ case PF_HPCR:
+ dd->WriteRGBASpan = write_span_HPCR_ximage;
+ dd->WriteRGBSpan = write_span_rgb_HPCR_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_HPCR_ximage;
+ dd->WriteRGBAPixels = write_pixels_HPCR_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_HPCR_ximage;
+ if (xmesa->xm_visual->hpcr_clear_flag) {
+ ctx->Driver.ClearColor = clear_color_HPCR_ximage;
+ }
+ break;
+ case PF_Lookup:
+ if (depth==8) {
+ dd->WriteRGBASpan = write_span_LOOKUP8_ximage;
+ dd->WriteRGBSpan = write_rgb_LOOKUP8_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_LOOKUP8_ximage;
+ dd->WriteRGBAPixels = write_pixels_LOOKUP8_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_LOOKUP8_ximage;
+ }
+ else {
+ dd->WriteRGBASpan = write_span_LOOKUP_ximage;
+ dd->WriteRGBSpan = write_span_rgb_LOOKUP_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_ximage;
+ dd->WriteRGBAPixels = write_pixels_LOOKUP_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_ximage;
+ }
+ break;
+ case PF_Grayscale:
+ if (depth==8) {
+ dd->WriteRGBASpan = write_span_GRAYSCALE8_ximage;
+ dd->WriteRGBSpan = write_span_rgb_GRAYSCALE8_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_GRAYSCALE8_ximage;
+ dd->WriteRGBAPixels = write_pixels_GRAYSCALE8_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_GRAYSCALE8_ximage;
+ }
+ else {
+ dd->WriteRGBASpan = write_span_GRAYSCALE_ximage;
+ dd->WriteRGBSpan = write_span_rgb_GRAYSCALE_ximage;
+ dd->WriteMonoRGBASpan = write_span_mono_ximage;
+ dd->WriteRGBAPixels = write_pixels_GRAYSCALE_ximage;
+ dd->WriteMonoRGBAPixels = write_pixels_mono_ximage;
+ }
+ break;
+ default:
+ _mesa_problem(NULL,"Bad pixel format in xmesa_update_state (2)");
+ return;
+ }
+ }
+
+ /* Pixel/span reading functions: */
+ dd->ReadCI32Span = read_index_span;
+ dd->ReadRGBASpan = read_color_span;
+ dd->ReadCI32Pixels = read_index_pixels;
+ dd->ReadRGBAPixels = read_color_pixels;
+}
diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c
new file mode 100644
index 0000000..9a71f91
--- /dev/null
+++ b/src/mesa/drivers/x11/xm_tri.c
@@ -0,0 +1,1609 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 5.1
+ *
+ * Copyright (C) 1999-2002 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.
+ */
+
+
+/*
+ * This file contains "accelerated" triangle functions. It should be
+ * fairly easy to write new special-purpose triangle functions and hook
+ * them into this module.
+ */
+
+
+#include "glxheader.h"
+#include "depth.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "xmesaP.h"
+
+/* Internal swrast includes:
+ */
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_triangle.h"
+
+
+
+/**********************************************************************/
+/*** Triangle rendering ***/
+/**********************************************************************/
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME smooth_TRUECOLOR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+
+#define RENDER_SPAN( span ) \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ GLuint i; \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ unsigned long p; \
+ PACK_TRUECOLOR(p, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ XMesaPutPixel(img, x, y, p); \
+ zRow[i] = z; \
+ } \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ span.z += span.zStep; \
+ }
+
+#include "swrast/s_tritemp.h"
+
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME smooth_8A8B8G8R_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8B8G8R(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME smooth_8A8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME smooth_8R8G8B24_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ PIXEL_TYPE *ptr = pRow + i; \
+ ptr->r = FixedToInt(span.red); \
+ ptr->g = FixedToInt(span.green); \
+ ptr->b = FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME smooth_TRUEDITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ unsigned long p; \
+ PACK_TRUEDITHER(p, x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ XMesaPutPixel(img, x, y, p); \
+ zRow[i] = z; \
+ } \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME smooth_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_5R6G5B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME smooth_DITHER_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+ */
+#define NAME smooth_DITHER8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ XDITHER_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),\
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ XDITHER_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ unsigned long p = XDITHER(x, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ XMesaPutPixel(img, x, y, p); \
+ zRow[i] = z; \
+ } \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME smooth_LOOKUP8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ LOOKUP_SETUP; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = LOOKUP(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME smooth_HPCR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(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"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME flat_TRUECOLOR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ unsigned long pixel; \
+ PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ XMesaPutPixel(img, x, y, pixel); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME flat_8A8B8G8R_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8B8G8R( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME flat_8A8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8R8G8B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME flat_8R8G8B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8R8G8B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME flat_8R8G8B24_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = v2->color;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ PIXEL_TYPE *ptr = pRow + i; \
+ ptr->r = color[RCOMP]; \
+ ptr->g = color[GCOMP]; \
+ ptr->b = color[BCOMP]; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME flat_TRUEDITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ unsigned long p; \
+ PACK_TRUEDITHER(p, x, y, v2->color[0], \
+ v2->color[1], v2->color[2]); \
+ XMesaPutPixel(img, x, y, p); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME flat_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_5R6G5B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME flat_DITHER_5R6G5B_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = v2->color;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP], \
+ color[GCOMP], color[BCOMP]); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME flat_DITHER8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y)); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, PF_DITHER triangle.
+ */
+#define NAME flat_DITHER_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ FLAT_DITHER_ROW_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ unsigned long p = FLAT_DITHER(x); \
+ XMesaPutPixel(img, x, y, p); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME flat_HPCR_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ GLubyte r = v2->color[0]; \
+ GLubyte g = v2->color[1]; \
+ GLubyte b = v2->color[2];
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b); \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME flat_LOOKUP8_z_triangle
+#define INTERP_Z 1
+#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ LOOKUP_SETUP; \
+ GLubyte r = v2->color[0]; \
+ GLubyte g = v2->color[1]; \
+ GLubyte b = v2->color[2]; \
+ GLubyte p = LOOKUP(r,g,b);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ const DEPTH_TYPE z = FixedToDepth(span.z); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ span.z += span.zStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME smooth_TRUECOLOR_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ unsigned long p; \
+ PACK_TRUECOLOR(p, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ XMesaPutPixel(img, x, y, p); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME smooth_8A8B8G8R_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = PACK_8B8G8R(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue) ); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME smooth_8A8R8G8B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue) ); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue) ); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME smooth_8R8G8B24_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (i = 0; i < span.end; i++, pixel++) { \
+ pixel->r = FixedToInt(span.red); \
+ pixel->g = FixedToInt(span.green); \
+ pixel->b = FixedToInt(span.blue); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME smooth_TRUEDITHER_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ unsigned long p; \
+ PACK_TRUEDITHER(p, x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ XMesaPutPixel(img, x, y, p ); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME smooth_5R6G5B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) PACK_5R6G5B(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME smooth_DITHER_5R6G5B_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER8_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ XDITHER_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue) ); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_DITHER triangle.
+ */
+#define NAME smooth_DITHER_triangle
+#define INTERP_RGB 1
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ XDITHER_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ unsigned long p = XDITHER(x, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue) ); \
+ XMesaPutPixel(img, x, y, p); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME smooth_LOOKUP8_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ LOOKUP_SETUP; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = LOOKUP(FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME smooth_HPCR_triangle
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red), \
+ FixedToInt(span.green), FixedToInt(span.blue)); \
+ span.red += span.redStep; \
+ span.green += span.greenStep; \
+ span.blue += span.blueStep; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_TRUECOLOR triangle.
+ */
+#define NAME flat_TRUECOLOR_triangle
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ unsigned long pixel; \
+ PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ XMesaPutPixel(img, x, y, pixel); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+#define NAME flat_8A8B8G8R_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8B8G8R( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8A8R8G8B triangle.
+ */
+#define NAME flat_8A8R8G8B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8R8G8B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+#define NAME flat_8R8G8B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLuint
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_8R8G8B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8R8G8B24 triangle.
+ */
+#define NAME flat_8R8G8B24_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE bgr_t
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = v2->color;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (i = 0; i < span.end; i++, pixel++) { \
+ pixel->r = color[RCOMP]; \
+ pixel->g = color[GCOMP]; \
+ pixel->b = color[BCOMP]; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_TRUEDITHER triangle.
+ */
+#define NAME flat_TRUEDITHER_triangle
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ unsigned long p; \
+ PACK_TRUEDITHER(p, x, y, v2->color[0], \
+ v2->color[1], v2->color[2] ); \
+ XMesaPutPixel(img, x, y, p); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+#define NAME flat_5R6G5B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ unsigned long p = PACK_5R6G5B( v2->color[0], \
+ v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_DITHER_5R6G5B triangle.
+ */
+#define NAME flat_DITHER_5R6G5B_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLushort
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ const GLubyte *color = v2->color;
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP], \
+ color[GCOMP], color[BCOMP]); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+#define NAME flat_DITHER8_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y)); \
+ for (i = 0; i < span.end; i++, x++) { \
+ pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_DITHER triangle.
+ */
+#define NAME flat_DITHER_triangle
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ XMesaImage *img = xmesa->xm_buffer->backimage; \
+ FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] );
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ FLAT_DITHER_ROW_SETUP(y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ unsigned long p = FLAT_DITHER(x); \
+ XMesaPutPixel(img, x, y, p ); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_HPCR triangle.
+ */
+#define NAME flat_HPCR_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ GLubyte r = v2->color[0]; \
+ GLubyte g = v2->color[1]; \
+ GLubyte b = v2->color[2];
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \
+ for (i = 0; i < span.end; i++, x++) { \
+ pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b); \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+#define NAME flat_LOOKUP8_triangle
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line)
+#define SETUP_CODE \
+ XMesaContext xmesa = XMESA_CONTEXT(ctx); \
+ LOOKUP_SETUP; \
+ GLubyte r = v2->color[0]; \
+ GLubyte g = v2->color[1]; \
+ GLubyte b = v2->color[2]; \
+ GLubyte p = LOOKUP(r,g,b);
+#define RENDER_SPAN( span ) \
+ GLuint i; \
+ for (i = 0; i < span.end; i++) { \
+ pRow[i] = (PIXEL_TYPE) p; \
+ }
+#include "swrast/s_tritemp.h"
+
+
+
+#ifdef DEBUG
+extern void _xmesa_print_triangle_func( swrast_tri_func triFunc );
+void _xmesa_print_triangle_func( swrast_tri_func triFunc )
+{
+ _mesa_printf("XMesa tri func = ");
+ if (triFunc ==smooth_TRUECOLOR_z_triangle)
+ _mesa_printf("smooth_TRUECOLOR_z_triangle\n");
+ else if (triFunc ==smooth_8A8B8G8R_z_triangle)
+ _mesa_printf("smooth_8A8B8G8R_z_triangle\n");
+ else if (triFunc ==smooth_8A8R8G8B_z_triangle)
+ _mesa_printf("smooth_8A8R8G8B_z_triangle\n");
+ else if (triFunc ==smooth_8R8G8B_z_triangle)
+ _mesa_printf("smooth_8R8G8B_z_triangle\n");
+ else if (triFunc ==smooth_8R8G8B24_z_triangle)
+ _mesa_printf("smooth_8R8G8B24_z_triangle\n");
+ else if (triFunc ==smooth_TRUEDITHER_z_triangle)
+ _mesa_printf("smooth_TRUEDITHER_z_triangle\n");
+ else if (triFunc ==smooth_5R6G5B_z_triangle)
+ _mesa_printf("smooth_5R6G5B_z_triangle\n");
+ else if (triFunc ==smooth_DITHER_5R6G5B_z_triangle)
+ _mesa_printf("smooth_DITHER_5R6G5B_z_triangle\n");
+ else if (triFunc ==smooth_HPCR_z_triangle)
+ _mesa_printf("smooth_HPCR_z_triangle\n");
+ else if (triFunc ==smooth_DITHER8_z_triangle)
+ _mesa_printf("smooth_DITHER8_z_triangle\n");
+ else if (triFunc ==smooth_LOOKUP8_z_triangle)
+ _mesa_printf("smooth_LOOKUP8_z_triangle\n");
+ else if (triFunc ==flat_TRUECOLOR_z_triangle)
+ _mesa_printf("flat_TRUECOLOR_z_triangle\n");
+ else if (triFunc ==flat_8A8B8G8R_z_triangle)
+ _mesa_printf("flat_8A8B8G8R_z_triangle\n");
+ else if (triFunc ==flat_8A8R8G8B_z_triangle)
+ _mesa_printf("flat_8A8R8G8B_z_triangle\n");
+ else if (triFunc ==flat_8R8G8B_z_triangle)
+ _mesa_printf("flat_8R8G8B_z_triangle\n");
+ else if (triFunc ==flat_8R8G8B24_z_triangle)
+ _mesa_printf("flat_8R8G8B24_z_triangle\n");
+ else if (triFunc ==flat_TRUEDITHER_z_triangle)
+ _mesa_printf("flat_TRUEDITHER_z_triangle\n");
+ else if (triFunc ==flat_5R6G5B_z_triangle)
+ _mesa_printf("flat_5R6G5B_z_triangle\n");
+ else if (triFunc ==flat_DITHER_5R6G5B_z_triangle)
+ _mesa_printf("flat_DITHER_5R6G5B_z_triangle\n");
+ else if (triFunc ==flat_HPCR_z_triangle)
+ _mesa_printf("flat_HPCR_z_triangle\n");
+ else if (triFunc ==flat_DITHER8_z_triangle)
+ _mesa_printf("flat_DITHER8_z_triangle\n");
+ else if (triFunc ==flat_LOOKUP8_z_triangle)
+ _mesa_printf("flat_LOOKUP8_z_triangle\n");
+ else if (triFunc ==smooth_TRUECOLOR_triangle)
+ _mesa_printf("smooth_TRUECOLOR_triangle\n");
+ else if (triFunc ==smooth_8A8B8G8R_triangle)
+ _mesa_printf("smooth_8A8B8G8R_triangle\n");
+ else if (triFunc ==smooth_8A8R8G8B_triangle)
+ _mesa_printf("smooth_8A8R8G8B_triangle\n");
+ else if (triFunc ==smooth_8R8G8B_triangle)
+ _mesa_printf("smooth_8R8G8B_triangle\n");
+ else if (triFunc ==smooth_8R8G8B24_triangle)
+ _mesa_printf("smooth_8R8G8B24_triangle\n");
+ else if (triFunc ==smooth_TRUEDITHER_triangle)
+ _mesa_printf("smooth_TRUEDITHER_triangle\n");
+ else if (triFunc ==smooth_5R6G5B_triangle)
+ _mesa_printf("smooth_5R6G5B_triangle\n");
+ else if (triFunc ==smooth_DITHER_5R6G5B_triangle)
+ _mesa_printf("smooth_DITHER_5R6G5B_triangle\n");
+ else if (triFunc ==smooth_HPCR_triangle)
+ _mesa_printf("smooth_HPCR_triangle\n");
+ else if (triFunc ==smooth_DITHER8_triangle)
+ _mesa_printf("smooth_DITHER8_triangle\n");
+ else if (triFunc ==smooth_LOOKUP8_triangle)
+ _mesa_printf("smooth_LOOKUP8_triangle\n");
+ else if (triFunc ==flat_TRUECOLOR_triangle)
+ _mesa_printf("flat_TRUECOLOR_triangle\n");
+ else if (triFunc ==flat_TRUEDITHER_triangle)
+ _mesa_printf("flat_TRUEDITHER_triangle\n");
+ else if (triFunc ==flat_8A8B8G8R_triangle)
+ _mesa_printf("flat_8A8B8G8R_triangle\n");
+ else if (triFunc ==flat_8A8R8G8B_triangle)
+ _mesa_printf("flat_8A8R8G8B_triangle\n");
+ else if (triFunc ==flat_8R8G8B_triangle)
+ _mesa_printf("flat_8R8G8B_triangle\n");
+ else if (triFunc ==flat_8R8G8B24_triangle)
+ _mesa_printf("flat_8R8G8B24_triangle\n");
+ else if (triFunc ==flat_5R6G5B_triangle)
+ _mesa_printf("flat_5R6G5B_triangle\n");
+ else if (triFunc ==flat_DITHER_5R6G5B_triangle)
+ _mesa_printf("flat_DITHER_5R6G5B_triangle\n");
+ else if (triFunc ==flat_HPCR_triangle)
+ _mesa_printf("flat_HPCR_triangle\n");
+ else if (triFunc ==flat_DITHER8_triangle)
+ _mesa_printf("flat_DITHER8_triangle\n");
+ else if (triFunc ==flat_LOOKUP8_triangle)
+ _mesa_printf("flat_LOOKUP8_triangle\n");
+ else
+ _mesa_printf("???\n");
+}
+#endif
+
+
+#ifdef DEBUG
+
+/* record the current triangle function name */
+static const char *triFuncName = NULL;
+
+#define USE(triFunc) \
+do { \
+ triFuncName = #triFunc; \
+ return triFunc; \
+} while (0)
+
+#else
+
+#define USE(triFunc) return triFunc
+
+#endif
+
+
+static swrast_tri_func get_triangle_func( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ XMesaContext xmesa = XMESA_CONTEXT(ctx);
+ int depth = GET_VISUAL_DEPTH(xmesa->xm_visual);
+
+#ifdef DEBUG
+ triFuncName = NULL;
+#endif
+
+ if ((ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) ==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->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
+ return (swrast_tri_func) NULL;
+
+ if (xmesa->xm_buffer->buffer==XIMAGE) {
+ if ( ctx->Light.ShadeModel==GL_SMOOTH
+ && swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ USE(smooth_TRUECOLOR_z_triangle);
+ case PF_8A8B8G8R:
+ USE(smooth_8A8B8G8R_z_triangle);
+ case PF_8A8R8G8B:
+ USE(smooth_8A8R8G8B_z_triangle);
+ case PF_8R8G8B:
+ USE(smooth_8R8G8B_z_triangle);
+ case PF_8R8G8B24:
+ USE(smooth_8R8G8B24_z_triangle);
+ case PF_Dither_True:
+ USE(smooth_TRUEDITHER_z_triangle);
+ case PF_5R6G5B:
+ USE(smooth_5R6G5B_z_triangle);
+ case PF_Dither_5R6G5B:
+ USE(smooth_DITHER_5R6G5B_z_triangle);
+ case PF_HPCR:
+ USE(smooth_HPCR_z_triangle);
+ case PF_Dither:
+ if (depth == 8)
+ USE(smooth_DITHER8_z_triangle);
+ else
+ USE(smooth_DITHER_z_triangle);
+ case PF_Lookup:
+ if (depth == 8)
+ USE(smooth_LOOKUP8_z_triangle);
+ else
+ return (swrast_tri_func) NULL;
+ default:
+ return (swrast_tri_func) NULL;
+ }
+ }
+ if ( ctx->Light.ShadeModel==GL_FLAT
+ && swrast->_RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ USE(flat_TRUECOLOR_z_triangle);
+ case PF_8A8B8G8R:
+ USE(flat_8A8B8G8R_z_triangle);
+ case PF_8A8R8G8B:
+ USE(flat_8A8R8G8B_z_triangle);
+ case PF_8R8G8B:
+ USE(flat_8R8G8B_z_triangle);
+ case PF_8R8G8B24:
+ USE(flat_8R8G8B24_z_triangle);
+ case PF_Dither_True:
+ USE(flat_TRUEDITHER_z_triangle);
+ case PF_5R6G5B:
+ USE(flat_5R6G5B_z_triangle);
+ case PF_Dither_5R6G5B:
+ USE(flat_DITHER_5R6G5B_z_triangle);
+ case PF_HPCR:
+ USE(flat_HPCR_z_triangle);
+ case PF_Dither:
+ if (depth == 8)
+ USE(flat_DITHER8_z_triangle);
+ else
+ USE(flat_DITHER_z_triangle);
+ case PF_Lookup:
+ if (depth == 8)
+ USE(flat_LOOKUP8_z_triangle);
+ else
+ return (swrast_tri_func) NULL;
+ default:
+ return (swrast_tri_func) NULL;
+ }
+ }
+ if ( swrast->_RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ USE(smooth_TRUECOLOR_triangle);
+ case PF_8A8B8G8R:
+ USE(smooth_8A8B8G8R_triangle);
+ case PF_8A8R8G8B:
+ USE(smooth_8A8R8G8B_triangle);
+ case PF_8R8G8B:
+ USE(smooth_8R8G8B_triangle);
+ case PF_8R8G8B24:
+ USE(smooth_8R8G8B24_triangle);
+ case PF_Dither_True:
+ USE(smooth_TRUEDITHER_triangle);
+ case PF_5R6G5B:
+ USE(smooth_5R6G5B_triangle);
+ case PF_Dither_5R6G5B:
+ USE(smooth_DITHER_5R6G5B_triangle);
+ case PF_HPCR:
+ USE(smooth_HPCR_triangle);
+ case PF_Dither:
+ if (depth == 8)
+ USE(smooth_DITHER8_triangle);
+ else
+ USE(smooth_DITHER_triangle);
+ case PF_Lookup:
+ if (depth == 8)
+ USE(smooth_LOOKUP8_triangle);
+ else
+ return (swrast_tri_func) NULL;
+ default:
+ return (swrast_tri_func) NULL;
+ }
+ }
+
+ if ( swrast->_RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_FLAT
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (xmesa->pixelformat) {
+ case PF_Truecolor:
+ USE(flat_TRUECOLOR_triangle);
+ case PF_Dither_True:
+ USE(flat_TRUEDITHER_triangle);
+ case PF_8A8B8G8R:
+ USE(flat_8A8B8G8R_triangle);
+ case PF_8A8R8G8B:
+ USE(flat_8A8R8G8B_triangle);
+ case PF_8R8G8B:
+ USE(flat_8R8G8B_triangle);
+ case PF_8R8G8B24:
+ USE(flat_8R8G8B24_triangle);
+ case PF_5R6G5B:
+ USE(flat_5R6G5B_triangle);
+ case PF_Dither_5R6G5B:
+ USE(flat_DITHER_5R6G5B_triangle);
+ case PF_HPCR:
+ USE(flat_HPCR_triangle);
+ case PF_Dither:
+ if (depth == 8)
+ USE(flat_DITHER8_triangle);
+ else
+ USE(flat_DITHER_triangle);
+ case PF_Lookup:
+ if (depth == 8)
+ USE(flat_LOOKUP8_triangle);
+ else
+ return (swrast_tri_func) NULL;
+ default:
+ return (swrast_tri_func) NULL;
+ }
+ }
+
+ return (swrast_tri_func) NULL;
+ }
+ else {
+ /* draw to pixmap */
+ return (swrast_tri_func) NULL;
+ }
+}
+
+
+/* Override for the swrast tri-selection function. Try to use one
+ * of our internal tri functions, otherwise fall back to the
+ * standard swrast functions.
+ */
+void xmesa_choose_triangle( GLcontext *ctx )
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ if (!(swrast->Triangle = get_triangle_func( ctx )))
+ _swrast_choose_triangle( ctx );
+}
+
diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h
new file mode 100644
index 0000000..455d7af
--- /dev/null
+++ b/src/mesa/drivers/x11/xmesaP.h
@@ -0,0 +1,531 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.1
+ *
+ * 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.
+ */
+
+
+#ifndef XMESAP_H
+#define XMESAP_H
+
+
+#ifdef XFree86Server
+# include "GL/xf86glx.h"
+# include "xf86glx_util.h"
+#elif defined(USE_XSHM)
+# include <X11/extensions/XShm.h>
+#endif
+#include "GL/xmesa.h"
+#include "mtypes.h"
+#if defined(FX)
+#include "GL/fxmesa.h"
+#include "../glide/fxdrv.h"
+#endif
+
+
+extern _glthread_Mutex _xmesa_lock;
+
+
+/* for PF_8R8G8B24 pixel format */
+typedef struct {
+ GLubyte b;
+ GLubyte g;
+ GLubyte r;
+} bgr_t;
+
+
+/* Function pointer for clearing color buffers */
+typedef void (*clear_func)( GLcontext *ctx,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height );
+
+
+
+
+/** Framebuffer pixel formats */
+enum pixel_format {
+ PF_Index, /**< Color Index mode */
+ PF_Truecolor, /**< TrueColor or DirectColor, any depth */
+ PF_Dither_True, /**< TrueColor with dithering */
+ PF_8A8B8G8R, /**< 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */
+ PF_8R8G8B, /**< 32-bit TrueColor: 8-R, 8-G, 8-B bits */
+ PF_5R6G5B, /**< 16-bit TrueColor: 5-R, 6-G, 5-B bits */
+ PF_Dither, /**< Color-mapped RGB with dither */
+ PF_Lookup, /**< Color-mapped RGB without dither */
+ PF_HPCR, /**< HP Color Recovery (ad@lms.be 30/08/95) */
+ PF_1Bit, /**< monochrome dithering of RGB */
+ PF_Grayscale, /**< Grayscale or StaticGray */
+ PF_8R8G8B24, /**< 24-bit TrueColor: 8-R, 8-G, 8-B bits */
+ PF_Dither_5R6G5B, /**< 16-bit dithered TrueColor: 5-R, 6-G, 5-B */
+ PF_8A8R8G8B /**< 32-bit TrueColor: 8-A, 8-R, 8-G, 8-B */
+};
+
+
+/*
+ * "Derived" from GLvisual. Basically corresponds to an XVisualInfo.
+ */
+struct xmesa_visual {
+ GLvisual mesa_visual; /* Device independent visual parameters */
+ XMesaDisplay *display; /* The X11 display */
+#ifdef XFree86Server
+ GLint ColormapEntries;
+ GLint nplanes;
+#else
+ XMesaVisualInfo visinfo; /* X's visual info (pointer to private copy) */
+ XVisualInfo *vishandle; /* Only used in fakeglx.c */
+#endif
+ GLint BitsPerPixel; /* True bits per pixel for XImages */
+
+ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
+
+ enum pixel_format dithered_pf; /* Pixel format when dithering */
+ enum pixel_format undithered_pf;/* Pixel format when not dithering */
+
+ GLfloat RedGamma; /* Gamma values, 1.0 is default */
+ GLfloat GreenGamma;
+ GLfloat BlueGamma;
+
+ /* For PF_TRUECOLOR */
+ GLint rshift, gshift, bshift;/* Pixel color component shifts */
+ GLubyte Kernel[16]; /* Dither kernel */
+ unsigned long RtoPixel[512]; /* RGB to pixel conversion */
+ unsigned long GtoPixel[512];
+ unsigned long BtoPixel[512];
+ GLubyte PixelToR[256]; /* Pixel to RGB conversion */
+ GLubyte PixelToG[256];
+ GLubyte PixelToB[256];
+
+ /* For PF_HPCR */
+ short hpcr_rgbTbl[3][256];
+ GLboolean hpcr_clear_flag;
+ GLubyte hpcr_clear_ximage_pattern[2][16];
+ XMesaImage *hpcr_clear_ximage;
+ XMesaPixmap hpcr_clear_pixmap;
+
+ /* For PF_1BIT */
+ int bitFlip;
+};
+
+
+/*
+ * "Derived" from __GLcontextRec. Basically corresponds to a GLXContext.
+ */
+struct xmesa_context {
+ GLcontext mesa; /* the core library context (containment) */
+ XMesaVisual xm_visual; /* Describes the buffers */
+ XMesaBuffer xm_draw_buffer; /* current draw framebuffer */
+ XMesaBuffer xm_read_buffer; /* current read framebuffer */
+ XMesaBuffer xm_buffer; /* current span/point/line/triangle buffer */
+
+ XMesaDisplay *display; /* == xm_visual->display */
+ GLboolean swapbytes; /* Host byte order != display byte order? */
+ GLboolean direct; /* Direct rendering context? */
+
+ enum pixel_format pixelformat;
+
+ GLubyte clearcolor[4]; /* current clearing color */
+ unsigned long clearpixel; /* current clearing pixel value */
+};
+
+
+
+typedef enum {
+ WINDOW, /* An X window */
+ GLXWINDOW, /* GLX window */
+ PIXMAP, /* GLX pixmap */
+ PBUFFER /* GLX Pbuffer */
+} BufferType;
+
+
+/*
+ * "Derived" from GLframebuffer. Basically corresponds to a GLXDrawable.
+ */
+struct xmesa_buffer {
+ GLframebuffer mesa_buffer; /* depth, stencil, accum, etc buffers */
+ /* This MUST BE FIRST! */
+ GLboolean wasCurrent; /* was ever the current buffer? */
+ XMesaVisual xm_visual; /* the X/Mesa visual */
+
+ XMesaDisplay *display;
+ BufferType type; /* window, pixmap, pbuffer or glxwindow */
+ XMesaDrawable frontbuffer; /* either a window or pixmap */
+ XMesaPixmap backpixmap; /* back buffer Pixmap */
+ XMesaImage *backimage; /* back buffer simulated XImage */
+
+ XMesaDrawable buffer; /* the current buffer, either equal to */
+ /* frontbuffer, backpixmap or XIMAGE (None) */
+
+ XMesaColormap cmap; /* the X colormap */
+
+ unsigned long selectedEvents;/* for pbuffers only */
+
+ GLint db_state; /* 0 = single buffered */
+ /* BACK_PIXMAP = use Pixmap for back buffer */
+ /* BACK_XIMAGE = use XImage for back buffer */
+
+#ifndef XFree86Server
+ GLuint shm; /* X Shared Memory extension status: */
+ /* 0 = not available */
+ /* 1 = XImage support available */
+ /* 2 = Pixmap support available too */
+#ifdef USE_XSHM
+ XShmSegmentInfo shminfo;
+#endif
+#endif
+
+ XMesaImage *rowimage; /* Used for optimized span writing */
+
+ GLuint width, height; /* size of buffer */
+
+ GLint bottom; /* used for FLIP macro below */
+ GLubyte *ximage_origin1; /* used for PIXELADDR1 macro */
+ GLint ximage_width1;
+ GLushort *ximage_origin2; /* used for PIXELADDR2 macro */
+ GLint ximage_width2;
+ GLubyte *ximage_origin3; /* used for PIXELADDR3 macro */
+ GLint ximage_width3;
+ GLuint *ximage_origin4; /* used for PIXELADDR4 macro */
+ GLint ximage_width4;
+
+ XMesaPixmap stipple_pixmap; /* For polygon stippling */
+ XMesaGC stipple_gc; /* For polygon stippling */
+
+ XMesaGC gc; /* scratch GC for span, line, tri drawing */
+ XMesaGC cleargc; /* GC for clearing the color buffer */
+ XMesaGC swapgc; /* GC for swapping the color buffers */
+
+ /* The following are here instead of in the XMesaVisual
+ * because they depend on the window's colormap.
+ */
+
+ /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+ unsigned long color_table[576]; /* RGB -> pixel value */
+
+ /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+ GLubyte pixel_to_r[65536]; /* pixel value -> red */
+ GLubyte pixel_to_g[65536]; /* pixel value -> green */
+ GLubyte pixel_to_b[65536]; /* pixel value -> blue */
+
+ /* Used to do XAllocColor/XFreeColors accounting: */
+ int num_alloced;
+#if defined(XFree86Server)
+ Pixel alloced_colors[256];
+#else
+ unsigned long alloced_colors[256];
+#endif
+
+#if defined( FX )
+ /* For 3Dfx Glide only */
+ GLboolean FXisHackUsable; /* Can we render into window? */
+ GLboolean FXwindowHack; /* Are we rendering into a window? */
+ fxMesaContext FXctx;
+#endif
+
+ /* functions for clearing the front and back color buffers */
+ clear_func front_clear_func;
+ clear_func back_clear_func;
+
+ struct xmesa_buffer *Next; /* Linked list pointer: */
+};
+
+
+
+/* Values for xmesa->dest: */
+#define FRONT_PIXMAP 1
+#define BACK_PIXMAP 2
+#define BACK_XIMAGE 4
+
+/* Special value for X Drawable variables to indicate use of XImage instead */
+#define XIMAGE None
+
+
+/*
+ * If pixelformat==PF_TRUECOLOR:
+ */
+#define PACK_TRUECOLOR( PIXEL, R, G, B ) \
+ PIXEL = xmesa->xm_visual->RtoPixel[R] \
+ | xmesa->xm_visual->GtoPixel[G] \
+ | xmesa->xm_visual->BtoPixel[B]; \
+
+
+/*
+ * If pixelformat==PF_TRUEDITHER:
+ */
+#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B ) \
+{ \
+ int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)]; \
+ PIXEL = xmesa->xm_visual->RtoPixel[(R)+d] \
+ | xmesa->xm_visual->GtoPixel[(G)+d] \
+ | xmesa->xm_visual->BtoPixel[(B)+d]; \
+}
+
+
+
+/*
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A ) \
+ ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/*
+ * Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+ * shortcut.
+ */
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+
+/*
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/*
+ * If pixelformat==PF_5R6G5B:
+ */
+#define PACK_5R6G5B( R, G, B) ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+
+
+/*
+ * If pixelformat==PF_8A8R8G8B:
+ */
+#define PACK_8A8R8G8B( R, G, B, A ) \
+ ( ((A) << 24) | ((R) << 16) | ((G) << 8) | (B) )
+
+
+
+/*
+ * If pixelformat==PF_DITHER:
+ *
+ * Improved 8-bit RGB dithering code contributed by Bob Mercier
+ * (mercier@hollywood.cinenet.net). Thanks Bob!
+ */
+#ifdef DITHER666
+# define DITH_R 6
+# define DITH_G 6
+# define DITH_B 6
+# define DITH_MIX(r,g,b) (((r) * DITH_G + (g)) * DITH_B + (b))
+#else
+# define DITH_R 5
+# define DITH_G 9
+# define DITH_B 5
+# define DITH_MIX(r,g,b) (((g) << 6) | ((b) << 3) | (r))
+#endif
+#define DITH_DX 4
+#define DITH_DY 4
+#define DITH_N (DITH_DX * DITH_DY)
+
+#define _dither(C, c, d) (((unsigned)((DITH_N * (C - 1) + 1) * c + d)) >> 12)
+
+#define MAXC 256
+extern const int xmesa_kernel8[DITH_DY * DITH_DX];
+
+/* Dither for random X,Y */
+#define DITHER_SETUP \
+ int __d; \
+ unsigned long *ctable = xmesa->xm_buffer->color_table;
+
+#define DITHER( X, Y, R, G, B ) \
+ (__d = xmesa_kernel8[(((Y)&3)<<2) | ((X)&3)], \
+ ctable[DITH_MIX(_dither(DITH_R, (R), __d), \
+ _dither(DITH_G, (G), __d), \
+ _dither(DITH_B, (B), __d))])
+
+/* Dither for random X, fixed Y */
+#define XDITHER_SETUP(Y) \
+ int __d; \
+ unsigned long *ctable = xmesa->xm_buffer->color_table; \
+ const int *kernel = &xmesa_kernel8[ ((Y)&3) << 2 ];
+
+#define XDITHER( X, R, G, B ) \
+ (__d = kernel[(X)&3], \
+ ctable[DITH_MIX(_dither(DITH_R, (R), __d), \
+ _dither(DITH_G, (G), __d), \
+ _dither(DITH_B, (B), __d))])
+
+
+
+/*
+ * Dithering for flat-shaded triangles. Precompute all 16 possible
+ * pixel values given the triangle's RGB color. Contributed by Martin Shenk.
+ */
+#define FLAT_DITHER_SETUP( R, G, B ) \
+ GLushort ditherValues[16]; \
+ { \
+ unsigned long *ctable = xmesa->xm_buffer->color_table; \
+ int msdr = (DITH_N*((DITH_R)-1)+1) * (R); \
+ int msdg = (DITH_N*((DITH_G)-1)+1) * (G); \
+ int msdb = (DITH_N*((DITH_B)-1)+1) * (B); \
+ int i; \
+ for (i=0;i<16;i++) { \
+ int k = xmesa_kernel8[i]; \
+ int j = DITH_MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 );\
+ ditherValues[i] = (GLushort) ctable[j]; \
+ } \
+ }
+
+#define FLAT_DITHER_ROW_SETUP(Y) \
+ GLushort *ditherRow = ditherValues + ( ((Y)&3) << 2);
+
+#define FLAT_DITHER(X) ditherRow[(X)&3]
+
+
+
+/*
+ * If pixelformat==PF_LOOKUP:
+ */
+#define _dither_lookup(C, c) (((unsigned)((DITH_N * (C - 1) + 1) * c)) >> 12)
+
+#define LOOKUP_SETUP \
+ unsigned long *ctable = xmesa->xm_buffer->color_table
+
+#define LOOKUP( R, G, B ) \
+ ctable[DITH_MIX(_dither_lookup(DITH_R, (R)), \
+ _dither_lookup(DITH_G, (G)), \
+ _dither_lookup(DITH_B, (B)))]
+
+
+
+/*
+ * If pixelformat==PF_HPCR:
+ *
+ * HP Color Recovery dithering (ad@lms.be 30/08/95)
+ * HP has on it's 8-bit 700-series computers, a feature called
+ * 'Color Recovery'. This allows near 24-bit output (so they say).
+ * It is enabled by selecting the 8-bit TrueColor visual AND
+ * corresponding colormap (see tkInitWindow) AND doing some special
+ * dither.
+ */
+extern const short xmesa_HPCR_DRGB[3][2][16];
+
+#define DITHER_HPCR( X, Y, R, G, B ) \
+ ( ((xmesa->xm_visual->hpcr_rgbTbl[0][R] + xmesa_HPCR_DRGB[0][(Y)&1][(X)&15]) & 0xE0) \
+ |(((xmesa->xm_visual->hpcr_rgbTbl[1][G] + xmesa_HPCR_DRGB[1][(Y)&1][(X)&15]) & 0xE0)>>3) \
+ | ((xmesa->xm_visual->hpcr_rgbTbl[2][B] + xmesa_HPCR_DRGB[2][(Y)&1][(X)&15])>>6) \
+ )
+
+
+
+/*
+ * If pixelformat==PF_1BIT:
+ */
+extern const int xmesa_kernel1[16];
+
+#define SETUP_1BIT int bitFlip = xmesa->xm_visual->bitFlip
+#define DITHER_1BIT( X, Y, R, G, B ) \
+ (( ((int)(R)+(int)(G)+(int)(B)) > xmesa_kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip)
+
+
+
+/*
+ * If pixelformat==PF_GRAYSCALE:
+ */
+#define GRAY_RGB( R, G, B ) xmesa->xm_buffer->color_table[((R) + (G) + (B))/3]
+
+
+
+/*
+ * Converts a GL window Y coord to an X window Y coord:
+ */
+#define FLIP(BUFFER, Y) ((BUFFER)->bottom-(Y))
+
+
+/*
+ * Return the address of a 1, 2 or 4-byte pixel in the back XImage:
+ * X==0 is left, Y==0 is bottom.
+ */
+#define PIXELADDR1( BUFFER, X, Y ) \
+ ( (BUFFER)->ximage_origin1 - (Y) * (BUFFER)->ximage_width1 + (X) )
+
+#define PIXELADDR2( BUFFER, X, Y ) \
+ ( (BUFFER)->ximage_origin2 - (Y) * (BUFFER)->ximage_width2 + (X) )
+
+#define PIXELADDR3( BUFFER, X, Y ) \
+ ( (bgr_t *) ( (BUFFER)->ximage_origin3 - (Y) * (BUFFER)->ximage_width3 + 3 * (X) ))
+
+#define PIXELADDR4( BUFFER, X, Y ) \
+ ( (BUFFER)->ximage_origin4 - (Y) * (BUFFER)->ximage_width4 + (X) )
+
+
+
+
+/*
+ * Return pointer to XMesaContext corresponding to a Mesa GLcontext.
+ * Since we're using structure containment, it's just a cast!.
+ */
+#define XMESA_CONTEXT(MESACTX) (XMesaContext) (MESACTX)
+
+
+
+/*
+ * External functions:
+ */
+
+extern unsigned long
+xmesa_color_to_pixel( XMesaContext xmesa,
+ GLubyte r, GLubyte g, GLubyte b, GLubyte a,
+ GLuint pixelFormat );
+
+extern void xmesa_alloc_back_buffer( XMesaBuffer b );
+
+extern void xmesa_resize_buffers( GLframebuffer *buffer );
+
+extern void xmesa_init_driver_functions( XMesaVisual xmvisual,
+ struct dd_function_table *driver );
+
+extern void xmesa_update_state( GLcontext *ctx, GLuint new_state );
+
+extern void xmesa_update_span_funcs( GLcontext *ctx );
+
+extern void xmesa_set_buffer( GLcontext *ctx, GLframebuffer *buffer,
+ GLuint bufferBit );
+
+
+/* Plugged into the software rasterizer. Try to use internal
+ * swrast-style point, line and triangle functions.
+ */
+extern void xmesa_choose_point( GLcontext *ctx );
+extern void xmesa_choose_line( GLcontext *ctx );
+extern void xmesa_choose_triangle( GLcontext *ctx );
+
+
+extern void xmesa_register_swrast_functions( GLcontext *ctx );
+
+
+
+/* XXX this is a hack to implement shared display lists with 3Dfx */
+extern XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v,
+ XMesaWindow w,
+ XMesaContext c );
+
+/*
+ * These are the extra routines required for integration with XFree86.
+ * None of these routines should be user visible. -KEM
+ */
+extern void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v );
+extern GLboolean XMesaForceCurrent(XMesaContext c);
+extern GLboolean XMesaLoseCurrent(XMesaContext c);
+extern void XMesaReset( void );
+
+
+#endif