summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2010-03-11 01:55:49 +0100
committerLuc Verhaegen <libv@skynet.be>2010-03-11 01:55:49 +0100
commit5347249ae0486e833f851e841c007bc4137395c2 (patch)
tree52474f816415a52b29e3659ed2eb01c819d1fe35
parent5dee9b7b19c1aa3a13618b08bc24f00677b5364b (diff)
Import mga dri driver from mesa 7.0.3.7.0.47.0.3
-rw-r--r--configure.ac5
-rw-r--r--src/Doxyfile234
-rw-r--r--src/Makefile.am24
-rw-r--r--src/README26
-rw-r--r--src/mga_texcombine.c672
-rw-r--r--src/mga_texstate.c902
-rw-r--r--src/mga_xmesa.c1046
-rw-r--r--src/mga_xmesa.h155
-rw-r--r--src/mgacontext.h365
-rw-r--r--src/mgadd.c80
-rw-r--r--src/mgadd.h36
-rw-r--r--src/mgaioctl.c751
-rw-r--r--src/mgaioctl.h111
-rw-r--r--src/mgapixel.c656
-rw-r--r--src/mgapixel.h36
-rw-r--r--src/mgaregs.h1395
-rw-r--r--src/mgarender.c172
-rw-r--r--src/mgaspan.c223
-rw-r--r--src/mgaspan.h40
-rw-r--r--src/mgastate.c1205
-rw-r--r--src/mgastate.h39
-rw-r--r--src/mgatex.c541
-rw-r--r--src/mgatex.h51
-rw-r--r--src/mgatexmem.c278
-rw-r--r--src/mgatris.c912
-rw-r--r--src/mgatris.h52
-rw-r--r--src/mgavb.c480
-rw-r--r--src/mgavb.h66
-rw-r--r--src/server/mga.h115
-rw-r--r--src/server/mga_bios.h143
-rw-r--r--src/server/mga_dri.c1089
-rw-r--r--src/server/mga_dri.h113
-rw-r--r--src/server/mga_macros.h118
-rw-r--r--src/server/mga_reg.h484
34 files changed, 12608 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac
index 2a78cfd..a4bb79b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script
AC_PREREQ(2.57)
-AC_INIT([mesa-dri-xxx], 7.0.3, [], mesa-dri-xxx)
+AC_INIT([mesa-dri-mga], 7.0.3, [], mesa-dri-mga)
AM_INIT_AUTOMAKE([dist-bzip2])
@@ -16,7 +16,8 @@ AC_PROG_CC
AC_HEADER_STDC
PKG_CHECK_MODULES([DRM], [libdrm >= 2.3.0])
-PKG_CHECK_MODULES([DRI], [libmesadri = 7.0.3 libmesadricommon = 7.0.3])
+PKG_CHECK_MODULES([DRI], [libmesadri >= 7.0.3 libmesadri < 7.1.0
+ libmesadricommon >= 7.0.3 libmesadricommon < 7.1.0])
AC_OUTPUT([
Makefile
diff --git a/src/Doxyfile b/src/Doxyfile
new file mode 100644
index 0000000..0d0c134
--- /dev/null
+++ b/src/Doxyfile
@@ -0,0 +1,234 @@
+# Doxyfile 1.3.3-Gideon
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = mga
+PROJECT_NUMBER = $VERSION$
+OUTPUT_DIRECTORY =
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+SHORT_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES =
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SHOW_USED_FILES = YES
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /home/newtree/temp/src/mesa/drivers/dri/mga
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.moc \
+ *.xpm \
+ *.dox
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = yes
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+CGI_NAME = search.cgi
+CGI_URL =
+DOC_URL =
+DOC_ABSPATH =
+BIN_ABSPATH = /usr/local/bin/
+EXT_DOC_PATHS =
diff --git a/src/Makefile.am b/src/Makefile.am
index aa854c5..db3e79d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,21 @@
AM_CFLAGS = -DIN_DRI_DRIVER -DGLX_DIRECT_RENDERING -DGLX_INDIRECT_RENDERING
-xxx_dri_la_LTLIBRARIES = xxx_dri.la
-xxx_dri_la_CFLAGS = $(AM_CFLAGS) $(DRM_CFLAGS) $(DRI_CFLAGS) -Iserver
-xxx_dri_la_LDFLAGS = -module -noprefix -lm -ldl $(DRM_LIBS) $(DRI_LIBS)
-xxx_dri_ladir = @libdir@/dri
-xxx_dri_la_SOURCES = \
+mga_dri_la_LTLIBRARIES = mga_dri.la
+mga_dri_la_CFLAGS = $(AM_CFLAGS) $(DRM_CFLAGS) $(DRI_CFLAGS) -Iserver
+mga_dri_la_LDFLAGS = -module -noprefix -avoid-version -lm -ldl \
+ $(DRM_LIBS) $(DRI_LIBS)
+mga_dri_ladir = @libdir@/dri
+mga_dri_la_SOURCES = \
+ mgadd.c \
+ mgaioctl.c \
+ mgarender.c \
+ mgastate.c \
+ mgatris.c \
+ mgapixel.c \
+ mgaspan.c \
+ mgatex.c \
+ mgatexmem.c \
+ mga_texstate.c \
+ mga_texcombine.c \
+ mgavb.c \
+ mga_xmesa.c
diff --git a/src/README b/src/README
new file mode 100644
index 0000000..a7133fa
--- /dev/null
+++ b/src/README
@@ -0,0 +1,26 @@
+MGA DRI driver ported from XF86DRI to FBDRI
+by Denis Oliver Kropp <dok@directfb.org>
+
+
+INFO
+
+This driver has been ported from the head branch of XFree86 to
+the embedded-1-branch of Mesa.
+
+
+STATUS
+
+Already working very well as far as I've tested it (16/32 bit).
+glxgears runs at 935 fps (G550 32MB AGP 4x, Athlon 1.33) vs 744 fps with XFree.
+Other demos (terrain, fire, etc.) have been successfully tested as well.
+
+
+TODO
+
+- mgaEngineShutdown
+- mgaEngineRestore
+- SGRAM detection
+- remove some unused bits from server/*
+- subset driver support
+- mgaWaitForVBlank
+- deinitialization (from MGADRICloseScreen) a la radeonDestroyScreen
diff --git a/src/mga_texcombine.c b/src/mga_texcombine.c
new file mode 100644
index 0000000..bbfa29b
--- /dev/null
+++ b/src/mga_texcombine.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 2003 Ville Syrjala
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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:
+ * Ville Syrjala <syrjala@sci.fi>
+ */
+
+#include "glheader.h"
+
+#include "mgacontext.h"
+#include "mgatex.h"
+#include "mgaregs.h"
+
+/*
+ * GL_ARB_texture_env_combine
+ * GL_EXT_texture_env_combine
+ * GL_ARB_texture_env_crossbar
+ * GL_ATI_texture_env_combine3
+ */
+
+#define ARG_DISABLE 0xffffffff
+#define MGA_ARG1 0
+#define MGA_ARG2 1
+#define MGA_ALPHA 2
+
+GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
+ GLuint numColorArgs = 0, numAlphaArgs = 0;
+ GLuint arg1[3], arg2[3], alpha[3];
+ int args[3];
+ int i;
+
+ switch (texUnit->Combine.ModeRGB) {
+ case GL_REPLACE:
+ numColorArgs = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ numColorArgs = 2;
+ break;
+ case GL_INTERPOLATE:
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ case GL_MODULATE_SUBTRACT_ATI:
+ numColorArgs = 3;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ switch (texUnit->Combine.ModeA) {
+ case GL_REPLACE:
+ numAlphaArgs = 1;
+ break;
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ numAlphaArgs = 2;
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ /* Start fresh :) */
+ *reg = 0;
+
+ /* COLOR */
+ for (i = 0; i < 3; i++) {
+ arg1[i] = 0;
+ arg2[i] = 0;
+ alpha[i] = 0;
+ }
+
+ for (i = 0;i < numColorArgs; i++) {
+ switch (texUnit->Combine.SourceRGB[i]) {
+ case GL_TEXTURE:
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ alpha[i] |= TD0_color_alpha_currtex;
+ break;
+ case GL_TEXTURE0:
+ if (source == 0) {
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ alpha[i] |= TD0_color_alpha_currtex;
+ } else {
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* disable texturing */
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_trap;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ /* return GL_TRUE since we don't need a fallback */
+ return GL_TRUE;
+ }
+ arg1[i] |= ARG_DISABLE;
+ arg2[i] |= ARG_DISABLE;
+ alpha[i] |= TD0_color_alpha_prevtex;
+ }
+ break;
+ case GL_TEXTURE1:
+ if (source == 0) {
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* disable texturing */
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_trap;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ /* return GL_TRUE since we don't need a fallback */
+ return GL_TRUE;
+ }
+ arg1[i] |= ARG_DISABLE;
+ /* G400 specs (TDUALSTAGE0) */
+ arg2[i] |= TD0_color_arg2_prevstage;
+ alpha[i] |= TD0_color_alpha_prevstage;
+ } else {
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ alpha[i] |= TD0_color_alpha_currtex;
+ }
+ break;
+ case GL_CONSTANT:
+ if (mmesa->fcol_used &&
+ mmesa->envcolor[source] != mmesa->envcolor[!source])
+ return GL_FALSE;
+
+ arg1[i] |= ARG_DISABLE;
+ arg2[i] |= TD0_color_arg2_fcol;
+ alpha[i] |= TD0_color_alpha_fcol;
+
+ mmesa->setup.fcol = mmesa->envcolor[source];
+ mmesa->fcol_used = GL_TRUE;
+ break;
+ case GL_PRIMARY_COLOR:
+ arg1[i] |= ARG_DISABLE;
+ /* G400 specs (TDUALSTAGE1) */
+ if (unit == 0 || (mmesa->setup.tdualstage0 &
+ ((TD0_color_sel_mul & TD0_color_sel_add) |
+ (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
+ arg2[i] |= TD0_color_arg2_diffuse;
+ alpha[i] |= TD0_color_alpha_diffuse;
+ } else {
+ arg2[i] |= ARG_DISABLE;
+ alpha[i] |= ARG_DISABLE;
+ }
+ break;
+ case GL_PREVIOUS:
+ arg1[i] |= ARG_DISABLE;
+ if (unit == 0) {
+ arg2[i] |= TD0_color_arg2_diffuse;
+ alpha[i] |= TD0_color_alpha_diffuse;
+ } else {
+ arg2[i] |= TD0_color_arg2_prevstage;
+ alpha[i] |= TD0_color_alpha_prevstage;
+ }
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ switch (texUnit->Combine.OperandRGB[i]) {
+ case GL_SRC_COLOR:
+ arg1[i] |= 0;
+ arg2[i] |= 0;
+ if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT &&
+ RGBA_EQUAL( mmesa->envcolor[source] )) {
+ alpha[i] |= 0;
+ } else {
+ alpha[i] |= ARG_DISABLE;
+ }
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ arg1[i] |= TD0_color_arg1_inv_enable;
+ arg2[i] |= TD0_color_arg2_inv_enable;
+ if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT &&
+ RGBA_EQUAL( mmesa->envcolor[source] )) {
+ alpha[i] |= (TD0_color_alpha1inv_enable |
+ TD0_color_alpha2inv_enable);
+ } else {
+ alpha[i] |= ARG_DISABLE;
+ }
+ break;
+ case GL_SRC_ALPHA:
+ arg1[i] |= TD0_color_arg1_replicatealpha_enable;
+ arg2[i] |= TD0_color_arg2_replicatealpha_enable;
+ alpha[i] |= 0;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ arg1[i] |= (TD0_color_arg1_replicatealpha_enable |
+ TD0_color_arg1_inv_enable);
+ arg2[i] |= (TD0_color_arg2_replicatealpha_enable |
+ TD0_color_arg2_inv_enable);
+ alpha[i] |= (TD0_color_alpha1inv_enable |
+ TD0_color_alpha2inv_enable);
+ break;
+ }
+ }
+
+ switch (texUnit->Combine.ModeRGB) {
+ case GL_MODULATE_ADD_ATI:
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ /* Special handling for ATI_texture_env_combine3.
+ * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for
+ * both multiplier and adder.
+ */
+ /* Arg1 == arg1 */
+ if (arg1[1] == arg1[0]) {
+ if ((arg1[1] | arg2[2]) != ARG_DISABLE) {
+ *reg |= arg1[1] | arg2[2];
+ args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
+ break;
+ } else
+ if ((arg1[1] | alpha[2]) != ARG_DISABLE) {
+ *reg |= arg1[1] | alpha[2];
+ args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
+ break;
+ }
+ }
+ if (arg1[1] == arg1[2]) {
+ if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
+ *reg |= arg1[1] | arg2[0];
+ args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
+ break;
+ } else
+ if ((arg1[1] | alpha[0]) != ARG_DISABLE) {
+ *reg |= arg1[1] | alpha[0];
+ args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG1;
+ break;
+ }
+ }
+ /* fallthrough */
+ case GL_MODULATE_SUBTRACT_ATI:
+ /* Arg1 == arg2 */
+ if (arg2[1] == arg2[0]) {
+ if ((arg2[1] | arg1[2]) != ARG_DISABLE) {
+ *reg |= arg2[1] | arg1[2];
+ args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
+ break;
+ } else
+ if ((arg2[1] | alpha[2]) != ARG_DISABLE) {
+ *reg |= arg2[1] | alpha[2];
+ args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
+ break;
+ }
+ }
+ if (arg2[1] == arg2[2]) {
+ if ((arg2[1] | arg1[0]) != ARG_DISABLE) {
+ *reg |= arg2[1] | arg1[0];
+ args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
+ break;
+ } else
+ if ((arg2[1] | alpha[0]) != ARG_DISABLE) {
+ *reg |= arg2[1] | alpha[0];
+ args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG2;
+ break;
+ }
+ }
+ /* fallthrough */
+ default:
+ /* Find working combo of arg1, arg2 and alpha.
+ *
+ * Keep the Arg0 != alpha cases first since there's
+ * no way to get alpha out by itself (GL_REPLACE).
+ *
+ * Keep the Arg2 == alpha cases first because only alpha has the
+ * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for
+ * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the
+ * adder.
+ *
+ * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI,
+ * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the
+ * adder.
+ *
+ * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires
+ * that Arg1 == arg2. This requirement clashes with those of other modes.
+ */
+ if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) {
+ *reg |= arg1[0] | arg2[1] | alpha[2];
+ args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA;
+ } else
+ if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE &&
+ texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) {
+ *reg |= arg1[1] | arg2[0] | alpha[2];
+ args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA;
+ } else
+ if ((arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE &&
+ texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) {
+ *reg |= arg1[1] | arg2[2] | alpha[0];
+ args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2;
+ } else
+ if ((arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) {
+ *reg |= arg1[2] | arg2[1] | alpha[0];
+ args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1;
+ } else
+ if ((arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) {
+ *reg |= arg1[0] | arg2[2] | alpha[1];
+ args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2;
+ } else
+ if ((arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) {
+ *reg |= arg1[2] | arg2[0] | alpha[1];
+ args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1;
+ } else {
+ /* nothing suitable */
+ return GL_FALSE;
+ }
+ }
+
+ switch (texUnit->Combine.ModeRGB) {
+ case GL_REPLACE:
+ if (texUnit->Combine.ScaleShiftRGB) {
+ return GL_FALSE;
+ }
+
+ if (args[0] == MGA_ARG1) {
+ *reg |= TD0_color_sel_arg1;
+ } else if (args[0] == MGA_ARG2) {
+ *reg |= TD0_color_sel_arg2;
+ } else if (args[0] == MGA_ALPHA) {
+ /* Can't get alpha out by itself */
+ return GL_FALSE;
+ }
+ break;
+ case GL_MODULATE:
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_modbright_2x;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ *reg |= TD0_color_modbright_4x;
+ }
+
+ *reg |= TD0_color_sel_mul;
+
+ if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
+ if (args[0] == MGA_ARG1 || args[1] == MGA_ARG1) {
+ *reg |= TD0_color_arg2mul_alpha2;
+ } else if (args[0] == MGA_ARG2 || args[1] == MGA_ARG2) {
+ *reg |= TD0_color_arg1mul_alpha1;
+ }
+ }
+ break;
+ case GL_ADD_SIGNED:
+ *reg |= TD0_color_addbias_enable;
+ /* fallthrough */
+ case GL_ADD:
+ if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
+ /* Can't get alpha to the adder */
+ return GL_FALSE;
+ }
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_color_add_add |
+ TD0_color_sel_add);
+ break;
+ case GL_INTERPOLATE:
+ if (args[2] != MGA_ALPHA) {
+ /* Only alpha can function as Arg2 */
+ return GL_FALSE;
+ }
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_color_arg1mul_alpha1 |
+ TD0_color_blend_enable |
+ TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout |
+ TD0_color_add_add |
+ TD0_color_sel_add);
+
+ /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have
+ * already touched this bit.
+ */
+ *reg ^= TD0_color_alpha1inv_enable;
+
+ if (args[0] == MGA_ARG2) {
+ /* Swap arguments */
+ *reg ^= (TD0_color_arg1mul_alpha1 |
+ TD0_color_arg2mul_alpha2 |
+ TD0_color_alpha1inv_enable |
+ TD0_color_alpha2inv_enable);
+ }
+
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* Linear blending mode needs dualtex enabled */
+ *(reg+1) = (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2);
+ mmesa->force_dualtex = GL_TRUE;
+ }
+ break;
+ case GL_SUBTRACT:
+ if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) {
+ /* Can't get alpha to the adder */
+ return GL_FALSE;
+ }
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_color_add_sub |
+ TD0_color_sel_add);
+
+ if (args[0] == MGA_ARG2) {
+ /* Swap arguments */
+ *reg ^= (TD0_color_arg1_inv_enable |
+ TD0_color_arg2_inv_enable);
+ }
+ break;
+ case GL_MODULATE_SIGNED_ADD_ATI:
+ *reg |= TD0_color_addbias_enable;
+ /* fallthrough */
+ case GL_MODULATE_ADD_ATI:
+ if (args[1] == MGA_ALPHA) {
+ /* Can't get alpha to the adder */
+ return GL_FALSE;
+ }
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_color_add_add |
+ TD0_color_sel_add);
+
+ if (args[1] == args[0] || args[1] == args[2]) {
+ *reg |= TD0_color_arg1add_mulout;
+ if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
+ *reg |= TD0_color_arg1mul_alpha1;
+
+ if (args[1] == MGA_ARG1) {
+ /* Swap adder arguments */
+ *reg ^= (TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout);
+ if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA) {
+ /* Swap multiplier arguments */
+ *reg ^= (TD0_color_arg1mul_alpha1 |
+ TD0_color_arg2mul_alpha2);
+ }
+ }
+ } else {
+ *reg |= (TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1add_mulout);
+
+ if (args[1] == MGA_ARG1) {
+ /* Swap arguments */
+ *reg ^= (TD0_color_arg1mul_alpha1 |
+ TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout);
+ }
+ }
+ break;
+ case GL_MODULATE_SUBTRACT_ATI:
+ if (args[1] != MGA_ARG2) {
+ /* Can't swap arguments */
+ return GL_FALSE;
+ }
+ if (texUnit->Combine.ScaleShiftRGB == 1) {
+ *reg |= TD0_color_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftRGB == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_color_add_sub |
+ TD0_color_sel_add);
+
+ if (args[1] == args[0] || args[1] == args[2]) {
+ *reg |= TD0_color_arg1add_mulout;
+ if (args[0] == MGA_ALPHA || args[2] == MGA_ALPHA)
+ *reg |= TD0_color_arg1mul_alpha1;
+ } else {
+ *reg |= (TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1add_mulout);
+ }
+ break;
+ }
+
+
+ /* ALPHA */
+ for (i = 0; i < 2; i++) {
+ arg1[i] = 0;
+ arg2[i] = 0;
+ }
+
+ for (i = 0; i < numAlphaArgs; i++) {
+ switch (texUnit->Combine.SourceA[i]) {
+ case GL_TEXTURE:
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ break;
+ case GL_TEXTURE0:
+ if (source == 0) {
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ } else {
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* disable texturing */
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_trap;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ /* return GL_TRUE since we don't need a fallback */
+ return GL_TRUE;
+ }
+ arg1[i] |= ARG_DISABLE;
+ arg2[i] |= TD0_alpha_arg2_prevtex;
+ }
+ break;
+ case GL_TEXTURE1:
+ if (source == 0) {
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* disable texturing */
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_trap;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ /* return GL_TRUE since we don't need a fallback */
+ return GL_TRUE;
+ }
+ arg1[i] |= ARG_DISABLE;
+ /* G400 specs (TDUALSTAGE0) */
+ arg2[i] |= TD0_alpha_arg2_prevstage;
+ } else {
+ arg1[i] |= 0;
+ arg2[i] |= ARG_DISABLE;
+ }
+ break;
+ case GL_CONSTANT:
+ if (mmesa->fcol_used &&
+ mmesa->envcolor[source] != mmesa->envcolor[!source])
+ return GL_FALSE;
+
+ arg1[i] |= ARG_DISABLE;
+ arg2[i] |= TD0_alpha_arg2_fcol;
+
+ mmesa->setup.fcol = mmesa->envcolor[source];
+ mmesa->fcol_used = GL_TRUE;
+ break;
+ case GL_PRIMARY_COLOR:
+ arg1[i] |= ARG_DISABLE;
+ /* G400 specs (TDUALSTAGE1) */
+ if (unit == 0 || (mmesa->setup.tdualstage0 &
+ ((TD0_color_sel_mul & TD0_color_sel_add) |
+ (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) {
+ arg2[i] |= TD0_alpha_arg2_diffuse;
+ } else {
+ arg2[i] |= ARG_DISABLE;
+ }
+ break;
+ case GL_PREVIOUS:
+ arg1[i] |= ARG_DISABLE;
+ if (unit == 0) {
+ arg2[i] |= TD0_alpha_arg2_diffuse;
+ } else {
+ arg2[i] |= TD0_alpha_arg2_prevstage;
+ }
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ switch (texUnit->Combine.OperandA[i]) {
+ case GL_SRC_ALPHA:
+ arg1[i] |= 0;
+ arg2[i] |= 0;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ arg1[i] |= TD0_alpha_arg1_inv_enable;
+ arg2[i] |= TD0_alpha_arg2_inv_enable;
+ break;
+ }
+ }
+
+ /* Find a working combo of arg1 and arg2 */
+ if ((arg1[0] | arg2[1]) != ARG_DISABLE) {
+ *reg |= arg1[0] | arg2[1];
+ args[0] = MGA_ARG1; args[1] = MGA_ARG2;
+ } else
+ if ((arg1[1] | arg2[0]) != ARG_DISABLE) {
+ *reg |= arg1[1] | arg2[0];
+ args[0] = MGA_ARG2; args[1] = MGA_ARG1;
+ } else {
+ /* nothing suitable */
+ return GL_FALSE;
+ }
+
+ switch (texUnit->Combine.ModeA) {
+ case GL_REPLACE:
+ if (texUnit->Combine.ScaleShiftA) {
+ return GL_FALSE;
+ }
+
+ if (args[0] == MGA_ARG1) {
+ *reg |= TD0_alpha_sel_arg1;
+ } else if (args[0] == MGA_ARG2) {
+ *reg |= TD0_alpha_sel_arg2;
+ }
+ break;
+ case GL_MODULATE:
+ if (texUnit->Combine.ScaleShiftA == 1) {
+ *reg |= TD0_alpha_modbright_2x;
+ } else if (texUnit->Combine.ScaleShiftA == 2) {
+ *reg |= TD0_alpha_modbright_4x;
+ }
+
+ *reg |= TD0_alpha_sel_mul;
+ break;
+ case GL_ADD_SIGNED:
+ *reg |= TD0_alpha_addbias_enable;
+ /* fallthrough */
+ case GL_ADD:
+ if (texUnit->Combine.ScaleShiftA == 1) {
+ *reg |= TD0_alpha_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftA == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_alpha_add_enable |
+ TD0_alpha_sel_add);
+ break;
+ case GL_SUBTRACT:
+ if (texUnit->Combine.ScaleShiftA == 1) {
+ *reg |= TD0_alpha_add2x_enable;
+ } else if (texUnit->Combine.ScaleShiftA == 2) {
+ return GL_FALSE;
+ }
+
+ *reg |= (TD0_alpha_add_disable |
+ TD0_alpha_sel_add);
+
+ if (args[0] == MGA_ARG2) {
+ /* Swap arguments */
+ *reg ^= (TD0_alpha_arg1_inv_enable |
+ TD0_alpha_arg2_inv_enable);
+ }
+ break;
+ }
+
+ return GL_TRUE;
+}
+
+
diff --git a/src/mga_texstate.c b/src/mga_texstate.c
new file mode 100644
index 0000000..71d264b
--- /dev/null
+++ b/src/mga_texstate.c
@@ -0,0 +1,902 @@
+/*
+ * 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 SYSTEMS, 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>
+ */
+/* $XFree86:$ */
+
+#include <stdlib.h>
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgatex.h"
+#include "mgaregs.h"
+#include "mgatris.h"
+#include "mgaioctl.h"
+
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "imports.h"
+
+#include "simple_list.h"
+#include "texformat.h"
+
+#define MGA_USE_TABLE_FOR_FORMAT
+#ifdef MGA_USE_TABLE_FOR_FORMAT
+#define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
+static const unsigned TMC_tformat[ TMC_nr_tformat ] =
+{
+ [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32,
+ [MESA_FORMAT_RGB565] = TMC_tformat_tw16,
+ [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12,
+ [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15,
+ [MESA_FORMAT_AL88] = TMC_tformat_tw8al,
+ [MESA_FORMAT_I8] = TMC_tformat_tw8a,
+ [MESA_FORMAT_CI8] = TMC_tformat_tw8 ,
+ [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy,
+ [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422,
+};
+#endif
+
+static void
+mgaSetTexImages( mgaContextPtr mmesa,
+ const struct gl_texture_object * tObj )
+{
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+ struct gl_texture_image *baseImage = tObj->Image[0][ tObj->BaseLevel ];
+ GLint totalSize;
+ GLint width, height;
+ GLint i;
+ GLint numLevels;
+ GLint log2Width, log2Height;
+ GLuint txformat = 0;
+ GLint ofs;
+
+ /* Set the hardware texture format
+ */
+#ifndef MGA_USE_TABLE_FOR_FORMAT
+ switch (baseImage->TexFormat->MesaFormat) {
+
+ case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
+ case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break;
+ case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
+ case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
+ case MESA_FORMAT_AL88: txformat = TMC_tformat_tw8al; break;
+ case MESA_FORMAT_I8: txformat = TMC_tformat_tw8a; break;
+ case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break;
+ case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break;
+ case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
+
+ default:
+ _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+ return;
+ }
+#else
+ if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat)
+ || (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) )
+ {
+ _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+ return;
+ }
+
+ txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ];
+
+#endif /* MGA_USE_TABLE_FOR_FORMAT */
+
+ driCalculateTextureFirstLastLevel( (driTextureObject *) t );
+ if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+ log2Width = 0;
+ log2Height = 0;
+ } else {
+ log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
+ log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
+ }
+
+ width = tObj->Image[0][t->base.firstLevel]->Width;
+ height = tObj->Image[0][t->base.firstLevel]->Height;
+
+ numLevels = MIN2( t->base.lastLevel - t->base.firstLevel + 1,
+ MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
+
+
+ totalSize = 0;
+ for ( i = 0 ; i < numLevels ; i++ ) {
+ const struct gl_texture_image * const texImage =
+ tObj->Image[0][ i + t->base.firstLevel ];
+ int size;
+
+ if (texImage == NULL)
+ break;
+
+ size = texImage->Width * texImage->Height *
+ baseImage->TexFormat->TexelBytes;
+
+ t->offsets[i] = totalSize;
+ t->base.dirty_images[0] |= (1<<i);
+
+ /* All mipmaps must be 32-byte aligned */
+ totalSize += (size + 31) & ~31;
+
+ /* Since G400 calculates the offsets in hardware
+ * it can't handle more than one < 32 byte mipmap.
+ *
+ * Further testing has indicated that it can't
+ * handle any < 32 byte mipmaps.
+ */
+ if (MGA_IS_G400( mmesa ) && size <= 32) {
+ i++;
+ break;
+ }
+ }
+
+ /* save these values */
+ numLevels = i;
+ t->base.lastLevel = t->base.firstLevel + numLevels - 1;
+ t->base.totalSize = totalSize;
+
+ /* setup hardware register values */
+ t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK
+ & TMC_tpitchext_MASK);
+ t->setup.texctl |= txformat;
+
+
+ /* Set the texture width. In order to support non-power of 2 textures and
+ * textures larger than 1024 texels wide, "linear" pitch must be used. For
+ * the linear pitch, if the width is 2048, a value of zero is used.
+ */
+
+ t->setup.texctl |= TMC_tpitchlin_enable;
+ t->setup.texctl |= MGA_FIELD( TMC_tpitchext, width & (2048 - 1) );
+
+
+ /* G400 specifies the number of mip levels in a strange way. Since there
+ * are up to 11 levels, it requires 4 bits. Three of the bits are at the
+ * high end of TEXFILTER. The other bit is in the middle. Weird.
+ */
+ numLevels--;
+ t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
+ t->setup.texfilter |= MGA_FIELD( TF_mapnb, numLevels & 0x7 );
+ t->setup.texfilter |= MGA_FIELD( TF_mapnbhigh, (numLevels >> 3) & 0x1 );
+
+ /* warp texture registers */
+ ofs = MGA_IS_G200(mmesa) ? 28 : 11;
+
+ t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
+ MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
+ MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
+
+ t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
+ MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
+ MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
+
+ mgaUploadTexImages( mmesa, t );
+}
+
+
+/* ================================================================
+ * Texture unit state management
+ */
+
+static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+ GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
+
+ if (tObj != ctx->Texture.Unit[0].Current2D &&
+ tObj != ctx->Texture.Unit[0].CurrentRect)
+ return;
+
+
+ t->setup.texctl &= ~TMC_tmodulate_enable;
+ t->setup.texctl2 &= ~(TMC_decalblend_enable |
+ TMC_idecal_enable |
+ TMC_decaldis_enable);
+
+ switch (ctx->Texture.Unit[0].EnvMode) {
+ case GL_REPLACE:
+ if (format == GL_ALPHA)
+ t->setup.texctl2 |= TMC_idecal_enable;
+
+ if (format == GL_RGB || format == GL_LUMINANCE)
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ else
+ mmesa->hw.alpha_sel = AC_alphasel_fromtex;
+ break;
+
+ case GL_MODULATE:
+ t->setup.texctl |= TMC_tmodulate_enable;
+
+ if (format == GL_ALPHA)
+ t->setup.texctl2 |= (TMC_idecal_enable |
+ TMC_decaldis_enable);
+
+ if (format == GL_RGB || format == GL_LUMINANCE)
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ else
+ mmesa->hw.alpha_sel = AC_alphasel_modulated;
+ break;
+
+ case GL_DECAL:
+ if (format == GL_RGB || format == GL_RGBA)
+ t->setup.texctl2 |= TMC_decalblend_enable;
+ else
+ t->setup.texctl2 |= TMC_idecal_enable;
+
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ break;
+
+ case GL_BLEND:
+ if (format == GL_ALPHA) {
+ t->setup.texctl2 |= TMC_idecal_enable;
+ mmesa->hw.alpha_sel = AC_alphasel_modulated;
+ } else {
+ t->texenv_fallback = GL_TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+#define MGA_REPLACE 0
+#define MGA_MODULATE 1
+#define MGA_DECAL 2
+#define MGA_ADD 3
+#define MGA_MAX_COMBFUNC 4
+
+static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cs
+ * Av = Af
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_MODULATE
+ * Cv = Cf Cs
+ * Av = Af
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_DECAL
+ * Cv = Cs
+ * Av = Af
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cf + Cs
+ * Av = Af
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cs
+ * Av = Ap
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_MODULATE
+ * Cv = Cp Cs
+ * Av = Ap
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_DECAL
+ * Cv = Cs
+ * Av = Ap
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cp + Cs
+ * Av = Ap
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+ },
+};
+
+static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cs
+ * Av = As
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_sel_arg1),
+
+ /* GL_MODULATE
+ * Cv = Cf Cs
+ * Av = Af As
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ * tmp = Cf ( 1 - As )
+ * Cv = tmp + Cs As
+ * Av = Af
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_alpha_currtex |
+ TD0_color_alpha1inv_enable |
+ TD0_color_arg1mul_alpha1 |
+ TD0_color_blend_enable |
+ TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cf + Cs
+ * Av = Af As
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cs
+ * Av = As
+ */
+ (TD0_color_sel_arg1 |
+ TD0_alpha_sel_arg1),
+
+ /* GL_MODULATE
+ * Cv = Cp Cs
+ * Av = Ap As
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_mul |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL
+ * tmp = Cp ( 1 - As )
+ * Cv = tmp + Cs As
+ * Av = Ap
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_alpha_currtex |
+ TD0_color_alpha1inv_enable |
+ TD0_color_arg1mul_alpha1 |
+ TD0_color_blend_enable |
+ TD0_color_arg1add_mulout |
+ TD0_color_arg2add_mulout |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cp + Cs
+ * Av = Ap As
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+ },
+};
+
+static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
+{
+ /* Unit 0:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cf
+ * Av = As
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2 |
+ TD0_alpha_sel_arg1),
+
+ /* GL_MODULATE
+ * Cv = Cf
+ * Av = Af As
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL (undefined)
+ * Cv = Cf
+ * Av = Af
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cf
+ * Av = Af As
+ */
+ (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul),
+ },
+
+ /* Unit 1:
+ */
+ {
+ /* GL_REPLACE
+ * Cv = Cp
+ * Av = As
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_sel_arg1),
+
+ /* GL_MODULATE
+ * Cv = Cp
+ * Av = Ap As
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+
+ /* GL_DECAL (undefined)
+ * Cv = Cp
+ * Av = Ap
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2),
+
+ /* GL_ADD
+ * Cv = Cp
+ * Av = Ap As
+ */
+ (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_mul),
+ },
+};
+
+static GLboolean mgaUpdateTextureEnvBlend( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
+ GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
+
+ *reg = 0;
+
+ if (format == GL_ALPHA) {
+ /* Cv = Cf */
+ *reg |= (TD0_color_arg2_diffuse |
+ TD0_color_sel_arg2);
+ /* Av = Af As */
+ *reg |= (TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul);
+ return GL_TRUE;
+ }
+
+ /* C1 = Cf ( 1 - Cs ) */
+ *reg |= (TD0_color_arg1_inv_enable |
+ TD0_color_arg2_diffuse |
+ TD0_color_sel_mul);
+
+ if (format == GL_RGB || format == GL_LUMINANCE) {
+ /* A1 = Af */
+ *reg |= (TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_arg2);
+ } else
+ if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
+ /* A1 = Af As */
+ *reg |= (TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul);
+ } else
+ if (format == GL_INTENSITY) {
+ /* A1 = Af ( 1 - As ) */
+ *reg |= (TD0_alpha_arg1_inv_enable |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_sel_mul);
+ }
+
+ if (RGB_ZERO(mmesa->envcolor[source]) &&
+ (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])))
+ return GL_TRUE; /* all done */
+
+ if (ctx->Texture._EnabledUnits == 0x03)
+ return GL_FALSE; /* need both units */
+
+ mmesa->force_dualtex = GL_TRUE;
+ reg = &mmesa->setup.tdualstage1;
+ *reg = 0;
+
+ if (RGB_ZERO(mmesa->envcolor[source])) {
+ /* Cv = C1 */
+ *reg |= (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2);
+ } else
+ if (RGB_ONE(mmesa->envcolor[source])) {
+ /* Cv = C1 + Cs */
+ *reg |= (TD0_color_arg2_prevstage |
+ TD0_color_add_add |
+ TD0_color_sel_add);
+ } else
+ if (RGBA_EQUAL(mmesa->envcolor[source])) {
+ /* Cv = C1 + Cc Cs */
+ *reg |= (TD0_color_arg2_prevstage |
+ TD0_color_alpha_fcol |
+ TD0_color_arg2mul_alpha2 |
+ TD0_color_arg1add_mulout |
+ TD0_color_add_add |
+ TD0_color_sel_add);
+
+ mmesa->setup.fcol = mmesa->envcolor[source];
+ } else {
+ return GL_FALSE;
+ }
+
+ if (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])) {
+ /* Av = A1 */
+ *reg |= (TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2);
+ } else
+ if (ALPHA_ONE(mmesa->envcolor[source])) {
+ /* Av = A1 + As */
+ *reg |= (TD0_alpha_arg2_prevstage |
+ TD0_alpha_add_enable |
+ TD0_alpha_sel_add);
+ } else {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+ GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
+
+ if (tObj != ctx->Texture.Unit[source].Current2D &&
+ tObj != ctx->Texture.Unit[source].CurrentRect)
+ return;
+
+ switch (ctx->Texture.Unit[source].EnvMode) {
+ case GL_REPLACE:
+ if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_REPLACE];
+ } else if (format == GL_RGB || format == GL_LUMINANCE) {
+ *reg = g400_color_combine[unit][MGA_REPLACE];
+ } else {
+ *reg = g400_color_alpha_combine[unit][MGA_REPLACE];
+ }
+ break;
+
+ case GL_MODULATE:
+ if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_MODULATE];
+ } else if (format == GL_RGB || format == GL_LUMINANCE) {
+ *reg = g400_color_combine[unit][MGA_MODULATE];
+ } else {
+ *reg = g400_color_alpha_combine[unit][MGA_MODULATE];
+ }
+ break;
+
+ case GL_DECAL:
+ if (format == GL_RGB) {
+ *reg = g400_color_combine[unit][MGA_DECAL];
+ } else if (format == GL_RGBA) {
+ *reg = g400_color_alpha_combine[unit][MGA_DECAL];
+ if (ctx->Texture._EnabledUnits != 0x03) {
+ /* Linear blending mode needs dual texturing enabled */
+ *(reg+1) = (TD0_color_arg2_prevstage |
+ TD0_color_sel_arg2 |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_sel_arg2);
+ mmesa->force_dualtex = GL_TRUE;
+ }
+ } else {
+ /* Undefined */
+ *reg = g400_alpha_combine[unit][MGA_DECAL];
+ }
+ break;
+
+ case GL_ADD:
+ if (format == GL_ALPHA) {
+ *reg = g400_alpha_combine[unit][MGA_ADD];
+ } else if (format == GL_RGB || format == GL_LUMINANCE) {
+ *reg = g400_color_combine[unit][MGA_ADD];
+ } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) {
+ *reg = g400_color_alpha_combine[unit][MGA_ADD];
+ } else if (format == GL_INTENSITY) {
+ /* Cv = Cf + Cs
+ * Av = Af + As
+ */
+ if (unit == 0) {
+ *reg = (TD0_color_arg2_diffuse |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_diffuse |
+ TD0_alpha_add_enable |
+ TD0_alpha_sel_add);
+ } else {
+ *reg = (TD0_color_arg2_prevstage |
+ TD0_color_add_add |
+ TD0_color_sel_add |
+ TD0_alpha_arg2_prevstage |
+ TD0_alpha_add_enable |
+ TD0_alpha_sel_add);
+ }
+ }
+ break;
+
+ case GL_BLEND:
+ if (!mgaUpdateTextureEnvBlend(ctx, unit))
+ t->texenv_fallback = GL_TRUE;
+ break;
+
+ case GL_COMBINE:
+ if (!mgaUpdateTextureEnvCombine(ctx, unit))
+ t->texenv_fallback = GL_TRUE;
+ break;
+ default:
+ break;
+ }
+}
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ /* Texture unit disabled */
+
+ if ( mmesa->CurrentTexObj[unit] != NULL ) {
+ /* The old texture is no longer bound to this texture unit.
+ * Mark it as such.
+ */
+
+ mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
+ mmesa->CurrentTexObj[unit] = NULL;
+ }
+
+ if ( unit != 0 && !mmesa->force_dualtex ) {
+ mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
+ }
+
+ if ( ctx->Texture._EnabledUnits == 0 ) {
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_trap;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
+}
+
+static GLboolean enable_tex( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+
+ /* Upload teximages (not pipelined)
+ */
+ if (t->base.dirty_images[0]) {
+ FLUSH_BATCH( mmesa );
+ mgaSetTexImages( mmesa, tObj );
+ if ( t->base.memBlock == NULL ) {
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+
+ /* Fallback if there's a texture border */
+ if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) {
+ return GL_FALSE;
+ }
+
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+ if ( mmesa->CurrentTexObj[unit] != t ) {
+ if ( mmesa->CurrentTexObj[unit] != NULL ) {
+ /* The old texture is no longer bound to this texture unit.
+ * Mark it as such.
+ */
+
+ mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
+ }
+
+ mmesa->CurrentTexObj[unit] = t;
+ t->base.bound |= (1UL << unit);
+
+ driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
+ }
+
+ /* register setup */
+ if ( unit == 1 ) {
+ mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
+ }
+
+ t->texenv_fallback = GL_FALSE;
+
+ /* Set this before mgaUpdateTextureEnvG400() since
+ * GL_ARB_texture_env_crossbar may have to disable texturing.
+ */
+ mmesa->setup.dwgctl &= DC_opcod_MASK;
+ mmesa->setup.dwgctl |= DC_opcod_texture_trap;
+
+ /* FIXME: The Radeon has some cached state so that it can avoid calling
+ * FIXME: UpdateTextureEnv in some cases. Is that possible here?
+ */
+ if (MGA_IS_G400(mmesa)) {
+ /* G400: Regardless of texture env mode, we use the alpha from the
+ * texture unit (AC_alphasel_fromtex) since it will have already
+ * been modulated by the incoming fragment color, if needed.
+ * We don't want (AC_alphasel_modulate) since that'll effectively
+ * do the modulation twice.
+ */
+ mmesa->hw.alpha_sel = AC_alphasel_fromtex;
+
+ mgaUpdateTextureEnvG400( ctx, unit );
+ } else {
+ mgaUpdateTextureEnvG200( ctx, unit );
+ }
+
+ t->setup.texctl2 &= TMC_dualtex_MASK;
+ if (ctx->Texture._EnabledUnits == 0x03 || mmesa->force_dualtex) {
+ t->setup.texctl2 |= TMC_dualtex_enable;
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
+
+ FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
+ return !t->border_fallback && !t->texenv_fallback;
+}
+
+
+static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ const int source = mmesa->tmu_source[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+
+
+ if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT ||
+ texUnit->_ReallyEnabled == TEXTURE_RECT_BIT ) {
+ return(enable_tex( ctx, unit ) &&
+ update_tex_common( ctx, unit ));
+ }
+ else if ( texUnit->_ReallyEnabled ) {
+ return GL_FALSE;
+ }
+ else {
+ disable_tex( ctx, unit );
+ return GL_TRUE;
+ }
+}
+
+/* The G400 is now programmed quite differently wrt texture environment.
+ */
+void mgaUpdateTextureState( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ GLboolean ok;
+ unsigned i;
+
+ mmesa->force_dualtex = GL_FALSE;
+ mmesa->fcol_used = GL_FALSE;
+
+ /* This works around a quirk with the MGA hardware. If only OpenGL
+ * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
+ * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
+ */
+
+ mmesa->tmu_source[0] = 0;
+ mmesa->tmu_source[1] = 1;
+
+ if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
+ /* only texture 1 enabled */
+ mmesa->tmu_source[0] = 1;
+ mmesa->tmu_source[1] = 0;
+ }
+
+ for ( i = 0, ok = GL_TRUE
+ ; (i < ctx->Const.MaxTextureUnits) && ok
+ ; i++ ) {
+ ok = updateTextureUnit( ctx, i );
+ }
+
+ FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
+}
diff --git a/src/mga_xmesa.c b/src/mga_xmesa.c
new file mode 100644
index 0000000..f4e651a
--- /dev/null
+++ b/src/mga_xmesa.c
@@ -0,0 +1,1046 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS 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.
+ */
+
+/**
+ * \file mga_xmesa.c
+ * MGA screen and context initialization / creation code.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "drm.h"
+#include "mga_drm.h"
+#include "mga_xmesa.h"
+#include "context.h"
+#include "matrix.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "framebuffer.h"
+#include "renderbuffer.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "vbo/vbo.h"
+
+#include "tnl/t_pipeline.h"
+
+#include "drivers/common/driverfuncs.h"
+
+#include "mgadd.h"
+#include "mgastate.h"
+#include "mgatex.h"
+#include "mgaspan.h"
+#include "mgaioctl.h"
+#include "mgatris.h"
+#include "mgavb.h"
+#include "mgapixel.h"
+#include "mga_xmesa.h"
+#include "mga_dri.h"
+
+#include "utils.h"
+#include "vblank.h"
+
+#include "extensions.h"
+#include "drirenderbuffer.h"
+
+#include "GL/internal/dri_interface.h"
+
+#define need_GL_ARB_multisample
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_vertex_program
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_secondary_color
+#if 0
+#define need_GL_EXT_paletted_texture
+#endif
+#define need_GL_NV_vertex_program
+#include "extension_helper.h"
+
+/* MGA configuration
+ */
+#include "xmlpool.h"
+
+PUBLIC const char __driConfigOptions[] =
+DRI_CONF_BEGIN
+ DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+ DRI_CONF_SECTION_END
+ DRI_CONF_SECTION_QUALITY
+ DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB)
+ DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER)
+ DRI_CONF_SECTION_END
+ DRI_CONF_SECTION_SOFTWARE
+ DRI_CONF_ARB_VERTEX_PROGRAM(true)
+ DRI_CONF_NV_VERTEX_PROGRAM(true)
+ DRI_CONF_SECTION_END
+ DRI_CONF_SECTION_DEBUG
+ DRI_CONF_NO_RAST(false)
+ DRI_CONF_SECTION_END
+DRI_CONF_END;
+static const GLuint __driNConfigOptions = 6;
+
+#ifndef MGA_DEBUG
+int MGA_DEBUG = 0;
+#endif
+
+static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+static __GLcontextModes *
+mgaFillInModes( unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, GLboolean have_back_buffer )
+{
+ __GLcontextModes * modes;
+ __GLcontextModes * m;
+ unsigned num_modes;
+ unsigned depth_buffer_factor;
+ unsigned back_buffer_factor;
+ GLenum fb_format;
+ GLenum fb_type;
+
+ /* GLX_SWAP_COPY_OML is only supported because the MGA driver doesn't
+ * support pageflipping at all.
+ */
+ static const GLenum back_buffer_modes[] = {
+ GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+ };
+
+ u_int8_t depth_bits_array[3];
+ u_int8_t stencil_bits_array[3];
+
+
+ depth_bits_array[0] = 0;
+ depth_bits_array[1] = depth_bits;
+ depth_bits_array[2] = depth_bits;
+
+ /* Just like with the accumulation buffer, always provide some modes
+ * with a stencil buffer. It will be a sw fallback, but some apps won't
+ * care about that.
+ */
+ stencil_bits_array[0] = 0;
+ stencil_bits_array[1] = 0;
+ stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
+ back_buffer_factor = (have_back_buffer) ? 2 : 1;
+
+ num_modes = depth_buffer_factor * back_buffer_factor * 4;
+
+ if ( pixel_bits == 16 ) {
+ fb_format = GL_RGB;
+ fb_type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+ else {
+ fb_format = GL_BGR;
+ fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ }
+
+ modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) );
+ m = modes;
+ if ( ! driFillInModes( & m, fb_format, fb_type,
+ depth_bits_array, stencil_bits_array, depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ GLX_TRUE_COLOR ) ) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ if ( ! driFillInModes( & m, fb_format, fb_type,
+ depth_bits_array, stencil_bits_array, depth_buffer_factor,
+ back_buffer_modes, back_buffer_factor,
+ GLX_DIRECT_COLOR ) ) {
+ fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
+ __func__, __LINE__ );
+ return NULL;
+ }
+
+ /* Mark the visual as slow if there are "fake" stencil bits.
+ */
+ for ( m = modes ; m != NULL ; m = m->next ) {
+ if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
+ m->visualRating = GLX_SLOW_CONFIG;
+ }
+ }
+
+ return modes;
+}
+
+
+static GLboolean
+mgaInitDriver(__DRIscreenPrivate *sPriv)
+{
+ mgaScreenPrivate *mgaScreen;
+ MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
+ PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
+ (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension"));
+ void * const psc = sPriv->psc->screenConfigs;
+
+ if (sPriv->devPrivSize != sizeof(MGADRIRec)) {
+ fprintf(stderr,"\nERROR! sizeof(MGADRIRec) does not match passed size from device driver\n");
+ return GL_FALSE;
+ }
+
+ /* Allocate the private area */
+ mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
+ if (!mgaScreen) {
+ __driUtilMessage("Couldn't malloc screen struct");
+ return GL_FALSE;
+ }
+
+ mgaScreen->sPriv = sPriv;
+ sPriv->private = (void *)mgaScreen;
+
+ if (sPriv->drmMinor >= 1) {
+ int ret;
+ drm_mga_getparam_t gp;
+
+ gp.param = MGA_PARAM_IRQ_NR;
+ gp.value = &mgaScreen->irq;
+ mgaScreen->irq = 0;
+
+ ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
+ &gp, sizeof(gp));
+ if (ret) {
+ fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
+ FREE(mgaScreen);
+ sPriv->private = NULL;
+ return GL_FALSE;
+ }
+ }
+
+ if ( glx_enable_extension != NULL ) {
+ (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
+ (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
+ (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
+ (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
+ (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
+ }
+
+ if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
+ serverInfo->chipset != MGA_CARD_TYPE_G400) {
+ FREE(mgaScreen);
+ sPriv->private = NULL;
+ __driUtilMessage("Unrecognized chipset");
+ return GL_FALSE;
+ }
+
+
+ mgaScreen->chipset = serverInfo->chipset;
+ mgaScreen->cpp = serverInfo->cpp;
+
+ mgaScreen->agpMode = serverInfo->agpMode;
+
+ mgaScreen->frontPitch = serverInfo->frontPitch;
+ mgaScreen->frontOffset = serverInfo->frontOffset;
+ mgaScreen->backOffset = serverInfo->backOffset;
+ mgaScreen->backPitch = serverInfo->backPitch;
+ mgaScreen->depthOffset = serverInfo->depthOffset;
+ mgaScreen->depthPitch = serverInfo->depthPitch;
+
+
+ /* The only reason that the MMIO region needs to be accessable and the
+ * primary DMA region base address needs to be known is so that the driver
+ * can busy wait for certain DMA operations to complete (see
+ * mgaWaitForFrameCompletion in mgaioctl.c).
+ *
+ * Starting with MGA DRM version 3.2, these are completely unneeded as
+ * there is a new, in-kernel mechanism for handling the wait.
+ */
+
+ if (mgaScreen->sPriv->drmMinor < 2) {
+ mgaScreen->mmio.handle = serverInfo->registers.handle;
+ mgaScreen->mmio.size = serverInfo->registers.size;
+ if ( drmMap( sPriv->fd,
+ mgaScreen->mmio.handle, mgaScreen->mmio.size,
+ &mgaScreen->mmio.map ) < 0 ) {
+ FREE( mgaScreen );
+ sPriv->private = NULL;
+ __driUtilMessage( "Couldn't map MMIO registers" );
+ return GL_FALSE;
+ }
+
+ mgaScreen->primary.handle = serverInfo->primary.handle;
+ mgaScreen->primary.size = serverInfo->primary.size;
+ }
+ else {
+ (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
+ (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
+ }
+
+ mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
+ mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
+ PDEA_pagpxfer_enable | 1);
+
+ mgaScreen->textureSize[MGA_CARD_HEAP] = serverInfo->textureSize;
+ mgaScreen->textureSize[MGA_AGP_HEAP] = serverInfo->agpTextureSize;
+
+
+ /* The texVirtual array stores the base addresses in the CPU's address
+ * space of the texture memory pools. The base address of the on-card
+ * memory pool is calculated as an offset of the base of video memory. The
+ * AGP texture pool has to be mapped into the processes address space by
+ * the DRM.
+ */
+
+ mgaScreen->texVirtual[MGA_CARD_HEAP] = (char *)(mgaScreen->sPriv->pFB +
+ serverInfo->textureOffset);
+
+ if ( serverInfo->agpTextureSize > 0 ) {
+ if (drmMap(sPriv->fd, serverInfo->agpTextureOffset,
+ serverInfo->agpTextureSize,
+ (drmAddress *)&mgaScreen->texVirtual[MGA_AGP_HEAP]) != 0) {
+ FREE(mgaScreen);
+ sPriv->private = NULL;
+ __driUtilMessage("Couldn't map agptexture region");
+ return GL_FALSE;
+ }
+ }
+
+
+ /* For calculating setupdma addresses.
+ */
+
+ mgaScreen->bufs = drmMapBufs(sPriv->fd);
+ if (!mgaScreen->bufs) {
+ FREE(mgaScreen);
+ sPriv->private = NULL;
+ __driUtilMessage("Couldn't map dma buffers");
+ return GL_FALSE;
+ }
+ mgaScreen->sarea_priv_offset = serverInfo->sarea_priv_offset;
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo (&mgaScreen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ return GL_TRUE;
+}
+
+
+static void
+mgaDestroyScreen(__DRIscreenPrivate *sPriv)
+{
+ mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *) sPriv->private;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+ fprintf(stderr, "mgaDestroyScreen\n");
+
+ drmUnmapBufs(mgaScreen->bufs);
+
+
+ /* free all option information */
+ driDestroyOptionInfo (&mgaScreen->optionCache);
+
+ FREE(mgaScreen);
+ sPriv->private = NULL;
+}
+
+
+extern const struct tnl_pipeline_stage _mga_render_stage;
+
+static const struct tnl_pipeline_stage *mga_pipeline[] = {
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_vertex_program_stage,
+
+ /* REMOVE: point attenuation stage */
+#if 0
+ &_mga_render_stage, /* ADD: unclipped rastersetup-to-dma */
+ /* Need new ioctl for wacceptseq */
+#endif
+ &_tnl_render_stage,
+ 0,
+};
+
+
+static const struct dri_extension g400_extensions[] =
+{
+ { "GL_ARB_multitexture", NULL },
+ { "GL_ARB_texture_env_add", NULL },
+ { "GL_ARB_texture_env_combine", NULL },
+ { "GL_ARB_texture_env_crossbar", NULL },
+ { "GL_EXT_texture_env_combine", NULL },
+ { "GL_EXT_texture_edge_clamp", NULL },
+ { "GL_ATI_texture_env_combine3", NULL },
+ { NULL, NULL }
+};
+
+static const struct dri_extension card_extensions[] =
+{
+ { "GL_ARB_multisample", GL_ARB_multisample_functions },
+ { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions },
+ { "GL_ARB_texture_rectangle", NULL },
+ { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions },
+ { "GL_EXT_blend_logic_op", NULL },
+ { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions },
+ { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions },
+ /* paletted_textures currently doesn't work, but we could fix them later */
+#if defined( need_GL_EXT_paletted_texture )
+ { "GL_EXT_shared_texture_palette", NULL },
+ { "GL_EXT_paletted_texture", GL_EXT_paletted_texture_functions },
+#endif
+ { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions },
+ { "GL_EXT_stencil_wrap", NULL },
+ { "GL_MESA_ycbcr_texture", NULL },
+ { "GL_SGIS_generate_mipmap", NULL },
+ { NULL, NULL }
+};
+
+static const struct dri_extension ARB_vp_extension[] = {
+ { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions },
+ { NULL, NULL }
+};
+
+static const struct dri_extension NV_vp_extensions[] = {
+ { "GL_NV_vertex_program", GL_NV_vertex_program_functions },
+ { "GL_NV_vertex_program1_1", NULL },
+ { NULL, NULL }
+};
+
+static const struct dri_debug_control debug_control[] =
+{
+ { "fall", DEBUG_VERBOSE_FALLBACK },
+ { "tex", DEBUG_VERBOSE_TEXTURE },
+ { "ioctl", DEBUG_VERBOSE_IOCTL },
+ { "verb", DEBUG_VERBOSE_MSG },
+ { "dri", DEBUG_VERBOSE_DRI },
+ { NULL, 0 }
+};
+
+
+static GLboolean
+mgaCreateContext( const __GLcontextModes *mesaVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate )
+{
+ int i;
+ unsigned maxlevels;
+ GLcontext *ctx, *shareCtx;
+ mgaContextPtr mmesa;
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
+ drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
+ mgaScreen->sarea_priv_offset);
+ struct dd_function_table functions;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+ fprintf(stderr, "mgaCreateContext\n");
+
+ /* allocate mga context */
+ mmesa = (mgaContextPtr) CALLOC(sizeof(mgaContext));
+ if (!mmesa) {
+ return GL_FALSE;
+ }
+
+ /* Init default driver functions then plug in our Radeon-specific functions
+ * (the texture functions are especially important)
+ */
+ _mesa_init_driver_functions( &functions );
+ mgaInitDriverFuncs( &functions );
+ mgaInitTextureFuncs( &functions );
+ mgaInitIoctlFuncs( &functions );
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx,
+ &functions, (void *) mmesa);
+ if (!mmesa->glCtx) {
+ FREE(mmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = mmesa;
+
+ /* Init mga state */
+ mmesa->hHWContext = driContextPriv->hHWContext;
+ mmesa->driFd = sPriv->fd;
+ mmesa->driHwLock = &sPriv->pSAREA->lock;
+
+ mmesa->mgaScreen = mgaScreen;
+ mmesa->driScreen = sPriv;
+ mmesa->sarea = (void *)saPriv;
+
+ /* Parse configuration files */
+ driParseConfigFiles (&mmesa->optionCache, &mgaScreen->optionCache,
+ sPriv->myNum, "mga");
+
+ (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
+ make_empty_list( & mmesa->swapped );
+
+ mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
+ for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+ mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
+ mgaScreen->textureSize[i],
+ 6,
+ MGA_NR_TEX_REGIONS,
+ (drmTextureRegionPtr)mmesa->sarea->texList[i],
+ &mmesa->sarea->texAge[i],
+ &mmesa->swapped,
+ sizeof( mgaTextureObject_t ),
+ (destroy_texture_object_t *) mgaDestroyTexObj );
+ }
+
+ /* Set the maximum texture size small enough that we can guarentee
+ * that both texture units can bind a maximal texture and have them
+ * on the card at once.
+ */
+ ctx = mmesa->glCtx;
+ if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
+ ctx->Const.MaxTextureUnits = 1;
+ ctx->Const.MaxTextureImageUnits = 1;
+ ctx->Const.MaxTextureCoordUnits = 1;
+ maxlevels = G200_TEX_MAXLEVELS;
+
+ }
+ else {
+ ctx->Const.MaxTextureUnits = 2;
+ ctx->Const.MaxTextureImageUnits = 2;
+ ctx->Const.MaxTextureCoordUnits = 2;
+ maxlevels = G400_TEX_MAXLEVELS;
+ }
+
+ driCalculateMaxTextureLevels( mmesa->texture_heaps,
+ mmesa->nr_heaps,
+ & ctx->Const,
+ 4,
+ 11, /* max 2D texture size is 2048x2048 */
+ 0, /* 3D textures unsupported. */
+ 0, /* cube textures unsupported. */
+ 11, /* max texture rect size is 2048x2048 */
+ maxlevels,
+ GL_FALSE,
+ 0 );
+
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 10.0;
+ ctx->Const.MaxLineWidthAA = 10.0;
+ ctx->Const.LineWidthGranularity = 1.0;
+
+ mmesa->texture_depth = driQueryOptioni (&mmesa->optionCache,
+ "texture_depth");
+ if (mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
+ mmesa->texture_depth = ( mesaVis->rgbBits >= 24 ) ?
+ DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
+ mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
+
+ switch (mesaVis->depthBits) {
+ case 16:
+ mmesa->depth_scale = 1.0/(GLdouble)0xffff;
+ mmesa->depth_clear_mask = ~0;
+ mmesa->ClearDepth = 0xffff;
+ break;
+ case 24:
+ mmesa->depth_scale = 1.0/(GLdouble)0xffffff;
+ if (mmesa->hw_stencil) {
+ mmesa->depth_clear_mask = 0xffffff00;
+ mmesa->stencil_clear_mask = 0x000000ff;
+ } else
+ mmesa->depth_clear_mask = ~0;
+ mmesa->ClearDepth = 0xffffff00;
+ break;
+ case 32:
+ mmesa->depth_scale = 1.0/(GLdouble)0xffffffff;
+ mmesa->depth_clear_mask = ~0;
+ mmesa->ClearDepth = 0xffffffff;
+ break;
+ };
+
+ mmesa->haveHwStipple = GL_FALSE;
+ mmesa->RenderIndex = -1; /* impossible value */
+ mmesa->dirty = ~0;
+ mmesa->vertex_format = 0;
+ mmesa->CurrentTexObj[0] = 0;
+ mmesa->CurrentTexObj[1] = 0;
+ mmesa->tmu_source[0] = 0;
+ mmesa->tmu_source[1] = 1;
+
+ mmesa->texAge[0] = 0;
+ mmesa->texAge[1] = 0;
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext( ctx );
+ _vbo_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+
+ _swsetup_CreateContext( ctx );
+
+ /* Install the customized pipeline:
+ */
+ _tnl_destroy_pipeline( ctx );
+ _tnl_install_pipeline( ctx, mga_pipeline );
+
+ /* Configure swrast and T&L to match hardware characteristics:
+ */
+ _swrast_allow_pixel_fog( ctx, GL_FALSE );
+ _swrast_allow_vertex_fog( ctx, GL_TRUE );
+ _tnl_allow_pixel_fog( ctx, GL_FALSE );
+ _tnl_allow_vertex_fog( ctx, GL_TRUE );
+
+ mmesa->primary_offset = mmesa->mgaScreen->primary.handle;
+
+ ctx->DriverCtx = (void *) mmesa;
+ mmesa->glCtx = ctx;
+
+ driInitExtensions( ctx, card_extensions, GL_FALSE );
+
+ if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
+ driInitExtensions( ctx, g400_extensions, GL_FALSE );
+ }
+
+ if ( driQueryOptionb( &mmesa->optionCache, "arb_vertex_program" ) ) {
+ driInitSingleExtension( ctx, ARB_vp_extension );
+ }
+
+ if ( driQueryOptionb( &mmesa->optionCache, "nv_vertex_program" ) ) {
+ driInitExtensions( ctx, NV_vp_extensions, GL_FALSE );
+ }
+
+
+ /* XXX these should really go right after _mesa_init_driver_functions() */
+ mgaDDInitStateFuncs( ctx );
+ mgaDDInitSpanFuncs( ctx );
+ mgaDDInitPixelFuncs( ctx );
+ mgaDDInitTriFuncs( ctx );
+
+ mgaInitVB( ctx );
+ mgaInitState( mmesa );
+
+ driContextPriv->driverPrivate = (void *) mmesa;
+
+#if DO_DEBUG
+ MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
+ debug_control );
+#endif
+
+ mmesa->vblank_flags = (mmesa->mgaScreen->irq == 0)
+ ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache);
+
+ (*dri_interface->getUST)( & mmesa->swap_ust );
+
+ if (driQueryOptionb(&mmesa->optionCache, "no_rast")) {
+ fprintf(stderr, "disabling 3D acceleration\n");
+ FALLBACK(mmesa->glCtx, MGA_FALLBACK_DISABLE, 1);
+ }
+
+ return GL_TRUE;
+}
+
+static void
+mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
+{
+ mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+ fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
+ __FILE__, __LINE__ );
+
+ assert(mmesa); /* should never be null */
+ if (mmesa) {
+ GLboolean release_texture_heaps;
+
+
+ release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
+ _swsetup_DestroyContext( mmesa->glCtx );
+ _tnl_DestroyContext( mmesa->glCtx );
+ _vbo_DestroyContext( mmesa->glCtx );
+ _swrast_DestroyContext( mmesa->glCtx );
+
+ mgaFreeVB( mmesa->glCtx );
+
+ /* free the Mesa context */
+ mmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(mmesa->glCtx);
+
+ if ( release_texture_heaps ) {
+ /* This share group is about to go away, free our private
+ * texture object data.
+ */
+ int i;
+
+ for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+ driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
+ mmesa->texture_heaps[ i ] = NULL;
+ }
+
+ assert( is_empty_list( & mmesa->swapped ) );
+ }
+
+ /* free the option cache */
+ driDestroyOptionCache (&mmesa->optionCache);
+
+ FREE(mmesa);
+ }
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+ fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
+ __FILE__, __LINE__ );
+}
+
+
+static GLboolean
+mgaCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ mgaScreenPrivate *screen = (mgaScreenPrivate *) driScrnPriv->private;
+
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ GLboolean swStencil = (mesaVis->stencilBits > 0 &&
+ mesaVis->depthBits != 24);
+
+#if 0
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer(mesaVis,
+ GL_FALSE, /* software depth buffer? */
+ swStencil,
+ mesaVis->accumRedBits > 0,
+ mesaVis->alphaBits > 0 );
+#else
+ struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+
+ {
+ driRenderbuffer *frontRb
+ = driNewRenderbuffer(GL_RGBA,
+ NULL,
+ screen->cpp,
+ screen->frontOffset, screen->frontPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(frontRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
+ }
+
+ if (mesaVis->doubleBufferMode) {
+ driRenderbuffer *backRb
+ = driNewRenderbuffer(GL_RGBA,
+ NULL,
+ screen->cpp,
+ screen->backOffset, screen->backPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(backRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
+ }
+
+ if (mesaVis->depthBits == 16) {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(GL_DEPTH_COMPONENT16,
+ NULL,
+ screen->cpp,
+ screen->depthOffset, screen->depthPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+ else if (mesaVis->depthBits == 24) {
+ /* XXX is this right? */
+ if (mesaVis->stencilBits) {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(GL_DEPTH_COMPONENT24,
+ NULL,
+ screen->cpp,
+ screen->depthOffset, screen->depthPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+ else {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
+ NULL,
+ screen->cpp,
+ screen->depthOffset, screen->depthPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+ }
+ else if (mesaVis->depthBits == 32) {
+ driRenderbuffer *depthRb
+ = driNewRenderbuffer(GL_DEPTH_COMPONENT32,
+ NULL,
+ screen->cpp,
+ screen->depthOffset, screen->depthPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(depthRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+ }
+
+ if (mesaVis->stencilBits > 0 && !swStencil) {
+ driRenderbuffer *stencilRb
+ = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT,
+ NULL,
+ screen->cpp,
+ screen->depthOffset, screen->depthPitch,
+ driDrawPriv);
+ mgaSetSpanFunctions(stencilRb, mesaVis);
+ _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
+ }
+
+ _mesa_add_soft_renderbuffers(fb,
+ GL_FALSE, /* color */
+ GL_FALSE, /* depth */
+ swStencil,
+ mesaVis->accumRedBits > 0,
+ GL_FALSE, /* alpha */
+ GL_FALSE /* aux */);
+ driDrawPriv->driverPrivate = (void *) fb;
+#endif
+
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+mgaDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+}
+
+static void
+mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
+{
+ if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+ mgaContextPtr mmesa;
+ GLcontext *ctx;
+ mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
+ ctx = mmesa->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ _mesa_notifySwapBuffers( ctx );
+ mgaCopyBuffer( dPriv );
+ }
+ } else {
+ /* XXX this shouldn't be an error but we can't handle it for now */
+ _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__);
+ }
+}
+
+static GLboolean
+mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
+{
+ mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
+ if (mmesa)
+ mmesa->dirty = ~0;
+
+ return GL_TRUE;
+}
+
+/* This looks buggy to me - the 'b' variable isn't used anywhere...
+ * Hmm - It seems that the drawable is already hooked in to
+ * driDrawablePriv.
+ *
+ * But why are we doing context initialization here???
+ */
+static GLboolean
+mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv)
+{
+ if (driContextPriv) {
+ mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
+
+ if (mmesa->driDrawable != driDrawPriv) {
+ driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags,
+ &mmesa->vbl_seq );
+ mmesa->driDrawable = driDrawPriv;
+ mmesa->dirty = ~0;
+ mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
+ }
+
+ mmesa->driReadable = driReadPriv;
+
+ _mesa_make_current(mmesa->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate);
+ }
+ else {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+
+void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
+ drm_mga_sarea_t *sarea = mmesa->sarea;
+ int me = mmesa->hHWContext;
+ int i;
+
+ drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
+
+ DRI_VALIDATE_DRAWABLE_INFO( mmesa->driScreen, dPriv );
+ if (*(dPriv->pStamp) != mmesa->lastStamp) {
+ mmesa->lastStamp = *(dPriv->pStamp);
+ mmesa->SetupNewInputs |= VERT_BIT_POS;
+ mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
+ mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
+ driUpdateFramebufferSize(mmesa->glCtx, dPriv);
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
+
+ mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
+
+ if (sarea->ctxOwner != me) {
+ mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
+ MGA_UPLOAD_TEX1 | MGA_UPLOAD_PIPE);
+ sarea->ctxOwner=me;
+ }
+
+ for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+ DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
+ }
+}
+
+
+static const struct __DriverAPIRec mgaAPI = {
+ .InitDriver = mgaInitDriver,
+ .DestroyScreen = mgaDestroyScreen,
+ .CreateContext = mgaCreateContext,
+ .DestroyContext = mgaDestroyContext,
+ .CreateBuffer = mgaCreateBuffer,
+ .DestroyBuffer = mgaDestroyBuffer,
+ .SwapBuffers = mgaSwapBuffers,
+ .MakeCurrent = mgaMakeCurrent,
+ .UnbindContext = mgaUnbindContext,
+ .GetSwapInfo = getSwapInfo,
+ .GetMSC = driGetMSC32,
+ .WaitForMSC = driWaitForMSC32,
+ .WaitForSBC = NULL,
+ .SwapBuffersMSC = NULL
+};
+
+
+/**
+ * This is the bootstrap function for the driver. libGL supplies all of the
+ * requisite information about the system, and the driver initializes itself.
+ * This routine also fills in the linked list pointed to by \c driver_modes
+ * with the \c __GLcontextModes that the driver can support for windows or
+ * pbuffers.
+ *
+ * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
+ * failure.
+ */
+PUBLIC
+void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
+ const __GLcontextModes * modes,
+ const __DRIversion * ddx_version,
+ const __DRIversion * dri_version,
+ const __DRIversion * drm_version,
+ const __DRIframebuffer * frame_buffer,
+ drmAddress pSAREA, int fd,
+ int internal_api_version,
+ const __DRIinterfaceMethods * interface,
+ __GLcontextModes ** driver_modes )
+
+{
+ __DRIscreenPrivate *psp;
+ static const __DRIversion ddx_expected = { 1, 2, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 3, 0, 0 };
+
+ dri_interface = interface;
+
+ if ( ! driCheckDriDdxDrmVersions2( "MGA",
+ dri_version, & dri_expected,
+ ddx_version, & ddx_expected,
+ drm_version, & drm_expected ) ) {
+ return NULL;
+ }
+
+ psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+ ddx_version, dri_version, drm_version,
+ frame_buffer, pSAREA, fd,
+ internal_api_version, &mgaAPI);
+ if ( psp != NULL ) {
+ MGADRIPtr dri_priv = (MGADRIPtr) psp->pDevPriv;
+ *driver_modes = mgaFillInModes( dri_priv->cpp * 8,
+ (dri_priv->cpp == 2) ? 16 : 24,
+ (dri_priv->cpp == 2) ? 0 : 8,
+ (dri_priv->backOffset != dri_priv->depthOffset) );
+
+ /* Calling driInitExtensions here, with a NULL context pointer, does not actually
+ * enable the extensions. It just makes sure that all the dispatch offsets for all
+ * the extensions that *might* be enables are known. This is needed because the
+ * dispatch offsets need to be known when _mesa_context_create is called, but we can't
+ * enable the extensions until we have a context pointer.
+ *
+ * Hello chicken. Hello egg. How are you two today?
+ */
+ driInitExtensions( NULL, card_extensions, GL_FALSE );
+ driInitExtensions( NULL, g400_extensions, GL_FALSE );
+ driInitSingleExtension( NULL, ARB_vp_extension );
+ driInitExtensions( NULL, NV_vp_extensions, GL_FALSE );
+
+ }
+
+ return (void *) psp;
+}
+
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+{
+ mgaContextPtr mmesa;
+
+ if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+ || (dPriv->driContextPriv->driverPrivate == NULL)
+ || (sInfo == NULL) ) {
+ return -1;
+ }
+
+ mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
+ sInfo->swap_count = mmesa->swap_count;
+ sInfo->swap_ust = mmesa->swap_ust;
+ sInfo->swap_missed_count = mmesa->swap_missed_count;
+
+ sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+ ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
+ : 0.0;
+
+ return 0;
+}
diff --git a/src/mga_xmesa.h b/src/mga_xmesa.h
new file mode 100644
index 0000000..0ab0c63
--- /dev/null
+++ b/src/mga_xmesa.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.h,v 1.12 2002/12/16 16:18:52 dawes Exp $ */
+
+#ifndef _MGA_INIT_H_
+#define _MGA_INIT_H_
+
+#include <sys/time.h>
+#include "dri_util.h"
+#include "mga_drm.h"
+#include "mtypes.h"
+#include "mgaregs.h"
+#include "xmlconfig.h"
+
+typedef struct mga_screen_private_s {
+ /**
+ * Chipset "family" of this card. Currently only \c MGA_CARD_TYPE_G200 and
+ * \c MGA_CARD_TYPE_G400 are possible.
+ */
+ int chipset;
+
+
+ /**
+ * Characters (bytes) per-pixel for both the front and back buffers.
+ *
+ * \note
+ * This is also implicitly the bytes per-pixel for the depth-buffer.
+ */
+ int cpp;
+
+ GLint agpMode;
+ unsigned int irq; /**< IRQ number (0 means none) */
+
+ unsigned int frontOffset;
+ unsigned int frontPitch;
+ unsigned int backOffset;
+ unsigned int backPitch;
+
+ unsigned int depthOffset;
+ unsigned int depthPitch;
+
+ unsigned int textureOffset[MGA_NR_TEX_HEAPS];
+ unsigned int textureSize[MGA_NR_TEX_HEAPS];
+ char *texVirtual[MGA_NR_TEX_HEAPS];
+
+
+ __DRIscreenPrivate *sPriv;
+ drmBufMapPtr bufs;
+
+ drmRegion mmio;
+ drmRegion primary;
+ unsigned int sarea_priv_offset;
+
+ /** Configuration cache with default values for all contexts */
+ driOptionCache optionCache;
+} mgaScreenPrivate;
+
+
+/**
+ * mgaRenderbuffer, derived from Mesa's gl_renderbuffer
+ */
+typedef struct {
+ struct gl_renderbuffer Base;
+ /* XXX per-window info should go here */
+ int foo, bar;
+} mgaRenderbuffer;
+
+
+
+#include "mgacontext.h"
+
+extern void mgaGetLock( mgaContextPtr mmesa, GLuint flags );
+extern void mgaEmitHwStateLocked( mgaContextPtr mmesa );
+extern void mgaEmitScissorValues( mgaContextPtr mmesa, int box_nr, int emit );
+
+#define GET_DISPATCH_AGE( mmesa ) mmesa->sarea->last_dispatch
+
+
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( mmesa ) \
+ do { \
+ char __ret=0; \
+ DRM_CAS(mmesa->driHwLock, mmesa->hHWContext, \
+ (DRM_LOCK_HELD|mmesa->hHWContext), __ret); \
+ if (__ret) \
+ mgaGetLock( mmesa, 0 ); \
+ } while (0)
+
+
+/*
+ */
+#define LOCK_HARDWARE_QUIESCENT( mmesa ) do { \
+ LOCK_HARDWARE( mmesa ); \
+ UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH ); \
+} while (0)
+
+
+/* Unlock the hardware using the global current context
+ */
+#define UNLOCK_HARDWARE(mmesa) \
+ DRM_UNLOCK(mmesa->driFd, mmesa->driHwLock, mmesa->hHWContext);
+
+
+/* Freshen our snapshot of the drawables
+ */
+#define REFRESH_DRAWABLE_INFO( mmesa ) \
+do { \
+ LOCK_HARDWARE( mmesa ); \
+ mmesa->lastX = mmesa->drawX; \
+ mmesa->lastY = mmesa->drawY; \
+ UNLOCK_HARDWARE( mmesa ); \
+} while (0)
+
+
+#define GET_DRAWABLE_LOCK( mmesa ) while(0)
+#define RELEASE_DRAWABLE_LOCK( mmesa ) while(0)
+
+
+/* The 2D driver macros are busted -- we can't use them here as they
+ * rely on the 2D driver data structures rather than taking an explicit
+ * base address.
+ */
+#define MGA_BASE( reg ) ((unsigned long)(mmesa->mgaScreen->mmio.map))
+#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
+
+#define MGA_DEREF( reg ) *(volatile u_int32_t *)MGA_ADDR( reg )
+#define MGA_READ( reg ) MGA_DEREF( reg )
+
+#endif
diff --git a/src/mgacontext.h b/src/mgacontext.h
new file mode 100644
index 0000000..2124006
--- /dev/null
+++ b/src/mgacontext.h
@@ -0,0 +1,365 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgacontext.h,v 1.7 2002/12/16 16:18:52 dawes Exp $*/
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef MGALIB_INC
+#define MGALIB_INC
+
+#include <stdint.h>
+#include "drm.h"
+#include "mga_drm.h"
+#include "dri_util.h"
+#include "mtypes.h"
+#include "xf86drm.h"
+#include "mm.h"
+#include "colormac.h"
+#include "texmem.h"
+#include "macros.h"
+#include "xmlconfig.h"
+
+#define MGA_SET_FIELD(reg,mask,val) reg = ((reg) & (mask)) | ((val) & ~(mask))
+#define MGA_FIELD(field,val) (((val) << (field ## _SHIFT)) & ~(field ## _MASK))
+#define MGA_GET_FIELD(field, val) ((val & ~(field ## _MASK)) >> (field ## _SHIFT))
+
+#define MGA_IS_G200(mmesa) (mmesa->mgaScreen->chipset == MGA_CARD_TYPE_G200)
+#define MGA_IS_G400(mmesa) (mmesa->mgaScreen->chipset == MGA_CARD_TYPE_G400)
+
+
+/* SoftwareFallback
+ * - texture env GL_BLEND -- can be fixed
+ * - 1D and 3D textures
+ * - incomplete textures
+ * - GL_DEPTH_FUNC == GL_NEVER not in h/w
+ */
+#define MGA_FALLBACK_TEXTURE 0x1
+#define MGA_FALLBACK_DRAW_BUFFER 0x2
+#define MGA_FALLBACK_READ_BUFFER 0x4
+#define MGA_FALLBACK_BLEND 0x8
+#define MGA_FALLBACK_RENDERMODE 0x10
+#define MGA_FALLBACK_STENCIL 0x20
+#define MGA_FALLBACK_DEPTH 0x40
+#define MGA_FALLBACK_BORDER_MODE 0x80
+#define MGA_FALLBACK_DISABLE 0x100
+
+
+/* Use the templated vertex formats:
+ */
+#define TAG(x) mga##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+typedef struct mga_context_t mgaContext;
+typedef struct mga_context_t *mgaContextPtr;
+
+typedef void (*mga_tri_func)( mgaContextPtr, mgaVertex *, mgaVertex *,
+ mgaVertex * );
+typedef void (*mga_line_func)( mgaContextPtr, mgaVertex *, mgaVertex * );
+typedef void (*mga_point_func)( mgaContextPtr, mgaVertex * );
+
+
+
+/* Texture environment color
+ */
+#define RGB_ZERO(c) (((c) & 0xffffff) == 0x000000)
+#define RGB_ONE(c) (((c) & 0xffffff) == 0xffffff)
+#define ALPHA_ZERO(c) (((c) >> 24) == 0x00)
+#define ALPHA_ONE(c) (((c) >> 24) == 0xff)
+#define RGBA_EQUAL(c) ((c) == PACK_COLOR_8888( (c) & 0xff, (c) & 0xff, \
+ (c) & 0xff, (c) & 0xff ))
+
+struct mga_texture_object_s;
+struct mga_screen_private_s;
+
+#define G200_TEX_MAXLEVELS 5
+#define G400_TEX_MAXLEVELS 11
+
+typedef struct mga_texture_object_s
+{
+ driTextureObject base;
+
+ /* The G200 only has the ability to use 5 mipmap levels (including the
+ * base level). The G400 does not have this restriction, but it still
+ * only has 5 offset pointers in the hardware. The trick on the G400 is
+ * upto the first 4 offset pointers point to mipmap levels. The last
+ * offset pointer tells how large the preceeding mipmap is. This value is
+ * then used to determine where the remaining mipmaps are.
+ *
+ * For example, if the first offsets[0] through offsets[2] are used as
+ * pointers, then offset[3] will be the size of the mipmap pointed to by
+ * offsets[2]. So mipmap level 3 will be at (offsets[2]+offsets[3]). For
+ * each successive mipmap level, offsets[3] is divided by 4 and added to
+ * the previous address. So mipmap level 4 will be at
+ * (offsets[2]+offsets[3]+(offsets[3] / 4)).
+ *
+ * The last pointer is selected by setting TO_texorgoffsetsel in its
+ * pointer. In the previous example, offset[2] would have
+ * TO_texorgoffsetsel or'ed in before writing it to the hardware.
+ *
+ * In the current driver all of the mipmaps are packed together linearly
+ * with mipmap level 0. Therefore offsets[0] points to the base of the
+ * texture (and has TO_texorgoffsetsel or'ed in), and offsets[1] is the
+ * size of the base texture.
+ *
+ * There is a possible optimization available here. At times the driver
+ * may not be able to allocate a single block of memory for the complete
+ * texture without ejecting some other textures from memory. It may be
+ * possible to put some of the lower mipmap levels (i.e., the larger
+ * mipmaps) in memory separate from the higher levels.
+ *
+ * The implementation should be fairly obvious, but getting "right" would
+ * likely be non-trivial. A first allocation for the entire texture would
+ * be attempted with a flag that says "don't eject other textures." If
+ * that failed, an additional allocation would be attmpted for just the
+ * base map. The process would repeat with the block of lower maps. The
+ * tricky parts would be in detecting when some of the levels had been
+ * ejected from texture memory by other textures and preventing the
+ * 4th allocation (for all the smallest mipmap levels) from kicking out
+ * any of the first three.
+ *
+ * This array holds G400_TEX_MAXLEVELS pointers to remove an if-statement
+ * in a loop in mgaSetTexImages. Values past G200_TEX_MAXLEVELS are not
+ * used.
+ */
+ GLuint offsets[G400_TEX_MAXLEVELS];
+
+ int texelBytes;
+ GLuint age;
+
+ drm_mga_texture_regs_t setup;
+
+ /* If one texture dimension wraps with GL_CLAMP and the other with
+ * GL_CLAMP_TO_EDGE, we have to fallback to software. We would also have
+ * to fallback for GL_CLAMP_TO_BORDER.
+ */
+ GLboolean border_fallback;
+ /* Depending on multitxturing and environment color
+ * GL_BLEND may have to be a software fallback.
+ */
+ GLboolean texenv_fallback;
+} mgaTextureObject_t;
+
+struct mga_hw_state {
+ GLuint specen;
+ GLuint cull;
+ GLuint cull_dualtex;
+ GLuint stencil;
+ GLuint stencilctl;
+ GLuint stencil_enable;
+ GLuint zmode;
+ GLuint rop;
+ GLuint alpha_func;
+ GLuint alpha_func_enable;
+ GLuint blend_func;
+ GLuint blend_func_enable;
+ GLuint alpha_sel;
+};
+
+struct mga_context_t {
+
+ GLcontext *glCtx;
+ unsigned int lastStamp; /* fullscreen breaks dpriv->laststamp,
+ * need to shadow it here. */
+
+ /* Hardware state management
+ */
+ struct mga_hw_state hw;
+
+ /* Bookkeeping for texturing
+ */
+ unsigned nr_heaps;
+ driTexHeap * texture_heaps[ MGA_NR_TEX_HEAPS ];
+ driTextureObject swapped;
+
+ struct mga_texture_object_s *CurrentTexObj[2];
+
+
+ /* Map GL texture units onto hardware.
+ */
+ GLuint tmu_source[2];
+
+ int texture_depth;
+
+ /* Manage fallbacks
+ */
+ GLuint Fallback;
+
+ /* Texture environment color.
+ */
+ unsigned int envcolor[2];
+ GLboolean fcol_used;
+ GLboolean force_dualtex;
+
+ /* Rasterization state
+ */
+ GLuint SetupNewInputs;
+ GLuint SetupIndex;
+ GLuint RenderIndex;
+
+ GLuint hw_primitive;
+ GLenum raster_primitive;
+ GLenum render_primitive;
+
+ GLubyte *verts;
+ GLint vertex_stride_shift;
+ GLuint vertex_format;
+ GLuint vertex_size;
+
+ /* Fallback rasterization functions
+ */
+ mga_point_func draw_point;
+ mga_line_func draw_line;
+ mga_tri_func draw_tri;
+
+
+ /* Manage driver and hardware state
+ */
+ GLuint NewGLState;
+ GLuint dirty;
+
+ drm_mga_context_regs_t setup;
+
+ GLuint ClearColor;
+ GLuint ClearDepth;
+ GLuint poly_stipple;
+ GLfloat depth_scale;
+
+ GLuint depth_clear_mask;
+ GLuint stencil_clear_mask;
+ GLuint hw_stencil;
+ GLuint haveHwStipple;
+ GLfloat hw_viewport[16];
+
+ /* Dma buffers
+ */
+ drmBufPtr vertex_dma_buffer;
+ drmBufPtr iload_buffer;
+
+ /* VBI
+ */
+ GLuint vbl_seq;
+ GLuint vblank_flags;
+
+ int64_t swap_ust;
+ int64_t swap_missed_ust;
+
+ GLuint swap_count;
+ GLuint swap_missed_count;
+
+ uint32_t last_frame_fence;
+
+ /* Drawable, cliprect and scissor information
+ */
+ int dirty_cliprects; /* which sets of cliprects are uptodate? */
+ int draw_buffer; /* which buffer are we rendering to */
+ unsigned int drawOffset; /* draw buffer address in space */
+ int readOffset;
+ int drawX, drawY; /* origin of drawable in draw buffer */
+ int lastX, lastY; /* detect DSTORG bug */
+ GLuint numClipRects; /* cliprects for the draw buffer */
+ drm_clip_rect_t *pClipRects;
+ drm_clip_rect_t draw_rect;
+ drm_clip_rect_t scissor_rect;
+ int scissor;
+
+ drm_clip_rect_t tmp_boxes[2][MGA_NR_SAREA_CLIPRECTS];
+
+
+ /* Texture aging and DMA based aging.
+ */
+ unsigned int texAge[MGA_NR_TEX_HEAPS];/* texture LRU age */
+ unsigned int dirtyAge; /* buffer age for synchronization */
+
+ GLuint primary_offset;
+
+ /* Mirrors of some DRI state.
+ */
+ drm_context_t hHWContext;
+ drm_hw_lock_t *driHwLock;
+ int driFd;
+ __DRIdrawablePrivate *driDrawable;
+ __DRIdrawablePrivate *driReadable;
+
+ __DRIscreenPrivate *driScreen;
+ struct mga_screen_private_s *mgaScreen;
+ drm_mga_sarea_t *sarea;
+
+ /* Configuration cache
+ */
+ driOptionCache optionCache;
+};
+
+#define MGA_CONTEXT(ctx) ((mgaContextPtr)(ctx->DriverCtx))
+
+
+
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG 1
+
+#if DO_DEBUG
+extern int MGA_DEBUG;
+#else
+#define MGA_DEBUG 0
+#endif
+
+#define DEBUG_VERBOSE_MSG 0x01
+#define DEBUG_VERBOSE_DRI 0x02
+#define DEBUG_VERBOSE_IOCTL 0x04
+#define DEBUG_VERBOSE_TEXTURE 0x08
+#define DEBUG_VERBOSE_FALLBACK 0x10
+
+static __inline__ GLuint mgaPackColor(GLuint cpp,
+ GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a)
+{
+ switch (cpp) {
+ case 2:
+ return PACK_COLOR_565( r, g, b );
+ case 4:
+ return PACK_COLOR_8888( a, r, g, b );
+ default:
+ return 0;
+ }
+}
+
+
+/*
+ * Subpixel offsets for window coordinates:
+ */
+#define SUBPIXEL_X (-0.5F)
+#define SUBPIXEL_Y (-0.5F + 0.125)
+
+
+#define MGA_WA_TRIANGLES 0x18000000
+#define MGA_WA_TRISTRIP_T0 0x02010200
+#define MGA_WA_TRIFAN_T0 0x01000408
+#define MGA_WA_TRISTRIP_T0T1 0x02010400
+#define MGA_WA_TRIFAN_T0T1 0x01000810
+
+#endif
diff --git a/src/mgadd.c b/src/mgadd.c
new file mode 100644
index 0000000..b1d5e0c
--- /dev/null
+++ b/src/mgadd.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgadd.c,v 1.14 2002/10/30 12:51:35 alanh Exp $ */
+
+
+#include "mtypes.h"
+#include "framebuffer.h"
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgadd.h"
+#include "mgastate.h"
+#include "mgaspan.h"
+#include "mgatex.h"
+#include "mgatris.h"
+#include "mgavb.h"
+#include "mga_xmesa.h"
+#include "utils.h"
+
+#define DRIVER_DATE "20061030"
+
+
+/***************************************
+ * Mesa's Driver Functions
+ ***************************************/
+
+
+static const GLubyte *mgaGetString( GLcontext *ctx, GLenum name )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ static char buffer[128];
+ unsigned offset;
+
+ switch ( name ) {
+ case GL_VENDOR:
+ return (GLubyte *) "VA Linux Systems Inc.";
+
+ case GL_RENDERER:
+ offset = driGetRendererString( buffer,
+ MGA_IS_G400(mmesa) ? "G400" :
+ MGA_IS_G200(mmesa) ? "G200" : "MGA",
+ DRIVER_DATE,
+ mmesa->mgaScreen->agpMode );
+
+ return (GLubyte *)buffer;
+
+ default:
+ return NULL;
+ }
+}
+
+
+void mgaInitDriverFuncs( struct dd_function_table *functions )
+{
+ functions->GetString = mgaGetString;
+}
diff --git a/src/mgadd.h b/src/mgadd.h
new file mode 100644
index 0000000..f98bfdc
--- /dev/null
+++ b/src/mgadd.h
@@ -0,0 +1,36 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgadd.h,v 1.3 2002/10/30 12:51:35 alanh Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef MGADD_INC
+#define MGADD_INC
+
+#include "context.h"
+
+extern void mgaInitDriverFuncs( struct dd_function_table *functions );
+
+#endif
diff --git a/src/mgaioctl.c b/src/mgaioctl.c
new file mode 100644
index 0000000..f8587fc
--- /dev/null
+++ b/src/mgaioctl.c
@@ -0,0 +1,751 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS 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.
+ */
+
+/**
+ * \file mgaioctl.c
+ * MGA IOCTL related wrapper functions.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+#include <errno.h>
+#include "mtypes.h"
+#include "macros.h"
+#include "dd.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+#include "drm.h"
+#include "mga_drm.h"
+#include "mgacontext.h"
+#include "mgadd.h"
+#include "mgastate.h"
+#include "mgatex.h"
+#include "mgavb.h"
+#include "mgaioctl.h"
+#include "mgatris.h"
+
+#include "vblank.h"
+
+
+static int
+mgaSetFence( mgaContextPtr mmesa, uint32_t * fence )
+{
+ int ret = ENOSYS;
+
+ if ( mmesa->driScreen->drmMinor >= 2 ) {
+ ret = drmCommandWriteRead( mmesa->driScreen->fd, DRM_MGA_SET_FENCE,
+ fence, sizeof( uint32_t ));
+ if (ret) {
+ fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+ exit(1);
+ }
+ }
+
+ return ret;
+}
+
+
+static int
+mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence )
+{
+ int ret = ENOSYS;
+
+ if ( mmesa->driScreen->drmMinor >= 2 ) {
+ uint32_t temp = fence;
+
+ ret = drmCommandWriteRead( mmesa->driScreen->fd,
+ DRM_MGA_WAIT_FENCE,
+ & temp, sizeof( uint32_t ));
+ if (ret) {
+ fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+ exit(1);
+ }
+
+ if ( curr_fence ) {
+ *curr_fence = temp;
+ }
+ }
+
+ return ret;
+}
+
+
+static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
+ unsigned long dest,
+ int length)
+{
+ drmBufPtr buf = mmesa->iload_buffer;
+ drm_mga_iload_t iload;
+ int ret, i;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n",
+ buf->idx, (int) dest, length);
+
+ if ( (length & MGA_ILOAD_MASK) != 0 ) {
+ UNLOCK_HARDWARE( mmesa );
+ fprintf( stderr, "%s: Invalid ILOAD datasize (%d), must be "
+ "multiple of %u.\n", __FUNCTION__, length, MGA_ILOAD_ALIGN );
+ exit( 1 );
+ }
+
+ iload.idx = buf->idx;
+ iload.dstorg = dest;
+ iload.length = length;
+
+ i = 0;
+ do {
+ ret = drmCommandWrite( mmesa->driFd, DRM_MGA_ILOAD,
+ &iload, sizeof(iload) );
+ } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
+
+ if ( ret < 0 ) {
+ printf("send iload retcode = %d\n", ret);
+ exit(1);
+ }
+
+ mmesa->iload_buffer = 0;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "finished iload dma put\n");
+
+}
+
+drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa )
+{
+ int idx = 0;
+ int size = 0;
+ drmDMAReq dma;
+ int retcode;
+ drmBufPtr buf;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "Getting dma buffer\n");
+
+ dma.context = mmesa->hHWContext;
+ dma.send_count = 0;
+ dma.send_list = NULL;
+ dma.send_sizes = NULL;
+ dma.flags = 0;
+ dma.request_count = 1;
+ dma.request_size = MGA_BUFFER_SIZE;
+ dma.request_list = &idx;
+ dma.request_sizes = &size;
+ dma.granted_count = 0;
+
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "drmDMA (get) ctx %d count %d size 0x%x\n",
+ dma.context, dma.request_count,
+ dma.request_size);
+
+ while (1) {
+ retcode = drmDMA(mmesa->driFd, &dma);
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "retcode %d sz %d idx %d count %d\n",
+ retcode,
+ dma.request_sizes[0],
+ dma.request_list[0],
+ dma.granted_count);
+
+ if (retcode == 0 &&
+ dma.request_sizes[0] &&
+ dma.granted_count)
+ break;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "\n\nflush");
+
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
+ }
+
+ buf = &(mmesa->mgaScreen->bufs->list[idx]);
+ buf->used = 0;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr,
+ "drmDMA (get) returns size[0] 0x%x idx[0] %d\n"
+ "dma_buffer now: buf idx: %d size: %d used: %d addr %p\n",
+ dma.request_sizes[0], dma.request_list[0],
+ buf->idx, buf->total,
+ buf->used, buf->address);
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "finished getbuffer\n");
+
+ return buf;
+}
+
+
+
+
+static void
+mgaClear( GLcontext *ctx, GLbitfield mask )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
+ GLuint flags = 0;
+ GLuint clear_color = mmesa->ClearColor;
+ GLuint clear_depth = 0;
+ GLuint color_mask = 0;
+ GLuint depth_mask = 0;
+ int ret;
+ int i;
+ static int nrclears;
+ drm_mga_clear_t clear;
+ GLint cx, cy, cw, ch;
+
+ FLUSH_BATCH( mmesa );
+
+ if ( mask & BUFFER_BIT_FRONT_LEFT ) {
+ flags |= MGA_FRONT;
+ color_mask = mmesa->setup.plnwt;
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
+ }
+
+ if ( mask & BUFFER_BIT_BACK_LEFT ) {
+ flags |= MGA_BACK;
+ color_mask = mmesa->setup.plnwt;
+ mask &= ~BUFFER_BIT_BACK_LEFT;
+ }
+
+ if ( (mask & BUFFER_BIT_DEPTH) && ctx->Depth.Mask ) {
+ flags |= MGA_DEPTH;
+ clear_depth = (mmesa->ClearDepth & mmesa->depth_clear_mask);
+ depth_mask |= mmesa->depth_clear_mask;
+ mask &= ~BUFFER_BIT_DEPTH;
+ }
+
+ if ( (mask & BUFFER_BIT_STENCIL) && mmesa->hw_stencil ) {
+ flags |= MGA_DEPTH;
+ clear_depth |= (ctx->Stencil.Clear & mmesa->stencil_clear_mask);
+ depth_mask |= mmesa->stencil_clear_mask;
+ mask &= ~BUFFER_BIT_STENCIL;
+ }
+
+ if ( flags ) {
+ LOCK_HARDWARE( mmesa );
+
+ /* compute region after locking: */
+ cx = ctx->DrawBuffer->_Xmin;
+ cy = ctx->DrawBuffer->_Ymin;
+ cw = ctx->DrawBuffer->_Xmax - cx;
+ ch = ctx->DrawBuffer->_Ymax - cy;
+
+ if ( mmesa->dirty_cliprects )
+ mgaUpdateRects( mmesa, (MGA_FRONT | MGA_BACK) );
+
+ /* flip top to bottom */
+ cy = dPriv->h-cy-ch;
+ cx += mmesa->drawX;
+ cy += mmesa->drawY;
+
+ if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL )
+ fprintf( stderr, "Clear, bufs %x nbox %d\n",
+ (int)flags, (int)mmesa->numClipRects );
+
+ for (i = 0 ; i < mmesa->numClipRects ; )
+ {
+ int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, mmesa->numClipRects);
+ drm_clip_rect_t *box = mmesa->pClipRects;
+ drm_clip_rect_t *b = mmesa->sarea->boxes;
+ int n = 0;
+
+ if (cw != dPriv->w || ch != dPriv->h) {
+ /* clear subregion */
+ for ( ; i < nr ; i++) {
+ GLint x = box[i].x1;
+ GLint y = box[i].y1;
+ GLint w = box[i].x2 - x;
+ GLint h = box[i].y2 - y;
+
+ if (x < cx) w -= cx - x, x = cx;
+ if (y < cy) h -= cy - y, y = cy;
+ if (x + w > cx + cw) w = cx + cw - x;
+ if (y + h > cy + ch) h = cy + ch - y;
+ if (w <= 0) continue;
+ if (h <= 0) continue;
+
+ b->x1 = x;
+ b->y1 = y;
+ b->x2 = x + w;
+ b->y2 = y + h;
+ b++;
+ n++;
+ }
+ } else {
+ /* clear whole window */
+ for ( ; i < nr ; i++) {
+ *b++ = box[i];
+ n++;
+ }
+ }
+
+
+ if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL )
+ fprintf( stderr,
+ "DRM_IOCTL_MGA_CLEAR flag 0x%x color %x depth %x nbox %d\n",
+ flags, clear_color, clear_depth, mmesa->sarea->nbox );
+
+ mmesa->sarea->nbox = n;
+
+ clear.flags = flags;
+ clear.clear_color = clear_color;
+ clear.clear_depth = clear_depth;
+ clear.color_mask = color_mask;
+ clear.depth_mask = depth_mask;
+ ret = drmCommandWrite( mmesa->driFd, DRM_MGA_CLEAR,
+ &clear, sizeof(clear));
+ if ( ret ) {
+ fprintf( stderr, "send clear retcode = %d\n", ret );
+ exit( 1 );
+ }
+ if ( MGA_DEBUG & DEBUG_VERBOSE_IOCTL )
+ fprintf( stderr, "finished clear %d\n", ++nrclears );
+ }
+
+ UNLOCK_HARDWARE( mmesa );
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS|MGA_UPLOAD_CONTEXT;
+ }
+
+ if (mask)
+ _swrast_Clear( ctx, mask );
+}
+
+
+/**
+ * Wait for the previous frame of rendering has completed.
+ *
+ * \param mmesa Hardware context pointer.
+ *
+ * \bug
+ * The loop in this function should have some sort of a timeout mechanism.
+ *
+ * \warning
+ * This routine used to assume that the hardware lock was held on entry. It
+ * now assumes that the lock is \b not held on entry.
+ */
+
+static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
+{
+ if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) {
+ unsigned wait = 0;
+ GLuint last_frame;
+ GLuint last_wrap;
+
+
+ LOCK_HARDWARE( mmesa );
+ last_frame = mmesa->sarea->last_frame.head;
+ last_wrap = mmesa->sarea->last_frame.wrap;
+
+ /* The DMA routines in the kernel track a couple values in the SAREA
+ * that we use here. The number of times that the primary DMA buffer
+ * has "wrapped" around is tracked in last_wrap. In addition, the
+ * wrap count and the buffer position at the end of the last frame are
+ * stored in last_frame.wrap and last_frame.head.
+ *
+ * By comparing the wrap counts and the current DMA pointer value
+ * (read directly from the hardware) to last_frame.head, we can
+ * determine when the graphics processor has processed all of the
+ * commands for the last frame.
+ *
+ * In this case "last frame" means the frame of the *previous* swap-
+ * buffers call. This is done to prevent queuing a second buffer swap
+ * before the previous swap is executed.
+ */
+ while ( 1 ) {
+ if ( last_wrap < mmesa->sarea->last_wrap ||
+ ( last_wrap == mmesa->sarea->last_wrap &&
+ last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) -
+ mmesa->primary_offset) ) ) {
+ break;
+ }
+ if ( 0 ) {
+ wait++;
+ fprintf( stderr, " last: head=0x%06x wrap=%d\n",
+ last_frame, last_wrap );
+ fprintf( stderr, " head: head=0x%06lx wrap=%d\n",
+ (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset),
+ mmesa->sarea->last_wrap );
+ }
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+
+ UNLOCK_HARDWARE( mmesa );
+ DO_USLEEP( 1 );
+ LOCK_HARDWARE( mmesa );
+ }
+ if ( wait )
+ fprintf( stderr, "\n" );
+
+ UNLOCK_HARDWARE( mmesa );
+ }
+}
+
+
+/*
+ * Copy the back buffer to the front buffer.
+ */
+void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv )
+{
+ mgaContextPtr mmesa;
+ drm_clip_rect_t *pbox;
+ GLint nbox;
+ GLint ret;
+ GLint i;
+ GLboolean missed_target;
+
+
+ assert(dPriv);
+ assert(dPriv->driContextPriv);
+ assert(dPriv->driContextPriv->driverPrivate);
+
+ mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
+
+ FLUSH_BATCH( mmesa );
+
+ mgaWaitForFrameCompletion( mmesa );
+ driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
+ & missed_target );
+ if ( missed_target ) {
+ mmesa->swap_missed_count++;
+ (void) (*dri_interface->getUST)( & mmesa->swap_missed_ust );
+ }
+ LOCK_HARDWARE( mmesa );
+
+ /* Use the frontbuffer cliprects
+ */
+ if (mmesa->dirty_cliprects & MGA_FRONT)
+ mgaUpdateRects( mmesa, MGA_FRONT );
+
+
+ pbox = dPriv->pClipRects;
+ nbox = dPriv->numClipRects;
+
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
+ drm_clip_rect_t *b = mmesa->sarea->boxes;
+
+ mmesa->sarea->nbox = nr - i;
+
+ for ( ; i < nr ; i++)
+ *b++ = pbox[i];
+
+ if (0)
+ fprintf(stderr, "DRM_IOCTL_MGA_SWAP\n");
+
+ ret = drmCommandNone( mmesa->driFd, DRM_MGA_SWAP );
+ if ( ret ) {
+ printf("send swap retcode = %d\n", ret);
+ exit(1);
+ }
+ }
+
+ (void) mgaSetFence( mmesa, & mmesa->last_frame_fence );
+ UNLOCK_HARDWARE( mmesa );
+
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+ mmesa->swap_count++;
+ (void) (*dri_interface->getUST)( & mmesa->swap_ust );
+}
+
+
+/**
+ * Implement the hardware-specific portion of \c glFinish.
+ *
+ * Flushes all pending commands to the hardware and wait for them to finish.
+ *
+ * \param ctx Context where the \c glFinish command was issued.
+ *
+ * \sa glFinish, mgaFlush, mgaFlushDMA
+ */
+static void mgaFinish( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ uint32_t fence;
+
+
+ LOCK_HARDWARE( mmesa );
+ if ( mmesa->vertex_dma_buffer != NULL ) {
+ mgaFlushVerticesLocked( mmesa );
+ }
+
+ if ( mgaSetFence( mmesa, & fence ) == 0 ) {
+ UNLOCK_HARDWARE( mmesa );
+ (void) mgaWaitFence( mmesa, fence, NULL );
+ }
+ else {
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) {
+ fprintf(stderr, "mgaRegetLockQuiescent\n");
+ }
+
+ UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH );
+ UNLOCK_HARDWARE( mmesa );
+ }
+}
+
+
+/**
+ * Flush all commands upto at least a certain point to the hardware.
+ *
+ * \note
+ * The term "wait" in the name of this function is misleading. It doesn't
+ * actually wait for anything. It just makes sure that the commands have
+ * been flushed to the hardware.
+ *
+ * \warning
+ * As the name implies, this function assumes that the hardware lock is
+ * held on entry.
+ */
+void mgaWaitAgeLocked( mgaContextPtr mmesa, int age )
+{
+ if (GET_DISPATCH_AGE(mmesa) < age) {
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+ }
+}
+
+
+static GLboolean intersect_rect( drm_clip_rect_t *out,
+ const drm_clip_rect_t *a,
+ const drm_clip_rect_t *b )
+{
+ *out = *a;
+ if (b->x1 > out->x1) out->x1 = b->x1;
+ if (b->y1 > out->y1) out->y1 = b->y1;
+ if (b->x2 < out->x2) out->x2 = b->x2;
+ if (b->y2 < out->y2) out->y2 = b->y2;
+
+ return ((out->x1 < out->x2) && (out->y1 < out->y2));
+}
+
+
+
+
+static void age_mmesa( mgaContextPtr mmesa, int age )
+{
+ if (mmesa->CurrentTexObj[0]) mmesa->CurrentTexObj[0]->age = age;
+ if (mmesa->CurrentTexObj[1]) mmesa->CurrentTexObj[1]->age = age;
+}
+
+
+void mgaFlushVerticesLocked( mgaContextPtr mmesa )
+{
+ drm_clip_rect_t *pbox = mmesa->pClipRects;
+ int nbox = mmesa->numClipRects;
+ drmBufPtr buffer = mmesa->vertex_dma_buffer;
+ drm_mga_vertex_t vertex;
+ int i;
+
+ mmesa->vertex_dma_buffer = 0;
+
+ if (!buffer)
+ return;
+
+ if (mmesa->dirty_cliprects & mmesa->draw_buffer)
+ mgaUpdateRects( mmesa, mmesa->draw_buffer );
+
+ if (mmesa->dirty & ~MGA_UPLOAD_CLIPRECTS)
+ mgaEmitHwStateLocked( mmesa );
+
+ /* FIXME: Workaround bug in kernel module.
+ */
+ mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
+
+ if (!nbox)
+ buffer->used = 0;
+
+ if (nbox >= MGA_NR_SAREA_CLIPRECTS)
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+
+#if 0
+ if (!buffer->used || !(mmesa->dirty & MGA_UPLOAD_CLIPRECTS))
+ {
+ if (nbox == 1)
+ mmesa->sarea->nbox = 0;
+ else
+ mmesa->sarea->nbox = nbox;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "Firing vertex -- case a nbox %d\n", nbox);
+
+ vertex.idx = buffer->idx;
+ vertex.used = buffer->used;
+ vertex.discard = 1;
+ drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
+ &vertex, sizeof(drmMGAVertex) );
+
+ age_mmesa(mmesa, mmesa->sarea->last_enqueue);
+ }
+ else
+#endif
+ {
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, nbox);
+ drm_clip_rect_t *b = mmesa->sarea->boxes;
+ int discard = 0;
+
+ if (mmesa->scissor) {
+ mmesa->sarea->nbox = 0;
+
+ for ( ; i < nr ; i++) {
+ *b = pbox[i];
+ if (intersect_rect(b, b, &mmesa->scissor_rect)) {
+ mmesa->sarea->nbox++;
+ b++;
+ }
+ }
+
+ /* Culled?
+ */
+ if (!mmesa->sarea->nbox) {
+ if (nr < nbox) continue;
+ buffer->used = 0;
+ }
+ } else {
+ mmesa->sarea->nbox = nr - i;
+ for ( ; i < nr ; i++)
+ *b++ = pbox[i];
+ }
+
+ /* Finished with the buffer?
+ */
+ if (nr == nbox)
+ discard = 1;
+
+ mmesa->sarea->dirty |= MGA_UPLOAD_CLIPRECTS;
+
+ vertex.idx = buffer->idx;
+ vertex.used = buffer->used;
+ vertex.discard = discard;
+ drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
+ &vertex, sizeof(vertex) );
+
+ age_mmesa(mmesa, mmesa->sarea->last_enqueue);
+ }
+ }
+
+ mmesa->dirty &= ~MGA_UPLOAD_CLIPRECTS;
+}
+
+void mgaFlushVertices( mgaContextPtr mmesa )
+{
+ LOCK_HARDWARE( mmesa );
+ mgaFlushVerticesLocked( mmesa );
+ UNLOCK_HARDWARE( mmesa );
+}
+
+
+void mgaFireILoadLocked( mgaContextPtr mmesa,
+ GLuint offset, GLuint length )
+{
+ if (!mmesa->iload_buffer) {
+ fprintf(stderr, "mgaFireILoad: no buffer\n");
+ return;
+ }
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "mgaFireILoad idx %d ofs 0x%x length %d\n",
+ mmesa->iload_buffer->idx, (int)offset, (int)length );
+
+ mga_iload_dma_ioctl( mmesa, offset, length );
+}
+
+void mgaGetILoadBufferLocked( mgaContextPtr mmesa )
+{
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL)
+ fprintf(stderr, "mgaGetIloadBuffer (buffer now %p)\n",
+ (void *) mmesa->iload_buffer);
+
+ mmesa->iload_buffer = mga_get_buffer_ioctl( mmesa );
+}
+
+
+/**
+ * Implement the hardware-specific portion of \c glFlush.
+ *
+ * \param ctx Context to be flushed.
+ *
+ * \sa glFlush, mgaFinish, mgaFlushDMA
+ */
+static void mgaFlush( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+
+ LOCK_HARDWARE( mmesa );
+ if ( mmesa->vertex_dma_buffer != NULL ) {
+ mgaFlushVerticesLocked( mmesa );
+ }
+
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+ UNLOCK_HARDWARE( mmesa );
+}
+
+
+int mgaFlushDMA( int fd, drmLockFlags flags )
+{
+ drm_lock_t lock;
+ int ret, i = 0;
+
+ memset( &lock, 0, sizeof(lock) );
+
+ lock.flags = flags & (DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH
+ | DRM_LOCK_FLUSH_ALL);
+
+ do {
+ ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) );
+ } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY );
+
+ if ( ret == 0 )
+ return 0;
+ if ( errno != EBUSY )
+ return -errno;
+
+ if ( lock.flags & DRM_LOCK_QUIESCENT ) {
+ /* Only keep trying if we need quiescence.
+ */
+ lock.flags &= ~(DRM_LOCK_FLUSH | DRM_LOCK_FLUSH_ALL);
+
+ do {
+ ret = drmCommandWrite( fd, DRM_MGA_FLUSH, &lock, sizeof(lock) );
+ } while ( ret && errno == EBUSY && i++ < DRM_MGA_IDLE_RETRY );
+ }
+
+ if ( ret == 0 ) {
+ return 0;
+ } else {
+ return -errno;
+ }
+}
+
+void mgaInitIoctlFuncs( struct dd_function_table *functions )
+{
+ functions->Clear = mgaClear;
+ functions->Flush = mgaFlush;
+ functions->Finish = mgaFinish;
+}
diff --git a/src/mgaioctl.h b/src/mgaioctl.h
new file mode 100644
index 0000000..f3ae749
--- /dev/null
+++ b/src/mgaioctl.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.h,v 1.11 2002/10/30 12:51:36 alanh Exp $ */
+
+#ifndef MGA_IOCTL_H
+#define MGA_IOCTL_H
+
+#include "mgacontext.h"
+#include "mga_xmesa.h"
+
+void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv );
+void mgaWaitForVBlank( mgaContextPtr mmesa );
+
+void mgaGetILoadBufferLocked( mgaContextPtr mmesa );
+void mgaFireILoadLocked( mgaContextPtr mmesa,
+ GLuint offset, GLuint length );
+
+void mgaWaitAgeLocked( mgaContextPtr mmesa, int age );
+
+void mgaFlushVertices( mgaContextPtr mmesa );
+void mgaFlushVerticesLocked( mgaContextPtr mmesa );
+int mgaFlushDMA( int fd, drmLockFlags flags );
+
+void mgaInitIoctlFuncs( struct dd_function_table *functions );
+
+#define FLUSH_BATCH(mmesa) do { \
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) \
+ fprintf(stderr, "FLUSH_BATCH in %s\n", __FUNCTION__); \
+ if (mmesa->vertex_dma_buffer) mgaFlushVertices(mmesa); \
+} while (0)
+
+#define MGA_STATECHANGE(mmesa, flag) do { \
+ FLUSH_BATCH(mmesa); \
+ mmesa->dirty |= flag; \
+} while (0)
+
+
+extern drmBufPtr mga_get_buffer_ioctl( mgaContextPtr mmesa );
+
+static __inline
+GLuint *mgaAllocDmaLow( mgaContextPtr mmesa, int bytes )
+{
+ GLuint *head;
+
+ /* If there is no DMA buffer currently allocated or the currently
+ * allocated DMA buffer doesn't have enough room left for this request,
+ * a new buffer will need to be allocated.
+ */
+ if ( (mmesa->vertex_dma_buffer == NULL)
+ || ((mmesa->vertex_dma_buffer->used + bytes)
+ > mmesa->vertex_dma_buffer->total) ) {
+ LOCK_HARDWARE( mmesa );
+
+ /* In the case where the existing buffer does not have enough room,
+ * we need to flush it out to the hardware.
+ */
+ if ( mmesa->vertex_dma_buffer != NULL ) {
+ mgaFlushVerticesLocked( mmesa );
+ }
+
+ mmesa->vertex_dma_buffer = mga_get_buffer_ioctl( mmesa );
+ UNLOCK_HARDWARE( mmesa );
+ }
+
+ head = (GLuint *)((char *)mmesa->vertex_dma_buffer->address +
+ mmesa->vertex_dma_buffer->used);
+
+ mmesa->vertex_dma_buffer->used += bytes;
+ return head;
+}
+
+
+#define UPDATE_LOCK( mmesa, flags ) \
+do { \
+ GLint ret = mgaFlushDMA( mmesa->driFd, flags ); \
+ if ( ret < 0 ) { \
+ drmCommandNone( mmesa->driFd, DRM_MGA_RESET ); \
+ UNLOCK_HARDWARE( mmesa ); \
+ fprintf( stderr, "%s: flush return = %s (%d), flags = 0x%08x\n", \
+ __FUNCTION__, strerror( -ret ), -ret, \
+ (unsigned)(flags) ); \
+ exit( 1 ); \
+ } \
+} while (0)
+
+#endif
diff --git a/src/mgapixel.c b/src/mgapixel.c
new file mode 100644
index 0000000..2b9da8c
--- /dev/null
+++ b/src/mgapixel.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright 2000 Compaq Computer Inc. and VA Linux Systems, 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
+ * 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 SYSTEMS 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.
+ */
+
+/**
+ * \file mgapixel.c
+ * Implement framebuffer pixel operations for MGA.
+ *
+ * \todo
+ * Someday the accelerated \c glReadPixels and \c glDrawPixels paths need to
+ * be resurrected. They are currently ifdef'ed out because they don't seem
+ * to work and they only get activated some very rare circumstances.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgapixel.c,v 1.9 2002/11/05 17:46:08 tsi Exp $ */
+
+#include "mtypes.h"
+#include "macros.h"
+#include "mgadd.h"
+#include "mgacontext.h"
+#include "mgaioctl.h"
+#include "mgapixel.h"
+#include "mgastate.h"
+
+#include "swrast/swrast.h"
+#include "imports.h"
+
+#if 0
+#define IS_AGP_MEM( mmesa, p ) \
+ ((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \
+ (unsigned long)mmesa->mgaScreen->buffers.map + \
+ (unsigned long)mmesa->mgaScreen->buffers.size > ((unsigned long)p))
+#define AGP_OFFSET( mmesa, p ) \
+ (((unsigned long)p) - (unsigned long)mmesa->mgaScreen->buffers.map)
+
+
+#if defined(MESA_packed_depth_stencil)
+static GLboolean
+check_depth_stencil_24_8( const GLcontext *ctx, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ const void *pixels, GLint sz,
+ GLint pitch )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ return ( type == GL_UNSIGNED_INT_24_8_MESA &&
+ ctx->Visual->DepthBits == 24 &&
+ ctx->Visual->StencilBits == 8 &&
+ mmesa->mgaScreen->cpp == 4 &&
+ mmesa->hw_stencil &&
+ !ctx->Pixel.IndexShift &&
+ !ctx->Pixel.IndexOffset &&
+ !ctx->Pixel.MapStencilFlag &&
+ ctx->Pixel.DepthBias == 0.0 &&
+ ctx->Pixel.DepthScale == 1.0 &&
+ !packing->SwapBytes &&
+ pitch % 32 == 0 &&
+ pitch < 4096 );
+}
+#endif
+
+
+static GLboolean
+check_depth( const GLcontext *ctx, GLenum type,
+ const struct gl_pixelstore_attrib *packing,
+ const void *pixels, GLint sz, GLint pitch )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if ( IS_AGP_MEM( mmesa, pixels ) &&
+ !( ( type == GL_UNSIGNED_INT && mmesa->mgaScreen->cpp == 4 ) ||
+ ( type == GL_UNSIGNED_SHORT && mmesa->mgaScreen->cpp == 2 ) ) )
+ return GL_FALSE;
+
+ return ( ctx->Pixel.DepthBias == 0.0 &&
+ ctx->Pixel.DepthScale == 1.0 &&
+ !packing->SwapBytes &&
+ pitch % 32 == 0 &&
+ pitch < 4096 );
+}
+
+
+static GLboolean
+check_color( const GLcontext *ctx, GLenum type, GLenum format,
+ const struct gl_pixelstore_attrib *packing,
+ const void *pixels, GLint sz, GLint pitch )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint cpp = mmesa->mgaScreen->cpp;
+
+ /* Can't do conversions on agp reads/draws.
+ */
+ if ( IS_AGP_MEM( mmesa, pixels ) &&
+ !( pitch % 32 == 0 && pitch < 4096 &&
+ ( ( type == GL_UNSIGNED_BYTE &&
+ cpp == 4 && format == GL_BGRA ) ||
+ ( type == GL_UNSIGNED_INT_8_8_8_8 &&
+ cpp == 4 && format == GL_BGRA ) ||
+ ( type == GL_UNSIGNED_SHORT_5_6_5_REV &&
+ cpp == 2 && format == GL_RGB ) ) ) )
+ return GL_FALSE;
+
+ return (!ctx->_ImageTransferState &&
+ !packing->SwapBytes &&
+ !packing->LsbFirst);
+}
+
+static GLboolean
+check_color_per_fragment_ops( const GLcontext *ctx )
+{
+ return (!( ctx->Color.AlphaEnabled ||
+ ctx->Depth.Test ||
+ ctx->Fog.Enabled ||
+ ctx->Scissor.Enabled ||
+ ctx->Stencil.Enabled ||
+ !ctx->Color.ColorMask[0] ||
+ !ctx->Color.ColorMask[1] ||
+ !ctx->Color.ColorMask[2] ||
+ !ctx->Color.ColorMask[3] ||
+ ctx->Color.ColorLogicOpEnabled ||
+ ctx->Texture._EnabledUnits
+ ) &&
+ ctx->Current.RasterPosValid &&
+ ctx->Pixel.ZoomX == 1.0F &&
+ (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F));
+}
+
+static GLboolean
+check_depth_per_fragment_ops( const GLcontext *ctx )
+{
+ return ( ctx->Current.RasterPosValid &&
+ ctx->Color.ColorMask[RCOMP] == 0 &&
+ ctx->Color.ColorMask[BCOMP] == 0 &&
+ ctx->Color.ColorMask[GCOMP] == 0 &&
+ ctx->Color.ColorMask[ACOMP] == 0 &&
+ ctx->Pixel.ZoomX == 1.0F &&
+ ( ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F ) );
+}
+
+/* In addition to the requirements for depth:
+ */
+#if defined(MESA_packed_depth_stencil)
+static GLboolean
+check_stencil_per_fragment_ops( const GLcontext *ctx )
+{
+ return ( !ctx->Pixel.IndexShift &&
+ !ctx->Pixel.IndexOffset );
+}
+#endif
+
+
+static GLboolean
+clip_pixelrect( const GLcontext *ctx,
+ const GLframebuffer *buffer,
+ GLint *x, GLint *y,
+ GLsizei *width, GLsizei *height,
+ GLint *skipPixels, GLint *skipRows,
+ GLint *size )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ *width = MIN2(*width, MAX_WIDTH); /* redundant? */
+
+ /* left clipping */
+ if (*x < buffer->_Xmin) {
+ *skipPixels += (buffer->_Xmin - *x);
+ *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) {
+ *skipRows += (buffer->_Ymin - *y);
+ *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;
+
+ *size = ((*y + *height - 1) * mmesa->mgaScreen->frontPitch +
+ (*x + *width - 1) * mmesa->mgaScreen->cpp);
+
+ return GL_TRUE;
+}
+
+static GLboolean
+mgaTryReadPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *pixels )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLint size, skipPixels, skipRows;
+ GLint pitch = pack->RowLength ? pack->RowLength : width;
+ GLboolean ok;
+
+ GLuint planemask;
+ GLuint source;
+#if 0
+ drmMGABlit blit;
+ GLuint dest;
+ GLint source_pitch, dest_pitch;
+ GLint delta_sx, delta_sy;
+ GLint delta_dx, delta_dy;
+ GLint blit_height, ydir;
+#endif
+
+ if (!clip_pixelrect(ctx, ctx->ReadBuffer,
+ &x, &y, &width, &height,
+ &skipPixels, &skipRows, &size)) {
+ return GL_TRUE;
+ }
+
+ /* Only accelerate reading to agp buffers.
+ */
+ if ( !IS_AGP_MEM(mmesa, (char *)pixels) ||
+ !IS_AGP_MEM(mmesa, (char *)pixels + size) )
+ return GL_FALSE;
+
+ switch (format) {
+#if defined(MESA_packed_depth_stencil)
+ case GL_DEPTH_STENCIL_MESA:
+ ok = check_depth_stencil_24_8(ctx, type, pack, pixels, size, pitch);
+ planemask = ~0;
+ source = mmesa->mgaScreen->depthOffset;
+ break;
+#endif
+
+ case GL_DEPTH_COMPONENT:
+ ok = check_depth(ctx, type, pack, pixels, size, pitch);
+
+ /* Can't accelerate at this depth -- planemask does the wrong
+ * thing; it doesn't clear the low order bits in the
+ * destination, instead it leaves them untouched.
+ *
+ * Could get the acclerator to solid fill the destination with
+ * zeros first... Or get the cpu to do it...
+ */
+ if (ctx->Visual.depthBits == 24)
+ return GL_FALSE;
+
+ planemask = ~0;
+ source = mmesa->mgaScreen->depthOffset;
+ break;
+
+ case GL_RGB:
+ case GL_BGRA:
+ ok = check_color(ctx, type, format, pack, pixels, size, pitch);
+ planemask = ~0;
+ source = (mmesa->draw_buffer == MGA_FRONT ?
+ mmesa->mgaScreen->frontOffset :
+ mmesa->mgaScreen->backOffset);
+ break;
+
+ default:
+ return GL_FALSE;
+ }
+
+ if (!ok) {
+ return GL_FALSE;
+ }
+
+
+ LOCK_HARDWARE( mmesa );
+
+#if 0
+ {
+ __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
+ int nbox, retcode, i;
+
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
+
+ if (mmesa->dirty_cliprects & MGA_FRONT)
+ mgaUpdateRects( mmesa, MGA_FRONT );
+
+ nbox = dPriv->numClipRects;
+
+ y = dPriv->h - y - height;
+ x += mmesa->drawX;
+ y += mmesa->drawY;
+
+ dest = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels)) |
+ DO_dstmap_sys | DO_dstacc_agp);
+ source_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp;
+ dest_pitch = pitch;
+ delta_sx = 0;
+ delta_sy = 0;
+ delta_dx = -x;
+ delta_dy = -y;
+ blit_height = 2*y + height;
+ ydir = -1;
+
+ if (0) fprintf(stderr, "XX doing readpixel blit src_pitch %d dst_pitch %d\n",
+ source_pitch, dest_pitch);
+
+
+
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
+ drm_clip_rect_t *box = dPriv->pClipRects;
+ drm_clip_rect_t *b = mmesa->sarea->boxes;
+ int n = 0;
+
+ for ( ; i < nr ; i++) {
+ GLint bx = box[i].x1;
+ GLint by = box[i].y1;
+ GLint bw = box[i].x2 - bx;
+ GLint bh = box[i].y2 - by;
+
+ if (bx < x) bw -= x - bx, bx = x;
+ if (by < y) bh -= y - by, by = y;
+ if (bx + bw > x + width) bw = x + width - bx;
+ if (by + bh > y + height) bh = y + height - by;
+ if (bw <= 0) continue;
+ if (bh <= 0) continue;
+
+ b->x1 = bx;
+ b->y1 = by;
+ b->x2 = bx + bw;
+ b->y2 = by + bh;
+ b++;
+ n++;
+ }
+
+ mmesa->sarea->nbox = n;
+
+ if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT,
+ &blit, sizeof(drmMGABlit)))) {
+ fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode);
+ UNLOCK_HARDWARE( mmesa );
+ exit(1);
+ }
+ }
+
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
+ }
+#endif
+
+ UNLOCK_HARDWARE( mmesa );
+
+ return GL_TRUE;
+}
+
+static void
+mgaDDReadPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *pixels )
+{
+ if (!mgaTryReadPixels( ctx, x, y, width, height, format, type, pack, pixels))
+ _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, pixels);
+}
+
+
+
+
+static void do_draw_pix( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint pitch,
+ const void *pixels,
+ GLuint dest, GLuint planemask)
+{
+#if 0
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ drmMGABlit blit;
+ __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
+ drm_clip_rect_t pbox = dPriv->pClipRects;
+ int nbox = dPriv->numClipRects;
+ int retcode, i;
+
+ y = dPriv->h - y - height;
+ x += mmesa->drawX;
+ y += mmesa->drawY;
+
+ blit.dest = dest;
+ blit.planemask = planemask;
+ blit.source = ((mmesa->mgaScreen->agp.handle + AGP_OFFSET(mmesa, pixels))
+ | SO_srcmap_sys | SO_srcacc_agp);
+ blit.dest_pitch = mmesa->mgaScreen->frontPitch / mmesa->mgaScreen->cpp;
+ blit.source_pitch = pitch;
+ blit.delta_sx = -x;
+ blit.delta_sy = -y;
+ blit.delta_dx = 0;
+ blit.delta_dy = 0;
+ if (ctx->Pixel.ZoomY == -1) {
+ blit.height = height;
+ blit.ydir = 1;
+ } else {
+ blit.height = height;
+ blit.ydir = -1;
+ }
+
+ if (0) fprintf(stderr,
+ "doing drawpixel blit src_pitch %d dst_pitch %d\n",
+ blit.source_pitch, blit.dest_pitch);
+
+ for (i = 0 ; i < nbox ; )
+ {
+ int nr = MIN2(i + MGA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
+ drm_clip_rect_t *box = mmesa->pClipRects;
+ drm_clip_rect_t *b = mmesa->sarea->boxes;
+ int n = 0;
+
+ for ( ; i < nr ; i++) {
+ GLint bx = box[i].x1;
+ GLint by = box[i].y1;
+ GLint bw = box[i].x2 - bx;
+ GLint bh = box[i].y2 - by;
+
+ if (bx < x) bw -= x - bx, bx = x;
+ if (by < y) bh -= y - by, by = y;
+ if (bx + bw > x + width) bw = x + width - bx;
+ if (by + bh > y + height) bh = y + height - by;
+ if (bw <= 0) continue;
+ if (bh <= 0) continue;
+
+ b->x1 = bx;
+ b->y1 = by;
+ b->x2 = bx + bw;
+ b->y2 = by + bh;
+ b++;
+ n++;
+ }
+
+ mmesa->sarea->nbox = n;
+
+ if (n && (retcode = drmCommandWrite( mmesa->driFd, DRM_MGA_BLIT,
+ &blit, sizeof(drmMGABlit)))) {
+ fprintf(stderr, "blit ioctl failed, retcode = %d\n", retcode);
+ UNLOCK_HARDWARE( mmesa );
+ exit(1);
+ }
+ }
+#endif
+}
+
+
+
+
+static GLboolean
+mgaTryDrawPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLint size, skipPixels, skipRows;
+ GLint pitch = unpack->RowLength ? unpack->RowLength : width;
+ GLuint dest, planemask;
+ GLuint cpp = mmesa->mgaScreen->cpp;
+
+ if (!clip_pixelrect(ctx, ctx->DrawBuffer,
+ &x, &y, &width, &height,
+ &skipPixels, &skipRows, &size)) {
+ return GL_TRUE;
+ }
+
+
+ switch (format) {
+#if defined(MESA_packed_depth_stencil)
+ case GL_DEPTH_STENCIL_MESA:
+ dest = mmesa->mgaScreen->depthOffset;
+ planemask = ~0;
+ if (!check_depth_stencil_24_8(ctx, type, unpack, pixels, size, pitch) ||
+ !check_depth_per_fragment_ops(ctx) ||
+ !check_stencil_per_fragment_ops(ctx))
+ return GL_FALSE;
+ break;
+#endif
+
+ case GL_DEPTH_COMPONENT:
+ dest = mmesa->mgaScreen->depthOffset;
+
+ if (ctx->Visual.depthBits == 24)
+ planemask = ~0xff;
+ else
+ planemask = ~0;
+
+ if (!check_depth(ctx, type, unpack, pixels, size, pitch) ||
+ !check_depth_per_fragment_ops(ctx))
+ return GL_FALSE;
+ break;
+
+ case GL_RGB:
+ case GL_BGRA:
+ dest = (mmesa->draw_buffer == MGA_FRONT ?
+ mmesa->mgaScreen->frontOffset :
+ mmesa->mgaScreen->backOffset);
+
+ planemask = mgaPackColor(cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ if (cpp == 2)
+ planemask |= planemask << 16;
+
+ if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) {
+ return GL_FALSE;
+ }
+ if (!check_color_per_fragment_ops(ctx)) {
+ return GL_FALSE;
+ }
+ break;
+
+ default:
+ return GL_FALSE;
+ }
+
+ LOCK_HARDWARE_QUIESCENT( mmesa );
+
+ if (mmesa->dirty_cliprects & MGA_FRONT)
+ mgaUpdateRects( mmesa, MGA_FRONT );
+
+ if ( IS_AGP_MEM(mmesa, (char *)pixels) &&
+ IS_AGP_MEM(mmesa, (char *)pixels + size) )
+ {
+ do_draw_pix( ctx, x, y, width, height, pitch, pixels,
+ dest, planemask );
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
+ }
+ else
+ {
+ /* Pixels is in regular memory -- get dma buffers and perform
+ * upload through them.
+ */
+/* drmBufPtr buf = mgaGetBufferLocked(mmesa); */
+ GLuint bufferpitch = (width*cpp+31)&~31;
+
+ char *address = 0; /* mmesa->mgaScreen->agp.map; */
+
+ do {
+/* GLuint rows = MIN2( height, MGA_DMA_BUF_SZ / bufferpitch ); */
+ GLuint rows = height;
+
+
+ if (0) fprintf(stderr, "trying to upload %d rows (pitch %d)\n",
+ rows, bufferpitch);
+
+ /* The texture conversion code is so slow that there is only
+ * negligble speedup when the buffers/images don't exactly
+ * match:
+ */
+#if 0
+ if (cpp == 2) {
+ if (!_mesa_convert_texsubimage2d( MESA_FORMAT_RGB565,
+ 0, 0, width, rows,
+ bufferpitch, format, type,
+ unpack, pixels, address )) {
+/* mgaReleaseBufLocked( mmesa, buf ); */
+ UNLOCK_HARDWARE(mmesa);
+ return GL_FALSE;
+ }
+ } else {
+ if (!_mesa_convert_texsubimage2d( MESA_FORMAT_ARGB8888,
+ 0, 0, width, rows,
+ bufferpitch, format, type,
+ unpack, pixels, address )) {
+/* mgaReleaseBufLocked( mmesa, buf ); */
+ UNLOCK_HARDWARE(mmesa);
+ return GL_FALSE;
+ }
+ }
+#else
+ MEMCPY( address, pixels, rows*bufferpitch );
+#endif
+
+ do_draw_pix( ctx, x, y, width, rows,
+ bufferpitch/cpp, address, dest, planemask );
+
+ /* Fix me -- use multiple buffers to avoid flush.
+ */
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT );
+
+ pixels = (void *)((char *) pixels + rows * pitch);
+ height -= rows;
+ y += rows;
+ } while (height);
+
+/* mgaReleaseBufLocked( mmesa, buf ); */
+ }
+
+ UNLOCK_HARDWARE( mmesa );
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+
+ return GL_TRUE;
+}
+
+static void
+mgaDDDrawPixels( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ if (!mgaTryDrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels ))
+ _swrast_DrawPixels( ctx, x, y, width, height, format, type,
+ unpack, pixels );
+}
+#endif
+
+
+/* Stub functions - not a real allocator, always returns pointer to
+ * the same block of agp space which isn't used for anything else at
+ * present.
+ */
+void mgaDDInitPixelFuncs( GLcontext *ctx )
+{
+#if 0
+ /* evidently, these functions don't always work */
+ if (getenv("MGA_BLIT_PIXELS")) {
+ ctx->Driver.ReadPixels = mgaDDReadPixels; /* requires agp dest */
+ ctx->Driver.DrawPixels = mgaDDDrawPixels; /* works with agp/normal mem */
+ }
+#endif
+}
diff --git a/src/mgapixel.h b/src/mgapixel.h
new file mode 100644
index 0000000..c44fd76
--- /dev/null
+++ b/src/mgapixel.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2001 Compaq Computer Inc. VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgapixel.h,v 1.5 2002/10/30 12:51:36 alanh Exp $ */
+
+#ifndef MGA_PIXELS_H
+#define MGA_PIXELS_H
+
+#include "mtypes.h"
+
+extern void mgaDDInitPixelFuncs( GLcontext *ctx );
+
+#endif
diff --git a/src/mgaregs.h b/src/mgaregs.h
new file mode 100644
index 0000000..e1291ca
--- /dev/null
+++ b/src/mgaregs.h
@@ -0,0 +1,1395 @@
+/* author: stephen crowley, crow@debian.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
+ * STEPHEN CROWLEY, 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/mga/mgaregs.h,v 1.6 2003/01/12 03:55:46 tsi Exp $ */
+
+#ifndef _MGAREGS_H_
+#define _MGAREGS_H_
+
+/*************** (START) AUTOMATICLY GENERATED REGISTER FILE *****************/
+/*
+ * Generated on Wed Jan 26 13:44:46 MST 2000
+ */
+
+
+
+/*
+ * Power Graphic Mode Memory Space Registers
+ */
+
+#define MGAREG_MGA_EXEC 0x0100
+#define MGAREG_AGP_PLL 0x1e4c
+
+# define AGP_PLL_agp2xpllen_MASK 0xfffffffe /* bit 0 */
+# define AGP_PLL_agp2xpllen_disable 0x0
+# define AGP_PLL_agp2xpllen_enable 0x1
+
+#define MGAREG_CFG_OR 0x1e4c
+
+# define CFG_OR_comp_or_MASK 0xfffffff7 /* bit 3 */
+# define CFG_OR_comp_or_disable 0x0
+# define CFG_OR_comp_or_enable 0x8
+# define CFG_OR_compfreq_MASK 0xffffff0f /* bits 4-7 */
+# define CFG_OR_compfreq_SHIFT 4
+# define CFG_OR_comporup_MASK 0xfffff0ff /* bits 8-11 */
+# define CFG_OR_comporup_SHIFT 8
+# define CFG_OR_compordn_MASK 0xffff0fff /* bits 12-15 */
+# define CFG_OR_compordn_SHIFT 12
+# define CFG_OR_e2pq_MASK 0xfffeffff /* bit 16 */
+# define CFG_OR_e2pq_disable 0x0
+# define CFG_OR_e2pq_enable 0x10000
+# define CFG_OR_e2pqbypcsn_MASK 0xfffdffff /* bit 17 */
+# define CFG_OR_e2pqbypcsn_disable 0x0
+# define CFG_OR_e2pqbypcsn_enable 0x20000
+# define CFG_OR_e2pqbypd_MASK 0xfffbffff /* bit 18 */
+# define CFG_OR_e2pqbypd_disable 0x0
+# define CFG_OR_e2pqbypd_enable 0x40000
+# define CFG_OR_e2pbypclk_MASK 0xfff7ffff /* bit 19 */
+# define CFG_OR_e2pbypclk_disable 0x0
+# define CFG_OR_e2pbypclk_enable 0x80000
+# define CFG_OR_e2pbyp_MASK 0xffefffff /* bit 20 */
+# define CFG_OR_e2pbyp_disable 0x0
+# define CFG_OR_e2pbyp_enable 0x100000
+# define CFG_OR_rate_cap_or_MASK 0xff1fffff /* bits 21-23 */
+# define CFG_OR_rate_cap_or_SHIFT 21
+# define CFG_OR_rq_or_MASK 0xe0ffffff /* bits 24-28 */
+# define CFG_OR_rq_or_SHIFT 24
+
+#define MGAREG_ALPHACTRL 0x2c7c
+
+# define AC_src_MASK 0xfffffff0 /* bits 0-3 */
+# define AC_src_zero 0x0 /* val 0, shift 0 */
+# define AC_src_one 0x1 /* val 1, shift 0 */
+# define AC_src_dst_color 0x2 /* val 2, shift 0 */
+# define AC_src_om_dst_color 0x3 /* val 3, shift 0 */
+# define AC_src_src_alpha 0x4 /* val 4, shift 0 */
+# define AC_src_om_src_alpha 0x5 /* val 5, shift 0 */
+# define AC_src_dst_alpha 0x6 /* val 6, shift 0 */
+# define AC_src_om_dst_alpha 0x7 /* val 7, shift 0 */
+# define AC_src_src_alpha_sat 0x8 /* val 8, shift 0 */
+# define AC_dst_MASK 0xffffff0f /* bits 4-7 */
+# define AC_dst_zero 0x0 /* val 0, shift 4 */
+# define AC_dst_one 0x10 /* val 1, shift 4 */
+# define AC_dst_src_color 0x20 /* val 2, shift 4 */
+# define AC_dst_om_src_color 0x30 /* val 3, shift 4 */
+# define AC_dst_src_alpha 0x40 /* val 4, shift 4 */
+# define AC_dst_om_src_alpha 0x50 /* val 5, shift 4 */
+# define AC_dst_dst_alpha 0x60 /* val 6, shift 4 */
+# define AC_dst_om_dst_alpha 0x70 /* val 7, shift 4 */
+# define AC_amode_MASK 0xfffffcff /* bits 8-9 */
+# define AC_amode_FCOL 0x0 /* val 0, shift 8 */
+# define AC_amode_alpha_channel 0x100 /* val 1, shift 8 */
+# define AC_amode_video_alpha 0x200 /* val 2, shift 8 */
+# define AC_amode_RSVD 0x300 /* val 3, shift 8 */
+# define AC_astipple_MASK 0xfffff7ff /* bit 11 */
+# define AC_astipple_disable 0x0
+# define AC_astipple_enable 0x800
+# define AC_aten_MASK 0xffffefff /* bit 12 */
+# define AC_aten_disable 0x0
+# define AC_aten_enable 0x1000
+# define AC_atmode_MASK 0xffff1fff /* bits 13-15 */
+# define AC_atmode_noacmp 0x0 /* val 0, shift 13 */
+# define AC_atmode_ae 0x4000 /* val 2, shift 13 */
+# define AC_atmode_ane 0x6000 /* val 3, shift 13 */
+# define AC_atmode_alt 0x8000 /* val 4, shift 13 */
+# define AC_atmode_alte 0xa000 /* val 5, shift 13 */
+# define AC_atmode_agt 0xc000 /* val 6, shift 13 */
+# define AC_atmode_agte 0xe000 /* val 7, shift 13 */
+# define AC_atref_MASK 0xff00ffff /* bits 16-23 */
+# define AC_atref_SHIFT 16
+# define AC_alphasel_MASK 0xfcffffff /* bits 24-25 */
+# define AC_alphasel_fromtex 0x0 /* val 0, shift 24 */
+# define AC_alphasel_diffused 0x1000000 /* val 1, shift 24 */
+# define AC_alphasel_modulated 0x2000000 /* val 2, shift 24 */
+# define AC_alphasel_trans 0x3000000 /* val 3, shift 24 */
+
+#define MGAREG_ALPHASTART 0x2c70
+#define MGAREG_ALPHAXINC 0x2c74
+#define MGAREG_ALPHAYINC 0x2c78
+#define MGAREG_AR0 0x1c60
+
+# define AR0_ar0_MASK 0xfffc0000 /* bits 0-17 */
+# define AR0_ar0_SHIFT 0
+
+#define MGAREG_AR1 0x1c64
+
+# define AR1_ar1_MASK 0xff000000 /* bits 0-23 */
+# define AR1_ar1_SHIFT 0
+
+#define MGAREG_AR2 0x1c68
+
+# define AR2_ar2_MASK 0xfffc0000 /* bits 0-17 */
+# define AR2_ar2_SHIFT 0
+
+#define MGAREG_AR3 0x1c6c
+
+# define AR3_ar3_MASK 0xff000000 /* bits 0-23 */
+# define AR3_ar3_SHIFT 0
+# define AR3_spage_MASK 0xf8ffffff /* bits 24-26 */
+# define AR3_spage_SHIFT 24
+
+#define MGAREG_AR4 0x1c70
+
+# define AR4_ar4_MASK 0xfffc0000 /* bits 0-17 */
+# define AR4_ar4_SHIFT 0
+
+#define MGAREG_AR5 0x1c74
+
+# define AR5_ar5_MASK 0xfffc0000 /* bits 0-17 */
+# define AR5_ar5_SHIFT 0
+
+#define MGAREG_AR6 0x1c78
+
+# define AR6_ar6_MASK 0xfffc0000 /* bits 0-17 */
+# define AR6_ar6_SHIFT 0
+
+#define MGAREG_BCOL 0x1c20
+#define MGAREG_BESA1CORG 0x3d10
+#define MGAREG_BESA1ORG 0x3d00
+#define MGAREG_BESA2CORG 0x3d14
+#define MGAREG_BESA2ORG 0x3d04
+#define MGAREG_BESB1CORG 0x3d18
+#define MGAREG_BESB1ORG 0x3d08
+#define MGAREG_BESB2CORG 0x3d1c
+#define MGAREG_BESB2ORG 0x3d0c
+#define MGAREG_BESCTL 0x3d20
+
+# define BC_besen_MASK 0xfffffffe /* bit 0 */
+# define BC_besen_disable 0x0
+# define BC_besen_enable 0x1
+# define BC_besv1srcstp_MASK 0xffffffbf /* bit 6 */
+# define BC_besv1srcstp_even 0x0
+# define BC_besv1srcstp_odd 0x40
+# define BC_besv2srcstp_MASK 0xfffffeff /* bit 8 */
+# define BC_besv2srcstp_disable 0x0
+# define BC_besv2srcstp_enable 0x100
+# define BC_beshfen_MASK 0xfffffbff /* bit 10 */
+# define BC_beshfen_disable 0x0
+# define BC_beshfen_enable 0x400
+# define BC_besvfen_MASK 0xfffff7ff /* bit 11 */
+# define BC_besvfen_disable 0x0
+# define BC_besvfen_enable 0x800
+# define BC_beshfixc_MASK 0xffffefff /* bit 12 */
+# define BC_beshfixc_weight 0x0
+# define BC_beshfixc_coeff 0x1000
+# define BC_bescups_MASK 0xfffeffff /* bit 16 */
+# define BC_bescups_disable 0x0
+# define BC_bescups_enable 0x10000
+# define BC_bes420pl_MASK 0xfffdffff /* bit 17 */
+# define BC_bes420pl_422 0x0
+# define BC_bes420pl_420 0x20000
+# define BC_besdith_MASK 0xfffbffff /* bit 18 */
+# define BC_besdith_disable 0x0
+# define BC_besdith_enable 0x40000
+# define BC_beshmir_MASK 0xfff7ffff /* bit 19 */
+# define BC_beshmir_disable 0x0
+# define BC_beshmir_enable 0x80000
+# define BC_besbwen_MASK 0xffefffff /* bit 20 */
+# define BC_besbwen_color 0x0
+# define BC_besbwen_bw 0x100000
+# define BC_besblank_MASK 0xffdfffff /* bit 21 */
+# define BC_besblank_disable 0x0
+# define BC_besblank_enable 0x200000
+# define BC_besfselm_MASK 0xfeffffff /* bit 24 */
+# define BC_besfselm_soft 0x0
+# define BC_besfselm_hard 0x1000000
+# define BC_besfsel_MASK 0xf9ffffff /* bits 25-26 */
+# define BC_besfsel_a1 0x0 /* val 0, shift 25 */
+# define BC_besfsel_a2 0x2000000 /* val 1, shift 25 */
+# define BC_besfsel_b1 0x4000000 /* val 2, shift 25 */
+# define BC_besfsel_b2 0x6000000 /* val 3, shift 25 */
+
+#define MGAREG_BESGLOBCTL 0x3dc0
+
+# define BGC_beshzoom_MASK 0xfffffffe /* bit 0 */
+# define BGC_beshzoom_disable 0x0
+# define BGC_beshzoom_enable 0x1
+# define BGC_beshzoomf_MASK 0xfffffffd /* bit 1 */
+# define BGC_beshzoomf_disable 0x0
+# define BGC_beshzoomf_enable 0x2
+# define BGC_bescorder_MASK 0xfffffff7 /* bit 3 */
+# define BGC_bescorder_even 0x0
+# define BGC_bescorder_odd 0x8
+# define BGC_besreghup_MASK 0xffffffef /* bit 4 */
+# define BGC_besreghup_disable 0x0
+# define BGC_besreghup_enable 0x10
+# define BGC_besvcnt_MASK 0xf000ffff /* bits 16-27 */
+# define BGC_besvcnt_SHIFT 16
+
+#define MGAREG_BESHCOORD 0x3d28
+
+# define BHC_besright_MASK 0xfffff800 /* bits 0-10 */
+# define BHC_besright_SHIFT 0
+# define BHC_besleft_MASK 0xf800ffff /* bits 16-26 */
+# define BHC_besleft_SHIFT 16
+
+#define MGAREG_BESHISCAL 0x3d30
+
+# define BHISF_beshiscal_MASK 0xffe00003 /* bits 2-20 */
+# define BHISF_beshiscal_SHIFT 2
+
+#define MGAREG_BESHSRCEND 0x3d3c
+
+# define BHSE_beshsrcend_MASK 0xfc000003 /* bits 2-25 */
+# define BHSE_beshsrcend_SHIFT 2
+
+#define MGAREG_BESHSRCLST 0x3d50
+
+# define BHSL_beshsrclst_MASK 0xfc00ffff /* bits 16-25 */
+# define BHSL_beshsrclst_SHIFT 16
+
+#define MGAREG_BESHSRCST 0x3d38
+
+# define BHSS_beshsrcst_MASK 0xfc000003 /* bits 2-25 */
+# define BHSS_beshsrcst_SHIFT 2
+
+#define MGAREG_BESPITCH 0x3d24
+
+# define BP_bespitch_MASK 0xfffff000 /* bits 0-11 */
+# define BP_bespitch_SHIFT 0
+
+#define MGAREG_BESSTATUS 0x3dc4
+
+# define BS_besstat_MASK 0xfffffffc /* bits 0-1 */
+# define BS_besstat_a1 0x0 /* val 0, shift 0 */
+# define BS_besstat_a2 0x1 /* val 1, shift 0 */
+# define BS_besstat_b1 0x2 /* val 2, shift 0 */
+# define BS_besstat_b2 0x3 /* val 3, shift 0 */
+
+#define MGAREG_BESV1SRCLST 0x3d54
+
+# define BSF_besv1srclast_MASK 0xfffffc00 /* bits 0-9 */
+# define BSF_besv1srclast_SHIFT 0
+
+#define MGAREG_BESV2SRCLST 0x3d58
+
+# define BSF_besv2srclst_MASK 0xfffffc00 /* bits 0-9 */
+# define BSF_besv2srclst_SHIFT 0
+
+#define MGAREG_BESV1WGHT 0x3d48
+
+# define BSF_besv1wght_MASK 0xffff0003 /* bits 2-15 */
+# define BSF_besv1wght_SHIFT 2
+# define BSF_besv1wghts_MASK 0xfffeffff /* bit 16 */
+# define BSF_besv1wghts_disable 0x0
+# define BSF_besv1wghts_enable 0x10000
+
+#define MGAREG_BESV2WGHT 0x3d4c
+
+# define BSF_besv2wght_MASK 0xffff0003 /* bits 2-15 */
+# define BSF_besv2wght_SHIFT 2
+# define BSF_besv2wghts_MASK 0xfffeffff /* bit 16 */
+# define BSF_besv2wghts_disable 0x0
+# define BSF_besv2wghts_enable 0x10000
+
+#define MGAREG_BESVCOORD 0x3d2c
+
+# define BVC_besbot_MASK 0xfffff800 /* bits 0-10 */
+# define BVC_besbot_SHIFT 0
+# define BVC_bestop_MASK 0xf800ffff /* bits 16-26 */
+# define BVC_bestop_SHIFT 16
+
+#define MGAREG_BESVISCAL 0x3d34
+
+# define BVISF_besviscal_MASK 0xffe00003 /* bits 2-20 */
+# define BVISF_besviscal_SHIFT 2
+
+#define MGAREG_CODECADDR 0x3e44
+#define MGAREG_CODECCTL 0x3e40
+#define MGAREG_CODECHARDPTR 0x3e4c
+#define MGAREG_CODECHOSTPTR 0x3e48
+#define MGAREG_CODECLCODE 0x3e50
+#define MGAREG_CXBNDRY 0x1c80
+
+# define CXB_cxleft_MASK 0xfffff000 /* bits 0-11 */
+# define CXB_cxleft_SHIFT 0
+# define CXB_cxright_MASK 0xf000ffff /* bits 16-27 */
+# define CXB_cxright_SHIFT 16
+
+#define MGAREG_CXLEFT 0x1ca0
+#define MGAREG_CXRIGHT 0x1ca4
+#define MGAREG_DMAMAP30 0x1e30
+#define MGAREG_DMAMAP74 0x1e34
+#define MGAREG_DMAMAPB8 0x1e38
+#define MGAREG_DMAMAPFC 0x1e3c
+#define MGAREG_DMAPAD 0x1c54
+#define MGAREG_DR0_Z32LSB 0x2c50
+#define MGAREG_DR0_Z32MSB 0x2c54
+#define MGAREG_DR2_Z32LSB 0x2c60
+#define MGAREG_DR2_Z32MSB 0x2c64
+#define MGAREG_DR3_Z32LSB 0x2c68
+#define MGAREG_DR3_Z32MSB 0x2c6c
+#define MGAREG_DR0 0x1cc0
+#define MGAREG_DR2 0x1cc8
+#define MGAREG_DR3 0x1ccc
+#define MGAREG_DR4 0x1cd0
+#define MGAREG_DR6 0x1cd8
+#define MGAREG_DR7 0x1cdc
+#define MGAREG_DR8 0x1ce0
+#define MGAREG_DR10 0x1ce8
+#define MGAREG_DR11 0x1cec
+#define MGAREG_DR12 0x1cf0
+#define MGAREG_DR14 0x1cf8
+#define MGAREG_DR15 0x1cfc
+#define MGAREG_DSTORG 0x2cb8
+
+# define DO_dstmap_MASK 0xfffffffe /* bit 0 */
+# define DO_dstmap_fb 0x0
+# define DO_dstmap_sys 0x1
+# define DO_dstacc_MASK 0xfffffffd /* bit 1 */
+# define DO_dstacc_pci 0x0
+# define DO_dstacc_agp 0x2
+# define DO_dstorg_MASK 0x7 /* bits 3-31 */
+# define DO_dstorg_SHIFT 3
+
+#define MGAREG_DWG_INDIR_WT 0x1e80
+#define MGAREG_DWGCTL 0x1c00
+
+# define DC_opcod_MASK 0xfffffff0 /* bits 0-3 */
+# define DC_opcod_line_open 0x0 /* val 0, shift 0 */
+# define DC_opcod_autoline_open 0x1 /* val 1, shift 0 */
+# define DC_opcod_line_close 0x2 /* val 2, shift 0 */
+# define DC_opcod_autoline_close 0x3 /* val 3, shift 0 */
+# define DC_opcod_trap 0x4 /* val 4, shift 0 */
+# define DC_opcod_texture_trap 0x6 /* val 6, shift 0 */
+# define DC_opcod_bitblt 0x8 /* val 8, shift 0 */
+# define DC_opcod_iload 0x9 /* val 9, shift 0 */
+# define DC_atype_MASK 0xffffff8f /* bits 4-6 */
+# define DC_atype_rpl 0x0 /* val 0, shift 4 */
+# define DC_atype_rstr 0x10 /* val 1, shift 4 */
+# define DC_atype_zi 0x30 /* val 3, shift 4 */
+# define DC_atype_blk 0x40 /* val 4, shift 4 */
+# define DC_atype_i 0x70 /* val 7, shift 4 */
+# define DC_linear_MASK 0xffffff7f /* bit 7 */
+# define DC_linear_xy 0x0
+# define DC_linear_linear 0x80
+# define DC_zmode_MASK 0xfffff8ff /* bits 8-10 */
+# define DC_zmode_nozcmp 0x0 /* val 0, shift 8 */
+# define DC_zmode_ze 0x200 /* val 2, shift 8 */
+# define DC_zmode_zne 0x300 /* val 3, shift 8 */
+# define DC_zmode_zlt 0x400 /* val 4, shift 8 */
+# define DC_zmode_zlte 0x500 /* val 5, shift 8 */
+# define DC_zmode_zgt 0x600 /* val 6, shift 8 */
+# define DC_zmode_zgte 0x700 /* val 7, shift 8 */
+# define DC_solid_MASK 0xfffff7ff /* bit 11 */
+# define DC_solid_disable 0x0
+# define DC_solid_enable 0x800
+# define DC_arzero_MASK 0xffffefff /* bit 12 */
+# define DC_arzero_disable 0x0
+# define DC_arzero_enable 0x1000
+# define DC_sgnzero_MASK 0xffffdfff /* bit 13 */
+# define DC_sgnzero_disable 0x0
+# define DC_sgnzero_enable 0x2000
+# define DC_shftzero_MASK 0xffffbfff /* bit 14 */
+# define DC_shftzero_disable 0x0
+# define DC_shftzero_enable 0x4000
+# define DC_bop_MASK 0xfff0ffff /* bits 16-19 */
+# define DC_bop_SHIFT 16
+# define DC_trans_MASK 0xff0fffff /* bits 20-23 */
+# define DC_trans_SHIFT 20
+# define DC_bltmod_MASK 0xe1ffffff /* bits 25-28 */
+# define DC_bltmod_bmonolef 0x0 /* val 0, shift 25 */
+# define DC_bltmod_bmonowf 0x8000000 /* val 4, shift 25 */
+# define DC_bltmod_bplan 0x2000000 /* val 1, shift 25 */
+# define DC_bltmod_bfcol 0x4000000 /* val 2, shift 25 */
+# define DC_bltmod_bu32bgr 0x6000000 /* val 3, shift 25 */
+# define DC_bltmod_bu32rgb 0xe000000 /* val 7, shift 25 */
+# define DC_bltmod_bu24bgr 0x16000000 /* val 11, shift 25 */
+# define DC_bltmod_bu24rgb 0x1e000000 /* val 15, shift 25 */
+# define DC_pattern_MASK 0xdfffffff /* bit 29 */
+# define DC_pattern_disable 0x0
+# define DC_pattern_enable 0x20000000
+# define DC_transc_MASK 0xbfffffff /* bit 30 */
+# define DC_transc_disable 0x0
+# define DC_transc_enable 0x40000000
+# define DC_clipdis_MASK 0x7fffffff /* bit 31 */
+# define DC_clipdis_disable 0x0
+# define DC_clipdis_enable 0x80000000
+
+#define MGAREG_DWGSYNC 0x2c4c
+
+# define DS_dwgsyncaddr_MASK 0x3 /* bits 2-31 */
+# define DS_dwgsyncaddr_SHIFT 2
+
+#define MGAREG_FCOL 0x1c24
+#define MGAREG_FIFOSTATUS 0x1e10
+
+# define FS_fifocount_MASK 0xffffff80 /* bits 0-6 */
+# define FS_fifocount_SHIFT 0
+# define FS_bfull_MASK 0xfffffeff /* bit 8 */
+# define FS_bfull_disable 0x0
+# define FS_bfull_enable 0x100
+# define FS_bempty_MASK 0xfffffdff /* bit 9 */
+# define FS_bempty_disable 0x0
+# define FS_bempty_enable 0x200
+
+#define MGAREG_FOGCOL 0x1cf4
+#define MGAREG_FOGSTART 0x1cc4
+#define MGAREG_FOGXINC 0x1cd4
+#define MGAREG_FOGYINC 0x1ce4
+#define MGAREG_FXBNDRY 0x1c84
+
+# define XA_fxleft_MASK 0xffff0000 /* bits 0-15 */
+# define XA_fxleft_SHIFT 0
+# define XA_fxright_MASK 0xffff /* bits 16-31 */
+# define XA_fxright_SHIFT 16
+
+#define MGAREG_FXLEFT 0x1ca8
+#define MGAREG_FXRIGHT 0x1cac
+#define MGAREG_ICLEAR 0x1e18
+
+# define IC_softrapiclr_MASK 0xfffffffe /* bit 0 */
+# define IC_softrapiclr_disable 0x0
+# define IC_softrapiclr_enable 0x1
+# define IC_pickiclr_MASK 0xfffffffb /* bit 2 */
+# define IC_pickiclr_disable 0x0
+# define IC_pickiclr_enable 0x4
+# define IC_vlineiclr_MASK 0xffffffdf /* bit 5 */
+# define IC_vlineiclr_disable 0x0
+# define IC_vlineiclr_enable 0x20
+# define IC_wiclr_MASK 0xffffff7f /* bit 7 */
+# define IC_wiclr_disable 0x0
+# define IC_wiclr_enable 0x80
+# define IC_wciclr_MASK 0xfffffeff /* bit 8 */
+# define IC_wciclr_disable 0x0
+# define IC_wciclr_enable 0x100
+
+#define MGAREG_IEN 0x1e1c
+
+# define IE_softrapien_MASK 0xfffffffe /* bit 0 */
+# define IE_softrapien_disable 0x0
+# define IE_softrapien_enable 0x1
+# define IE_pickien_MASK 0xfffffffb /* bit 2 */
+# define IE_pickien_disable 0x0
+# define IE_pickien_enable 0x4
+# define IE_vlineien_MASK 0xffffffdf /* bit 5 */
+# define IE_vlineien_disable 0x0
+# define IE_vlineien_enable 0x20
+# define IE_extien_MASK 0xffffffbf /* bit 6 */
+# define IE_extien_disable 0x0
+# define IE_extien_enable 0x40
+# define IE_wien_MASK 0xffffff7f /* bit 7 */
+# define IE_wien_disable 0x0
+# define IE_wien_enable 0x80
+# define IE_wcien_MASK 0xfffffeff /* bit 8 */
+# define IE_wcien_disable 0x0
+# define IE_wcien_enable 0x100
+
+#define MGAREG_LEN 0x1c5c
+#define MGAREG_MACCESS 0x1c04
+
+# define MA_pwidth_MASK 0xfffffffc /* bits 0-1 */
+# define MA_pwidth_8 0x0 /* val 0, shift 0 */
+# define MA_pwidth_16 0x1 /* val 1, shift 0 */
+# define MA_pwidth_32 0x2 /* val 2, shift 0 */
+# define MA_pwidth_24 0x3 /* val 3, shift 0 */
+# define MA_zwidth_MASK 0xffffffe7 /* bits 3-4 */
+# define MA_zwidth_16 0x0 /* val 0, shift 3 */
+# define MA_zwidth_32 0x8 /* val 1, shift 3 */
+# define MA_zwidth_15 0x10 /* val 2, shift 3 */
+# define MA_zwidth_24 0x18 /* val 3, shift 3 */
+# define MA_memreset_MASK 0xffff7fff /* bit 15 */
+# define MA_memreset_disable 0x0
+# define MA_memreset_enable 0x8000
+# define MA_fogen_MASK 0xfbffffff /* bit 26 */
+# define MA_fogen_disable 0x0
+# define MA_fogen_enable 0x4000000
+# define MA_tlutload_MASK 0xdfffffff /* bit 29 */
+# define MA_tlutload_disable 0x0
+# define MA_tlutload_enable 0x20000000
+# define MA_nodither_MASK 0xbfffffff /* bit 30 */
+# define MA_nodither_disable 0x0
+# define MA_nodither_enable 0x40000000
+# define MA_dit555_MASK 0x7fffffff /* bit 31 */
+# define MA_dit555_disable 0x0
+# define MA_dit555_enable 0x80000000
+
+#define MGAREG_MCTLWTST 0x1c08
+
+# define MCWS_casltncy_MASK 0xfffffff8 /* bits 0-2 */
+# define MCWS_casltncy_SHIFT 0
+# define MCWS_rrddelay_MASK 0xffffffcf /* bits 4-5 */
+# define MCWS_rcddelay_MASK 0xfffffe7f /* bits 7-8 */
+# define MCWS_rasmin_MASK 0xffffe3ff /* bits 10-12 */
+# define MCWS_rasmin_SHIFT 10
+# define MCWS_rpdelay_MASK 0xffff3fff /* bits 14-15 */
+# define MCWS_wrdelay_MASK 0xfff3ffff /* bits 18-19 */
+# define MCWS_rddelay_MASK 0xffdfffff /* bit 21 */
+# define MCWS_rddelay_disable 0x0
+# define MCWS_rddelay_enable 0x200000
+# define MCWS_smrdelay_MASK 0xfe7fffff /* bits 23-24 */
+# define MCWS_bwcdelay_MASK 0xf3ffffff /* bits 26-27 */
+# define MCWS_bpldelay_MASK 0x1fffffff /* bits 29-31 */
+# define MCWS_bpldelay_SHIFT 29
+
+#define MGAREG_MEMRDBK 0x1e44
+
+# define MRB_mclkbrd0_MASK 0xfffffff0 /* bits 0-3 */
+# define MRB_mclkbrd0_SHIFT 0
+# define MRB_mclkbrd1_MASK 0xfffffe1f /* bits 5-8 */
+# define MRB_mclkbrd1_SHIFT 5
+# define MRB_strmfctl_MASK 0xff3fffff /* bits 22-23 */
+# define MRB_mrsopcod_MASK 0xe1ffffff /* bits 25-28 */
+# define MRB_mrsopcod_SHIFT 25
+
+#define MGAREG_OPMODE 0x1e54
+
+# define OM_dmamod_MASK 0xfffffff3 /* bits 2-3 */
+# define OM_dmamod_general 0x0 /* val 0, shift 2 */
+# define OM_dmamod_blit 0x4 /* val 1, shift 2 */
+# define OM_dmamod_vector 0x8 /* val 2, shift 2 */
+# define OM_dmamod_vertex 0xc /* val 3, shift 2 */
+# define OM_dmadatasiz_MASK 0xfffffcff /* bits 8-9 */
+# define OM_dmadatasiz_8 0x0 /* val 0, shift 8 */
+# define OM_dmadatasiz_16 0x100 /* val 1, shift 8 */
+# define OM_dmadatasiz_32 0x200 /* val 2, shift 8 */
+# define OM_dirdatasiz_MASK 0xfffcffff /* bits 16-17 */
+# define OM_dirdatasiz_8 0x0 /* val 0, shift 16 */
+# define OM_dirdatasiz_16 0x10000 /* val 1, shift 16 */
+# define OM_dirdatasiz_32 0x20000 /* val 2, shift 16 */
+
+#define MGAREG_PAT0 0x1c10
+#define MGAREG_PAT1 0x1c14
+#define MGAREG_PITCH 0x1c8c
+
+# define P_iy_MASK 0xffffe000 /* bits 0-12 */
+# define P_iy_SHIFT 0
+# define P_ylin_MASK 0xffff7fff /* bit 15 */
+# define P_ylin_disable 0x0
+# define P_ylin_enable 0x8000
+
+#define MGAREG_PLNWT 0x1c1c
+#define MGAREG_PRIMADDRESS 0x1e58
+
+# define PDCA_primod_MASK 0xfffffffc /* bits 0-1 */
+# define PDCA_primod_general 0x0 /* val 0, shift 0 */
+# define PDCA_primod_blit 0x1 /* val 1, shift 0 */
+# define PDCA_primod_vector 0x2 /* val 2, shift 0 */
+# define PDCA_primod_vertex 0x3 /* val 3, shift 0 */
+# define PDCA_primaddress_MASK 0x3 /* bits 2-31 */
+# define PDCA_primaddress_SHIFT 2
+
+#define MGAREG_PRIMEND 0x1e5c
+
+# define PDEA_primnostart_MASK 0xfffffffe /* bit 0 */
+# define PDEA_primnostart_disable 0x0
+# define PDEA_primnostart_enable 0x1
+# define PDEA_pagpxfer_MASK 0xfffffffd /* bit 1 */
+# define PDEA_pagpxfer_disable 0x0
+# define PDEA_pagpxfer_enable 0x2
+# define PDEA_primend_MASK 0x3 /* bits 2-31 */
+# define PDEA_primend_SHIFT 2
+
+#define MGAREG_PRIMPTR 0x1e50
+
+# define PLS_primptren0_MASK 0xfffffffe /* bit 0 */
+# define PLS_primptren0_disable 0x0
+# define PLS_primptren0_enable 0x1
+# define PLS_primptren1_MASK 0xfffffffd /* bit 1 */
+# define PLS_primptren1_disable 0x0
+# define PLS_primptren1_enable 0x2
+# define PLS_primptr_MASK 0x7 /* bits 3-31 */
+# define PLS_primptr_SHIFT 3
+
+#define MGAREG_RST 0x1e40
+
+# define R_softreset_MASK 0xfffffffe /* bit 0 */
+# define R_softreset_disable 0x0
+# define R_softreset_enable 0x1
+# define R_softextrst_MASK 0xfffffffd /* bit 1 */
+# define R_softextrst_disable 0x0
+# define R_softextrst_enable 0x2
+
+#define MGAREG_SECADDRESS 0x2c40
+
+# define SDCA_secmod_MASK 0xfffffffc /* bits 0-1 */
+# define SDCA_secmod_general 0x0 /* val 0, shift 0 */
+# define SDCA_secmod_blit 0x1 /* val 1, shift 0 */
+# define SDCA_secmod_vector 0x2 /* val 2, shift 0 */
+# define SDCA_secmod_vertex 0x3 /* val 3, shift 0 */
+# define SDCA_secaddress_MASK 0x3 /* bits 2-31 */
+# define SDCA_secaddress_SHIFT 2
+
+#define MGAREG_SECEND 0x2c44
+
+# define SDEA_sagpxfer_MASK 0xfffffffd /* bit 1 */
+# define SDEA_sagpxfer_disable 0x0
+# define SDEA_sagpxfer_enable 0x2
+# define SDEA_secend_MASK 0x3 /* bits 2-31 */
+# define SDEA_secend_SHIFT 2
+
+#define MGAREG_SETUPADDRESS 0x2cd0
+
+# define SETADD_mode_MASK 0xfffffffc /* bits 0-1 */
+# define SETADD_mode_vertlist 0x0 /* val 0, shift 0 */
+# define SETADD_address_MASK 0x3 /* bits 2-31 */
+# define SETADD_address_SHIFT 2
+
+#define MGAREG_SETUPEND 0x2cd4
+
+# define SETEND_agpxfer_MASK 0xfffffffd /* bit 1 */
+# define SETEND_agpxfer_disable 0x0
+# define SETEND_agpxfer_enable 0x2
+# define SETEND_address_MASK 0x3 /* bits 2-31 */
+# define SETEND_address_SHIFT 2
+
+#define MGAREG_SGN 0x1c58
+
+# define S_sdydxl_MASK 0xfffffffe /* bit 0 */
+# define S_sdydxl_y 0x0
+# define S_sdydxl_x 0x1
+# define S_scanleft_MASK 0xfffffffe /* bit 0 */
+# define S_scanleft_disable 0x0
+# define S_scanleft_enable 0x1
+# define S_sdxl_MASK 0xfffffffd /* bit 1 */
+# define S_sdxl_pos 0x0
+# define S_sdxl_neg 0x2
+# define S_sdy_MASK 0xfffffffb /* bit 2 */
+# define S_sdy_pos 0x0
+# define S_sdy_neg 0x4
+# define S_sdxr_MASK 0xffffffdf /* bit 5 */
+# define S_sdxr_pos 0x0
+# define S_sdxr_neg 0x20
+# define S_brkleft_MASK 0xfffffeff /* bit 8 */
+# define S_brkleft_disable 0x0
+# define S_brkleft_enable 0x100
+# define S_errorinit_MASK 0x7fffffff /* bit 31 */
+# define S_errorinit_disable 0x0
+# define S_errorinit_enable 0x80000000
+
+#define MGAREG_SHIFT 0x1c50
+
+# define FSC_x_off_MASK 0xfffffff0 /* bits 0-3 */
+# define FSC_x_off_SHIFT 0
+# define FSC_funcnt_MASK 0xffffff80 /* bits 0-6 */
+# define FSC_funcnt_SHIFT 0
+# define FSC_y_off_MASK 0xffffff8f /* bits 4-6 */
+# define FSC_y_off_SHIFT 4
+# define FSC_funoff_MASK 0xffc0ffff /* bits 16-21 */
+# define FSC_funoff_SHIFT 16
+# define FSC_stylelen_MASK 0xffc0ffff /* bits 16-21 */
+# define FSC_stylelen_SHIFT 16
+
+#define MGAREG_SOFTRAP 0x2c48
+
+# define STH_softraphand_MASK 0x3 /* bits 2-31 */
+# define STH_softraphand_SHIFT 2
+
+#define MGAREG_SPECBSTART 0x2c98
+#define MGAREG_SPECBXINC 0x2c9c
+#define MGAREG_SPECBYINC 0x2ca0
+#define MGAREG_SPECGSTART 0x2c8c
+#define MGAREG_SPECGXINC 0x2c90
+#define MGAREG_SPECGYINC 0x2c94
+#define MGAREG_SPECRSTART 0x2c80
+#define MGAREG_SPECRXINC 0x2c84
+#define MGAREG_SPECRYINC 0x2c88
+#define MGAREG_SRC0 0x1c30
+#define MGAREG_SRC1 0x1c34
+#define MGAREG_SRC2 0x1c38
+#define MGAREG_SRC3 0x1c3c
+#define MGAREG_SRCORG 0x2cb4
+
+# define SO_srcmap_MASK 0xfffffffe /* bit 0 */
+# define SO_srcmap_fb 0x0
+# define SO_srcmap_sys 0x1
+# define SO_srcacc_MASK 0xfffffffd /* bit 1 */
+# define SO_srcacc_pci 0x0
+# define SO_srcacc_agp 0x2
+# define SO_srcorg_MASK 0x7 /* bits 3-31 */
+# define SO_srcorg_SHIFT 3
+
+#define MGAREG_STATUS 0x1e14
+
+# define STAT_softrapen_MASK 0xfffffffe /* bit 0 */
+# define STAT_softrapen_disable 0x0
+# define STAT_softrapen_enable 0x1
+# define STAT_pickpen_MASK 0xfffffffb /* bit 2 */
+# define STAT_pickpen_disable 0x0
+# define STAT_pickpen_enable 0x4
+# define STAT_vsyncsts_MASK 0xfffffff7 /* bit 3 */
+# define STAT_vsyncsts_disable 0x0
+# define STAT_vsyncsts_enable 0x8
+# define STAT_vsyncpen_MASK 0xffffffef /* bit 4 */
+# define STAT_vsyncpen_disable 0x0
+# define STAT_vsyncpen_enable 0x10
+# define STAT_vlinepen_MASK 0xffffffdf /* bit 5 */
+# define STAT_vlinepen_disable 0x0
+# define STAT_vlinepen_enable 0x20
+# define STAT_extpen_MASK 0xffffffbf /* bit 6 */
+# define STAT_extpen_disable 0x0
+# define STAT_extpen_enable 0x40
+# define STAT_wpen_MASK 0xffffff7f /* bit 7 */
+# define STAT_wpen_disable 0x0
+# define STAT_wpen_enable 0x80
+# define STAT_wcpen_MASK 0xfffffeff /* bit 8 */
+# define STAT_wcpen_disable 0x0
+# define STAT_wcpen_enable 0x100
+# define STAT_dwgengsts_MASK 0xfffeffff /* bit 16 */
+# define STAT_dwgengsts_disable 0x0
+# define STAT_dwgengsts_enable 0x10000
+# define STAT_endprdmasts_MASK 0xfffdffff /* bit 17 */
+# define STAT_endprdmasts_disable 0x0
+# define STAT_endprdmasts_enable 0x20000
+# define STAT_wbusy_MASK 0xfffbffff /* bit 18 */
+# define STAT_wbusy_disable 0x0
+# define STAT_wbusy_enable 0x40000
+# define STAT_swflag_MASK 0xfffffff /* bits 28-31 */
+# define STAT_swflag_SHIFT 28
+
+#define MGAREG_STENCIL 0x2cc8
+
+# define S_sref_MASK 0xffffff00 /* bits 0-7 */
+# define S_sref_SHIFT 0
+# define S_smsk_MASK 0xffff00ff /* bits 8-15 */
+# define S_smsk_SHIFT 8
+# define S_swtmsk_MASK 0xff00ffff /* bits 16-23 */
+# define S_swtmsk_SHIFT 16
+
+#define MGAREG_STENCILCTL 0x2ccc
+
+# define SC_smode_MASK 0xfffffff8 /* bits 0-2 */
+# define SC_smode_salways 0x0 /* val 0, shift 0 */
+# define SC_smode_snever 0x1 /* val 1, shift 0 */
+# define SC_smode_se 0x2 /* val 2, shift 0 */
+# define SC_smode_sne 0x3 /* val 3, shift 0 */
+# define SC_smode_slt 0x4 /* val 4, shift 0 */
+# define SC_smode_slte 0x5 /* val 5, shift 0 */
+# define SC_smode_sgt 0x6 /* val 6, shift 0 */
+# define SC_smode_sgte 0x7 /* val 7, shift 0 */
+# define SC_sfailop_MASK 0xffffffc7 /* bits 3-5 */
+# define SC_sfailop_keep 0x0 /* val 0, shift 3 */
+# define SC_sfailop_zero 0x8 /* val 1, shift 3 */
+# define SC_sfailop_replace 0x10 /* val 2, shift 3 */
+# define SC_sfailop_incrsat 0x18 /* val 3, shift 3 */
+# define SC_sfailop_decrsat 0x20 /* val 4, shift 3 */
+# define SC_sfailop_invert 0x28 /* val 5, shift 3 */
+# define SC_sfailop_incr 0x30 /* val 6, shift 3 */
+# define SC_sfailop_decr 0x38 /* val 7, shift 3 */
+# define SC_szfailop_MASK 0xfffffe3f /* bits 6-8 */
+# define SC_szfailop_keep 0x0 /* val 0, shift 6 */
+# define SC_szfailop_zero 0x40 /* val 1, shift 6 */
+# define SC_szfailop_replace 0x80 /* val 2, shift 6 */
+# define SC_szfailop_incrsat 0xc0 /* val 3, shift 6 */
+# define SC_szfailop_decrsat 0x100 /* val 4, shift 6 */
+# define SC_szfailop_invert 0x140 /* val 5, shift 6 */
+# define SC_szfailop_incr 0x180 /* val 6, shift 6 */
+# define SC_szfailop_decr 0x1c0 /* val 7, shift 6 */
+# define SC_szpassop_MASK 0xfffff1ff /* bits 9-11 */
+# define SC_szpassop_keep 0x0 /* val 0, shift 9 */
+# define SC_szpassop_zero 0x200 /* val 1, shift 9 */
+# define SC_szpassop_replace 0x400 /* val 2, shift 9 */
+# define SC_szpassop_incrsat 0x600 /* val 3, shift 9 */
+# define SC_szpassop_decrsat 0x800 /* val 4, shift 9 */
+# define SC_szpassop_invert 0xa00 /* val 5, shift 9 */
+# define SC_szpassop_incr 0xc00 /* val 6, shift 9 */
+# define SC_szpassop_decr 0xe00 /* val 7, shift 9 */
+
+#define MGAREG_TDUALSTAGE0 0x2cf8
+
+# define TD0_color_arg2_MASK 0xfffffffc /* bits 0-1 */
+# define TD0_color_arg2_diffuse 0x0 /* val 0, shift 0 */
+# define TD0_color_arg2_specular 0x1 /* val 1, shift 0 */
+# define TD0_color_arg2_fcol 0x2 /* val 2, shift 0 */
+# define TD0_color_arg2_prevstage 0x3 /* val 3, shift 0 */
+# define TD0_color_alpha_MASK 0xffffffe3 /* bits 2-4 */
+# define TD0_color_alpha_diffuse 0x0 /* val 0, shift 2 */
+# define TD0_color_alpha_fcol 0x4 /* val 1, shift 2 */
+# define TD0_color_alpha_currtex 0x8 /* val 2, shift 2 */
+# define TD0_color_alpha_prevtex 0xc /* val 3, shift 2 */
+# define TD0_color_alpha_prevstage 0x10 /* val 4, shift 2 */
+# define TD0_color_arg1_replicatealpha_MASK 0xffffffdf /* bit 5 */
+# define TD0_color_arg1_replicatealpha_disable 0x0
+# define TD0_color_arg1_replicatealpha_enable 0x20
+# define TD0_color_arg1_inv_MASK 0xffffffbf /* bit 6 */
+# define TD0_color_arg1_inv_disable 0x0
+# define TD0_color_arg1_inv_enable 0x40
+# define TD0_color_arg2_replicatealpha_MASK 0xffffff7f /* bit 7 */
+# define TD0_color_arg2_replicatealpha_disable 0x0
+# define TD0_color_arg2_replicatealpha_enable 0x80
+# define TD0_color_arg2_inv_MASK 0xfffffeff /* bit 8 */
+# define TD0_color_arg2_inv_disable 0x0
+# define TD0_color_arg2_inv_enable 0x100
+# define TD0_color_alpha1inv_MASK 0xfffffdff /* bit 9 */
+# define TD0_color_alpha1inv_disable 0x0
+# define TD0_color_alpha1inv_enable 0x200
+# define TD0_color_alpha2inv_MASK 0xfffffbff /* bit 10 */
+# define TD0_color_alpha2inv_disable 0x0
+# define TD0_color_alpha2inv_enable 0x400
+# define TD0_color_arg1mul_MASK 0xfffff7ff /* bit 11 */
+# define TD0_color_arg1mul_disable 0x0 /* val 0, shift 11 */
+# define TD0_color_arg1mul_alpha1 0x800 /* val 1, shift 11 */
+# define TD0_color_arg2mul_MASK 0xffffefff /* bit 12 */
+# define TD0_color_arg2mul_disable 0x0 /* val 0, shift 12 */
+# define TD0_color_arg2mul_alpha2 0x1000 /* val 1, shift 12 */
+# define TD0_color_arg1add_MASK 0xffffdfff /* bit 13 */
+# define TD0_color_arg1add_disable 0x0 /* val 0, shift 13 */
+# define TD0_color_arg1add_mulout 0x2000 /* val 1, shift 13 */
+# define TD0_color_arg2add_MASK 0xffffbfff /* bit 14 */
+# define TD0_color_arg2add_disable 0x0 /* val 0, shift 14 */
+# define TD0_color_arg2add_mulout 0x4000 /* val 1, shift 14 */
+# define TD0_color_modbright_MASK 0xfffe7fff /* bits 15-16 */
+# define TD0_color_modbright_disable 0x0 /* val 0, shift 15 */
+# define TD0_color_modbright_2x 0x8000 /* val 1, shift 15 */
+# define TD0_color_modbright_4x 0x10000 /* val 2, shift 15 */
+# define TD0_color_add_MASK 0xfffdffff /* bit 17 */
+# define TD0_color_add_sub 0x0 /* val 0, shift 17 */
+# define TD0_color_add_add 0x20000 /* val 1, shift 17 */
+# define TD0_color_add2x_MASK 0xfffbffff /* bit 18 */
+# define TD0_color_add2x_disable 0x0
+# define TD0_color_add2x_enable 0x40000
+# define TD0_color_addbias_MASK 0xfff7ffff /* bit 19 */
+# define TD0_color_addbias_disable 0x0
+# define TD0_color_addbias_enable 0x80000
+# define TD0_color_blend_MASK 0xffefffff /* bit 20 */
+# define TD0_color_blend_disable 0x0
+# define TD0_color_blend_enable 0x100000
+# define TD0_color_sel_MASK 0xff9fffff /* bits 21-22 */
+# define TD0_color_sel_arg1 0x0 /* val 0, shift 21 */
+# define TD0_color_sel_arg2 0x200000 /* val 1, shift 21 */
+# define TD0_color_sel_add 0x400000 /* val 2, shift 21 */
+# define TD0_color_sel_mul 0x600000 /* val 3, shift 21 */
+# define TD0_alpha_arg1_inv_MASK 0xff7fffff /* bit 23 */
+# define TD0_alpha_arg1_inv_disable 0x0
+# define TD0_alpha_arg1_inv_enable 0x800000
+# define TD0_alpha_arg2_MASK 0xfcffffff /* bits 24-25 */
+# define TD0_alpha_arg2_diffuse 0x0 /* val 0, shift 24 */
+# define TD0_alpha_arg2_fcol 0x1000000 /* val 1, shift 24 */
+# define TD0_alpha_arg2_prevtex 0x2000000 /* val 2, shift 24 */
+# define TD0_alpha_arg2_prevstage 0x3000000 /* val 3, shift 24 */
+# define TD0_alpha_arg2_inv_MASK 0xfbffffff /* bit 26 */
+# define TD0_alpha_arg2_inv_disable 0x0
+# define TD0_alpha_arg2_inv_enable 0x4000000
+# define TD0_alpha_add_MASK 0xf7ffffff /* bit 27 */
+# define TD0_alpha_add_disable 0x0
+# define TD0_alpha_add_enable 0x8000000
+# define TD0_alpha_addbias_MASK 0xefffffff /* bit 28 */
+# define TD0_alpha_addbias_disable 0x0
+# define TD0_alpha_addbias_enable 0x10000000
+# define TD0_alpha_add2x_MASK 0xdfffffff /* bit 29 */
+# define TD0_alpha_add2x_disable 0x0
+# define TD0_alpha_add2x_enable 0x20000000
+# define TD0_alpha_modbright_MASK 0xcfffffff /* bits 28-29 */
+# define TD0_alpha_modbright_disable 0x0 /* val 0, shift 28 */
+# define TD0_alpha_modbright_2x 0x10000000 /* val 1, shift 28 */
+# define TD0_alpha_modbright_4x 0x20000000 /* val 2, shift 28 */
+# define TD0_alpha_sel_MASK 0x3fffffff /* bits 30-31 */
+# define TD0_alpha_sel_arg1 0x0 /* val 0, shift 30 */
+# define TD0_alpha_sel_arg2 0x40000000 /* val 1, shift 30 */
+# define TD0_alpha_sel_add 0x80000000 /* val 2, shift 30 */
+# define TD0_alpha_sel_mul 0xc0000000 /* val 3, shift 30 */
+
+#define MGAREG_TDUALSTAGE1 0x2cfc
+
+# define TD1_color_arg2_MASK 0xfffffffc /* bits 0-1 */
+# define TD1_color_arg2_diffuse 0x0 /* val 0, shift 0 */
+# define TD1_color_arg2_specular 0x1 /* val 1, shift 0 */
+# define TD1_color_arg2_fcol 0x2 /* val 2, shift 0 */
+# define TD1_color_arg2_prevstage 0x3 /* val 3, shift 0 */
+# define TD1_color_alpha_MASK 0xffffffe3 /* bits 2-4 */
+# define TD1_color_alpha_diffuse 0x0 /* val 0, shift 2 */
+# define TD1_color_alpha_fcol 0x4 /* val 1, shift 2 */
+# define TD1_color_alpha_tex0 0x8 /* val 2, shift 2 */
+# define TD1_color_alpha_prevtex 0xc /* val 3, shift 2 */
+# define TD1_color_alpha_prevstage 0x10 /* val 4, shift 2 */
+# define TD1_color_arg1_replicatealpha_MASK 0xffffffdf /* bit 5 */
+# define TD1_color_arg1_replicatealpha_disable 0x0
+# define TD1_color_arg1_replicatealpha_enable 0x20
+# define TD1_color_arg1_inv_MASK 0xffffffbf /* bit 6 */
+# define TD1_color_arg1_inv_disable 0x0
+# define TD1_color_arg1_inv_enable 0x40
+# define TD1_color_arg2_replicatealpha_MASK 0xffffff7f /* bit 7 */
+# define TD1_color_arg2_replicatealpha_disable 0x0
+# define TD1_color_arg2_replicatealpha_enable 0x80
+# define TD1_color_arg2_inv_MASK 0xfffffeff /* bit 8 */
+# define TD1_color_arg2_inv_disable 0x0
+# define TD1_color_arg2_inv_enable 0x100
+# define TD1_color_alpha1inv_MASK 0xfffffdff /* bit 9 */
+# define TD1_color_alpha1inv_disable 0x0
+# define TD1_color_alpha1inv_enable 0x200
+# define TD1_color_alpha2inv_MASK 0xfffffbff /* bit 10 */
+# define TD1_color_alpha2inv_disable 0x0
+# define TD1_color_alpha2inv_enable 0x400
+# define TD1_color_arg1mul_MASK 0xfffff7ff /* bit 11 */
+# define TD1_color_arg1mul_disable 0x0 /* val 0, shift 11 */
+# define TD1_color_arg1mul_alpha1 0x800 /* val 1, shift 11 */
+# define TD1_color_arg2mul_MASK 0xffffefff /* bit 12 */
+# define TD1_color_arg2mul_disable 0x0 /* val 0, shift 12 */
+# define TD1_color_arg2mul_alpha2 0x1000 /* val 1, shift 12 */
+# define TD1_color_arg1add_MASK 0xffffdfff /* bit 13 */
+# define TD1_color_arg1add_disable 0x0 /* val 0, shift 13 */
+# define TD1_color_arg1add_mulout 0x2000 /* val 1, shift 13 */
+# define TD1_color_arg2add_MASK 0xffffbfff /* bit 14 */
+# define TD1_color_arg2add_disable 0x0 /* val 0, shift 14 */
+# define TD1_color_arg2add_mulout 0x4000 /* val 1, shift 14 */
+# define TD1_color_modbright_MASK 0xfffe7fff /* bits 15-16 */
+# define TD1_color_modbright_disable 0x0 /* val 0, shift 15 */
+# define TD1_color_modbright_2x 0x8000 /* val 1, shift 15 */
+# define TD1_color_modbright_4x 0x10000 /* val 2, shift 15 */
+# define TD1_color_add_MASK 0xfffdffff /* bit 17 */
+# define TD1_color_add_sub 0x0 /* val 0, shift 17 */
+# define TD1_color_add_add 0x20000 /* val 1, shift 17 */
+# define TD1_color_add2x_MASK 0xfffbffff /* bit 18 */
+# define TD1_color_add2x_disable 0x0
+# define TD1_color_add2x_enable 0x40000
+# define TD1_color_addbias_MASK 0xfff7ffff /* bit 19 */
+# define TD1_color_addbias_disable 0x0
+# define TD1_color_addbias_enable 0x80000
+# define TD1_color_blend_MASK 0xffefffff /* bit 20 */
+# define TD1_color_blend_disable 0x0
+# define TD1_color_blend_enable 0x100000
+# define TD1_color_sel_MASK 0xff9fffff /* bits 21-22 */
+# define TD1_color_sel_arg1 0x0 /* val 0, shift 21 */
+# define TD1_color_sel_arg2 0x200000 /* val 1, shift 21 */
+# define TD1_color_sel_add 0x400000 /* val 2, shift 21 */
+# define TD1_color_sel_mul 0x600000 /* val 3, shift 21 */
+# define TD1_alpha_arg1_inv_MASK 0xff7fffff /* bit 23 */
+# define TD1_alpha_arg1_inv_disable 0x0
+# define TD1_alpha_arg1_inv_enable 0x800000
+# define TD1_alpha_arg2_MASK 0xfcffffff /* bits 24-25 */
+# define TD1_alpha_arg2_diffuse 0x0 /* val 0, shift 24 */
+# define TD1_alpha_arg2_fcol 0x1000000 /* val 1, shift 24 */
+# define TD1_alpha_arg2_prevtex 0x2000000 /* val 2, shift 24 */
+# define TD1_alpha_arg2_prevstage 0x3000000 /* val 3, shift 24 */
+# define TD1_alpha_arg2_inv_MASK 0xfbffffff /* bit 26 */
+# define TD1_alpha_arg2_inv_disable 0x0
+# define TD1_alpha_arg2_inv_enable 0x4000000
+# define TD1_alpha_add_MASK 0xf7ffffff /* bit 27 */
+# define TD1_alpha_add_disable 0x0
+# define TD1_alpha_add_enable 0x8000000
+# define TD1_alpha_addbias_MASK 0xefffffff /* bit 28 */
+# define TD1_alpha_addbias_disable 0x0
+# define TD1_alpha_addbias_enable 0x10000000
+# define TD1_alpha_add2x_MASK 0xdfffffff /* bit 29 */
+# define TD1_alpha_add2x_disable 0x0
+# define TD1_alpha_add2x_enable 0x20000000
+# define TD1_alpha_modbright_MASK 0xcfffffff /* bits 28-29 */
+# define TD1_alpha_modbright_disable 0x0 /* val 0, shift 28 */
+# define TD1_alpha_modbright_2x 0x10000000 /* val 1, shift 28 */
+# define TD1_alpha_modbright_4x 0x20000000 /* val 2, shift 28 */
+# define TD1_alpha_sel_MASK 0x3fffffff /* bits 30-31 */
+# define TD1_alpha_sel_arg1 0x0 /* val 0, shift 30 */
+# define TD1_alpha_sel_arg2 0x40000000 /* val 1, shift 30 */
+# define TD1_alpha_sel_add 0x80000000 /* val 2, shift 30 */
+# define TD1_alpha_sel_mul 0xc0000000 /* val 3, shift 30 */
+
+#define MGAREG_TEST0 0x1e48
+
+# define TST_ramtsten_MASK 0xfffffffe /* bit 0 */
+# define TST_ramtsten_disable 0x0
+# define TST_ramtsten_enable 0x1
+# define TST_ramtstdone_MASK 0xfffffffd /* bit 1 */
+# define TST_ramtstdone_disable 0x0
+# define TST_ramtstdone_enable 0x2
+# define TST_wramtstpass_MASK 0xfffffffb /* bit 2 */
+# define TST_wramtstpass_disable 0x0
+# define TST_wramtstpass_enable 0x4
+# define TST_tcachetstpass_MASK 0xfffffff7 /* bit 3 */
+# define TST_tcachetstpass_disable 0x0
+# define TST_tcachetstpass_enable 0x8
+# define TST_tluttstpass_MASK 0xffffffef /* bit 4 */
+# define TST_tluttstpass_disable 0x0
+# define TST_tluttstpass_enable 0x10
+# define TST_luttstpass_MASK 0xffffffdf /* bit 5 */
+# define TST_luttstpass_disable 0x0
+# define TST_luttstpass_enable 0x20
+# define TST_besramtstpass_MASK 0xffffffbf /* bit 6 */
+# define TST_besramtstpass_disable 0x0
+# define TST_besramtstpass_enable 0x40
+# define TST_ringen_MASK 0xfffffeff /* bit 8 */
+# define TST_ringen_disable 0x0
+# define TST_ringen_enable 0x100
+# define TST_apllbyp_MASK 0xfffffdff /* bit 9 */
+# define TST_apllbyp_disable 0x0
+# define TST_apllbyp_enable 0x200
+# define TST_hiten_MASK 0xfffffbff /* bit 10 */
+# define TST_hiten_disable 0x0
+# define TST_hiten_enable 0x400
+# define TST_tmode_MASK 0xffffc7ff /* bits 11-13 */
+# define TST_tmode_SHIFT 11
+# define TST_tclksel_MASK 0xfffe3fff /* bits 14-16 */
+# define TST_tclksel_SHIFT 14
+# define TST_ringcnten_MASK 0xfffdffff /* bit 17 */
+# define TST_ringcnten_disable 0x0
+# define TST_ringcnten_enable 0x20000
+# define TST_ringcnt_MASK 0xc003ffff /* bits 18-29 */
+# define TST_ringcnt_SHIFT 18
+# define TST_ringcntclksl_MASK 0xbfffffff /* bit 30 */
+# define TST_ringcntclksl_disable 0x0
+# define TST_ringcntclksl_enable 0x40000000
+# define TST_biosboot_MASK 0x7fffffff /* bit 31 */
+# define TST_biosboot_disable 0x0
+# define TST_biosboot_enable 0x80000000
+
+#define MGAREG_TEXBORDERCOL 0x2c5c
+#define MGAREG_TEXCTL 0x2c30
+
+# define TMC_tformat_MASK 0xfffffff0 /* bits 0-3 */
+# define TMC_tformat_tw4 0x0 /* val 0, shift 0 */
+# define TMC_tformat_tw8 0x1 /* val 1, shift 0 */
+# define TMC_tformat_tw15 0x2 /* val 2, shift 0 */
+# define TMC_tformat_tw16 0x3 /* val 3, shift 0 */
+# define TMC_tformat_tw12 0x4 /* val 4, shift 0 */
+# define TMC_tformat_tw32 0x6 /* val 6, shift 0 */
+# define TMC_tformat_tw8a 0x7 /* val 7, shift 0 */
+# define TMC_tformat_tw8al 0x8 /* val 8, shift 0 */
+# define TMC_tformat_tw422 0xa /* val 10, shift 0 */
+# define TMC_tformat_tw422uyvy 0xb /* val 11, shift 0 */
+# define TMC_tpitchlin_MASK 0xfffffeff /* bit 8 */
+# define TMC_tpitchlin_disable 0x0
+# define TMC_tpitchlin_enable 0x100
+# define TMC_tpitchext_MASK 0xfff001ff /* bits 9-19 */
+# define TMC_tpitchext_SHIFT 9
+# define TMC_tpitch_MASK 0xfff8ffff /* bits 16-18 */
+# define TMC_tpitch_SHIFT 16
+# define TMC_owalpha_MASK 0xffbfffff /* bit 22 */
+# define TMC_owalpha_disable 0x0
+# define TMC_owalpha_enable 0x400000
+# define TMC_azeroextend_MASK 0xff7fffff /* bit 23 */
+# define TMC_azeroextend_disable 0x0
+# define TMC_azeroextend_enable 0x800000
+# define TMC_decalckey_MASK 0xfeffffff /* bit 24 */
+# define TMC_decalckey_disable 0x0
+# define TMC_decalckey_enable 0x1000000
+# define TMC_takey_MASK 0xfdffffff /* bit 25 */
+# define TMC_takey_0 0x0
+# define TMC_takey_1 0x2000000
+# define TMC_tamask_MASK 0xfbffffff /* bit 26 */
+# define TMC_tamask_0 0x0
+# define TMC_tamask_1 0x4000000
+# define TMC_clampv_MASK 0xf7ffffff /* bit 27 */
+# define TMC_clampv_disable 0x0
+# define TMC_clampv_enable 0x8000000
+# define TMC_clampu_MASK 0xefffffff /* bit 28 */
+# define TMC_clampu_disable 0x0
+# define TMC_clampu_enable 0x10000000
+# define TMC_tmodulate_MASK 0xdfffffff /* bit 29 */
+# define TMC_tmodulate_disable 0x0
+# define TMC_tmodulate_enable 0x20000000
+# define TMC_strans_MASK 0xbfffffff /* bit 30 */
+# define TMC_strans_disable 0x0
+# define TMC_strans_enable 0x40000000
+# define TMC_itrans_MASK 0x7fffffff /* bit 31 */
+# define TMC_itrans_disable 0x0
+# define TMC_itrans_enable 0x80000000
+
+#define MGAREG_TEXCTL2 0x2c3c
+
+# define TMC_decalblend_MASK 0xfffffffe /* bit 0 */
+# define TMC_decalblend_disable 0x0
+# define TMC_decalblend_enable 0x1
+# define TMC_idecal_MASK 0xfffffffd /* bit 1 */
+# define TMC_idecal_disable 0x0
+# define TMC_idecal_enable 0x2
+# define TMC_decaldis_MASK 0xfffffffb /* bit 2 */
+# define TMC_decaldis_disable 0x0
+# define TMC_decaldis_enable 0x4
+# define TMC_ckstransdis_MASK 0xffffffef /* bit 4 */
+# define TMC_ckstransdis_disable 0x0
+# define TMC_ckstransdis_enable 0x10
+# define TMC_borderen_MASK 0xffffffdf /* bit 5 */
+# define TMC_borderen_disable 0x0
+# define TMC_borderen_enable 0x20
+# define TMC_specen_MASK 0xffffffbf /* bit 6 */
+# define TMC_specen_disable 0x0
+# define TMC_specen_enable 0x40
+# define TMC_dualtex_MASK 0xffffff7f /* bit 7 */
+# define TMC_dualtex_disable 0x0
+# define TMC_dualtex_enable 0x80
+# define TMC_tablefog_MASK 0xfffffeff /* bit 8 */
+# define TMC_tablefog_disable 0x0
+# define TMC_tablefog_enable 0x100
+# define TMC_bumpmap_MASK 0xfffffdff /* bit 9 */
+# define TMC_bumpmap_disable 0x0
+# define TMC_bumpmap_enable 0x200
+# define TMC_map1_MASK 0x7fffffff /* bit 31 */
+# define TMC_map1_disable 0x0
+# define TMC_map1_enable 0x80000000
+
+#define MGAREG_TEXFILTER 0x2c58
+
+# define TF_minfilter_MASK 0xfffffff0 /* bits 0-3 */
+# define TF_minfilter_nrst 0x0 /* val 0, shift 0 */
+# define TF_minfilter_bilin 0x2 /* val 2, shift 0 */
+# define TF_minfilter_cnst 0x3 /* val 3, shift 0 */
+# define TF_minfilter_mm1s 0x8 /* val 8, shift 0 */
+# define TF_minfilter_mm2s 0x9 /* val 9, shift 0 */
+# define TF_minfilter_mm4s 0xa /* val 10, shift 0 */
+# define TF_minfilter_mm8s 0xc /* val 12, shift 0 */
+# define TF_magfilter_MASK 0xffffff0f /* bits 4-7 */
+# define TF_magfilter_nrst 0x0 /* val 0, shift 4 */
+# define TF_magfilter_bilin 0x20 /* val 2, shift 4 */
+# define TF_magfilter_cnst 0x30 /* val 3, shift 4 */
+# define TF_uvoffset_SHIFT 17
+# define TF_uvoffset_OGL (0U << TF_uvoffset_SHIFT)
+# define TF_uvoffset_D3D (1U << TF_uvoffset_SHIFT)
+# define TF_uvoffset_MASK (~(1U << TF_uvoffset_SHIFT))
+# define TF_reserved_MASK (~0x1ff00) /* bits 8-16 */
+# define TF_mapnbhigh_SHIFT 18
+# define TF_mapnbhigh_MASK (~(1U << TF_mapnbhigh_SHIFT))
+# define TF_avgstride_MASK 0xfff7ffff /* bit 19 */
+# define TF_avgstride_disable 0x0
+# define TF_avgstride_enable 0x80000
+# define TF_filteralpha_MASK 0xffefffff /* bit 20 */
+# define TF_filteralpha_disable 0x0
+# define TF_filteralpha_enable 0x100000
+# define TF_fthres_MASK 0xe01fffff /* bits 21-28 */
+# define TF_fthres_SHIFT 21
+# define TF_mapnb_MASK 0x1fffffff /* bits 29-31 */
+# define TF_mapnb_SHIFT 29
+
+#define MGAREG_TEXHEIGHT 0x2c2c
+
+# define TH_th_MASK 0xffffffc0 /* bits 0-5 */
+# define TH_th_SHIFT 0
+# define TH_rfh_MASK 0xffff81ff /* bits 9-14 */
+# define TH_rfh_SHIFT 9
+# define TH_thmask_MASK 0xe003ffff /* bits 18-28 */
+# define TH_thmask_SHIFT 18
+
+#define MGAREG_TEXORG 0x2c24
+
+# define TO_texorgmap_MASK 0xfffffffe /* bit 0 */
+# define TO_texorgmap_fb 0x0
+# define TO_texorgmap_sys 0x1
+# define TO_texorgacc_MASK 0xfffffffd /* bit 1 */
+# define TO_texorgacc_pci 0x0
+# define TO_texorgacc_agp 0x2
+# define TO_texorgoffsetsel 0x4
+# define TO_texorg_MASK 0x1f /* bits 5-31 */
+# define TO_texorg_SHIFT 5
+
+#define MGAREG_TEXORG1 0x2ca4
+#define MGAREG_TEXORG2 0x2ca8
+#define MGAREG_TEXORG3 0x2cac
+#define MGAREG_TEXORG4 0x2cb0
+#define MGAREG_TEXTRANS 0x2c34
+
+# define TT_tckey_MASK 0xffff0000 /* bits 0-15 */
+# define TT_tckey_SHIFT 0
+# define TT_tkmask_MASK 0xffff /* bits 16-31 */
+# define TT_tkmask_SHIFT 16
+
+#define MGAREG_TEXTRANSHIGH 0x2c38
+
+# define TT_tckeyh_MASK 0xffff0000 /* bits 0-15 */
+# define TT_tckeyh_SHIFT 0
+# define TT_tkmaskh_MASK 0xffff /* bits 16-31 */
+# define TT_tkmaskh_SHIFT 16
+
+#define MGAREG_TEXWIDTH 0x2c28
+
+# define TW_tw_MASK 0xffffffc0 /* bits 0-5 */
+# define TW_tw_SHIFT 0
+# define TW_rfw_MASK 0xffff81ff /* bits 9-14 */
+# define TW_rfw_SHIFT 9
+# define TW_twmask_MASK 0xe003ffff /* bits 18-28 */
+# define TW_twmask_SHIFT 18
+
+#define MGAREG_TMR0 0x2c00
+#define MGAREG_TMR1 0x2c04
+#define MGAREG_TMR2 0x2c08
+#define MGAREG_TMR3 0x2c0c
+#define MGAREG_TMR4 0x2c10
+#define MGAREG_TMR5 0x2c14
+#define MGAREG_TMR6 0x2c18
+#define MGAREG_TMR7 0x2c1c
+#define MGAREG_TMR8 0x2c20
+#define MGAREG_VBIADDR0 0x3e08
+#define MGAREG_VBIADDR1 0x3e0c
+#define MGAREG_VCOUNT 0x1e20
+#define MGAREG_WACCEPTSEQ 0x1dd4
+
+# define WAS_seqdst0_MASK 0xffffffc0 /* bits 0-5 */
+# define WAS_seqdst0_SHIFT 0
+# define WAS_seqdst1_MASK 0xfffff03f /* bits 6-11 */
+# define WAS_seqdst1_SHIFT 6
+# define WAS_seqdst2_MASK 0xfffc0fff /* bits 12-17 */
+# define WAS_seqdst2_SHIFT 12
+# define WAS_seqdst3_MASK 0xff03ffff /* bits 18-23 */
+# define WAS_seqdst3_SHIFT 18
+# define WAS_seqlen_MASK 0xfcffffff /* bits 24-25 */
+# define WAS_wfirsttag_MASK 0xfbffffff /* bit 26 */
+# define WAS_wfirsttag_disable 0x0
+# define WAS_wfirsttag_enable 0x4000000
+# define WAS_wsametag_MASK 0xf7ffffff /* bit 27 */
+# define WAS_wsametag_disable 0x0
+# define WAS_wsametag_enable 0x8000000
+# define WAS_seqoff_MASK 0xefffffff /* bit 28 */
+# define WAS_seqoff_disable 0x0
+# define WAS_seqoff_enable 0x10000000
+
+#define MGAREG_WCODEADDR 0x1e6c
+
+# define WMA_wcodeaddr_MASK 0xff /* bits 8-31 */
+# define WMA_wcodeaddr_SHIFT 8
+
+#define MGAREG_WFLAG 0x1dc4
+
+# define WF_walustsflag_MASK 0xffffff00 /* bits 0-7 */
+# define WF_walustsflag_SHIFT 0
+# define WF_walucfgflag_MASK 0xffff00ff /* bits 8-15 */
+# define WF_walucfgflag_SHIFT 8
+# define WF_wprgflag_MASK 0xffff /* bits 16-31 */
+# define WF_wprgflag_SHIFT 16
+
+#define MGAREG_WFLAG1 0x1de0
+
+# define WF1_walustsflag1_MASK 0xffffff00 /* bits 0-7 */
+# define WF1_walustsflag1_SHIFT 0
+# define WF1_walucfgflag1_MASK 0xffff00ff /* bits 8-15 */
+# define WF1_walucfgflag1_SHIFT 8
+# define WF1_wprgflag1_MASK 0xffff /* bits 16-31 */
+# define WF1_wprgflag1_SHIFT 16
+
+#define MGAREG_WFLAGNB 0x1e64
+#define MGAREG_WFLAGNB1 0x1e08
+#define MGAREG_WGETMSB 0x1dc8
+
+# define WGV_wgetmsbmin_MASK 0xffffffe0 /* bits 0-4 */
+# define WGV_wgetmsbmin_SHIFT 0
+# define WGV_wgetmsbmax_MASK 0xffffe0ff /* bits 8-12 */
+# define WGV_wgetmsbmax_SHIFT 8
+# define WGV_wbrklefttop_MASK 0xfffeffff /* bit 16 */
+# define WGV_wbrklefttop_disable 0x0
+# define WGV_wbrklefttop_enable 0x10000
+# define WGV_wfastcrop_MASK 0xfffdffff /* bit 17 */
+# define WGV_wfastcrop_disable 0x0
+# define WGV_wfastcrop_enable 0x20000
+# define WGV_wcentersnap_MASK 0xfffbffff /* bit 18 */
+# define WGV_wcentersnap_disable 0x0
+# define WGV_wcentersnap_enable 0x40000
+# define WGV_wbrkrighttop_MASK 0xfff7ffff /* bit 19 */
+# define WGV_wbrkrighttop_disable 0x0
+# define WGV_wbrkrighttop_enable 0x80000
+
+#define MGAREG_WIADDR 0x1dc0
+
+# define WIA_wmode_MASK 0xfffffffc /* bits 0-1 */
+# define WIA_wmode_suspend 0x0 /* val 0, shift 0 */
+# define WIA_wmode_resume 0x1 /* val 1, shift 0 */
+# define WIA_wmode_jump 0x2 /* val 2, shift 0 */
+# define WIA_wmode_start 0x3 /* val 3, shift 0 */
+# define WIA_wagp_MASK 0xfffffffb /* bit 2 */
+# define WIA_wagp_pci 0x0
+# define WIA_wagp_agp 0x4
+# define WIA_wiaddr_MASK 0x7 /* bits 3-31 */
+# define WIA_wiaddr_SHIFT 3
+
+#define MGAREG_WIADDR2 0x1dd8
+
+# define WIA2_wmode_MASK 0xfffffffc /* bits 0-1 */
+# define WIA2_wmode_suspend 0x0 /* val 0, shift 0 */
+# define WIA2_wmode_resume 0x1 /* val 1, shift 0 */
+# define WIA2_wmode_jump 0x2 /* val 2, shift 0 */
+# define WIA2_wmode_start 0x3 /* val 3, shift 0 */
+# define WIA2_wagp_MASK 0xfffffffb /* bit 2 */
+# define WIA2_wagp_pci 0x0
+# define WIA2_wagp_agp 0x4
+# define WIA2_wiaddr_MASK 0x7 /* bits 3-31 */
+# define WIA2_wiaddr_SHIFT 3
+
+#define MGAREG_WIADDRNB 0x1e60
+#define MGAREG_WIADDRNB1 0x1e04
+#define MGAREG_WIADDRNB2 0x1e00
+#define MGAREG_WIMEMADDR 0x1e68
+
+# define WIMA_wimemaddr_MASK 0xffffff00 /* bits 0-7 */
+# define WIMA_wimemaddr_SHIFT 0
+
+#define MGAREG_WIMEMDATA 0x2000
+#define MGAREG_WIMEMDATA1 0x2100
+#define MGAREG_WMISC 0x1e70
+
+# define WM_wucodecache_MASK 0xfffffffe /* bit 0 */
+# define WM_wucodecache_disable 0x0
+# define WM_wucodecache_enable 0x1
+# define WM_wmaster_MASK 0xfffffffd /* bit 1 */
+# define WM_wmaster_disable 0x0
+# define WM_wmaster_enable 0x2
+# define WM_wcacheflush_MASK 0xfffffff7 /* bit 3 */
+# define WM_wcacheflush_disable 0x0
+# define WM_wcacheflush_enable 0x8
+
+#define MGAREG_WR 0x2d00
+#define MGAREG_WVRTXSZ 0x1dcc
+
+# define WVS_wvrtxsz_MASK 0xffffffc0 /* bits 0-5 */
+# define WVS_wvrtxsz_SHIFT 0
+# define WVS_primsz_MASK 0xffffc0ff /* bits 8-13 */
+# define WVS_primsz_SHIFT 8
+
+#define MGAREG_XDST 0x1cb0
+#define MGAREG_XYEND 0x1c44
+
+# define XYEA_x_end_MASK 0xffff0000 /* bits 0-15 */
+# define XYEA_x_end_SHIFT 0
+# define XYEA_y_end_MASK 0xffff /* bits 16-31 */
+# define XYEA_y_end_SHIFT 16
+
+#define MGAREG_XYSTRT 0x1c40
+
+# define XYSA_x_start_MASK 0xffff0000 /* bits 0-15 */
+# define XYSA_x_start_SHIFT 0
+# define XYSA_y_start_MASK 0xffff /* bits 16-31 */
+# define XYSA_y_start_SHIFT 16
+
+#define MGAREG_YBOT 0x1c9c
+#define MGAREG_YDST 0x1c90
+
+# define YA_ydst_MASK 0xff800000 /* bits 0-22 */
+# define YA_ydst_SHIFT 0
+# define YA_sellin_MASK 0x1fffffff /* bits 29-31 */
+# define YA_sellin_SHIFT 29
+
+#define MGAREG_YDSTLEN 0x1c88
+
+# define YDL_length_MASK 0xffff0000 /* bits 0-15 */
+# define YDL_length_SHIFT 0
+# define YDL_yval_MASK 0xffff /* bits 16-31 */
+# define YDL_yval_SHIFT 16
+
+#define MGAREG_YDSTORG 0x1c94
+#define MGAREG_YTOP 0x1c98
+#define MGAREG_ZORG 0x1c0c
+
+# define ZO_zorgmap_MASK 0xfffffffe /* bit 0 */
+# define ZO_zorgmap_fb 0x0
+# define ZO_zorgmap_sys 0x1
+# define ZO_zorgacc_MASK 0xfffffffd /* bit 1 */
+# define ZO_zorgacc_pci 0x0
+# define ZO_zorgacc_agp 0x2
+# define ZO_zorg_MASK 0x3 /* bits 2-31 */
+# define ZO_zorg_SHIFT 2
+
+
+
+
+/**************** (END) AUTOMATICLY GENERATED REGISTER FILE ******************/
+
+/* Copied from mga_drv.h kernel file.
+ */
+
+#define MGA_ILOAD_ALIGN 64
+#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
+
+#endif /* _MGAREGS_H_ */
+
diff --git a/src/mgarender.c b/src/mgarender.c
new file mode 100644
index 0000000..c151f79
--- /dev/null
+++ b/src/mgarender.c
@@ -0,0 +1,172 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgarender.c,v 1.4 2002/10/30 12:51:36 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+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
+ATI, VA LINUX SYSTEMS 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:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers. Use strip/fan hardware primitives where possible.
+ * Simulate missing primitives with indexed vertices.
+ */
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "imports.h"
+#include "mtypes.h"
+
+#include "tnl/t_context.h"
+
+#include "mgacontext.h"
+#include "mgatris.h"
+#include "mgastate.h"
+#include "mgaioctl.h"
+#include "mgavb.h"
+
+#define HAVE_POINTS 0
+#define HAVE_LINES 0
+#define HAVE_LINE_STRIPS 0
+#define HAVE_TRIANGLES 1
+#define HAVE_TRI_STRIPS 1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS 1
+#define HAVE_POLYGONS 0
+#define HAVE_QUADS 0
+#define HAVE_QUAD_STRIPS 0
+
+#define HAVE_ELTS 0 /* for now */
+
+static void mgaDmaPrimitive( GLcontext *ctx, GLenum prim )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint hwprim;
+
+ switch (prim) {
+ case GL_TRIANGLES:
+ hwprim = MGA_WA_TRIANGLES;
+ break;
+ case GL_TRIANGLE_STRIP:
+ if (mmesa->vertex_size == 8)
+ hwprim = MGA_WA_TRISTRIP_T0;
+ else
+ hwprim = MGA_WA_TRISTRIP_T0T1;
+ break;
+ case GL_TRIANGLE_FAN:
+ if (mmesa->vertex_size == 8)
+ hwprim = MGA_WA_TRIFAN_T0;
+ else
+ hwprim = MGA_WA_TRIFAN_T0T1;
+ break;
+ default:
+ return;
+ }
+
+ mgaRasterPrimitive( ctx, GL_TRIANGLES, hwprim );
+}
+
+
+#define LOCAL_VARS mgaContextPtr mmesa = MGA_CONTEXT(ctx)
+#define INIT( prim ) do { \
+ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
+ FLUSH_BATCH(mmesa); \
+ mgaDmaPrimitive( ctx, prim ); \
+} while (0)
+#define FLUSH() FLUSH_BATCH( mmesa )
+#define GET_CURRENT_VB_MAX_VERTS() \
+ 0 /* fix me */
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+ MGA_BUFFER_SIZE / (mmesa->vertex_size * 4)
+
+
+#define ALLOC_VERTS( nr ) \
+ mgaAllocDmaLow( mmesa, (nr) * mmesa->vertex_size * 4)
+#define EMIT_VERTS( ctx, j, nr, buf ) \
+ mga_emit_contiguous_verts(ctx, j, (j)+(nr), buf)
+
+
+#define TAG(x) mga_##x
+#include "tnl_dd/t_dd_dmatmp.h"
+
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+static GLboolean mga_run_render( GLcontext *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+
+ /* Don't handle clipping or indexed vertices or vertex manipulations.
+ */
+ if (mmesa->RenderIndex != 0 ||
+ !mga_validate_render( ctx, VB )) {
+ return GL_TRUE;
+ }
+
+ tnl->Driver.Render.Start( ctx );
+ mmesa->SetupNewInputs = ~0;
+
+ for (i = 0 ; i < VB->PrimitiveCount ; i++)
+ {
+ GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
+ GLuint start = VB->Primitive[i].start;
+ GLuint length = VB->Primitive[i].count;
+
+ if (!length)
+ continue;
+
+ mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
+ prim);
+ }
+
+ tnl->Driver.Render.Finish( ctx );
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+const struct tnl_pipeline_stage _mga_render_stage =
+{
+ "mga render",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ mga_run_render /* run */
+};
diff --git a/src/mgaspan.c b/src/mgaspan.c
new file mode 100644
index 0000000..05dcbb8
--- /dev/null
+++ b/src/mgaspan.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "mtypes.h"
+#include "mgadd.h"
+#include "mgacontext.h"
+#include "mgaspan.h"
+#include "mgaioctl.h"
+#include "swrast/swrast.h"
+
+#define DBG 0
+
+#define LOCAL_VARS \
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx); \
+ __DRIscreenPrivate *sPriv = mmesa->driScreen; \
+ driRenderbuffer *drb = (driRenderbuffer *) rb; \
+ const __DRIdrawablePrivate *dPriv = drb->dPriv; \
+ GLuint pitch = drb->pitch; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(sPriv->pFB + \
+ drb->offset + \
+ dPriv->x * drb->cpp + \
+ dPriv->y * pitch); \
+ GLuint p; \
+ (void) buf; (void) p
+
+
+
+#define LOCAL_DEPTH_VARS \
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx); \
+ __DRIscreenPrivate *sPriv = mmesa->driScreen; \
+ driRenderbuffer *drb = (driRenderbuffer *) rb; \
+ const __DRIdrawablePrivate *dPriv = drb->dPriv; \
+ GLuint pitch = drb->pitch; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(sPriv->pFB + \
+ drb->offset + \
+ dPriv->x * drb->cpp + \
+ dPriv->y * pitch)
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+#define HW_LOCK()
+
+/* FIXME could/should we use dPriv->numClipRects like the other drivers? */
+#define HW_CLIPLOOP() \
+ do { \
+ int _nc = mmesa->numClipRects; \
+ while (_nc--) { \
+ int minx = mmesa->pClipRects[_nc].x1 - mmesa->drawX; \
+ int miny = mmesa->pClipRects[_nc].y1 - mmesa->drawY; \
+ int maxx = mmesa->pClipRects[_nc].x2 - mmesa->drawX; \
+ int maxy = mmesa->pClipRects[_nc].y2 - mmesa->drawY;
+
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+
+#define HW_UNLOCK()
+
+
+
+#define Y_FLIP(_y) (height - _y - 1)
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_RGB
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_SHORT_5_6_5
+
+#define TAG(x) mga##x##_565
+#define TAG2(x,y) mga##x##_565##y
+#include "spantmp2.h"
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#define SPANTMP_PIXEL_FMT GL_BGRA
+#define SPANTMP_PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
+
+#define TAG(x) mga##x##_8888
+#define TAG2(x,y) mga##x##_8888##y
+#include "spantmp2.h"
+
+
+/* 16 bit depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLushort *)(buf + (_x)*2 + (_y)*pitch) = d;
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLushort *)(buf + (_x)*2 + (_y)*pitch);
+
+#define TAG(x) mga##x##_z16
+#include "depthtmp.h"
+
+
+
+
+/* 32 bit depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = d;
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint *)(buf + (_x)*4 + (_y)*pitch);
+
+#define TAG(x) mga##x##_z32
+#include "depthtmp.h"
+
+
+
+/* 24/8 bit interleaved depth/stencil functions
+ */
+#define WRITE_DEPTH( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + (_x)*4 + (_y)*pitch); \
+ tmp &= 0xff; \
+ tmp |= (d) << 8; \
+ *(GLuint *)(buf + (_x)*4 + (_y)*pitch) = tmp; \
+}
+
+#define READ_DEPTH( d, _x, _y ) { \
+ d = (*(GLuint *)(buf + (_x)*4 + (_y)*pitch) & ~0xff) >> 8; \
+}
+
+#define TAG(x) mga##x##_z24_s8
+#include "depthtmp.h"
+
+#define WRITE_STENCIL( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \
+ tmp &= 0xffffff00; \
+ tmp |= d & 0xff; \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \
+}
+
+#define READ_STENCIL( d, _x, _y ) \
+ d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xff;
+
+#define TAG(x) mga##x##_z24_s8
+#include "stenciltmp.h"
+
+
+static void
+mgaSpanRenderStart( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ FLUSH_BATCH( mmesa );
+ LOCK_HARDWARE_QUIESCENT( mmesa );
+}
+
+static void
+mgaSpanRenderFinish( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ _swrast_flush( ctx );
+ UNLOCK_HARDWARE( mmesa );
+}
+
+/**
+ * Initialize the driver callbacks for the read / write span functions.
+ *
+ * \bug
+ * To really support RGB888 and RGBA8888 visuals, we need separate read and
+ * write routines for 888 and 8888. We also need to determine whether or not
+ * the visual has destination alpha.
+ */
+void mgaDDInitSpanFuncs( GLcontext *ctx )
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+ swdd->SpanRenderStart = mgaSpanRenderStart;
+ swdd->SpanRenderFinish = mgaSpanRenderFinish;
+}
+
+
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+mgaSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
+{
+ if (drb->Base.InternalFormat == GL_RGBA) {
+ if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) {
+ mgaInitPointers_565(&drb->Base);
+ }
+ else {
+ mgaInitPointers_8888(&drb->Base);
+ }
+ }
+ else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16) {
+ mgaInitDepthPointers_z16(&drb->Base);
+ }
+ else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) {
+ mgaInitDepthPointers_z24_s8(&drb->Base);
+ }
+ else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT32) {
+ mgaInitDepthPointers_z32(&drb->Base);
+ }
+ else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) {
+ mgaInitStencilPointers_z24_s8(&drb->Base);
+ }
+}
diff --git a/src/mgaspan.h b/src/mgaspan.h
new file mode 100644
index 0000000..f133a51
--- /dev/null
+++ b/src/mgaspan.h
@@ -0,0 +1,40 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaspan.h,v 1.3 2002/10/30 12:51:36 alanh Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef _MGA_SPAN_H
+#define _MGA_SPAN_H
+
+#include "drirenderbuffer.h"
+
+extern void mgaDDInitSpanFuncs( GLcontext *ctx );
+
+extern void
+mgaSetSpanFunctions(driRenderbuffer *rb, const GLvisual *vis);
+
+
+#endif
diff --git a/src/mgastate.c b/src/mgastate.c
new file mode 100644
index 0000000..c20a76f
--- /dev/null
+++ b/src/mgastate.c
@@ -0,0 +1,1205 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "mtypes.h"
+#include "colormac.h"
+#include "dd.h"
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgadd.h"
+#include "mgastate.h"
+#include "mgatex.h"
+#include "mgavb.h"
+#include "mgatris.h"
+#include "mgaioctl.h"
+#include "mgaregs.h"
+
+#include "swrast/swrast.h"
+#include "vbo/vbo.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "xmlpool.h"
+#include "drirenderbuffer.h"
+
+
+static void updateSpecularLighting( GLcontext *ctx );
+
+static const GLuint mgarop_NoBLK[16] = {
+ DC_atype_rpl | 0x00000000, DC_atype_rstr | 0x00080000,
+ DC_atype_rstr | 0x00040000, DC_atype_rpl | 0x000c0000,
+ DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000,
+ DC_atype_rstr | 0x00060000, DC_atype_rstr | 0x000e0000,
+ DC_atype_rstr | 0x00010000, DC_atype_rstr | 0x00090000,
+ DC_atype_rstr | 0x00050000, DC_atype_rstr | 0x000d0000,
+ DC_atype_rpl | 0x00030000, DC_atype_rstr | 0x000b0000,
+ DC_atype_rstr | 0x00070000, DC_atype_rpl | 0x000f0000
+};
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLubyte refByte;
+ GLuint a;
+
+ CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+
+ switch ( func ) {
+ case GL_NEVER:
+ a = AC_atmode_alt;
+ refByte = 0;
+ break;
+ case GL_LESS:
+ a = AC_atmode_alt;
+ break;
+ case GL_GEQUAL:
+ a = AC_atmode_agte;
+ break;
+ case GL_LEQUAL:
+ a = AC_atmode_alte;
+ break;
+ case GL_GREATER:
+ a = AC_atmode_agt;
+ break;
+ case GL_NOTEQUAL:
+ a = AC_atmode_ane;
+ break;
+ case GL_EQUAL:
+ a = AC_atmode_ae;
+ break;
+ case GL_ALWAYS:
+ a = AC_atmode_noacmp;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte );
+}
+
+static void updateBlendLogicOp(GLcontext *ctx)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLboolean logicOp = RGBA_LOGICOP_ENABLED(ctx);
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+
+ mmesa->hw.blend_func_enable =
+ (ctx->Color.BlendEnabled && !logicOp) ? ~0 : 0;
+
+ FALLBACK( ctx, MGA_FALLBACK_BLEND,
+ ctx->Color.BlendEnabled && !logicOp &&
+ mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
+}
+
+static void mgaDDBlendEquationSeparate(GLcontext *ctx,
+ GLenum modeRGB, GLenum modeA)
+{
+ assert( modeRGB == modeA );
+ updateBlendLogicOp( ctx );
+}
+
+static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
+ GLenum dfactorRGB, GLenum sfactorA,
+ GLenum dfactorA )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint src;
+ GLuint dst;
+
+ switch (ctx->Color.BlendSrcRGB) {
+ case GL_ZERO:
+ src = AC_src_zero; break;
+ case GL_SRC_ALPHA:
+ src = AC_src_src_alpha; break;
+ case GL_ONE:
+ default: /* never happens */
+ src = AC_src_one; break;
+ case GL_DST_COLOR:
+ src = AC_src_dst_color; break;
+ case GL_ONE_MINUS_DST_COLOR:
+ src = AC_src_om_dst_color; break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ src = AC_src_om_src_alpha; break;
+ case GL_DST_ALPHA:
+ src = (ctx->Visual.alphaBits > 0)
+ ? AC_src_dst_alpha : AC_src_one;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ src = (ctx->Visual.alphaBits > 0)
+ ? AC_src_om_dst_alpha : AC_src_zero;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ src = (ctx->Visual.alphaBits > 0)
+ ? AC_src_src_alpha_sat : AC_src_zero;
+ break;
+ }
+
+ switch (ctx->Color.BlendDstRGB) {
+ case GL_SRC_ALPHA:
+ dst = AC_dst_src_alpha; break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dst = AC_dst_om_src_alpha; break;
+ default: /* never happens */
+ case GL_ZERO:
+ dst = AC_dst_zero; break;
+ case GL_ONE:
+ dst = AC_dst_one; break;
+ case GL_SRC_COLOR:
+ dst = AC_dst_src_color; break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dst = AC_dst_om_src_color; break;
+ case GL_DST_ALPHA:
+ dst = (ctx->Visual.alphaBits > 0)
+ ? AC_dst_dst_alpha : AC_dst_one;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dst = (ctx->Visual.alphaBits > 0)
+ ? AC_dst_om_dst_alpha : AC_dst_zero;
+ break;
+ }
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.blend_func = (src | dst);
+
+ FALLBACK( ctx, MGA_FALLBACK_BLEND,
+ ctx->Color.BlendEnabled && !RGBA_LOGICOP_ENABLED(ctx) &&
+ mmesa->hw.blend_func == (AC_src_src_alpha_sat | AC_dst_zero) );
+}
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ int zmode;
+
+ switch (func) {
+ case GL_NEVER:
+ /* can't do this in h/w, we'll use a s/w fallback */
+ FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test);
+
+ /* FALLTHROUGH */
+ case GL_ALWAYS:
+ zmode = DC_zmode_nozcmp; break;
+ case GL_LESS:
+ zmode = DC_zmode_zlt; break;
+ case GL_LEQUAL:
+ zmode = DC_zmode_zlte; break;
+ case GL_EQUAL:
+ zmode = DC_zmode_ze; break;
+ case GL_GREATER:
+ zmode = DC_zmode_zgt; break;
+ case GL_GEQUAL:
+ zmode = DC_zmode_zgte; break;
+ case GL_NOTEQUAL:
+ zmode = DC_zmode_zne; break;
+ default:
+ zmode = 0; break;
+ }
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.zmode &= DC_zmode_MASK;
+ mmesa->hw.zmode |= zmode;
+}
+
+static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.zmode &= DC_atype_MASK;
+ mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i;
+}
+
+
+static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ /* Select the Z depth. The ~ is used because the _MASK values in the
+ * MGA driver are used to mask OFF the selected bits. In this case,
+ * we want to mask off everything except the MA_zwidth bits.
+ */
+ switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
+ case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
+ case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
+ case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
+ default: return;
+ }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+
+static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if (pname == GL_FOG_COLOR) {
+ GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
+ (GLubyte)(ctx->Fog.Color[1]*255.0F),
+ (GLubyte)(ctx->Fog.Color[2]*255.0F));
+
+ MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);
+ mmesa->setup.fogcolor = color;
+ }
+}
+
+
+/* =============================================================
+ * Scissoring
+ */
+
+
+void mgaUpdateClipping(const GLcontext *ctx)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if (mmesa->driDrawable)
+ {
+ int x1 = mmesa->driDrawable->x + ctx->Scissor.X;
+ int y1 = mmesa->driDrawable->y + mmesa->driDrawable->h
+ - (ctx->Scissor.Y + ctx->Scissor.Height);
+ int x2 = x1 + ctx->Scissor.Width;
+ int y2 = y1 + ctx->Scissor.Height;
+
+ if (x1 < 0) x1 = 0;
+ if (y1 < 0) y1 = 0;
+ if (x2 < 0) x2 = 0;
+ if (y2 < 0) y2 = 0;
+
+ mmesa->scissor_rect.x1 = x1;
+ mmesa->scissor_rect.y1 = y1;
+ mmesa->scissor_rect.x2 = x2;
+ mmesa->scissor_rect.y2 = y2;
+
+ mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+ }
+}
+
+
+static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y,
+ GLsizei w, GLsizei h )
+{
+ if ( ctx->Scissor.Enabled ) {
+ FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */
+ mgaUpdateClipping( ctx );
+ }
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+
+#define _CULL_DISABLE 0
+#define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
+#define _CULL_POSITIVE (1<<11)
+
+static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ if (ctx->Polygon.CullFlag &&
+ ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK)
+ {
+ mmesa->hw.cull = _CULL_NEGATIVE;
+
+ if (ctx->Polygon.CullFaceMode == GL_FRONT)
+ mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+
+ if (ctx->Polygon.FrontFace != GL_CCW)
+ mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+
+ mmesa->hw.cull_dualtex = mmesa->hw.cull ^
+ (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
+ }
+ else {
+ mmesa->hw.cull = _CULL_DISABLE;
+ mmesa->hw.cull_dualtex = _CULL_DISABLE;
+ }
+}
+
+
+/* =============================================================
+ * Masks
+ */
+
+static void mgaDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+
+
+ GLuint mask = mgaPackColor(mgaScreen->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP]);
+
+ if (mgaScreen->cpp == 2)
+ mask = mask | (mask << 16);
+
+ if (mmesa->setup.plnwt != mask) {
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->setup.plnwt = mask;
+ }
+}
+
+
+/* =============================================================
+ * Polygon state
+ */
+
+static int mgaStipples[16] = {
+ 0xffff,
+ 0xa5a5,
+ 0x5a5a,
+ 0xa0a0,
+ 0x5050,
+ 0x0a0a,
+ 0x0505,
+ 0x8020,
+ 0x0401,
+ 0x1040,
+ 0x0208,
+ 0x0802,
+ 0x4010,
+ 0x0104,
+ 0x2080,
+ 0x0000
+};
+
+/**
+ * The MGA supports a subset of possible 4x4 stipples natively, GL
+ * wants 32x32. Fortunately stipple is usually a repeating pattern.
+ *
+ * \param ctx GL rendering context to be affected
+ * \param mask Pointer to the 32x32 stipple mask
+ */
+
+static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const GLubyte *m = mask;
+ GLubyte p[4];
+ int i,j,k;
+ int active = (ctx->Polygon.StippleFlag &&
+ mmesa->raster_primitive == GL_TRIANGLES);
+ GLuint stipple;
+
+ FLUSH_BATCH(mmesa);
+ mmesa->haveHwStipple = 0;
+
+ if (active) {
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ }
+
+ p[0] = mask[0] & 0xf; p[0] |= p[0] << 4;
+ p[1] = mask[4] & 0xf; p[1] |= p[1] << 4;
+ p[2] = mask[8] & 0xf; p[2] |= p[2] << 4;
+ p[3] = mask[12] & 0xf; p[3] |= p[3] << 4;
+
+ for (k = 0 ; k < 8 ; k++)
+ for (j = 0 ; j < 4; j++)
+ for (i = 0 ; i < 4 ; i++)
+ if (*m++ != p[j]) {
+ return;
+ }
+
+ stipple = ( ((p[0] & 0xf) << 0) |
+ ((p[1] & 0xf) << 4) |
+ ((p[2] & 0xf) << 8) |
+ ((p[3] & 0xf) << 12) );
+
+ for (i = 0 ; i < 16 ; i++)
+ if (mgaStipples[i] == stipple) {
+ mmesa->poly_stipple = i<<20;
+ mmesa->haveHwStipple = 1;
+ break;
+ }
+
+ if (active) {
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+}
+
+
+/* =============================================================
+ * Rendering attributes
+ *
+ * We really don't want to recalculate all this every time we bind a
+ * texture. These things shouldn't change all that often, so it makes
+ * sense to break them out of the core texture state update routines.
+ */
+
+static void updateSpecularLighting( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ unsigned int specen;
+
+ specen = NEED_SECONDARY_COLOR(ctx) ? TMC_specen_enable : 0;
+
+ if ( specen != mmesa->hw.specen ) {
+ mmesa->hw.specen = specen;
+ mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
+ }
+}
+
+
+/* =============================================================
+ * Materials
+ */
+
+
+static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
+ const GLfloat *param)
+{
+ if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+ FLUSH_BATCH( MGA_CONTEXT(ctx) );
+ updateSpecularLighting( ctx );
+ }
+}
+
+
+/* =============================================================
+ * Stencil
+ */
+
+
+static void
+mgaDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
+ GLuint mask)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint stencil;
+ GLuint stencilctl;
+
+ stencil = MGA_FIELD( S_sref, ref ) | MGA_FIELD( S_smsk, mask );
+ switch (func)
+ {
+ case GL_NEVER:
+ stencilctl = SC_smode_snever;
+ break;
+ case GL_LESS:
+ stencilctl = SC_smode_slt;
+ break;
+ case GL_LEQUAL:
+ stencilctl = SC_smode_slte;
+ break;
+ case GL_GREATER:
+ stencilctl = SC_smode_sgt;
+ break;
+ case GL_GEQUAL:
+ stencilctl = SC_smode_sgte;
+ break;
+ case GL_NOTEQUAL:
+ stencilctl = SC_smode_sne;
+ break;
+ case GL_EQUAL:
+ stencilctl = SC_smode_se;
+ break;
+ case GL_ALWAYS:
+ default:
+ stencilctl = SC_smode_salways;
+ break;
+ }
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
+ mmesa->hw.stencil |= stencil;
+ mmesa->hw.stencilctl &= SC_smode_MASK;
+ mmesa->hw.stencilctl |= stencilctl;
+}
+
+static void
+mgaDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.stencil &= S_swtmsk_MASK;
+ mmesa->hw.stencil |= MGA_FIELD( S_swtmsk, mask );
+}
+
+static void
+mgaDDStencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
+ GLenum zpass)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint stencilctl;
+
+ stencilctl = 0;
+ switch (ctx->Stencil.FailFunc[0])
+ {
+ case GL_KEEP:
+ stencilctl |= SC_sfailop_keep;
+ break;
+ case GL_ZERO:
+ stencilctl |= SC_sfailop_zero;
+ break;
+ case GL_REPLACE:
+ stencilctl |= SC_sfailop_replace;
+ break;
+ case GL_INCR:
+ stencilctl |= SC_sfailop_incrsat;
+ break;
+ case GL_DECR:
+ stencilctl |= SC_sfailop_decrsat;
+ break;
+ case GL_INCR_WRAP:
+ stencilctl |= SC_sfailop_incr;
+ break;
+ case GL_DECR_WRAP:
+ stencilctl |= SC_sfailop_decr;
+ break;
+ case GL_INVERT:
+ stencilctl |= SC_sfailop_invert;
+ break;
+ default:
+ break;
+ }
+
+ switch (ctx->Stencil.ZFailFunc[0])
+ {
+ case GL_KEEP:
+ stencilctl |= SC_szfailop_keep;
+ break;
+ case GL_ZERO:
+ stencilctl |= SC_szfailop_zero;
+ break;
+ case GL_REPLACE:
+ stencilctl |= SC_szfailop_replace;
+ break;
+ case GL_INCR:
+ stencilctl |= SC_szfailop_incrsat;
+ break;
+ case GL_DECR:
+ stencilctl |= SC_szfailop_decrsat;
+ break;
+ case GL_INCR_WRAP:
+ stencilctl |= SC_szfailop_incr;
+ break;
+ case GL_DECR_WRAP:
+ stencilctl |= SC_szfailop_decr;
+ break;
+ case GL_INVERT:
+ stencilctl |= SC_szfailop_invert;
+ break;
+ default:
+ break;
+ }
+
+ switch (ctx->Stencil.ZPassFunc[0])
+ {
+ case GL_KEEP:
+ stencilctl |= SC_szpassop_keep;
+ break;
+ case GL_ZERO:
+ stencilctl |= SC_szpassop_zero;
+ break;
+ case GL_REPLACE:
+ stencilctl |= SC_szpassop_replace;
+ break;
+ case GL_INCR:
+ stencilctl |= SC_szpassop_incrsat;
+ break;
+ case GL_DECR:
+ stencilctl |= SC_szpassop_decrsat;
+ break;
+ case GL_INCR_WRAP:
+ stencilctl |= SC_szpassop_incr;
+ break;
+ case GL_DECR_WRAP:
+ stencilctl |= SC_szpassop_decr;
+ break;
+ case GL_INVERT:
+ stencilctl |= SC_szpassop_invert;
+ break;
+ default:
+ break;
+ }
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK
+ & SC_szpassop_MASK);
+ mmesa->hw.stencilctl |= stencilctl;
+}
+
+
+/* =============================================================
+ * Window position and viewport transformation
+ */
+
+void mgaCalcViewport( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+ GLfloat *m = mmesa->hw_viewport;
+
+ /* See also mga_translate_vertex.
+ */
+ m[MAT_SX] = v[MAT_SX];
+ m[MAT_TX] = v[MAT_TX] + mmesa->drawX + SUBPIXEL_X;
+ m[MAT_SY] = - v[MAT_SY];
+ m[MAT_TY] = - v[MAT_TY] + mmesa->driDrawable->h + mmesa->drawY + SUBPIXEL_Y;
+ m[MAT_SZ] = v[MAT_SZ] * mmesa->depth_scale;
+ m[MAT_TZ] = v[MAT_TZ] * mmesa->depth_scale;
+
+ mmesa->SetupNewInputs = ~0;
+}
+
+static void mgaViewport( GLcontext *ctx,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ mgaCalcViewport( ctx );
+}
+
+static void mgaDepthRange( GLcontext *ctx,
+ GLclampd nearval, GLclampd farval )
+{
+ mgaCalcViewport( ctx );
+}
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void mgaDDClearColor(GLcontext *ctx,
+ const GLfloat color[4] )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLubyte c[4];
+ CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+ CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+
+ mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
+ c[0], c[1], c[2], c[3]);
+}
+
+
+/* Fallback to swrast for select and feedback.
+ */
+static void mgaRenderMode( GLcontext *ctx, GLenum mode )
+{
+ FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+}
+
+
+static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
+}
+
+
+static void mga_set_cliprects(mgaContextPtr mmesa)
+{
+ __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+
+ if ((mmesa->draw_buffer != MGA_FRONT)
+ || (driDrawable->numBackClipRects == 0)) {
+ if (driDrawable->numClipRects == 0) {
+ static drm_clip_rect_t zeroareacliprect = {0,0,0,0};
+ mmesa->numClipRects = 1;
+ mmesa->pClipRects = &zeroareacliprect;
+ } else {
+ mmesa->numClipRects = driDrawable->numClipRects;
+ mmesa->pClipRects = driDrawable->pClipRects;
+ }
+ mmesa->drawX = driDrawable->x;
+ mmesa->drawY = driDrawable->y;
+ } else {
+ mmesa->numClipRects = driDrawable->numBackClipRects;
+ mmesa->pClipRects = driDrawable->pBackClipRects;
+ mmesa->drawX = driDrawable->backX;
+ mmesa->drawY = driDrawable->backY;
+ }
+
+ mmesa->setup.dstorg = mmesa->drawOffset;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
+}
+
+
+void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
+{
+ __DRIdrawablePrivate *const driDrawable = mmesa->driDrawable;
+ __DRIdrawablePrivate *const driReadable = mmesa->driReadable;
+ drm_mga_sarea_t *sarea = mmesa->sarea;
+
+
+ mmesa->dirty_cliprects = 0;
+
+ driUpdateFramebufferSize(mmesa->glCtx, driDrawable);
+ if (driDrawable != driReadable) {
+ driUpdateFramebufferSize(mmesa->glCtx, driReadable);
+ }
+
+ mga_set_cliprects(mmesa);
+
+ sarea->req_drawable = driDrawable->draw;
+ sarea->req_draw_buffer = mmesa->draw_buffer;
+
+ mgaUpdateClipping( mmesa->glCtx );
+ mgaCalcViewport( mmesa->glCtx );
+}
+
+
+static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ FLUSH_BATCH( mmesa );
+
+ /*
+ * _DrawDestMask is easier to cope with than <mode>.
+ */
+ switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
+ case BUFFER_BIT_FRONT_LEFT:
+ mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
+ mmesa->draw_buffer = MGA_FRONT;
+ break;
+ case BUFFER_BIT_BACK_LEFT:
+ mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
+ mmesa->draw_buffer = MGA_BACK;
+ break;
+ default:
+ /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+ FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
+ return;
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mga_set_cliprects(mmesa);
+ FALLBACK(ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE);
+}
+
+
+static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
+{
+ /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+/* =============================================================
+ * State enable/disable
+ */
+
+
+static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ switch(cap) {
+ case GL_DITHER:
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ if (!ctx->Color.DitherFlag)
+ mmesa->setup.maccess |= MA_nodither_enable;
+ else
+ mmesa->setup.maccess &= ~MA_nodither_enable;
+ break;
+ case GL_LIGHTING:
+ case GL_COLOR_SUM_EXT:
+ FLUSH_BATCH( mmesa );
+ updateSpecularLighting( ctx );
+ break;
+ case GL_ALPHA_TEST:
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
+ break;
+ case GL_DEPTH_TEST:
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ FALLBACK (ctx, MGA_FALLBACK_DEPTH,
+ ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
+ break;
+
+ case GL_SCISSOR_TEST:
+ FLUSH_BATCH( mmesa );
+ mmesa->scissor = state;
+ mgaUpdateClipping( ctx );
+ break;
+
+ case GL_FOG:
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ if (ctx->Fog.Enabled)
+ mmesa->setup.maccess |= MA_fogen_enable;
+ else
+ mmesa->setup.maccess &= ~MA_fogen_enable;
+ break;
+ case GL_CULL_FACE:
+ mgaDDCullFaceFrontFace( ctx, 0 );
+ break;
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ if (state)
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+ break;
+
+ case GL_BLEND:
+ case GL_COLOR_LOGIC_OP:
+ updateBlendLogicOp( ctx );
+ break;
+
+ case GL_STENCIL_TEST:
+ MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
+ if (mmesa->hw_stencil) {
+ mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
+ }
+ else {
+ FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
+ }
+ default:
+ break;
+ }
+}
+
+
+/* =============================================================
+ */
+
+static void mgaDDPrintDirty( const char *msg, GLuint state )
+{
+ fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
+ msg,
+ (unsigned int) state,
+ (state & MGA_WAIT_AGE) ? "wait-age " : "",
+ (state & MGA_UPLOAD_TEX0IMAGE) ? "upload-tex0-img " : "",
+ (state & MGA_UPLOAD_TEX1IMAGE) ? "upload-tex1-img " : "",
+ (state & MGA_UPLOAD_CONTEXT) ? "upload-ctx " : "",
+ (state & MGA_UPLOAD_TEX0) ? "upload-tex0 " : "",
+ (state & MGA_UPLOAD_TEX1) ? "upload-tex1 " : "",
+ (state & MGA_UPLOAD_PIPE) ? "upload-pipe " : ""
+ );
+}
+
+/* Push the state into the sarea and/or texture memory.
+ */
+void mgaEmitHwStateLocked( mgaContextPtr mmesa )
+{
+ drm_mga_sarea_t *sarea = mmesa->sarea;
+ GLcontext * ctx = mmesa->glCtx;
+
+ if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
+ mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
+
+ if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
+ mmesa->setup.wflag = _CULL_DISABLE;
+ if (mmesa->raster_primitive == GL_TRIANGLES) {
+ if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
+ ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
+ mmesa->setup.wflag = mmesa->hw.cull_dualtex;
+ }
+ else {
+ mmesa->setup.wflag = mmesa->hw.cull;
+ }
+ }
+
+ mmesa->setup.stencil = mmesa->hw.stencil
+ & mmesa->hw.stencil_enable;
+ mmesa->setup.stencilctl = mmesa->hw.stencilctl
+ & mmesa->hw.stencil_enable;
+
+ /* If depth testing is not enabled, then use the no Z-compare / no
+ * Z-write mode. Otherwise, use whatever is set in hw.zmode.
+ */
+ mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
+ mmesa->setup.dwgctl |= (ctx->Depth.Test)
+ ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
+
+ mmesa->setup.dwgctl &= DC_bop_MASK;
+ mmesa->setup.dwgctl |= RGBA_LOGICOP_ENABLED(ctx)
+ ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
+
+ mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
+ & AC_atref_MASK & AC_alphasel_MASK;
+ mmesa->setup.alphactrl |=
+ (mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable) |
+ (mmesa->hw.blend_func & mmesa->hw.blend_func_enable) |
+ ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable) |
+ mmesa->hw.alpha_sel;
+
+ memcpy( &sarea->context_state, &mmesa->setup, sizeof(mmesa->setup));
+ }
+
+ if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
+ memcpy(&sarea->tex_state[0],
+ &mmesa->CurrentTexObj[0]->setup,
+ sizeof(sarea->tex_state[0]));
+ }
+
+ if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
+ memcpy(&sarea->tex_state[1],
+ &mmesa->CurrentTexObj[1]->setup,
+ sizeof(sarea->tex_state[1]));
+ }
+
+ if (mmesa->dirty & (MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1)) {
+ sarea->tex_state[0].texctl2 &= ~TMC_specen_enable;
+ sarea->tex_state[1].texctl2 &= ~TMC_specen_enable;
+ sarea->tex_state[0].texctl2 |= mmesa->hw.specen;
+ sarea->tex_state[1].texctl2 |= mmesa->hw.specen;
+ }
+
+ if (mmesa->dirty & MGA_UPLOAD_PIPE) {
+/* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
+ mmesa->sarea->warp_pipe = mmesa->vertex_format;
+ mmesa->sarea->vertsize = mmesa->vertex_size;
+ }
+
+ mmesa->sarea->dirty |= mmesa->dirty;
+ mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
+}
+
+/* =============================================================
+ */
+
+
+static void mgaDDValidateState( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ FLUSH_BATCH( mmesa );
+
+ if (mmesa->NewGLState & _NEW_TEXTURE) {
+ mgaUpdateTextureState(ctx);
+ }
+
+ if (!mmesa->Fallback) {
+ if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
+ mgaChooseVertexState( ctx );
+ }
+
+ if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
+ mgaChooseRenderState( ctx );
+ }
+ }
+
+ mmesa->NewGLState = 0;
+}
+
+
+static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _vbo_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ MGA_CONTEXT(ctx)->NewGLState |= new_state;
+}
+
+
+static void mgaRunPipeline( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ if (mmesa->NewGLState) {
+ mgaDDValidateState( ctx );
+ }
+
+ if (mmesa->dirty) {
+ mgaEmitHwStateLocked( mmesa );
+ }
+
+ _tnl_run_pipeline( ctx );
+}
+
+
+void mgaInitState( mgaContextPtr mmesa )
+{
+ mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+ GLcontext *ctx = mmesa->glCtx;
+
+ if (ctx->Visual.doubleBufferMode) {
+ /* use back buffer by default */
+ mmesa->draw_buffer = MGA_BACK;
+ mmesa->drawOffset = mmesa->mgaScreen->backOffset;
+ mmesa->readOffset = mmesa->mgaScreen->backOffset;
+ mmesa->setup.dstorg = mgaScreen->backOffset;
+ } else {
+ /* use front buffer by default */
+ mmesa->draw_buffer = MGA_FRONT;
+ mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
+ mmesa->readOffset = mmesa->mgaScreen->frontOffset;
+ mmesa->setup.dstorg = mgaScreen->frontOffset;
+ }
+
+ mmesa->setup.maccess = (MA_memreset_disable |
+ MA_fogen_disable |
+ MA_tlutload_disable |
+ MA_nodither_disable |
+ MA_dit555_disable);
+ if (driQueryOptioni (&mmesa->optionCache, "color_reduction") !=
+ DRI_CONF_COLOR_REDUCTION_DITHER)
+ mmesa->setup.maccess |= MA_nodither_enable;
+
+ switch (mmesa->mgaScreen->cpp) {
+ case 2:
+ mmesa->setup.maccess |= MA_pwidth_16;
+ break;
+ case 4:
+ mmesa->setup.maccess |= MA_pwidth_32;
+ break;
+ default:
+ fprintf( stderr, "Error: unknown cpp %d, exiting...\n",
+ mmesa->mgaScreen->cpp );
+ exit( 1 );
+ }
+
+ switch (mmesa->glCtx->Visual.depthBits) {
+ case 16:
+ mmesa->setup.maccess |= MA_zwidth_16;
+ break;
+ case 24:
+ mmesa->setup.maccess |= MA_zwidth_24;
+ break;
+ case 32:
+ mmesa->setup.maccess |= MA_zwidth_32;
+ break;
+ }
+
+ mmesa->hw.blend_func = AC_src_one | AC_dst_zero;
+ mmesa->hw.blend_func_enable = 0;
+ mmesa->hw.alpha_func = AC_atmode_noacmp | MGA_FIELD( AC_atref, 0x00 );
+ mmesa->hw.alpha_func_enable = 0;
+ mmesa->hw.rop = mgarop_NoBLK[ GL_COPY & 0x0f ];
+ mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
+ mmesa->hw.stencil = MGA_FIELD( S_sref, 0x00) | MGA_FIELD( S_smsk, 0xff ) |
+ MGA_FIELD( S_swtmsk, 0xff );
+ mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep
+ | SC_szfailop_keep | SC_szpassop_keep;
+ mmesa->hw.stencil_enable = 0;
+ mmesa->hw.cull = _CULL_DISABLE;
+ mmesa->hw.cull_dualtex = _CULL_DISABLE;
+ mmesa->hw.specen = 0;
+ mmesa->hw.alpha_sel = AC_alphasel_diffused;
+
+ mmesa->setup.dwgctl = (DC_opcod_trap |
+ DC_linear_xy |
+ DC_solid_disable |
+ DC_arzero_disable |
+ DC_sgnzero_disable |
+ DC_shftzero_enable |
+ MGA_FIELD( DC_bop, 0xC ) |
+ MGA_FIELD( DC_trans, 0x0 ) |
+ DC_bltmod_bmonolef |
+ DC_pattern_disable |
+ DC_transc_disable |
+ DC_clipdis_disable);
+
+ mmesa->setup.plnwt = ~0;
+ mmesa->setup.alphactrl = (AC_amode_alpha_channel |
+ AC_astipple_disable |
+ AC_aten_disable);
+
+ mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
+ (GLubyte)(ctx->Fog.Color[1]*255.0F),
+ (GLubyte)(ctx->Fog.Color[2]*255.0F));
+
+ mmesa->setup.wflag = 0;
+ mmesa->setup.tdualstage0 = 0;
+ mmesa->setup.tdualstage1 = 0;
+ mmesa->setup.fcol = 0;
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+
+ mmesa->envcolor[0] = 0;
+ mmesa->envcolor[1] = 0;
+}
+
+
+void mgaDDInitStateFuncs( GLcontext *ctx )
+{
+ ctx->Driver.UpdateState = mgaDDInvalidateState;
+ ctx->Driver.Enable = mgaDDEnable;
+ ctx->Driver.LightModelfv = mgaDDLightModelfv;
+ ctx->Driver.AlphaFunc = mgaDDAlphaFunc;
+ ctx->Driver.BlendEquationSeparate = mgaDDBlendEquationSeparate;
+ ctx->Driver.BlendFuncSeparate = mgaDDBlendFuncSeparate;
+ ctx->Driver.DepthFunc = mgaDDDepthFunc;
+ ctx->Driver.DepthMask = mgaDDDepthMask;
+ ctx->Driver.Fogfv = mgaDDFogfv;
+ ctx->Driver.Scissor = mgaDDScissor;
+ ctx->Driver.CullFace = mgaDDCullFaceFrontFace;
+ ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
+ ctx->Driver.ColorMask = mgaDDColorMask;
+
+ ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
+ ctx->Driver.ReadBuffer = mgaDDReadBuffer;
+ ctx->Driver.ClearColor = mgaDDClearColor;
+ ctx->Driver.ClearDepth = mgaDDClearDepth;
+ ctx->Driver.LogicOpcode = mgaDDLogicOp;
+
+ ctx->Driver.PolygonStipple = mgaDDPolygonStipple;
+
+ ctx->Driver.StencilFuncSeparate = mgaDDStencilFuncSeparate;
+ ctx->Driver.StencilMaskSeparate = mgaDDStencilMaskSeparate;
+ ctx->Driver.StencilOpSeparate = mgaDDStencilOpSeparate;
+
+ ctx->Driver.DepthRange = mgaDepthRange;
+ ctx->Driver.Viewport = mgaViewport;
+ ctx->Driver.RenderMode = mgaRenderMode;
+
+ ctx->Driver.ClearIndex = 0;
+ ctx->Driver.IndexMask = 0;
+
+ TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
+}
diff --git a/src/mgastate.h b/src/mgastate.h
new file mode 100644
index 0000000..afbe0aa
--- /dev/null
+++ b/src/mgastate.h
@@ -0,0 +1,39 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.h,v 1.5 2002/10/30 12:51:36 alanh Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef _MGA_STATE_H
+#define _MGA_STATE_H
+
+extern void mgaInitState( mgaContextPtr mmesa );
+extern void mgaDDInitStateFuncs(GLcontext *ctx);
+extern void mgaUpdateClipping(const GLcontext *ctx);
+extern void mgaUpdateCull( GLcontext *ctx );
+extern void mgaCalcViewport( GLcontext *ctx );
+extern void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers );
+
+#endif
diff --git a/src/mgatex.c b/src/mgatex.c
new file mode 100644
index 0000000..a7d7431
--- /dev/null
+++ b/src/mgatex.c
@@ -0,0 +1,541 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
+
+#include "glheader.h"
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgatex.h"
+#include "mgaregs.h"
+#include "mgatris.h"
+#include "mgaioctl.h"
+
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "macros.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+#include "texobj.h"
+
+#include "swrast/swrast.h"
+
+#include "xmlpool.h"
+
+/**
+ * Set the texture wrap modes.
+ * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
+ *
+ * \param t Texture object whose wrap modes are to be set
+ * \param swrap Wrap mode for the \a s texture coordinate
+ * \param twrap Wrap mode for the \a t texture coordinate
+ */
+
+static void
+mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
+{
+ GLboolean is_clamp = GL_FALSE;
+ GLboolean is_clamp_to_edge = GL_FALSE;
+
+ t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
+ t->setup.texctl2 &= (TMC_borderen_MASK);
+
+ switch( swrap ) {
+ case GL_REPEAT:
+ break;
+ case GL_CLAMP:
+ t->setup.texctl |= TMC_clampu_enable;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->setup.texctl |= TMC_clampu_enable;
+ is_clamp_to_edge = GL_TRUE;
+ break;
+ default:
+ _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
+ }
+
+ switch( twrap ) {
+ case GL_REPEAT:
+ break;
+ case GL_CLAMP:
+ t->setup.texctl |= TMC_clampv_enable;
+ is_clamp = GL_TRUE;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ t->setup.texctl |= TMC_clampv_enable;
+ is_clamp_to_edge = GL_TRUE;
+ break;
+ default:
+ _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
+ }
+
+ if ( is_clamp ) {
+ t->setup.texctl2 |= TMC_borderen_enable;
+ }
+
+ t->border_fallback = (is_clamp && is_clamp_to_edge);
+}
+
+
+/**
+ * Set the texture magnification and minification modes.
+ *
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
+ */
+
+static void
+mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
+{
+ GLuint val = 0;
+
+ switch (minf) {
+ case GL_NEAREST: val = TF_minfilter_nrst; break;
+ case GL_LINEAR: val = TF_minfilter_bilin; break;
+ case GL_NEAREST_MIPMAP_NEAREST: val = TF_minfilter_mm1s; break;
+ case GL_LINEAR_MIPMAP_NEAREST: val = TF_minfilter_mm4s; break;
+ case GL_NEAREST_MIPMAP_LINEAR: val = TF_minfilter_mm2s; break;
+ case GL_LINEAR_MIPMAP_LINEAR: val = TF_minfilter_mm8s; break;
+ default: val = TF_minfilter_nrst; break;
+ }
+
+ switch (magf) {
+ case GL_NEAREST: val |= TF_magfilter_nrst; break;
+ case GL_LINEAR: val |= TF_magfilter_bilin; break;
+ default: val |= TF_magfilter_nrst; break;
+ }
+
+ /* See OpenGL 1.2 specification */
+ if (magf == GL_LINEAR && (minf == GL_NEAREST_MIPMAP_NEAREST ||
+ minf == GL_NEAREST_MIPMAP_LINEAR)) {
+ val |= MGA_FIELD( TF_fthres, 0x20 ); /* c = 0.5 */
+ } else {
+ val |= MGA_FIELD( TF_fthres, 0x10 ); /* c = 0 */
+ }
+
+
+ /* Mask off the bits for the fields we are setting. Remember, the MGA mask
+ * defines have 0s for the bits in the named fields. This is the opposite
+ * of most of the other drivers.
+ */
+
+ t->setup.texfilter &= (TF_minfilter_MASK &
+ TF_magfilter_MASK &
+ TF_fthres_MASK);
+ t->setup.texfilter |= val;
+}
+
+static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
+{
+ t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0],
+ color[1], color[2] );
+}
+
+
+static const struct gl_texture_format *
+mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+ GLenum format, GLenum type )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ const GLboolean do32bpt =
+ ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32 );
+ const GLboolean force16bpt =
+ ( mmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
+ (void) format;
+
+ switch ( internalFormat ) {
+ case 4:
+ case GL_RGBA:
+ case GL_COMPRESSED_RGBA:
+ switch ( type ) {
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return &_mesa_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return &_mesa_texformat_argb1555;
+ default:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+ }
+
+ case 3:
+ case GL_RGB:
+ case GL_COMPRESSED_RGB:
+ switch ( type ) {
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return &_mesa_texformat_argb4444;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return &_mesa_texformat_argb1555;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return &_mesa_texformat_rgb565;
+ default:
+ return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+ }
+
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return !force16bpt ?
+ &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
+
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444;
+
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return !force16bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
+
+ case GL_RGB5:
+ case GL_RGB4:
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb565;
+
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case GL_COMPRESSED_ALPHA:
+ /* FIXME: This will report incorrect component sizes... */
+ return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444;
+
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_COMPRESSED_LUMINANCE:
+ /* FIXME: This will report incorrect component sizes... */
+ return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_rgb565;
+
+ 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:
+ /* FIXME: This will report incorrect component sizes... */
+ return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444;
+
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case GL_COMPRESSED_INTENSITY:
+ /* FIXME: This will report incorrect component sizes... */
+ return MGA_IS_G400(mmesa) ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444;
+
+ case GL_YCBCR_MESA:
+ if (MGA_IS_G400(mmesa) &&
+ (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+ type == GL_UNSIGNED_BYTE))
+ return &_mesa_texformat_ycbcr;
+ else
+ return &_mesa_texformat_ycbcr_rev;
+
+ 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;
+
+ default:
+ _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
+ return NULL;
+ }
+
+ return NULL; /* never get here */
+}
+
+
+
+
+/**
+ * Allocate space for and load the mesa images into the texture memory block.
+ * This will happen before drawing with a new texture, or drawing with a
+ * texture after it was swapped out or teximaged again.
+ */
+
+static mgaTextureObjectPtr
+mgaAllocTexObj( struct gl_texture_object *tObj )
+{
+ mgaTextureObjectPtr t;
+
+
+ t = CALLOC( sizeof( *t ) );
+ tObj->DriverData = t;
+ if ( t != NULL ) {
+ /* Initialize non-image-dependent parts of the state:
+ */
+ t->base.tObj = tObj;
+
+ t->setup.texctl = TMC_takey_1 | TMC_tamask_0;
+ t->setup.texctl2 = TMC_ckstransdis_enable;
+ t->setup.texfilter = TF_filteralpha_enable | TF_uvoffset_OGL;
+
+ t->border_fallback = GL_FALSE;
+ t->texenv_fallback = GL_FALSE;
+
+ make_empty_list( & t->base );
+
+ mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
+ mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+ mgaSetTexBorderColor( t, tObj->_BorderChan );
+ }
+
+ return( t );
+}
+
+
+static void mgaTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+ switch( pname ) {
+ case GL_TEXTURE_ENV_COLOR: {
+ GLubyte c[4];
+
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+ mmesa->envcolor[unit] = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
+ break;
+ }
+ }
+}
+
+
+static void mgaTexImage2D( 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 )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ if ( t != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) mgaAllocTexObj( texObj );
+ if ( t == NULL ) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+ return;
+ }
+ }
+
+ _mesa_store_teximage2d( ctx, target, level, internalFormat,
+ width, height, border, format, type,
+ pixels, packing, texObj, texImage );
+ level -= t->firstLevel;
+ if (level >= 0)
+ t->dirty_images[0] |= (1UL << level);
+}
+
+static void mgaTexSubImage2D( 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 )
+{
+ driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+ assert( t ); /* this _should_ be true */
+ if ( t != NULL ) {
+ driSwapOutTextureObject( t );
+ }
+ else {
+ t = (driTextureObject *) mgaAllocTexObj( texObj );
+ if ( t == NULL ) {
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+ return;
+ }
+ }
+
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+ height, format, type, pixels, packing, texObj,
+ texImage);
+ level -= t->firstLevel;
+ if (level >= 0)
+ t->dirty_images[0] |= (1UL << level);
+}
+
+
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
+ */
+
+static void
+mgaTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+
+ /* If we don't have a hardware texture, it will be automatically
+ * created with current state before it is used, so we don't have
+ * to do anything now
+ */
+ if ( (t == NULL) ||
+ (target != GL_TEXTURE_2D &&
+ target != GL_TEXTURE_RECTANGLE_NV) ) {
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ driSwapOutTextureObject( (driTextureObject *) t );
+ /* FALLTHROUGH */
+ case GL_TEXTURE_MAG_FILTER:
+ FLUSH_BATCH(mmesa);
+ mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ FLUSH_BATCH(mmesa);
+ mgaSetTexWrapping(t,tObj->WrapS,tObj->WrapT);
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ FLUSH_BATCH(mmesa);
+ mgaSetTexBorderColor(t, tObj->_BorderChan);
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ /* This isn't the most efficient solution but there doesn't appear to
+ * be a nice alternative. Since there's no LOD clamping,
+ * we just have to rely on loading the right subset of mipmap levels
+ * to simulate a clamped LOD.
+ */
+ driSwapOutTextureObject( (driTextureObject *) t );
+ break;
+
+ default:
+ return;
+ }
+}
+
+
+static void
+mgaBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj )
+{
+ assert( (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_NV) ||
+ (tObj->DriverData != NULL) );
+}
+
+
+static void
+mgaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ driTextureObject * t = (driTextureObject *) tObj->DriverData;
+
+ if ( t ) {
+ if ( mmesa ) {
+ FLUSH_BATCH( mmesa );
+ }
+
+ driDestroyTextureObject( t );
+ }
+
+ /* 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.
+ * Note: we could use containment here to 'derive' the driver-specific
+ * texture object from the core mesa gl_texture_object. Not done at this time.
+ */
+static struct gl_texture_object *
+mgaNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
+{
+ struct gl_texture_object *obj;
+ obj = _mesa_new_texture_object(ctx, name, target);
+ mgaAllocTexObj( obj );
+ return obj;
+}
+
+
+void
+mgaInitTextureFuncs( struct dd_function_table *functions )
+{
+ functions->ChooseTextureFormat = mgaChooseTextureFormat;
+ functions->TexImage2D = mgaTexImage2D;
+ functions->TexSubImage2D = mgaTexSubImage2D;
+ functions->BindTexture = mgaBindTexture;
+ functions->NewTextureObject = mgaNewTextureObject;
+ functions->DeleteTexture = mgaDeleteTexture;
+ functions->IsTextureResident = driIsTextureResident;
+ functions->TexEnv = mgaTexEnv;
+ functions->TexParameter = mgaTexParameter;
+}
diff --git a/src/mgatex.h b/src/mgatex.h
new file mode 100644
index 0000000..fb7ffcf
--- /dev/null
+++ b/src/mgatex.h
@@ -0,0 +1,51 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.h,v 1.7 2002/10/30 12:51:36 alanh Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef MGATEX_INC
+#define MGATEX_INC
+
+#include "mgacontext.h"
+
+typedef struct mga_texture_object_s *mgaTextureObjectPtr;
+
+
+/* Called before a primitive is rendered to make sure the texture
+ * state is properly setup. Texture residence is checked later
+ * when we grab the lock.
+ */
+void mgaUpdateTextureState( GLcontext *ctx );
+
+int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t );
+
+void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t );
+
+void mgaInitTextureFuncs( struct dd_function_table *functions );
+
+GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit );
+
+#endif
diff --git a/src/mgatexmem.c b/src/mgatexmem.c
new file mode 100644
index 0000000..1874333
--- /dev/null
+++ b/src/mgatexmem.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatexmem.c,v 1.7 2002/10/30 12:51:36 alanh Exp $ */
+
+#include "glheader.h"
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgatex.h"
+#include "mgaregs.h"
+#include "mgaioctl.h"
+#include "mga_xmesa.h"
+
+#include "imports.h"
+#include "simple_list.h"
+
+/**
+ * Destroy any device-dependent state associated with the texture. This may
+ * include NULLing out hardware state that points to the texture.
+ */
+void
+mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
+{
+ unsigned i;
+
+
+ /* See if it was the driver's current object.
+ */
+
+ if ( mmesa != NULL )
+ {
+ if ( t->age > mmesa->dirtyAge )
+ mmesa->dirtyAge = t->age;
+
+ for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ )
+ {
+ if ( t == mmesa->CurrentTexObj[ i ] ) {
+ mmesa->CurrentTexObj[ i ] = NULL;
+ }
+ }
+ }
+}
+
+
+/**
+ * Upload a texture image from system memory to either on-card or AGP
+ * memory. Uploads to on-card memory are performed using an ILOAD operation.
+ * This is used for both initial loading of the entire image, and texSubImage
+ * updates.
+ *
+ * Performed with the hardware lock held.
+ *
+ * Even though this function is named "upload subimage," the entire image
+ * is uploaded.
+ *
+ * \param mmesa Driver context.
+ * \param t Texture to be uploaded.
+ * \param hwlevel Mipmap level of the texture to be uploaded.
+ *
+ * \bug As mentioned above, this fuction actually copies the entier mipmap
+ * level. There should be a version of this function that performs
+ * sub-rectangle uploads. This will perform quite a bit better if only
+ * a small portion of a larger texture has been updated. Care would
+ * need to be take with such an implementation once glCopyTexImage has
+ * been hardware accelerated.
+ */
+static void mgaUploadSubImage( mgaContextPtr mmesa,
+ mgaTextureObjectPtr t, GLint hwlevel )
+{
+ struct gl_texture_image * texImage;
+ unsigned offset;
+ unsigned texelBytes;
+ unsigned length;
+ const int level = hwlevel + t->base.firstLevel;
+
+
+ if ( (hwlevel < 0)
+ || (hwlevel >= (MGA_IS_G200(mmesa)
+ ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS)) ) {
+ fprintf( stderr, "[%s:%d] level = %d\n", __FILE__, __LINE__, level );
+ return;
+ }
+
+ texImage = t->base.tObj->Image[0][level];
+ if ( texImage == NULL ) {
+ fprintf( stderr, "[%s:%d] Image[%d] = NULL\n", __FILE__, __LINE__,
+ level );
+ return;
+ }
+
+
+ if (texImage->Data == NULL) {
+ fprintf(stderr, "null texture image data tObj %p level %d\n",
+ (void *) t->base.tObj, level);
+ return;
+ }
+
+
+ /* find the proper destination offset for this level */
+ if ( MGA_IS_G200(mmesa) ) {
+ offset = (t->base.memBlock->ofs + t->offsets[hwlevel]);
+ }
+ else {
+ unsigned i;
+
+ offset = t->base.memBlock->ofs;
+ for ( i = 0 ; i < hwlevel ; i++ ) {
+ offset += (t->offsets[1] >> (i * 2));
+ }
+ }
+
+
+ /* Copy the texture from system memory to a memory space that can be
+ * directly used by the hardware for texturing.
+ */
+
+ texelBytes = texImage->TexFormat->TexelBytes;
+ length = texImage->Width * texImage->Height * texelBytes;
+ if ( t->base.heap->heapId == MGA_CARD_HEAP ) {
+ unsigned tex_offset = 0;
+ unsigned to_copy;
+
+
+ /* We may not be able to upload the entire texture in one batch due to
+ * register limits or dma buffer limits. Split the copy up into maximum
+ * sized chunks.
+ */
+
+ offset += mmesa->mgaScreen->textureOffset[ t->base.heap->heapId ];
+ while ( length != 0 ) {
+ mgaGetILoadBufferLocked( mmesa );
+
+ /* The kernel ILOAD ioctl requires that the lenght be an even multiple
+ * of MGA_ILOAD_ALIGN.
+ */
+ length = ((length) + MGA_ILOAD_MASK) & ~MGA_ILOAD_MASK;
+
+ to_copy = MIN2( length, MGA_BUFFER_SIZE );
+ (void) memcpy( mmesa->iload_buffer->address,
+ (GLubyte *) texImage->Data + tex_offset, to_copy );
+
+ if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
+ fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
+ __FILE__, __LINE__,
+ (long) (offset + tex_offset),
+ to_copy );
+
+ mgaFireILoadLocked( mmesa, offset + tex_offset, to_copy );
+ tex_offset += to_copy;
+ length -= to_copy;
+ }
+ } else {
+ /* FIXME: the sync for direct copy reduces speed.. */
+ /* This works, is slower for uploads to card space and needs
+ * additional synchronization with the dma stream.
+ */
+
+ UPDATE_LOCK(mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT);
+
+ memcpy( mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + offset,
+ texImage->Data, length );
+
+ if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
+ fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
+ __FILE__, __LINE__,
+ (long) (mmesa->mgaScreen->texVirtual[t->base.heap->heapId]
+ + offset),
+ length);
+ }
+}
+
+
+/**
+ * Upload the texture images associated with texture \a t. This might
+ * require the allocation of texture memory.
+ *
+ * \param mmesa Context pointer
+ * \param t Texture to be uploaded
+ */
+
+int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t )
+{
+ int i;
+ int ofs;
+
+
+ if ( (t == NULL) || (t->base.totalSize == 0) )
+ return 0;
+
+ LOCK_HARDWARE( mmesa );
+
+ if (t->base.memBlock == NULL ) {
+ int heap;
+
+ heap = driAllocateTexture( mmesa->texture_heaps, mmesa->nr_heaps,
+ (driTextureObject *) t );
+ if ( heap == -1 ) {
+ UNLOCK_HARDWARE( mmesa );
+ return -1;
+ }
+
+ ofs = mmesa->mgaScreen->textureOffset[ heap ]
+ + t->base.memBlock->ofs;
+
+ if ( MGA_IS_G200(mmesa) ) {
+ t->setup.texorg = ofs;
+ t->setup.texorg1 = ofs + t->offsets[1];
+ t->setup.texorg2 = ofs + t->offsets[2];
+ t->setup.texorg3 = ofs + t->offsets[3];
+ t->setup.texorg4 = ofs + t->offsets[4];
+ }
+ else {
+ t->setup.texorg = ofs | TO_texorgoffsetsel;
+ t->setup.texorg1 = t->offsets[1];
+ t->setup.texorg2 = 0;
+ t->setup.texorg3 = 0;
+ t->setup.texorg4 = 0;
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ }
+
+ /* Let the world know we've used this memory recently.
+ */
+ driUpdateTextureLRU( (driTextureObject *) t );
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
+ fprintf(stderr, "[%s:%d] dispatch age: %d age freed memory: %d\n",
+ __FILE__, __LINE__,
+ GET_DISPATCH_AGE(mmesa), mmesa->dirtyAge);
+
+ if (mmesa->dirtyAge >= GET_DISPATCH_AGE(mmesa))
+ mgaWaitAgeLocked( mmesa, mmesa->dirtyAge );
+
+ if (t->base.dirty_images[0]) {
+ const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+
+ if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
+ fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n",
+ __FILE__, __LINE__, t->base.dirty_images[0] );
+
+ for (i = 0 ; i < numLevels ; i++) {
+ if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) {
+ mgaUploadSubImage( mmesa, t, i );
+ }
+ }
+ t->base.dirty_images[0] = 0;
+ }
+
+
+ UNLOCK_HARDWARE( mmesa );
+
+ return 0;
+}
diff --git a/src/mgatris.c b/src/mgatris.c
new file mode 100644
index 0000000..2b7ea05
--- /dev/null
+++ b/src/mgatris.c
@@ -0,0 +1,912 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.c,v 1.10 2002/10/30 12:51:36 alanh Exp $ */
+
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgaioctl.h"
+#include "mgatris.h"
+#include "mgavb.h"
+#include "mgastate.h"
+
+
+static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim );
+
+/***********************************************************************
+ * Functions to draw basic primitives *
+ ***********************************************************************/
+
+
+#if defined (USE_X86_ASM)
+#define EMIT_VERT( j, vb, vertex_size, v ) \
+do { int __tmp; \
+ __asm__ __volatile__( "rep ; movsl" \
+ : "=%c" (j), "=D" (vb), "=S" (__tmp) \
+ : "0" (vertex_size), \
+ "D" ((long)vb), \
+ "S" ((long)v)); \
+} while (0)
+#else
+#define EMIT_VERT( j, vb, vertex_size, v ) \
+do { \
+ for ( j = 0 ; j < vertex_size ; j++ ) \
+ vb[j] = (v)->ui[j]; \
+ vb += vertex_size; \
+} while (0)
+#endif
+
+static void __inline__ mga_draw_triangle( mgaContextPtr mmesa,
+ mgaVertexPtr v0,
+ mgaVertexPtr v1,
+ mgaVertexPtr v2 )
+{
+ GLuint vertex_size = mmesa->vertex_size;
+ GLuint *vb = mgaAllocDmaLow( mmesa, 3 * 4 * vertex_size );
+ int j;
+
+ EMIT_VERT( j, vb, vertex_size, v0 );
+ EMIT_VERT( j, vb, vertex_size, v1 );
+ EMIT_VERT( j, vb, vertex_size, v2 );
+}
+
+
+static void __inline__ mga_draw_quad( mgaContextPtr mmesa,
+ mgaVertexPtr v0,
+ mgaVertexPtr v1,
+ mgaVertexPtr v2,
+ mgaVertexPtr v3 )
+{
+ GLuint vertex_size = mmesa->vertex_size;
+ GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size );
+ int j;
+
+ EMIT_VERT( j, vb, vertex_size, v0 );
+ EMIT_VERT( j, vb, vertex_size, v1 );
+ EMIT_VERT( j, vb, vertex_size, v3 );
+ EMIT_VERT( j, vb, vertex_size, v1 );
+ EMIT_VERT( j, vb, vertex_size, v2 );
+ EMIT_VERT( j, vb, vertex_size, v3 );
+}
+
+
+static __inline__ void mga_draw_point( mgaContextPtr mmesa,
+ mgaVertexPtr tmp )
+{
+ GLfloat sz = mmesa->glCtx->Point._Size * .5;
+ int vertex_size = mmesa->vertex_size;
+ GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size );
+ int j;
+
+#if 0
+ v0->v.x += PNT_X_OFFSET - TRI_X_OFFSET;
+ v0->v.y += PNT_Y_OFFSET - TRI_Y_OFFSET;
+#endif
+
+ /* Draw a point as two triangles.
+ */
+ *(float *)&vb[0] = tmp->v.x - sz;
+ *(float *)&vb[1] = tmp->v.y - sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = tmp->v.x + sz;
+ *(float *)&vb[1] = tmp->v.y - sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = tmp->v.x + sz;
+ *(float *)&vb[1] = tmp->v.y + sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = tmp->v.x + sz;
+ *(float *)&vb[1] = tmp->v.y + sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = tmp->v.x - sz;
+ *(float *)&vb[1] = tmp->v.y + sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = tmp->v.x - sz;
+ *(float *)&vb[1] = tmp->v.y - sz;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = tmp->ui[j];
+
+#if 0
+ v0->v.x -= PNT_X_OFFSET - TRI_X_OFFSET;
+ v0->v.y -= PNT_Y_OFFSET - TRI_Y_OFFSET;
+#endif
+}
+
+
+static __inline__ void mga_draw_line( mgaContextPtr mmesa,
+ mgaVertexPtr v0,
+ mgaVertexPtr v1 )
+{
+ GLuint vertex_size = mmesa->vertex_size;
+ GLuint *vb = mgaAllocDmaLow( mmesa, 6 * 4 * vertex_size );
+ GLfloat dx, dy, ix, iy;
+ GLfloat width = mmesa->glCtx->Line._Width;
+ GLint j;
+
+#if 0
+ v0->v.x += LINE_X_OFFSET - TRI_X_OFFSET;
+ v0->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET;
+ v1->v.x += LINE_X_OFFSET - TRI_X_OFFSET;
+ v1->v.y += LINE_Y_OFFSET - TRI_Y_OFFSET;
+#endif
+
+ dx = v0->v.x - v1->v.x;
+ dy = v0->v.y - v1->v.y;
+
+ ix = width * .5; iy = 0;
+ if (dx * dx > dy * dy) {
+ iy = ix; ix = 0;
+ }
+
+ *(float *)&vb[0] = v0->v.x - ix;
+ *(float *)&vb[1] = v0->v.y - iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v0->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = v1->v.x + ix;
+ *(float *)&vb[1] = v1->v.y + iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v1->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = v0->v.x + ix;
+ *(float *)&vb[1] = v0->v.y + iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v0->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = v0->v.x - ix;
+ *(float *)&vb[1] = v0->v.y - iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v0->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = v1->v.x - ix;
+ *(float *)&vb[1] = v1->v.y - iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v1->ui[j];
+ vb += vertex_size;
+
+ *(float *)&vb[0] = v1->v.x + ix;
+ *(float *)&vb[1] = v1->v.y + iy;
+ for (j = 2 ; j < vertex_size ; j++)
+ vb[j] = v1->ui[j];
+ vb += vertex_size;
+
+#if 0
+ v0->v.x -= LINE_X_OFFSET - TRI_X_OFFSET;
+ v0->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
+ v1->v.x -= LINE_X_OFFSET - TRI_X_OFFSET;
+ v1->v.y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
+#endif
+}
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define TRI( a, b, c ) \
+do { \
+ if (DO_FALLBACK) \
+ mmesa->draw_tri( mmesa, a, b, c ); \
+ else \
+ mga_draw_triangle( mmesa, a, b, c ); \
+} while (0)
+
+#define QUAD( a, b, c, d ) \
+do { \
+ if (DO_FALLBACK) { \
+ mmesa->draw_tri( mmesa, a, b, d ); \
+ mmesa->draw_tri( mmesa, b, c, d ); \
+ } else { \
+ mga_draw_quad( mmesa, a, b, c, d ); \
+ } \
+} while (0)
+
+#define LINE( v0, v1 ) \
+do { \
+ if (DO_FALLBACK) \
+ mmesa->draw_line( mmesa, v0, v1 ); \
+ else { \
+ mga_draw_line( mmesa, v0, v1 ); \
+ } \
+} while (0)
+
+#define POINT( v0 ) \
+do { \
+ if (DO_FALLBACK) \
+ mmesa->draw_point( mmesa, v0 ); \
+ else { \
+ mga_draw_point( mmesa, v0 ); \
+ } \
+} while (0)
+
+
+/***********************************************************************
+ * Fallback to swrast for basic primitives *
+ ***********************************************************************/
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+
+static void
+mga_fallback_tri( mgaContextPtr mmesa,
+ mgaVertex *v0,
+ mgaVertex *v1,
+ mgaVertex *v2 )
+{
+ GLcontext *ctx = mmesa->glCtx;
+ SWvertex v[3];
+ mga_translate_vertex( ctx, v0, &v[0] );
+ mga_translate_vertex( ctx, v1, &v[1] );
+ mga_translate_vertex( ctx, v2, &v[2] );
+ _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+}
+
+
+static void
+mga_fallback_line( mgaContextPtr mmesa,
+ mgaVertex *v0,
+ mgaVertex *v1 )
+{
+ GLcontext *ctx = mmesa->glCtx;
+ SWvertex v[2];
+ mga_translate_vertex( ctx, v0, &v[0] );
+ mga_translate_vertex( ctx, v1, &v[1] );
+ _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+
+static void
+mga_fallback_point( mgaContextPtr mmesa,
+ mgaVertex *v0 )
+{
+ GLcontext *ctx = mmesa->glCtx;
+ SWvertex v[1];
+ mga_translate_vertex( ctx, v0, &v[0] );
+ _swrast_Point( ctx, &v[0] );
+}
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+
+#define MGA_UNFILLED_BIT 0x1
+#define MGA_OFFSET_BIT 0x2
+#define MGA_TWOSIDE_BIT 0x4
+#define MGA_FLAT_BIT 0x8 /* mga can't flatshade? */
+#define MGA_FALLBACK_BIT 0x10
+#define MGA_MAX_TRIFUNC 0x20
+
+static struct {
+ tnl_points_func points;
+ tnl_line_func line;
+ tnl_triangle_func triangle;
+ tnl_quad_func quad;
+} rast_tab[MGA_MAX_TRIFUNC];
+
+#define DO_FALLBACK (IND & MGA_FALLBACK_BIT)
+#define DO_OFFSET (IND & MGA_OFFSET_BIT)
+#define DO_UNFILLED (IND & MGA_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & MGA_TWOSIDE_BIT)
+#define DO_FLAT (IND & MGA_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_BACK_COLORS 0
+#define HAVE_SPEC 1
+#define HAVE_HW_FLATSHADE 0
+#define VERTEX mgaVertex
+#define TAB rast_tab
+
+
+#define DEPTH_SCALE mmesa->depth_scale
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a > 0)
+#define GET_VERTEX(e) (mmesa->verts + (e * mmesa->vertex_size * sizeof(int)))
+
+#define VERT_SET_RGBA( v, c ) \
+do { \
+ mga_color_t *color = (mga_color_t *)&((v)->ui[4]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
+} while (0)
+
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4]
+
+#define VERT_SET_SPEC( v0, c ) \
+do { \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
+ UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
+} while (0)
+
+#define VERT_COPY_SPEC( v0, v1 ) \
+do { \
+ v0->v.specular.red = v1->v.specular.red; \
+ v0->v.specular.green = v1->v.specular.green; \
+ v0->v.specular.blue = v1->v.specular.blue; \
+} while (0)
+
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx]
+#define VERT_SAVE_SPEC( idx ) spec[idx] = v[idx]->ui[5]
+#define VERT_RESTORE_SPEC( idx ) v[idx]->ui[5] = spec[idx]
+
+#define LOCAL_VARS(n) \
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx); \
+ GLuint color[n], spec[n]; \
+ (void) color; (void) spec;
+
+
+
+/***********************************************************************
+ * Functions to draw basic unfilled primitives *
+ ***********************************************************************/
+
+#define RASTERIZE(x) if (mmesa->raster_primitive != x) \
+ mgaRasterPrimitive( ctx, x, MGA_WA_TRIANGLES )
+#define RENDER_PRIMITIVE mmesa->render_primitive
+#define IND MGA_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 (MGA_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \
+ MGA_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+/* Mga doesn't support provoking-vertex flat-shading?
+ */
+#define IND (MGA_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_offset_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_UNFILLED_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_offset_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_offset_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_offset_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_OFFSET_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_offset_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_UNFILLED_BIT|MGA_FALLBACK_BIT|MGA_FLAT_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback_flat
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (MGA_TWOSIDE_BIT|MGA_OFFSET_BIT|MGA_UNFILLED_BIT| \
+ MGA_FALLBACK_BIT|MGA_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 */
+/**********************************************************************/
+
+
+#define VERT(x) (mgaVertex *)(vertptr + ((x)*vertex_size*sizeof(int)))
+#define RENDER_POINTS( start, count ) \
+ for ( ; start < count ; start++) \
+ mga_draw_point( mmesa, VERT(ELT(start)) );
+#define RENDER_LINE( v0, v1 ) \
+ mga_draw_line( mmesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 ) \
+ mga_draw_triangle( mmesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ mga_draw_quad( mmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#define INIT(x) mgaRenderPrimitive( ctx, x )
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx); \
+ GLubyte *vertptr = (GLubyte *)mmesa->verts; \
+ const GLuint vertex_size = mmesa->vertex_size; \
+ const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
+ (void) elt;
+#define RESET_STIPPLE
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) x
+#define TAG(x) mga_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) mga_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Render clipped primitives */
+/**********************************************************************/
+
+
+
+static void mgaRenderClippedPoly( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint prim = mmesa->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 mgaRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ GLuint vertex_size = mmesa->vertex_size;
+ GLuint *vb = mgaAllocDmaLow( mmesa, (n-2) * 3 * 4 * vertex_size );
+ GLubyte *vertptr = (GLubyte *)mmesa->verts;
+ const GLuint *start = (const GLuint *)VERT(elts[0]);
+ int i,j;
+
+ for (i = 2 ; i < n ; i++) {
+ EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i-1]) );
+ EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) VERT(elts[i]) );
+ EMIT_VERT( j, vb, vertex_size, (mgaVertexPtr) start );
+ }
+}
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+
+#define POINT_FALLBACK (DD_POINT_SMOOTH)
+#define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE)
+#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED)
+#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 mgaChooseRenderState(GLcontext *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint index = 0;
+
+ if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS|DD_TRI_STIPPLE)) {
+ if (flags & ANY_RASTER_FLAGS) {
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= MGA_TWOSIDE_BIT;
+ if (flags & DD_TRI_OFFSET) index |= MGA_OFFSET_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= MGA_UNFILLED_BIT;
+ if (flags & DD_FLATSHADE) index |= MGA_FLAT_BIT;
+ }
+
+ mmesa->draw_point = mga_draw_point;
+ mmesa->draw_line = mga_draw_line;
+ mmesa->draw_tri = mga_draw_triangle;
+
+ /* Hook in fallbacks for specific primitives.
+ */
+ if (flags & ANY_FALLBACK_FLAGS)
+ {
+ if (flags & POINT_FALLBACK)
+ mmesa->draw_point = mga_fallback_point;
+
+ if (flags & LINE_FALLBACK)
+ mmesa->draw_line = mga_fallback_line;
+
+ if (flags & TRI_FALLBACK)
+ mmesa->draw_tri = mga_fallback_tri;
+
+ index |= MGA_FALLBACK_BIT;
+ }
+
+ if ((flags & DD_TRI_STIPPLE) && !mmesa->haveHwStipple) {
+ mmesa->draw_tri = mga_fallback_tri;
+ index |= MGA_FALLBACK_BIT;
+ }
+ }
+
+ if (mmesa->RenderIndex != index) {
+ mmesa->RenderIndex = index;
+
+ tnl->Driver.Render.Points = rast_tab[index].points;
+ tnl->Driver.Render.Line = 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 = mga_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = mga_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
+ tnl->Driver.Render.ClippedPolygon = mgaFastRenderClippedPoly;
+ } else {
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = mgaRenderClippedLine;
+ tnl->Driver.Render.ClippedPolygon = mgaRenderClippedPoly;
+ }
+ }
+}
+
+/**********************************************************************/
+/* Runtime render state and callbacks */
+/**********************************************************************/
+
+
+static 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
+};
+
+
+
+/* Always called between RenderStart and RenderFinish --> We already
+ * hold the lock.
+ */
+void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+ FLUSH_BATCH( mmesa );
+
+ /* Update culling */
+ if (mmesa->raster_primitive != prim)
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+
+ mmesa->raster_primitive = prim;
+/* mmesa->hw_primitive = hwprim; */
+ mmesa->hw_primitive = MGA_WA_TRIANGLES; /* disable mgarender.c for now */
+
+ if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
+ {
+ mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+ mmesa->setup.dwgctl &= ~(0xf<<20);
+ if (mmesa->raster_primitive == GL_TRIANGLES)
+ mmesa->setup.dwgctl |= mmesa->poly_stipple;
+ }
+}
+
+
+
+/* Determine the rasterized primitive when not drawing unfilled
+ * polygons.
+ *
+ * Used only for the default render stage which always decomposes
+ * primitives to trianges/lines/points. For the accelerated stage,
+ * which renders strips as strips, the equivalent calculations are
+ * performed in mgarender.c.
+ */
+static void mgaRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint rprim = reduced_prim[prim];
+
+ mmesa->render_primitive = prim;
+
+ if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+ return;
+
+ if (mmesa->raster_primitive != rprim) {
+ mgaRasterPrimitive( ctx, rprim, MGA_WA_TRIANGLES );
+ }
+}
+
+static void mgaRenderFinish( GLcontext *ctx )
+{
+ if (MGA_CONTEXT(ctx)->RenderIndex & MGA_FALLBACK_BIT)
+ _swrast_flush( ctx );
+}
+
+
+
+/**********************************************************************/
+/* Manage total rasterization fallbacks */
+/**********************************************************************/
+
+static const char * const fallbackStrings[] = {
+ "Texture mode",
+ "glDrawBuffer(GL_FRONT_AND_BACK)",
+ "read buffer",
+ "glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ZERO)",
+ "glRenderMode(selection or feedback)",
+ "No hardware stencil",
+ "glDepthFunc( GL_NEVER )",
+ "Mixing GL_CLAMP_TO_EDGE and GL_CLAMP",
+ "rasterization fallback option"
+};
+
+static const char *getFallbackString(GLuint bit)
+{
+ int i = 0;
+ while (bit > 1) {
+ i++;
+ bit >>= 1;
+ }
+ return fallbackStrings[i];
+}
+
+
+void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint oldfallback = mmesa->Fallback;
+
+ if (mode) {
+ mmesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ FLUSH_BATCH(mmesa);
+ _swsetup_Wakeup( ctx );
+ mmesa->RenderIndex = ~0;
+ if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
+ fprintf(stderr, "MGA begin rasterization fallback: 0x%x %s\n",
+ bit, getFallbackString(bit));
+ }
+ }
+ }
+ else {
+ mmesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = mgaCheckTexSizes;
+ tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
+ tnl->Driver.Render.Finish = mgaRenderFinish;
+ tnl->Driver.Render.BuildVertices = mgaBuildVertices;
+ mmesa->NewGLState |= (_MGA_NEW_RENDERSTATE |
+ _MGA_NEW_RASTERSETUP);
+ if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
+ fprintf(stderr, "MGA end rasterization fallback: 0x%x %s\n",
+ bit, getFallbackString(bit));
+ }
+ }
+ }
+}
+
+
+void mgaDDInitTriFuncs( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ static int firsttime = 1;
+ if (firsttime) {
+ init_rast_tab();
+ firsttime = 0;
+ }
+
+ mmesa->RenderIndex = ~0;
+
+ tnl->Driver.Render.Start = mgaCheckTexSizes;
+ tnl->Driver.Render.Finish = mgaRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+ tnl->Driver.Render.BuildVertices = mgaBuildVertices;
+ tnl->Driver.Render.Multipass = NULL;
+}
diff --git a/src/mgatris.h b/src/mgatris.h
new file mode 100644
index 0000000..f3ece3a
--- /dev/null
+++ b/src/mgatris.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.h,v 1.10 2002/10/30 12:51:36 alanh Exp $ */
+
+#ifndef MGATRIS_INC
+#define MGATRIS_INC
+
+#include "mtypes.h"
+
+extern void mgaDDInitTriFuncs( GLcontext *ctx );
+extern void mgaChooseRenderState( GLcontext *ctx );
+extern void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim );
+
+extern void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( ctx, bit, mode ) mgaFallback( ctx, bit, mode )
+
+#define _MGA_NEW_RENDERSTATE (_DD_NEW_POINT_SMOOTH | \
+ _DD_NEW_LINE_SMOOTH | \
+ _DD_NEW_LINE_STIPPLE | \
+ _DD_NEW_TRI_SMOOTH | \
+ _DD_NEW_FLATSHADE | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_OFFSET | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_STIPPLE | \
+ _NEW_POLYGONSTIPPLE)
+
+#endif
diff --git a/src/mgavb.c b/src/mgavb.c
new file mode 100644
index 0000000..902d8bd
--- /dev/null
+++ b/src/mgavb.c
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.15 2003/03/26 20:43:49 tsi Exp $ */
+
+#include <stdlib.h>
+#include "mgacontext.h"
+#include "mgavb.h"
+#include "mgatris.h"
+#include "mgaioctl.h"
+#include "mga_xmesa.h"
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "tnl/t_context.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/swrast.h"
+
+
+#define MGA_TEX1_BIT 0x1
+#define MGA_TEX0_BIT 0x2
+#define MGA_RGBA_BIT 0x4
+#define MGA_SPEC_BIT 0x8
+#define MGA_FOG_BIT 0x10
+#define MGA_XYZW_BIT 0x20
+#define MGA_PTEX_BIT 0x40
+#define MGA_MAX_SETUP 0x80
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+ tnl_interp_func interp;
+ tnl_copy_pv_func copy_pv;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_size;
+ GLuint vertex_format;
+} setup_tab[MGA_MAX_SETUP];
+
+
+#define TINY_VERTEX_FORMAT 0
+#define NOTEX_VERTEX_FORMAT 0
+#define TEX0_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F)
+#define TEX1_VERTEX_FORMAT (MGA_A|MGA_S|MGA_F|MGA_T2)
+#define PROJ_TEX1_VERTEX_FORMAT 0
+#define TEX2_VERTEX_FORMAT 0
+#define TEX3_VERTEX_FORMAT 0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & MGA_XYZW_BIT)
+#define DO_RGBA (IND & MGA_RGBA_BIT)
+#define DO_SPEC (IND & MGA_SPEC_BIT)
+#define DO_FOG (IND & MGA_FOG_BIT)
+#define DO_TEX0 (IND & MGA_TEX0_BIT)
+#define DO_TEX1 (IND & MGA_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & MGA_PTEX_BIT)
+
+
+#define VERTEX mgaVertex
+#define VERTEX_COLOR mga_color_t
+#define LOCALVARS mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+#define GET_VIEWPORT_MAT() mmesa->hw_viewport
+#define GET_TEXSOURCE(n) mmesa->tmu_source[n]
+#define GET_VERTEX_FORMAT() mmesa->vertex_format
+#define GET_VERTEX_STORE() mmesa->verts
+#define GET_VERTEX_SIZE() mmesa->vertex_size * sizeof(GLuint)
+
+#define HAVE_HW_VIEWPORT 0
+#define HAVE_HW_DIVIDE 0
+#define HAVE_RGBA_COLOR 0
+#define HAVE_TINY_VERTICES 0
+#define HAVE_NOTEX_VERTICES 0
+#define HAVE_TEX0_VERTICES 1
+#define HAVE_TEX1_VERTICES 1
+#define HAVE_TEX2_VERTICES 0
+#define HAVE_TEX3_VERTICES 0
+#define HAVE_PTEX_VERTICES 0
+
+#define UNVIEWPORT_VARS \
+ const GLfloat dx = - mmesa->drawX - SUBPIXEL_X; \
+ const GLfloat dy = (mmesa->driDrawable->h + \
+ mmesa->drawY + SUBPIXEL_Y); \
+ const GLfloat sz = 1.0 / mmesa->depth_scale
+
+#define UNVIEWPORT_X(x) x + dx;
+#define UNVIEWPORT_Y(y) - y + dy;
+#define UNVIEWPORT_Z(z) z * sz;
+
+#define PTEX_FALLBACK() FALLBACK(ctx, MGA_FALLBACK_TEXTURE, 1)
+
+#define INTERP_VERTEX setup_tab[mmesa->SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[mmesa->SetupIndex].copy_pv
+
+
+/***********************************************************************
+ * Generate pv-copying and translation functions *
+ ***********************************************************************/
+
+#define TAG(x) mga_##x
+#include "tnl_dd/t_dd_vb.c"
+
+/***********************************************************************
+ * Generate vertex emit and interp functions *
+ ***********************************************************************/
+
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT)
+#define TAG(x) x##_wgs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_wgst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_wgst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT)
+#define TAG(x) x##_wgspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT)
+#define TAG(x) x##_wgf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_wgft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_wgft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT)
+#define TAG(x) x##_wgfpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_XYZW_BIT|MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_TEX0_BIT)
+#define TAG(x) x##_t0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_t0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_FOG_BIT)
+#define TAG(x) x##_f
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_FOG_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_ft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_ft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT)
+#define TAG(x) x##_g
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT)
+#define TAG(x) x##_gs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_gt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_gt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_gst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_gst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT)
+#define TAG(x) x##_gf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT)
+#define TAG(x) x##_gfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_gft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_gft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT)
+#define TAG(x) x##_gfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (MGA_RGBA_BIT|MGA_FOG_BIT|MGA_SPEC_BIT|MGA_TEX0_BIT|MGA_TEX1_BIT)
+#define TAG(x) x##_gfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+
+static void init_setup_tab( void )
+{
+ init_wg();
+ init_wgs();
+ init_wgt0();
+ init_wgt0t1();
+ init_wgpt0();
+ init_wgst0();
+ init_wgst0t1();
+ init_wgspt0();
+ init_wgf();
+ init_wgfs();
+ init_wgft0();
+ init_wgft0t1();
+ init_wgfpt0();
+ init_wgfst0();
+ init_wgfst0t1();
+ init_wgfspt0();
+ init_t0();
+ init_t0t1();
+ init_f();
+ init_ft0();
+ init_ft0t1();
+ init_g();
+ init_gs();
+ init_gt0();
+ init_gt0t1();
+ init_gst0();
+ init_gst0t1();
+ init_gf();
+ init_gfs();
+ init_gft0();
+ init_gft0t1();
+ init_gfst0();
+ init_gfst0t1();
+}
+
+
+
+
+void mgaPrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s: %d %s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & MGA_XYZW_BIT) ? " xyzw," : "",
+ (flags & MGA_RGBA_BIT) ? " rgba," : "",
+ (flags & MGA_SPEC_BIT) ? " spec," : "",
+ (flags & MGA_FOG_BIT) ? " fog," : "",
+ (flags & MGA_TEX0_BIT) ? " tex-0," : "",
+ (flags & MGA_TEX1_BIT) ? " tex-1," : "");
+}
+
+
+void mgaCheckTexSizes( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /*fprintf(stderr, "%s\n", __FUNCTION__);*/
+
+ if (!setup_tab[mmesa->SetupIndex].check_tex_sizes(ctx)) {
+ mmesa->SetupIndex |= MGA_PTEX_BIT;
+ mmesa->SetupNewInputs = ~0;
+
+ if (!mmesa->Fallback &&
+ !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[mmesa->SetupIndex].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[mmesa->SetupIndex].copy_pv;
+ }
+ if (mmesa->Fallback) {
+ tnl->Driver.Render.Start(ctx);
+ }
+ }
+}
+
+
+void mgaBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ GLuint stride = mmesa->vertex_size * sizeof(int);
+ GLubyte *v = ((GLubyte *)mmesa->verts + (start * stride));
+
+ newinputs |= mmesa->SetupNewInputs;
+ mmesa->SetupNewInputs = 0;
+
+ if (!newinputs)
+ return;
+
+ if (newinputs & VERT_BIT_POS) {
+ setup_tab[mmesa->SetupIndex].emit( ctx, start, count, v, stride );
+ } else {
+ GLuint ind = 0;
+
+ if (newinputs & VERT_BIT_COLOR0)
+ ind |= MGA_RGBA_BIT;
+
+ if (newinputs & VERT_BIT_COLOR1)
+ ind |= MGA_SPEC_BIT;
+
+ if (newinputs & VERT_BIT_TEX0)
+ ind |= MGA_TEX0_BIT;
+
+ if (newinputs & VERT_BIT_TEX1)
+ ind |= MGA_TEX0_BIT|MGA_TEX1_BIT;
+
+ if (newinputs & VERT_BIT_FOG)
+ ind |= MGA_FOG_BIT;
+
+ if (mmesa->SetupIndex & MGA_PTEX_BIT)
+ ind = ~0;
+
+ ind &= mmesa->SetupIndex;
+
+ if (ind) {
+ setup_tab[ind].emit( ctx, start, count, v, stride );
+ }
+ }
+}
+
+
+void mgaChooseVertexState( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint ind = MGA_XYZW_BIT|MGA_RGBA_BIT;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ ind |= MGA_SPEC_BIT;
+
+ if (ctx->Fog.Enabled)
+ ind |= MGA_FOG_BIT;
+
+ if (ctx->Texture._EnabledUnits & 0x2) {
+ /* unit 1 enabled */
+ if (ctx->Texture._EnabledUnits & 0x1) {
+ /* unit 0 enabled */
+ ind |= MGA_TEX1_BIT|MGA_TEX0_BIT;
+ }
+ else {
+ ind |= MGA_TEX0_BIT;
+ }
+ }
+ else if (ctx->Texture._EnabledUnits & 0x1) {
+ /* unit 0 enabled */
+ ind |= MGA_TEX0_BIT;
+ }
+
+ mmesa->SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = mga_interp_extras;
+ tnl->Driver.Render.CopyPV = mga_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 != mmesa->vertex_format) {
+ FLUSH_BATCH(mmesa);
+ mmesa->dirty |= MGA_UPLOAD_PIPE;
+ mmesa->vertex_format = setup_tab[ind].vertex_format;
+ mmesa->vertex_size = setup_tab[ind].vertex_size;
+ }
+}
+
+
+
+void *mga_emit_contiguous_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ void *dest)
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint stride = mmesa->vertex_size * 4;
+ setup_tab[mmesa->SetupIndex].emit( ctx, start, count, dest, stride );
+ return (void *)((char *)dest + stride * (count - start));
+}
+
+
+
+void mgaInitVB( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+ mmesa->verts = (GLubyte *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
+
+ {
+ static int firsttime = 1;
+ if (firsttime) {
+ init_setup_tab();
+ firsttime = 0;
+ }
+ }
+
+ mmesa->dirty |= MGA_UPLOAD_PIPE;
+ mmesa->vertex_format = setup_tab[0].vertex_format;
+ mmesa->vertex_size = setup_tab[0].vertex_size;
+}
+
+
+void mgaFreeVB( GLcontext *ctx )
+{
+ mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ if (mmesa->verts) {
+ ALIGN_FREE(mmesa->verts);
+ mmesa->verts = 0;
+ }
+}
+
diff --git a/src/mgavb.h b/src/mgavb.h
new file mode 100644
index 0000000..5f6454a
--- /dev/null
+++ b/src/mgavb.h
@@ -0,0 +1,66 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.h,v 1.8 2002/10/30 12:51:36 alanh Exp $ */
+/*
+ * Copyright 2000-2001 VA Linux Systems, 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
+ * 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 SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef MGAVB_INC
+#define MGAVB_INC
+
+#include "mtypes.h"
+#include "mgacontext.h"
+#include "swrast/swrast.h"
+
+#define _MGA_NEW_RASTERSETUP (_NEW_TEXTURE | \
+ _DD_NEW_SEPARATE_SPECULAR | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _NEW_FOG)
+
+
+extern void mgaChooseVertexState( GLcontext *ctx );
+extern void mgaCheckTexSizes( GLcontext *ctx );
+extern void mgaBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs );
+
+extern void mgaPrintSetupFlags(char *msg, GLuint flags );
+
+extern void mgaInitVB( GLcontext *ctx );
+extern void mgaFreeVB( GLcontext *ctx );
+
+extern void *mga_emit_contiguous_verts( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ void *dest );
+
+extern void mga_translate_vertex(GLcontext *ctx,
+ const mgaVertex *src,
+ SWvertex *dst);
+
+extern void mga_print_vertex( GLcontext *ctx, const mgaVertex *v );
+
+#endif
diff --git a/src/server/mga.h b/src/server/mga.h
new file mode 100644
index 0000000..830d48d
--- /dev/null
+++ b/src/server/mga.h
@@ -0,0 +1,115 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga.h,v 1.85 2002/12/16 16:19:17 dawes Exp $ */
+/*
+ * MGA Millennium (MGA2064W) functions
+ *
+ * Copyright 1996 The XFree86 Project, Inc.
+ *
+ * Authors
+ * Dirk Hohndel
+ * hohndel@XFree86.Org
+ * David Dawes
+ * dawes@XFree86.Org
+ */
+
+#ifndef MGA_H
+#define MGA_H
+
+
+#include "xf86drm.h"
+#include "linux/types.h"
+
+
+#define PCI_CHIP_MGA2085 0x0518
+#define PCI_CHIP_MGA2064 0x0519
+#define PCI_CHIP_MGA1064 0x051A
+#define PCI_CHIP_MGA2164 0x051B
+#define PCI_CHIP_MGA2164_AGP 0x051F
+#define PCI_CHIP_MGAG200_PCI 0x0520
+#define PCI_CHIP_MGAG200 0x0521
+#define PCI_CHIP_MGAG400 0x0525
+#define PCI_CHIP_MGAG550 0x2527
+#define PCI_CHIP_MGAG100_PCI 0x1000
+#define PCI_CHIP_MGAG100 0x1001
+
+
+# define MMIO_IN8(base, offset) \
+ *(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
+# define MMIO_IN16(base, offset) \
+ *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset))
+# define MMIO_IN32(base, offset) \
+ *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset))
+# define MMIO_OUT8(base, offset, val) \
+ *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
+# define MMIO_OUT16(base, offset, val) \
+ *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
+# define MMIO_OUT32(base, offset, val) \
+ *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
+
+#define INREG8(addr) MMIO_IN8(pMga->IOBase, addr)
+#define INREG16(addr) MMIO_IN16(pMga->IOBase, addr)
+#define INREG(addr) MMIO_IN32(pMga->IOBase, addr)
+#define OUTREG8(addr, val) MMIO_OUT8(pMga->IOBase, addr, val)
+#define OUTREG16(addr, val) MMIO_OUT16(pMga->IOBase, addr, val)
+#define OUTREG(addr, val) MMIO_OUT32(pMga->IOBase, addr, val)
+
+#define MGAIOMAPSIZE 0x00004000
+
+
+typedef struct {
+ int Chipset; /**< \brief Chipset number */
+
+ int irq; /**< \brief IRQ number */
+
+
+ int frontOffset; /**< \brief Front color buffer offset */
+ int frontPitch; /**< \brief Front color buffer pitch */
+ int backOffset; /**< \brief Back color buffer offset */
+ int backPitch; /**< \brief Back color buffer pitch */
+ int depthOffset; /**< \brief Depth buffer offset */
+ int depthPitch; /**< \brief Depth buffer pitch */
+ int textureOffset; /**< \brief Texture area offset */
+ int textureSize; /**< \brief Texture area size */
+ int logTextureGranularity;
+
+ /**
+ * \name AGP
+ */
+ /*@{*/
+ drmSize agpSize; /**< \brief AGP map size */
+ int agpMode; /**< \brief AGP mode */
+ /*@}*/
+
+ drmRegion agp;
+
+ /* PCI mappings */
+ drmRegion registers;
+ drmRegion status;
+
+ /* AGP mappings */
+ drmRegion warp;
+ drmRegion primary;
+ drmRegion buffers;
+ drmRegion agpTextures;
+
+ drmBufMapPtr drmBuffers;
+
+ unsigned long IOAddress;
+ unsigned char *IOBase;
+ int HasSDRAM;
+
+ __u32 reg_ien;
+} MGARec, *MGAPtr;
+
+
+
+#define MGA_FRONT 0x1
+#define MGA_BACK 0x2
+#define MGA_DEPTH 0x4
+
+#define MGA_AGP_1X_MODE 0x01
+#define MGA_AGP_2X_MODE 0x02
+#define MGA_AGP_4X_MODE 0x04
+#define MGA_AGP_MODE_MASK 0x07
+
+
+#endif
diff --git a/src/server/mga_bios.h b/src/server/mga_bios.h
new file mode 100644
index 0000000..8fbf619
--- /dev/null
+++ b/src/server/mga_bios.h
@@ -0,0 +1,143 @@
+/* $XConsortium: mga_bios.h /main/2 1996/10/28 04:48:23 kaleb $ */
+#ifndef MGA_BIOS_H
+#define MGA_BIOS_H
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_bios.h,v 1.3 1998/07/25 16:55:51 dawes Exp $ */
+
+/*
+ * MGABiosInfo - This struct describes the video BIOS info block.
+ *
+ * DESCRIPTION
+ * Do not mess with this, unless you know what you are doing.
+ * The data lengths and types are critical.
+ *
+ * HISTORY
+ * October 7, 1996 - [aem] Andrew E. Mileski
+ * This struct was shamelessly stolen from the MGA DDK.
+ * It has been reformatted, and the data types changed.
+ */
+typedef struct {
+ /* Length of this structure in bytes */
+ __u16 StructLen;
+
+ /*
+ * Unique number identifying the product type
+ * 0 : MGA-S1P20 (2MB base with 175MHz Ramdac)
+ * 1 : MGA-S1P21 (2MB base with 220MHz Ramdac)
+ * 2 : Reserved
+ * 3 : Reserved
+ * 4 : MGA-S1P40 (4MB base with 175MHz Ramdac)
+ * 5 : MGA-S1P41 (4MB base with 220MHz Ramdac)
+ */
+ __u16 ProductID;
+
+ /* Serial number of the board */
+ __u8 SerNo[ 10 ];
+
+ /*
+ * Manufacturing date of the board (at product test)
+ * Format: yyyy yyym mmmd dddd
+ */
+ __u16 ManufDate;
+
+ /* Identification of manufacturing site */
+ __u16 ManufId;
+
+ /*
+ * Number and revision level of the PCB
+ * Format: nnnn nnnn nnnr rrrr
+ * n = PCB number ex:576 (from 0->2047)
+ * r = PCB revision (from 0->31)
+ */
+ __u16 PCBInfo;
+
+ /* Identification of any PMBs */
+ __u16 PMBInfo;
+
+ /*
+ * Bit 0-7 : Ramdac speed (0=175MHz, 1=220MHz)
+ * Bit 8-15 : Ramdac type (0=TVP3026, 1=TVP3027)
+ */
+ __u16 RamdacType;
+
+ /* Maximum PCLK of the ramdac */
+ __u16 PclkMax;
+
+ /* Maximum LDCLK supported by the WRAM memory */
+ __u16 LclkMax;
+
+ /* Maximum MCLK of base board */
+ __u16 ClkBase;
+
+ /* Maximum MCLK of 4Mb board */
+ __u16 Clk4MB;
+
+ /* Maximum MCLK of 8Mb board */
+ __u16 Clk8MB;
+
+ /* Maximum MCLK of board with multimedia module */
+ __u16 ClkMod;
+
+ /* Diagnostic test pass frequency */
+ __u16 TestClk;
+
+ /* Default VGA mode1 pixel frequency */
+ __u16 VGAFreq1;
+
+ /* Default VGA mode2 pixel frequency */
+ __u16 VGAFreq2;
+
+ /* Date of last BIOS programming/update */
+ __u16 ProgramDate;
+
+ /* Number of times BIOS has been programmed */
+ __u16 ProgramCnt;
+
+ /* Support for up to 32 hardware/software options */
+ __u32 Options;
+
+ /* Support for up to 32 hardware/software features */
+ __u32 FeatFlag;
+
+ /* Definition of VGA mode MCLK */
+ __u16 VGAClk;
+
+ /* Indicate the revision level of this header struct */
+ __u16 StructRev;
+
+ __u16 Reserved[ 3 ];
+} MGABiosInfo;
+
+/* from the PINS structure, refer pins info from MGA */
+typedef struct tagParamMGA {
+ __u16 PinID; /* 0 */
+ __u8 StructLen; /* 2 */
+ __u8 Rsvd1; /* 3 */
+ __u16 StructRev; /* 4 */
+ __u16 ProgramDate; /* 6 */
+ __u16 ProgramCnt; /* 8 */
+ __u16 ProductID; /* 10 */
+ __u8 SerNo[16]; /* 12 */
+ __u8 PLInfo[6]; /* 28 */
+ __u16 PCBInfo; /* 34 */
+ __u32 FeatFlag; /* 36 */
+ __u8 RamdacType; /* 40 */
+ __u8 RamdacSpeed; /* 41 */
+ __u8 PclkMax; /* 42 */
+ __u8 ClkGE; /* 43 */
+ __u8 ClkMem; /* 44 */
+ __u8 Clk4MB; /* 45 */
+ __u8 Clk8MB; /* 46 */
+ __u8 ClkMod; /* 47 */
+ __u8 TestClk; /* 48 */
+ __u8 VGAFreq1; /* 49 */
+ __u8 VGAFreq2; /* 50 */
+ __u8 MCTLWTST; /* 51 */
+ __u8 VidCtrl; /* 52 */
+ __u8 Clk12MB; /* 53 */
+ __u8 Clk16MB; /* 54 */
+ __u8 Reserved[8]; /* 55-62 */
+ __u8 PinCheck; /* 63 */
+} MGABios2Info;
+
+#endif
diff --git a/src/server/mga_dri.c b/src/server/mga_dri.c
new file mode 100644
index 0000000..258ace8
--- /dev/null
+++ b/src/server/mga_dri.c
@@ -0,0 +1,1089 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c,v 1.28 2003/02/08 21:26:58 dawes Exp $ */
+
+/*
+ * Copyright 2000 VA Linux Systems Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "driver.h"
+#include "drm.h"
+#include "memops.h"
+
+#include "mga_reg.h"
+#include "mga.h"
+#include "mga_macros.h"
+#include "mga_dri.h"
+
+
+/* Quiescence, locking
+ */
+#define MGA_TIMEOUT 2048
+
+static void MGAWaitForIdleDMA( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ drm_lock_t lock;
+ int ret;
+ int i = 0;
+
+ memset( &lock, 0, sizeof(lock) );
+
+ for (;;) {
+ do {
+ /* first ask for quiescent and flush */
+ lock.flags = DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH;
+ do {
+ ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
+ &lock, sizeof( lock ) );
+ } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
+
+ /* if it's still busy just try quiescent */
+ if ( ret == -EBUSY ) {
+ lock.flags = DRM_LOCK_QUIESCENT;
+ do {
+ ret = drmCommandWrite( ctx->drmFD, DRM_MGA_FLUSH,
+ &lock, sizeof( lock ) );
+ } while ( ret == -EBUSY && i++ < DRM_MGA_IDLE_RETRY );
+ }
+ } while ( ( ret == -EBUSY ) && ( i++ < MGA_TIMEOUT ) );
+
+ if ( ret == 0 )
+ return;
+
+ fprintf( stderr,
+ "[dri] Idle timed out, resetting engine...\n" );
+
+ drmCommandNone( ctx->drmFD, DRM_MGA_RESET );
+ }
+}
+
+static unsigned int mylog2( unsigned int n )
+{
+ unsigned int log2 = 1;
+ while ( n > 1 ) n >>= 1, log2++;
+ return log2;
+}
+
+static int MGADRIAgpInit(struct DRIDriverContextRec *ctx, MGAPtr pMga)
+{
+ unsigned long mode;
+ unsigned int vendor, device;
+ int ret, count, i;
+
+ if(pMga->agpSize < 12)pMga->agpSize = 12;
+ if(pMga->agpSize > 64)pMga->agpSize = 64; /* cap */
+
+ /* FIXME: Make these configurable...
+ */
+ pMga->agp.size = pMga->agpSize * 1024 * 1024;
+
+ pMga->warp.offset = 0;
+ pMga->warp.size = MGA_WARP_UCODE_SIZE;
+
+ pMga->primary.offset = (pMga->warp.offset +
+ pMga->warp.size);
+ pMga->primary.size = 1024 * 1024;
+
+ pMga->buffers.offset = (pMga->primary.offset +
+ pMga->primary.size);
+ pMga->buffers.size = MGA_NUM_BUFFERS * MGA_BUFFER_SIZE;
+
+
+ pMga->agpTextures.offset = (pMga->buffers.offset +
+ pMga->buffers.size);
+
+ pMga->agpTextures.size = pMga->agp.size -
+ pMga->agpTextures.offset;
+
+ if ( drmAgpAcquire( ctx->drmFD ) < 0 ) {
+ fprintf( stderr, "[agp] AGP not available\n" );
+ return 0;
+ }
+
+ mode = drmAgpGetMode( ctx->drmFD ); /* Default mode */
+ vendor = drmAgpVendorId( ctx->drmFD );
+ device = drmAgpDeviceId( ctx->drmFD );
+
+ mode &= ~MGA_AGP_MODE_MASK;
+ switch ( pMga->agpMode ) {
+ case 4:
+ mode |= MGA_AGP_4X_MODE;
+ case 2:
+ mode |= MGA_AGP_2X_MODE;
+ case 1:
+ default:
+ mode |= MGA_AGP_1X_MODE;
+ }
+
+#if 0
+ fprintf( stderr,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ ctx->pciVendor,
+ ctx->pciChipType );
+#endif
+
+ if ( drmAgpEnable( ctx->drmFD, mode ) < 0 ) {
+ fprintf( stderr, "[agp] AGP not enabled\n" );
+ drmAgpRelease( ctx->drmFD );
+ return 0;
+ }
+
+ if ( pMga->Chipset == PCI_CHIP_MGAG200 ) {
+ switch ( pMga->agpMode ) {
+ case 2:
+ fprintf( stderr,
+ "[drm] Enabling AGP 2x PLL encoding\n" );
+ OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_ENABLE );
+ break;
+
+ case 1:
+ default:
+ fprintf( stderr,
+ "[drm] Disabling AGP 2x PLL encoding\n" );
+ OUTREG( MGAREG_AGP_PLL, MGA_AGP2XPLL_DISABLE );
+ pMga->agpMode = 1;
+ break;
+ }
+ }
+
+ ret = drmAgpAlloc( ctx->drmFD, pMga->agp.size,
+ 0, NULL, &pMga->agp.handle );
+ if ( ret < 0 ) {
+ fprintf( stderr, "[agp] Out of memory (%d)\n", ret );
+ drmAgpRelease( ctx->drmFD );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ pMga->agp.size/1024, (unsigned int)pMga->agp.handle );
+
+ if ( drmAgpBind( ctx->drmFD, pMga->agp.handle, 0 ) < 0 ) {
+ fprintf( stderr, "[agp] Could not bind memory\n" );
+ drmAgpFree( ctx->drmFD, pMga->agp.handle );
+ drmAgpRelease( ctx->drmFD );
+ return 0;
+ }
+
+ /* WARP microcode space
+ */
+ if ( drmAddMap( ctx->drmFD,
+ pMga->warp.offset,
+ pMga->warp.size,
+ DRM_AGP, DRM_READ_ONLY,
+ &pMga->warp.handle ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not add WARP microcode mapping\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] WARP microcode handle = 0x%08x\n",
+ pMga->warp.handle );
+
+ if ( drmMap( ctx->drmFD,
+ pMga->warp.handle,
+ pMga->warp.size,
+ &pMga->warp.map ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not map WARP microcode\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] WARP microcode mapped at 0x%08lx\n",
+ (unsigned long)pMga->warp.map );
+
+ /* Primary DMA space
+ */
+ if ( drmAddMap( ctx->drmFD,
+ pMga->primary.offset,
+ pMga->primary.size,
+ DRM_AGP, DRM_READ_ONLY,
+ &pMga->primary.handle ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not add primary DMA mapping\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] Primary DMA handle = 0x%08x\n",
+ pMga->primary.handle );
+
+ if ( drmMap( ctx->drmFD,
+ pMga->primary.handle,
+ pMga->primary.size,
+ &pMga->primary.map ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not map primary DMA\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] Primary DMA mapped at 0x%08lx\n",
+ (unsigned long)pMga->primary.map );
+
+ /* DMA buffers
+ */
+ if ( drmAddMap( ctx->drmFD,
+ pMga->buffers.offset,
+ pMga->buffers.size,
+ DRM_AGP, 0,
+ &pMga->buffers.handle ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not add DMA buffers mapping\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] DMA buffers handle = 0x%08x\n",
+ pMga->buffers.handle );
+
+ if ( drmMap( ctx->drmFD,
+ pMga->buffers.handle,
+ pMga->buffers.size,
+ &pMga->buffers.map ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not map DMA buffers\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] DMA buffers mapped at 0x%08lx\n",
+ (unsigned long)pMga->buffers.map );
+
+ count = drmAddBufs( ctx->drmFD,
+ MGA_NUM_BUFFERS, MGA_BUFFER_SIZE,
+ DRM_AGP_BUFFER, pMga->buffers.offset );
+ if ( count <= 0 ) {
+ fprintf( stderr,
+ "[drm] failure adding %d %d byte DMA buffers\n",
+ MGA_NUM_BUFFERS, MGA_BUFFER_SIZE );
+ return 0;
+ }
+ fprintf( stderr,
+ "[drm] Added %d %d byte DMA buffers\n",
+ count, MGA_BUFFER_SIZE );
+
+ i = mylog2(pMga->agpTextures.size / MGA_NR_TEX_REGIONS);
+ if(i < MGA_LOG_MIN_TEX_REGION_SIZE)
+ i = MGA_LOG_MIN_TEX_REGION_SIZE;
+ pMga->agpTextures.size = (pMga->agpTextures.size >> i) << i;
+
+ if ( drmAddMap( ctx->drmFD,
+ pMga->agpTextures.offset,
+ pMga->agpTextures.size,
+ DRM_AGP, 0,
+ &pMga->agpTextures.handle ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not add agpTexture mapping\n" );
+ return 0;
+ }
+/* should i map it ? */
+ fprintf( stderr,
+ "[agp] agpTexture handle = 0x%08x\n",
+ pMga->agpTextures.handle );
+ fprintf( stderr,
+ "[agp] agpTexture size: %d kb\n", pMga->agpTextures.size/1024 );
+
+ return 1;
+}
+
+static int MGADRIMapInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ pMga->registers.size = MGAIOMAPSIZE;
+
+ if ( drmAddMap( ctx->drmFD,
+ (drm_handle_t)pMga->IOAddress,
+ pMga->registers.size,
+ DRM_REGISTERS, DRM_READ_ONLY,
+ &pMga->registers.handle ) < 0 ) {
+ fprintf( stderr,
+ "[drm] Could not add MMIO registers mapping\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[drm] Registers handle = 0x%08lx\n",
+ pMga->registers.handle );
+
+ pMga->status.size = SAREA_MAX;
+
+ if ( drmAddMap( ctx->drmFD, 0, pMga->status.size,
+ DRM_SHM, DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL,
+ &pMga->status.handle ) < 0 ) {
+ fprintf( stderr,
+ "[drm] Could not add status page mapping\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[drm] Status handle = 0x%08x\n",
+ pMga->status.handle );
+
+ if ( drmMap( ctx->drmFD,
+ pMga->status.handle,
+ pMga->status.size,
+ &pMga->status.map ) < 0 ) {
+ fprintf( stderr,
+ "[agp] Could not map status page\n" );
+ return 0;
+ }
+ fprintf( stderr,
+ "[agp] Status page mapped at 0x%08lx\n",
+ (unsigned long)pMga->status.map );
+
+ return 1;
+}
+
+static int MGADRIKernelInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ drm_mga_init_t init;
+ int ret;
+
+ memset( &init, 0, sizeof(init) );
+
+ init.func = MGA_INIT_DMA;
+ init.sarea_priv_offset = sizeof(drm_sarea_t);
+
+ switch ( pMga->Chipset ) {
+ case PCI_CHIP_MGAG550:
+ case PCI_CHIP_MGAG400:
+ init.chipset = MGA_CARD_TYPE_G400;
+ break;
+ case PCI_CHIP_MGAG200:
+ case PCI_CHIP_MGAG200_PCI:
+ init.chipset = MGA_CARD_TYPE_G200;
+ break;
+ default:
+ return 0;
+ }
+
+ init.sgram = 0; /* FIXME !pMga->HasSDRAM; */
+
+
+ switch (ctx->bpp)
+ {
+ case 16:
+ init.maccess = MGA_MACCESS_PW16;
+ break;
+ case 32:
+ init.maccess = MGA_MACCESS_PW32;
+ break;
+ default:
+ fprintf( stderr, "[mga] invalid bpp (%d)\n", ctx->bpp );
+ return 0;
+ }
+
+
+ init.fb_cpp = ctx->bpp / 8;
+ init.front_offset = pMga->frontOffset;
+ init.front_pitch = pMga->frontPitch / init.fb_cpp;
+ init.back_offset = pMga->backOffset;
+ init.back_pitch = pMga->backPitch / init.fb_cpp;
+
+ init.depth_cpp = ctx->bpp / 8;
+ init.depth_offset = pMga->depthOffset;
+ init.depth_pitch = pMga->depthPitch / init.depth_cpp;
+
+ init.texture_offset[0] = pMga->textureOffset;
+ init.texture_size[0] = pMga->textureSize;
+
+ init.fb_offset = ctx->shared.hFrameBuffer;
+ init.mmio_offset = pMga->registers.handle;
+ init.status_offset = pMga->status.handle;
+
+ init.warp_offset = pMga->warp.handle;
+ init.primary_offset = pMga->primary.handle;
+ init.buffers_offset = pMga->buffers.handle;
+
+ init.texture_offset[1] = pMga->agpTextures.handle;
+ init.texture_size[1] = pMga->agpTextures.size;
+
+ ret = drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(init));
+ if ( ret < 0 ) {
+ fprintf( stderr,
+ "[drm] Failed to initialize DMA! (%d)\n", ret );
+ return 0;
+ }
+
+ return 1;
+}
+
+static void MGADRIIrqInit(struct DRIDriverContextRec *ctx, MGAPtr pMga)
+{
+ if (!pMga->irq)
+ {
+ pMga->irq = drmGetInterruptFromBusID(ctx->drmFD,
+ ctx->pciBus,
+ ctx->pciDevice,
+ ctx->pciFunc);
+
+ fprintf(stderr, "[drm] got IRQ %d\n", pMga->irq);
+
+ if((drmCtlInstHandler(ctx->drmFD, pMga->irq)) != 0)
+ {
+ fprintf(stderr,
+ "[drm] failure adding irq handler, "
+ "there is a device already using that irq\n"
+ "[drm] falling back to irq-free operation\n");
+ pMga->irq = 0;
+ }
+ else
+ {
+ pMga->reg_ien = INREG( MGAREG_IEN );
+ }
+ }
+
+ if (pMga->irq)
+ fprintf(stderr,
+ "[drm] dma control initialized, using IRQ %d\n",
+ pMga->irq);
+}
+
+static int MGADRIBuffersInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ pMga->drmBuffers = drmMapBufs( ctx->drmFD );
+ if ( !pMga->drmBuffers )
+ {
+ fprintf( stderr,
+ "[drm] Failed to map DMA buffers list\n" );
+ return 0;
+ }
+
+ fprintf( stderr,
+ "[drm] Mapped %d DMA buffers\n",
+ pMga->drmBuffers->count );
+
+ return 1;
+}
+
+static int MGAMemoryInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ int width_bytes = ctx->shared.virtualWidth * ctx->cpp;
+ int bufferSize = ((ctx->shared.virtualHeight * width_bytes
+ + MGA_BUFFER_ALIGN)
+ & ~MGA_BUFFER_ALIGN);
+ int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes
+ + MGA_BUFFER_ALIGN)
+ & ~MGA_BUFFER_ALIGN);
+ int l;
+
+ pMga->frontOffset = 0;
+ pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp;
+
+ fprintf(stderr,
+ "Using %d MB AGP aperture\n", pMga->agpSize);
+ fprintf(stderr,
+ "Using %d MB for vertex/indirect buffers\n", pMga->buffers.size>>20);
+ fprintf(stderr,
+ "Using %d MB for AGP textures\n", pMga->agpTextures.size>>20);
+
+ /* Front, back and depth buffers - everything else texture??
+ */
+ pMga->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;
+
+ if (pMga->textureSize < 0)
+ return 0;
+
+ l = mylog2( pMga->textureSize / MGA_NR_TEX_REGIONS );
+ if ( l < MGA_LOG_MIN_TEX_REGION_SIZE )
+ l = MGA_LOG_MIN_TEX_REGION_SIZE;
+
+ /* Round the texture size up to the nearest whole number of
+ * texture regions. Again, be greedy about this, don't
+ * round down.
+ */
+ pMga->logTextureGranularity = l;
+ pMga->textureSize = (pMga->textureSize >> l) << l;
+
+ /* Set a minimum usable local texture heap size. This will fit
+ * two 256x256x32bpp textures.
+ */
+ if (pMga->textureSize < 512 * 1024) {
+ pMga->textureOffset = 0;
+ pMga->textureSize = 0;
+ }
+
+ /* Reserve space for textures */
+ pMga->textureOffset = ((ctx->shared.fbSize - pMga->textureSize +
+ MGA_BUFFER_ALIGN) &
+ ~MGA_BUFFER_ALIGN);
+
+ /* Reserve space for the shared depth
+ * buffer.
+ */
+ pMga->depthOffset = ((pMga->textureOffset - depthSize +
+ MGA_BUFFER_ALIGN) &
+ ~MGA_BUFFER_ALIGN);
+ pMga->depthPitch = ctx->shared.virtualWidth * ctx->cpp;
+
+ pMga->backOffset = ((pMga->depthOffset - bufferSize +
+ MGA_BUFFER_ALIGN) &
+ ~MGA_BUFFER_ALIGN);
+ pMga->backPitch = ctx->shared.virtualWidth * ctx->cpp;
+
+
+ fprintf(stderr,
+ "Will use back buffer at offset 0x%x\n",
+ pMga->backOffset);
+ fprintf(stderr,
+ "Will use depth buffer at offset 0x%x\n",
+ pMga->depthOffset);
+ fprintf(stderr,
+ "Will use %d kb for textures at offset 0x%x\n",
+ pMga->textureSize/1024, pMga->textureOffset);
+
+ return 1;
+}
+
+static int MGACheckDRMVersion( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ drmVersionPtr version;
+
+ /* Check the MGA DRM version */
+ version = drmGetVersion(ctx->drmFD);
+ if ( version ) {
+ if ( version->version_major != 3 ||
+ version->version_minor < 0 ) {
+ /* incompatible drm version */
+ fprintf( stderr,
+ "[dri] MGADRIScreenInit failed because of a version mismatch.\n"
+ "[dri] mga.o kernel module version is %d.%d.%d but version 3.0.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel );
+ drmFreeVersion( version );
+ return 0;
+ }
+ drmFreeVersion( version );
+ }
+
+ return 1;
+}
+
+static void print_client_msg( MGADRIPtr pMGADRI )
+{
+ fprintf( stderr, "chipset: %d\n", pMGADRI->chipset );
+
+ fprintf( stderr, "width: %d\n", pMGADRI->width );
+ fprintf( stderr, "height: %d\n", pMGADRI->height );
+ fprintf( stderr, "mem: %d\n", pMGADRI->mem );
+ fprintf( stderr, "cpp: %d\n", pMGADRI->cpp );
+
+ fprintf( stderr, "agpMode: %d\n", pMGADRI->agpMode );
+
+ fprintf( stderr, "frontOffset: %d\n", pMGADRI->frontOffset );
+ fprintf( stderr, "frontPitch: %d\n", pMGADRI->frontPitch );
+
+ fprintf( stderr, "backOffset: %d\n", pMGADRI->backOffset );
+ fprintf( stderr, "backPitch: %d\n", pMGADRI->backPitch );
+
+ fprintf( stderr, "depthOffset: %d\n", pMGADRI->depthOffset );
+ fprintf( stderr, "depthPitch: %d\n", pMGADRI->depthPitch );
+
+ fprintf( stderr, "textureOffset: %d\n", pMGADRI->textureOffset );
+ fprintf( stderr, "textureSize: %d\n", pMGADRI->textureSize );
+
+ fprintf( stderr, "logTextureGranularity: %d\n", pMGADRI->logTextureGranularity );
+ fprintf( stderr, "logAgpTextureGranularity: %d\n", pMGADRI->logAgpTextureGranularity );
+
+ fprintf( stderr, "agpTextureHandle: %u\n", (unsigned int)pMGADRI->agpTextureOffset );
+ fprintf( stderr, "agpTextureSize: %u\n", (unsigned int)pMGADRI->agpTextureSize );
+
+#if 0
+ pMGADRI->registers.handle = pMga->registers.handle;
+ pMGADRI->registers.size = pMga->registers.size;
+ pMGADRI->status.handle = pMga->status.handle;
+ pMGADRI->status.size = pMga->status.size;
+ pMGADRI->primary.handle = pMga->primary.handle;
+ pMGADRI->primary.size = pMga->primary.size;
+ pMGADRI->buffers.handle = pMga->buffers.handle;
+ pMGADRI->buffers.size = pMga->buffers.size;
+ pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t);
+#endif
+}
+
+static int MGAScreenInit( struct DRIDriverContextRec *ctx, MGAPtr pMga )
+{
+ int i;
+ int err;
+ MGADRIPtr pMGADRI;
+
+ usleep(100);
+ /*assert(!ctx->IsClient);*/
+
+ {
+ int width_bytes = (ctx->shared.virtualWidth * ctx->cpp);
+ int maxy = ctx->shared.fbSize / width_bytes;
+
+
+ if (maxy <= ctx->shared.virtualHeight * 3) {
+ fprintf(stderr,
+ "Static buffer allocation failed -- "
+ "need at least %d kB video memory (have %d kB)\n",
+ (ctx->shared.virtualWidth * ctx->shared.virtualHeight *
+ ctx->cpp * 3 + 1023) / 1024,
+ ctx->shared.fbSize / 1024);
+ return 0;
+ }
+ }
+
+ switch(pMga->Chipset) {
+ case PCI_CHIP_MGAG550:
+ case PCI_CHIP_MGAG400:
+ case PCI_CHIP_MGAG200:
+#if 0
+ case PCI_CHIP_MGAG200_PCI:
+#endif
+ break;
+ default:
+ fprintf(stderr, "[drm] Direct rendering only supported with G200/G400/G550 AGP\n");
+ return 0;
+ }
+
+ fprintf( stderr,
+ "[drm] bpp: %d depth: %d\n",
+ ctx->bpp, ctx->bpp /* FIXME: depth */ );
+
+ if ( (ctx->bpp / 8) != 2 &&
+ (ctx->bpp / 8) != 4 ) {
+ fprintf( stderr,
+ "[dri] Direct rendering only supported in 16 and 32 bpp modes\n" );
+ return 0;
+ }
+
+ ctx->shared.SAREASize = SAREA_MAX;
+
+
+ /* Note that drmOpen will try to load the kernel module, if needed. */
+ ctx->drmFD = drmOpen("mga", NULL );
+ if (ctx->drmFD < 0) {
+ fprintf(stderr, "[drm] drmOpen failed\n");
+ return 0;
+ }
+
+ if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
+ fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
+ ctx->drmFD, ctx->pciBusID, strerror(-err));
+ return 0;
+ }
+
+
+ if (drmAddMap( ctx->drmFD,
+ 0,
+ ctx->shared.SAREASize,
+ DRM_SHM,
+ DRM_CONTAINS_LOCK,
+ &ctx->shared.hSAREA) < 0)
+ {
+ fprintf(stderr, "[drm] drmAddMap failed\n");
+ return 0;
+ }
+ fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
+ ctx->shared.SAREASize, ctx->shared.hSAREA);
+
+ if (drmMap( ctx->drmFD,
+ ctx->shared.hSAREA,
+ ctx->shared.SAREASize,
+ (drmAddressPtr)(&ctx->pSAREA)) < 0)
+ {
+ fprintf(stderr, "[drm] drmMap failed\n");
+ return 0;
+ }
+ memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
+ fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
+ ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
+
+ /* Need to AddMap the framebuffer and mmio regions here:
+ */
+ if (drmAddMap( ctx->drmFD,
+ (drm_handle_t)ctx->FBStart,
+ ctx->FBSize,
+ DRM_FRAME_BUFFER,
+ 0,
+ &ctx->shared.hFrameBuffer) < 0)
+ {
+ fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
+ return 0;
+ }
+ fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
+ ctx->shared.hFrameBuffer);
+
+
+#if 0 /* will be done in MGADRIMapInit */
+ if (drmAddMap(ctx->drmFD,
+ ctx->FixedInfo.mmio_start,
+ ctx->FixedInfo.mmio_len,
+ DRM_REGISTERS,
+ DRM_READ_ONLY,
+ &pMga->registers.handle) < 0) {
+ fprintf(stderr, "[drm] drmAddMap mmio failed\n");
+ return 0;
+ }
+ fprintf(stderr,
+ "[drm] register handle = 0x%08lx\n", pMga->registers.handle);
+#endif
+
+
+ /* Check the mga DRM version */
+ if (!MGACheckDRMVersion(ctx, pMga)) {
+ return 0;
+ }
+
+ if ( !MGADRIAgpInit( ctx, pMga ) ) {
+ return 0;
+ }
+
+ if ( !MGADRIMapInit( ctx, pMga ) ) {
+ return 0;
+ }
+
+ /* Memory manager setup */
+ if (!MGAMemoryInit(ctx, pMga)) {
+ return 0;
+ }
+
+
+ /* Create a 'server' context so we can grab the lock for
+ * initialization ioctls.
+ */
+ if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
+ fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+ return 0;
+ }
+
+ DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
+
+ /* Initialize the kernel data structures */
+ if (!MGADRIKernelInit(ctx, pMga)) {
+ fprintf(stderr, "MGADRIKernelInit failed\n");
+ DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
+ return 0;
+ }
+
+ /* Initialize the vertex buffers list */
+ if (!MGADRIBuffersInit(ctx, pMga)) {
+ fprintf(stderr, "MGADRIBuffersInit failed\n");
+ DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);
+ return 0;
+ }
+
+ /* Initialize IRQ */
+ MGADRIIrqInit(ctx, pMga);
+
+
+ /* Initialize the SAREA private data structure */
+ {
+ drm_mga_sarea_t *pSAREAPriv;
+ pSAREAPriv = (drm_mga_sarea_t *)(((char*)ctx->pSAREA) +
+ sizeof(drm_sarea_t));
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+ }
+
+ /* Quick hack to clear the front & back buffers. Could also use
+ * the clear ioctl to do this, but would need to setup hw state
+ * first.
+ */
+ drimemsetio((char *)ctx->FBAddress + pMga->frontOffset,
+ 0,
+ pMga->frontPitch * ctx->shared.virtualHeight );
+
+ drimemsetio((char *)ctx->FBAddress + pMga->backOffset,
+ 0,
+ pMga->backPitch * ctx->shared.virtualHeight );
+
+ /* Can release the lock now */
+/* DRM_UNLOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext);*/
+
+ /* This is the struct passed to radeon_dri.so for its initialization */
+ ctx->driverClientMsg = malloc(sizeof(MGADRIRec));
+ ctx->driverClientMsgSize = sizeof(MGADRIRec);
+
+ pMGADRI = (MGADRIPtr)ctx->driverClientMsg;
+
+
+ switch(pMga->Chipset) {
+ case PCI_CHIP_MGAG550:
+ case PCI_CHIP_MGAG400:
+ pMGADRI->chipset = MGA_CARD_TYPE_G400;
+ break;
+ case PCI_CHIP_MGAG200:
+ case PCI_CHIP_MGAG200_PCI:
+ pMGADRI->chipset = MGA_CARD_TYPE_G200;
+ break;
+ default:
+ return 0;
+ }
+ pMGADRI->width = ctx->shared.virtualWidth;
+ pMGADRI->height = ctx->shared.virtualHeight;
+ pMGADRI->mem = ctx->shared.fbSize;
+ pMGADRI->cpp = ctx->bpp / 8;
+
+ pMGADRI->agpMode = pMga->agpMode;
+
+ pMGADRI->frontOffset = pMga->frontOffset;
+ pMGADRI->frontPitch = pMga->frontPitch;
+ pMGADRI->backOffset = pMga->backOffset;
+ pMGADRI->backPitch = pMga->backPitch;
+ pMGADRI->depthOffset = pMga->depthOffset;
+ pMGADRI->depthPitch = pMga->depthPitch;
+ pMGADRI->textureOffset = pMga->textureOffset;
+ pMGADRI->textureSize = pMga->textureSize;
+ pMGADRI->logTextureGranularity = pMga->logTextureGranularity;
+
+ i = mylog2( pMga->agpTextures.size / MGA_NR_TEX_REGIONS );
+ if ( i < MGA_LOG_MIN_TEX_REGION_SIZE )
+ i = MGA_LOG_MIN_TEX_REGION_SIZE;
+
+ pMGADRI->logAgpTextureGranularity = i;
+ pMGADRI->agpTextureOffset = (unsigned int)pMga->agpTextures.handle;
+ pMGADRI->agpTextureSize = (unsigned int)pMga->agpTextures.size;
+
+ pMGADRI->registers.handle = pMga->registers.handle;
+ pMGADRI->registers.size = pMga->registers.size;
+ pMGADRI->status.handle = pMga->status.handle;
+ pMGADRI->status.size = pMga->status.size;
+ pMGADRI->primary.handle = pMga->primary.handle;
+ pMGADRI->primary.size = pMga->primary.size;
+ pMGADRI->buffers.handle = pMga->buffers.handle;
+ pMGADRI->buffers.size = pMga->buffers.size;
+ pMGADRI->sarea_priv_offset = sizeof(drm_sarea_t);
+
+ print_client_msg( pMGADRI );
+
+ return 1;
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa mgaValidateMode().
+ */
+static int mgaValidateMode( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+
+/**
+ * \brief Examine mode returned by fbdev.
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Restores registers that fbdev has clobbered and returns 1.
+ *
+ * \sa mgaValidateMode().
+ */
+static int mgaPostValidateMode( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+
+/**
+ * \brief Initialize the framebuffer device mode
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Fills in \p info with some default values and some information from \p ctx
+ * and then calls MGAScreenInit() for the screen initialization.
+ *
+ * Before exiting clears the framebuffer memomry accessing it directly.
+ */
+static int mgaInitFBDev( struct DRIDriverContextRec *ctx )
+{
+ MGAPtr pMga = calloc(1, sizeof(*pMga));
+
+ {
+ int dummy = ctx->shared.virtualWidth;
+
+ switch (ctx->bpp / 8) {
+ case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
+ case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
+ case 3:
+ case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
+ }
+
+ ctx->shared.virtualWidth = dummy;
+ }
+
+ ctx->driverPrivate = (void *)pMga;
+
+ pMga->agpMode = MGA_DEFAULT_AGP_MODE;
+ pMga->agpSize = MGA_DEFAULT_AGP_SIZE;
+
+ pMga->Chipset = ctx->chipset;
+
+ pMga->IOAddress = ctx->MMIOStart;
+ pMga->IOBase = ctx->MMIOAddress;
+
+ pMga->frontPitch = ctx->shared.virtualWidth * ctx->cpp;
+
+ if (!MGAScreenInit( ctx, pMga ))
+ return 0;
+
+ return 1;
+}
+
+
+/**
+ * \brief The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ *
+ * \param ctx display handle.
+ *
+ * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
+ * private data.
+ */
+static void mgaHaltFBDev( struct DRIDriverContextRec *ctx )
+{
+ drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
+ drmClose(ctx->drmFD);
+
+ if (ctx->driverPrivate) {
+ free(ctx->driverPrivate);
+ ctx->driverPrivate = NULL;
+ }
+}
+
+
+static int mgaEngineShutdown( const DRIDriverContext *ctx )
+{
+ fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
+
+ return 1;
+}
+
+static int mgaEngineRestore( const DRIDriverContext *ctx )
+{
+ fprintf(stderr, "%s() is not yet implemented!\n", __FUNCTION__);
+
+ return 1;
+}
+
+/**
+ * \brief Exported driver interface for Mini GLX.
+ *
+ * \sa DRIDriverRec.
+ */
+struct DRIDriverRec __driDriver = {
+ mgaValidateMode,
+ mgaPostValidateMode,
+ mgaInitFBDev,
+ mgaHaltFBDev,
+ mgaEngineShutdown,
+ mgaEngineRestore,
+ 0
+};
+
+
+
+
+#if 0
+void MGADRICloseScreen( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ MGAPtr pMga = MGAPTR(pScrn);
+ MGADRIServerPrivatePtr pMga = pMga->DRIServerInfo;
+ drmMGAInit init;
+
+ if ( pMga->drmBuffers ) {
+ drmUnmapBufs( pMga->drmBuffers );
+ pMga->drmBuffers = NULL;
+ }
+
+ if (pMga->irq) {
+ drmCtlUninstHandler(ctx->drmFD);
+ pMga->irq = 0;
+ }
+
+ /* Cleanup DMA */
+ memset( &init, 0, sizeof(drmMGAInit) );
+ init.func = MGA_CLEANUP_DMA;
+ drmCommandWrite( ctx->drmFD, DRM_MGA_INIT, &init, sizeof(drmMGAInit) );
+
+ if ( pMga->status.map ) {
+ drmUnmap( pMga->status.map, pMga->status.size );
+ pMga->status.map = NULL;
+ }
+ if ( pMga->buffers.map ) {
+ drmUnmap( pMga->buffers.map, pMga->buffers.size );
+ pMga->buffers.map = NULL;
+ }
+ if ( pMga->primary.map ) {
+ drmUnmap( pMga->primary.map, pMga->primary.size );
+ pMga->primary.map = NULL;
+ }
+ if ( pMga->warp.map ) {
+ drmUnmap( pMga->warp.map, pMga->warp.size );
+ pMga->warp.map = NULL;
+ }
+
+ if ( pMga->agpTextures.map ) {
+ drmUnmap( pMga->agpTextures.map, pMga->agpTextures.size );
+ pMga->agpTextures.map = NULL;
+ }
+
+ if ( pMga->agp.handle ) {
+ drmAgpUnbind( ctx->drmFD, pMga->agp.handle );
+ drmAgpFree( ctx->drmFD, pMga->agp.handle );
+ pMga->agp.handle = 0;
+ drmAgpRelease( ctx->drmFD );
+ }
+
+ DRICloseScreen( pScreen );
+
+ if ( pMga->pDRIInfo ) {
+ if ( pMga->pDRIpMga->devPrivate ) {
+ xfree( pMga->pDRIpMga->devPrivate );
+ pMga->pDRIpMga->devPrivate = 0;
+ }
+ DRIDestroyInfoRec( pMga->pDRIInfo );
+ pMga->pDRIInfo = 0;
+ }
+ if ( pMga->DRIServerInfo ) {
+ xfree( pMga->DRIServerInfo );
+ pMga->DRIServerInfo = 0;
+ }
+ if ( pMga->pVisualConfigs ) {
+ xfree( pMga->pVisualConfigs );
+ }
+ if ( pMga->pVisualConfigsPriv ) {
+ xfree( pMga->pVisualConfigsPriv );
+ }
+}
+#endif
diff --git a/src/server/mga_dri.h b/src/server/mga_dri.h
new file mode 100644
index 0000000..03b8414
--- /dev/null
+++ b/src/server/mga_dri.h
@@ -0,0 +1,113 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.h,v 1.8 2002/11/29 11:06:42 eich Exp $ */
+
+/*
+ * Copyright 2000 VA Linux Systems Inc., Fremont, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES
+ * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __MGA_DRI_H__
+#define __MGA_DRI_H__
+
+#include "xf86drm.h"
+#include "drm.h"
+#include "mga_drm.h"
+
+#define MGA_DEFAULT_AGP_SIZE 64
+#define MGA_DEFAULT_AGP_MODE 4
+#define MGA_MAX_AGP_MODE 4
+
+/* Buffer are aligned on 4096 byte boundaries.
+ */
+#define MGA_BUFFER_ALIGN 0x00000fff
+
+#ifdef __GNUC__
+# define DEPRECATED __attribute__ ((deprecated))
+#else
+# define DEPRECATED
+#endif
+
+#if 1
+typedef struct _mgaDrmRegion {
+ drm_handle_t handle;
+ unsigned int offset;
+ drmSize size;
+} mgaDrmRegion, *mgaDrmRegionPtr;
+#else
+#define mgaDrmRegion drmRegion
+#endif
+
+typedef struct {
+ int chipset;
+ int width DEPRECATED;
+ int height DEPRECATED;
+ int mem DEPRECATED;
+ int cpp;
+
+ int agpMode;
+
+ unsigned int frontOffset;
+ unsigned int frontPitch;
+
+ unsigned int backOffset;
+ unsigned int backPitch;
+
+ unsigned int depthOffset;
+ unsigned int depthPitch;
+
+ unsigned int textureOffset;
+ unsigned int textureSize;
+ int logTextureGranularity DEPRECATED;
+
+ /* Allow calculation of setup dma addresses.
+ */
+ unsigned int agpBufferOffset DEPRECATED;
+
+ unsigned int agpTextureOffset;
+ unsigned int agpTextureSize;
+ int logAgpTextureGranularity DEPRECATED;
+
+ unsigned int mAccess DEPRECATED;
+
+ /**
+ * \name DRM memory regions.
+ *
+ * \todo
+ * Several of these fields are no longer used (and will never be used
+ * again) on the client-side. None of them, except \c registers, are used
+ * on the server-side. At some point when it is safe to do so (probably
+ * for the X.org 6.9 / 7.0 release), these fields should be removed.
+ */
+ /*@{*/
+ mgaDrmRegion registers; /**< MMIO registers. */
+ mgaDrmRegion status DEPRECATED; /**< No longer used on the client-side. */
+ mgaDrmRegion primary; /**< Primary DMA region. */
+ mgaDrmRegion buffers DEPRECATED; /**< No longer used on the client-side. */
+ /*@}*/
+
+ unsigned int sarea_priv_offset;
+} MGADRIRec, *MGADRIPtr;
+
+#endif
diff --git a/src/server/mga_macros.h b/src/server/mga_macros.h
new file mode 100644
index 0000000..d985081
--- /dev/null
+++ b/src/server/mga_macros.h
@@ -0,0 +1,118 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_macros.h,v 1.22 2002/02/20 17:17:50 dawes Exp $ */
+
+#ifndef _MGA_MACROS_H_
+#define _MGA_MACROS_H_
+
+#ifndef PSZ
+#define PSZ 8
+#endif
+
+#if PSZ == 8
+#define REPLICATE(r) r &= 0xFF; r |= r << 8; r |= r << 16
+#elif PSZ == 16
+#define REPLICATE(r) r &= 0xFFFF; r |= r << 16
+#elif PSZ == 24
+#define REPLICATE(r) r &= 0xFFFFFF; r |= r << 24
+#else
+#define REPLICATE(r) /* */
+#endif
+
+#define RGBEQUAL(c) (!((((c) >> 8) ^ (c)) & 0xffff))
+
+#ifdef XF86DRI
+#define MGA_SYNC_XTAG 0x275f4200
+
+#define MGABUSYWAIT() do { \
+OUTREG(MGAREG_DWGSYNC, MGA_SYNC_XTAG); \
+while(INREG(MGAREG_DWGSYNC) != MGA_SYNC_XTAG) ; \
+}while(0);
+
+#endif
+
+#define MGAISBUSY() (INREG8(MGAREG_Status + 2) & 0x01)
+
+#define WAITFIFO(cnt) \
+ if(!pMga->UsePCIRetry) {\
+ register int n = cnt; \
+ if(n > pMga->FifoSize) n = pMga->FifoSize; \
+ while(pMga->fifoCount < (n))\
+ pMga->fifoCount = INREG8(MGAREG_FIFOSTATUS);\
+ pMga->fifoCount -= n;\
+ }
+
+#define XYADDRESS(x,y) \
+ ((y) * pMga->CurrentLayout.displayWidth + (x) + pMga->YDstOrg)
+
+#define MAKEDMAINDEX(index) ((((index) >> 2) & 0x7f) | (((index) >> 6) & 0x80))
+
+#define DMAINDICES(one,two,three,four) \
+ ( MAKEDMAINDEX(one) | \
+ (MAKEDMAINDEX(two) << 8) | \
+ (MAKEDMAINDEX(three) << 16) | \
+ (MAKEDMAINDEX(four) << 24) )
+
+#if PSZ == 24
+#define SET_PLANEMASK(p) /**/
+#else
+#define SET_PLANEMASK(p) \
+ if(!(pMga->AccelFlags & MGA_NO_PLANEMASK) && ((p) != pMga->PlaneMask)) { \
+ pMga->PlaneMask = (p); \
+ REPLICATE((p)); \
+ OUTREG(MGAREG_PLNWT,(p)); \
+ }
+#endif
+
+#define SET_FOREGROUND(c) \
+ if((c) != pMga->FgColor) { \
+ pMga->FgColor = (c); \
+ REPLICATE((c)); \
+ OUTREG(MGAREG_FCOL,(c)); \
+ }
+
+#define SET_BACKGROUND(c) \
+ if((c) != pMga->BgColor) { \
+ pMga->BgColor = (c); \
+ REPLICATE((c)); \
+ OUTREG(MGAREG_BCOL,(c)); \
+ }
+
+#define DISABLE_CLIP() { \
+ pMga->AccelFlags &= ~CLIPPER_ON; \
+ WAITFIFO(1); \
+ OUTREG(MGAREG_CXBNDRY, 0xFFFF0000); }
+
+#ifdef XF86DRI
+#define CHECK_DMA_QUIESCENT(pMGA, pScrn) { \
+ if (!pMGA->haveQuiescense) { \
+ pMGA->GetQuiescence( pScrn ); \
+ } \
+}
+#else
+#define CHECK_DMA_QUIESCENT(pMGA, pScrn)
+#endif
+
+#ifdef USEMGAHAL
+#define HAL_CHIPSETS ((pMga->Chipset == PCI_CHIP_MGAG200_PCI) || \
+ (pMga->Chipset == PCI_CHIP_MGAG200) || \
+ (pMga->Chipset == PCI_CHIP_MGAG400) || \
+ (pMga->Chipset == PCI_CHIP_MGAG550))
+
+#define MGA_HAL(x) { \
+ MGAPtr pMga = MGAPTR(pScrn); \
+ if (pMga->HALLoaded && HAL_CHIPSETS) { x; } \
+}
+#define MGA_NOT_HAL(x) { \
+ MGAPtr pMga = MGAPTR(pScrn); \
+ if (!pMga->HALLoaded || !HAL_CHIPSETS) { x; } \
+}
+#else
+#define MGA_NOT_HAL(x) { x; }
+#endif
+
+#define MGAISGx50(x) ( (((x)->Chipset == PCI_CHIP_MGAG400) && ((x)->ChipRev >= 0x80)) || \
+ ((x)->Chipset == PCI_CHIP_MGAG550) )
+
+#define MGA_DH_NEEDS_HAL(x) (((x)->Chipset == PCI_CHIP_MGAG400) && \
+ ((x)->ChipRev < 0x80))
+
+#endif /* _MGA_MACROS_H_ */
diff --git a/src/server/mga_reg.h b/src/server/mga_reg.h
new file mode 100644
index 0000000..b8e3499
--- /dev/null
+++ b/src/server/mga_reg.h
@@ -0,0 +1,484 @@
+/* $XConsortium: mgareg.h /main/2 1996/10/25 10:33:21 kaleb $ */
+
+
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_reg.h,v 1.18 2001/09/26 12:59:18 alanh Exp $ */
+
+
+
+/*
+ * MGA Millennium (MGA2064W) functions
+ * MGA Mystique (MGA1064SG) functions
+ *
+ * Copyright 1996 The XFree86 Project, Inc.
+ *
+ * Authors
+ * Dirk Hohndel
+ * hohndel@XFree86.Org
+ * David Dawes
+ * dawes@XFree86.Org
+ * Contributors:
+ * Guy DESBIEF, Aix-en-provence, France
+ * g.desbief@aix.pacwan.net
+ * MGA1064SG Mystique register file
+ */
+
+
+#ifndef _MGA_REG_H_
+#define _MGA_REG_H_
+
+#define MGAREG_DWGCTL 0x1c00
+#define MGAREG_MACCESS 0x1c04
+#define MGA_MACCESS_PW16 0x00000001
+#define MGA_MACCESS_PW32 0x00000002
+/* the following is a mystique only register */
+#define MGAREG_MCTLWTST 0x1c08
+#define MGAREG_ZORG 0x1c0c
+
+#define MGAREG_PAT0 0x1c10
+#define MGAREG_PAT1 0x1c14
+#define MGAREG_PLNWT 0x1c1c
+
+#define MGAREG_BCOL 0x1c20
+#define MGAREG_FCOL 0x1c24
+
+#define MGAREG_SRC0 0x1c30
+#define MGAREG_SRC1 0x1c34
+#define MGAREG_SRC2 0x1c38
+#define MGAREG_SRC3 0x1c3c
+
+#define MGAREG_XYSTRT 0x1c40
+#define MGAREG_XYEND 0x1c44
+
+#define MGAREG_SHIFT 0x1c50
+/* the following is a mystique only register */
+#define MGAREG_DMAPAD 0x1c54
+#define MGAREG_SGN 0x1c58
+#define MGAREG_LEN 0x1c5c
+
+#define MGAREG_AR0 0x1c60
+#define MGAREG_AR1 0x1c64
+#define MGAREG_AR2 0x1c68
+#define MGAREG_AR3 0x1c6c
+#define MGAREG_AR4 0x1c70
+#define MGAREG_AR5 0x1c74
+#define MGAREG_AR6 0x1c78
+
+#define MGAREG_CXBNDRY 0x1c80
+#define MGAREG_FXBNDRY 0x1c84
+#define MGAREG_YDSTLEN 0x1c88
+#define MGAREG_PITCH 0x1c8c
+
+#define MGAREG_YDST 0x1c90
+#define MGAREG_YDSTORG 0x1c94
+#define MGAREG_YTOP 0x1c98
+#define MGAREG_YBOT 0x1c9c
+
+#define MGAREG_CXLEFT 0x1ca0
+#define MGAREG_CXRIGHT 0x1ca4
+#define MGAREG_FXLEFT 0x1ca8
+#define MGAREG_FXRIGHT 0x1cac
+
+#define MGAREG_XDST 0x1cb0
+
+#define MGAREG_DR0 0x1cc0
+#define MGAREG_DR1 0x1cc4
+#define MGAREG_DR2 0x1cc8
+#define MGAREG_DR3 0x1ccc
+
+#define MGAREG_DR4 0x1cd0
+#define MGAREG_DR5 0x1cd4
+#define MGAREG_DR6 0x1cd8
+#define MGAREG_DR7 0x1cdc
+
+#define MGAREG_DR8 0x1ce0
+#define MGAREG_DR9 0x1ce4
+#define MGAREG_DR10 0x1ce8
+#define MGAREG_DR11 0x1cec
+
+#define MGAREG_DR12 0x1cf0
+#define MGAREG_DR13 0x1cf4
+#define MGAREG_DR14 0x1cf8
+#define MGAREG_DR15 0x1cfc
+
+#define MGAREG_SRCORG 0x2cb4
+#define MGAREG_DSTORG 0x2cb8
+
+/* add or or this to one of the previous "power registers" to start
+ the drawing engine */
+
+#define MGAREG_EXEC 0x0100
+
+#define MGAREG_FIFOSTATUS 0x1e10
+#define MGAREG_Status 0x1e14
+#define MGAREG_ICLEAR 0x1e18
+#define MGAREG_IEN 0x1e1c
+
+#define MGAREG_VCOUNT 0x1e20
+
+#define MGAREG_Reset 0x1e40
+
+#define MGAREG_OPMODE 0x1e54
+
+/* Warp Registers */
+#define MGAREG_WIADDR 0x1dc0
+#define MGAREG_WIADDR2 0x1dd8
+#define MGAREG_WGETMSB 0x1dc8
+#define MGAREG_WVRTXSZ 0x1dcc
+#define MGAREG_WACCEPTSEQ 0x1dd4
+#define MGAREG_WMISC 0x1e70
+
+/* OPMODE register additives */
+
+#define MGAOPM_DMA_GENERAL (0x00 << 2)
+#define MGAOPM_DMA_BLIT (0x01 << 2)
+#define MGAOPM_DMA_VECTOR (0x10 << 2)
+
+/* DWGCTL register additives */
+
+/* Lines */
+
+#define MGADWG_LINE_OPEN 0x00
+#define MGADWG_AUTOLINE_OPEN 0x01
+#define MGADWG_LINE_CLOSE 0x02
+#define MGADWG_AUTOLINE_CLOSE 0x03
+
+/* Trapezoids */
+#define MGADWG_TRAP 0x04
+#define MGADWG_TEXTURE_TRAP 0x05
+
+/* BitBlts */
+
+#define MGADWG_BITBLT 0x08
+#define MGADWG_FBITBLT 0x0c
+#define MGADWG_ILOAD 0x09
+#define MGADWG_ILOAD_SCALE 0x0d
+#define MGADWG_ILOAD_FILTER 0x0f
+#define MGADWG_ILOAD_HIQH 0x07
+#define MGADWG_ILOAD_HIQHV 0x0e
+#define MGADWG_IDUMP 0x0a
+
+/* atype access to WRAM */
+
+#define MGADWG_RPL ( 0x00 << 4 )
+#define MGADWG_RSTR ( 0x01 << 4 )
+#define MGADWG_ZI ( 0x03 << 4 )
+#define MGADWG_BLK ( 0x04 << 4 )
+#define MGADWG_I ( 0x07 << 4 )
+
+/* specifies whether bit blits are linear or xy */
+#define MGADWG_LINEAR ( 0x01 << 7 )
+
+/* z drawing mode. use MGADWG_NOZCMP for always */
+
+#define MGADWG_NOZCMP ( 0x00 << 8 )
+#define MGADWG_ZE ( 0x02 << 8 )
+#define MGADWG_ZNE ( 0x03 << 8 )
+#define MGADWG_ZLT ( 0x04 << 8 )
+#define MGADWG_ZLTE ( 0x05 << 8 )
+#define MGADWG_GT ( 0x06 << 8 )
+#define MGADWG_GTE ( 0x07 << 8 )
+
+/* use this to force colour expansion circuitry to do its stuff */
+
+#define MGADWG_SOLID ( 0x01 << 11 )
+
+/* ar register at zero */
+
+#define MGADWG_ARZERO ( 0x01 << 12 )
+
+#define MGADWG_SGNZERO ( 0x01 << 13 )
+
+#define MGADWG_SHIFTZERO ( 0x01 << 14 )
+
+/* See table on 4-43 for bop ALU operations */
+
+/* See table on 4-44 for translucidity masks */
+
+#define MGADWG_BMONOLEF ( 0x00 << 25 )
+#define MGADWG_BMONOWF ( 0x04 << 25 )
+#define MGADWG_BPLAN ( 0x01 << 25 )
+
+/* note that if bfcol is specified and you're doing a bitblt, it causes
+ a fbitblt to be performed, so check that you obey the fbitblt rules */
+
+#define MGADWG_BFCOL ( 0x02 << 25 )
+#define MGADWG_BUYUV ( 0x0e << 25 )
+#define MGADWG_BU32BGR ( 0x03 << 25 )
+#define MGADWG_BU32RGB ( 0x07 << 25 )
+#define MGADWG_BU24BGR ( 0x0b << 25 )
+#define MGADWG_BU24RGB ( 0x0f << 25 )
+
+#define MGADWG_PATTERN ( 0x01 << 29 )
+#define MGADWG_TRANSC ( 0x01 << 30 )
+#define MGAREG_MISC_WRITE 0x3c2
+#define MGAREG_MISC_READ 0x3cc
+#define MGAREG_MISC_IOADSEL (0x1 << 0)
+#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
+#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
+#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
+#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
+#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
+#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
+#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
+
+/* MMIO VGA registers */
+#define MGAREG_SEQ_INDEX 0x1fc4
+#define MGAREG_SEQ_DATA 0x1fc5
+#define MGAREG_CRTC_INDEX 0x1fd4
+#define MGAREG_CRTC_DATA 0x1fd5
+#define MGAREG_CRTCEXT_INDEX 0x1fde
+#define MGAREG_CRTCEXT_DATA 0x1fdf
+
+
+
+/* MGA bits for registers PCI_OPTION_REG */
+#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 )
+#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 )
+#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 )
+#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 )
+
+#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 )
+#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 )
+#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 )
+
+#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 )
+#define MGA1064_OPT_VGA_ION ( 0x01 << 8 )
+
+/* MGA registers in PCI config space */
+#define PCI_MGA_INDEX 0x44
+#define PCI_MGA_DATA 0x48
+#define PCI_MGA_OPTION2 0x50
+#define PCI_MGA_OPTION3 0x54
+
+#define RAMDAC_OFFSET 0x3c00
+
+/* TVP3026 direct registers */
+
+#define TVP3026_INDEX 0x00
+#define TVP3026_WADR_PAL 0x00
+#define TVP3026_COL_PAL 0x01
+#define TVP3026_PIX_RD_MSK 0x02
+#define TVP3026_RADR_PAL 0x03
+#define TVP3026_CUR_COL_ADDR 0x04
+#define TVP3026_CUR_COL_DATA 0x05
+#define TVP3026_DATA 0x0a
+#define TVP3026_CUR_RAM 0x0b
+#define TVP3026_CUR_XLOW 0x0c
+#define TVP3026_CUR_XHI 0x0d
+#define TVP3026_CUR_YLOW 0x0e
+#define TVP3026_CUR_YHI 0x0f
+
+/* TVP3026 indirect registers */
+
+#define TVP3026_SILICON_REV 0x01
+#define TVP3026_CURSOR_CTL 0x06
+#define TVP3026_LATCH_CTL 0x0f
+#define TVP3026_TRUE_COLOR_CTL 0x18
+#define TVP3026_MUX_CTL 0x19
+#define TVP3026_CLK_SEL 0x1a
+#define TVP3026_PAL_PAGE 0x1c
+#define TVP3026_GEN_CTL 0x1d
+#define TVP3026_MISC_CTL 0x1e
+#define TVP3026_GEN_IO_CTL 0x2a
+#define TVP3026_GEN_IO_DATA 0x2b
+#define TVP3026_PLL_ADDR 0x2c
+#define TVP3026_PIX_CLK_DATA 0x2d
+#define TVP3026_MEM_CLK_DATA 0x2e
+#define TVP3026_LOAD_CLK_DATA 0x2f
+#define TVP3026_KEY_RED_LOW 0x32
+#define TVP3026_KEY_RED_HI 0x33
+#define TVP3026_KEY_GREEN_LOW 0x34
+#define TVP3026_KEY_GREEN_HI 0x35
+#define TVP3026_KEY_BLUE_LOW 0x36
+#define TVP3026_KEY_BLUE_HI 0x37
+#define TVP3026_KEY_CTL 0x38
+#define TVP3026_MCLK_CTL 0x39
+#define TVP3026_SENSE_TEST 0x3a
+#define TVP3026_TEST_DATA 0x3b
+#define TVP3026_CRC_LSB 0x3c
+#define TVP3026_CRC_MSB 0x3d
+#define TVP3026_CRC_CTL 0x3e
+#define TVP3026_ID 0x3f
+#define TVP3026_RESET 0xff
+
+
+/* MGA1064 DAC Register file */
+/* MGA1064 direct registers */
+
+#define MGA1064_INDEX 0x00
+#define MGA1064_WADR_PAL 0x00
+#define MGA1064_COL_PAL 0x01
+#define MGA1064_PIX_RD_MSK 0x02
+#define MGA1064_RADR_PAL 0x03
+#define MGA1064_DATA 0x0a
+
+#define MGA1064_CUR_XLOW 0x0c
+#define MGA1064_CUR_XHI 0x0d
+#define MGA1064_CUR_YLOW 0x0e
+#define MGA1064_CUR_YHI 0x0f
+
+/* MGA1064 indirect registers */
+#define MGA1064_DVI_PIPE_CTL 0x03
+#define MGA1064_CURSOR_BASE_ADR_LOW 0x04
+#define MGA1064_CURSOR_BASE_ADR_HI 0x05
+#define MGA1064_CURSOR_CTL 0x06
+#define MGA1064_CURSOR_COL0_RED 0x08
+#define MGA1064_CURSOR_COL0_GREEN 0x09
+#define MGA1064_CURSOR_COL0_BLUE 0x0a
+
+#define MGA1064_CURSOR_COL1_RED 0x0c
+#define MGA1064_CURSOR_COL1_GREEN 0x0d
+#define MGA1064_CURSOR_COL1_BLUE 0x0e
+
+#define MGA1064_CURSOR_COL2_RED 0x010
+#define MGA1064_CURSOR_COL2_GREEN 0x011
+#define MGA1064_CURSOR_COL2_BLUE 0x012
+
+#define MGA1064_VREF_CTL 0x018
+
+#define MGA1064_MUL_CTL 0x19
+#define MGA1064_MUL_CTL_8bits 0x0
+#define MGA1064_MUL_CTL_15bits 0x01
+#define MGA1064_MUL_CTL_16bits 0x02
+#define MGA1064_MUL_CTL_24bits 0x03
+#define MGA1064_MUL_CTL_32bits 0x04
+#define MGA1064_MUL_CTL_2G8V16bits 0x05
+#define MGA1064_MUL_CTL_G16V16bits 0x06
+#define MGA1064_MUL_CTL_32_24bits 0x07
+
+#define MGAGDAC_XVREFCTRL 0x18
+#define MGA1064_PIX_CLK_CTL 0x1a
+#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 )
+#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 )
+#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 )
+#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 )
+#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 )
+#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 )
+
+#define MGA1064_GEN_CTL 0x1d
+#define MGA1064_MISC_CTL 0x1e
+#define MGA1064_MISC_CTL_DAC_POW_DN ( 0x01 << 0 )
+#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 )
+#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 )
+#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 )
+#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 )
+#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 )
+
+#define MGA1064_GEN_IO_CTL 0x2a
+#define MGA1064_GEN_IO_DATA 0x2b
+#define MGA1064_SYS_PLL_M 0x2c
+#define MGA1064_SYS_PLL_N 0x2d
+#define MGA1064_SYS_PLL_P 0x2e
+#define MGA1064_SYS_PLL_STAT 0x2f
+#define MGA1064_ZOOM_CTL 0x38
+#define MGA1064_SENSE_TST 0x3a
+
+#define MGA1064_CRC_LSB 0x3c
+#define MGA1064_CRC_MSB 0x3d
+#define MGA1064_CRC_CTL 0x3e
+#define MGA1064_COL_KEY_MSK_LSB 0x40
+#define MGA1064_COL_KEY_MSK_MSB 0x41
+#define MGA1064_COL_KEY_LSB 0x42
+#define MGA1064_COL_KEY_MSB 0x43
+#define MGA1064_PIX_PLLA_M 0x44
+#define MGA1064_PIX_PLLA_N 0x45
+#define MGA1064_PIX_PLLA_P 0x46
+#define MGA1064_PIX_PLLB_M 0x48
+#define MGA1064_PIX_PLLB_N 0x49
+#define MGA1064_PIX_PLLB_P 0x4a
+#define MGA1064_PIX_PLLC_M 0x4c
+#define MGA1064_PIX_PLLC_N 0x4d
+#define MGA1064_PIX_PLLC_P 0x4e
+
+#define MGA1064_PIX_PLL_STAT 0x4f
+
+/*Added for G450 dual head*/
+/* Supported PLL*/
+#define __PIXEL_PLL 1
+#define __SYSTEM_PLL 2
+#define __VIDEO_PLL 3
+
+#define MGA1064_VID_PLL_P 0x8D
+#define MGA1064_VID_PLL_M 0x8E
+#define MGA1064_VID_PLL_N 0x8F
+
+#define MGA1064_DISP_CTL 0x8a
+#define MGA1064_SYNC_CTL 0x8b
+#define MGA1064_PWR_CTL 0xa0
+#define MGA1064_PAN_CTL 0xa2
+
+/* Using crtc2 */
+#define MGAREG2_C2CTL 0x10
+#define MGAREG2_C2HPARAM 0x14
+#define MGAREG2_C2HSYNC 0x18
+#define MGAREG2_C2VPARAM 0x1c
+#define MGAREG2_C2VSYNC 0x20
+#define MGAREG2_C2STARTADD0 0x28
+
+#define MGAREG2_C2OFFSET 0x40
+#define MGAREG2_C2DATACTL 0x4c
+
+#define MGAREG_C2CTL 0x3c10
+#define MGAREG_C2HPARAM 0x3c14
+#define MGAREG_C2HSYNC 0x3c18
+#define MGAREG_C2VPARAM 0x3c1c
+#define MGAREG_C2VSYNC 0x3c20
+#define MGAREG_C2STARTADD0 0x3c28
+
+#define MGAREG_C2OFFSET 0x3c40
+#define MGAREG_C2DATACTL 0x3c4c
+
+#define MGA1064_DISP_CTL 0x8a
+#define MGA1064_SYNC_CTL 0x8b
+#define MGA1064_PWR_CTL 0xa0
+
+/* video register */
+
+#define MGAREG_BESA1C3ORG 0x3d60
+#define MGAREG_BESA1CORG 0x3d10
+#define MGAREG_BESA1ORG 0x3d00
+#define MGAREG_BESCTL 0x3d20
+#define MGAREG_BESGLOBCTL 0x3dc0
+#define MGAREG_BESHCOORD 0x3d28
+#define MGAREG_BESHISCAL 0x3d30
+#define MGAREG_BESHSRCEND 0x3d3c
+#define MGAREG_BESHSRCLST 0x3d50
+#define MGAREG_BESHSRCST 0x3d38
+#define MGAREG_BESLUMACTL 0x3d40
+#define MGAREG_BESPITCH 0x3d24
+#define MGAREG_BESV1SRCLST 0x3d54
+#define MGAREG_BESV1WGHT 0x3d48
+#define MGAREG_BESVCOORD 0x3d2c
+#define MGAREG_BESVISCAL 0x3d34
+
+/* texture engine registers */
+
+#define MGAREG_TMR0 0x2c00
+#define MGAREG_TMR1 0x2c04
+#define MGAREG_TMR2 0x2c08
+#define MGAREG_TMR3 0x2c0c
+#define MGAREG_TMR4 0x2c10
+#define MGAREG_TMR5 0x2c14
+#define MGAREG_TMR6 0x2c18
+#define MGAREG_TMR7 0x2c1c
+#define MGAREG_TMR8 0x2c20
+#define MGAREG_TEXORG 0x2c24
+#define MGAREG_TEXWIDTH 0x2c28
+#define MGAREG_TEXHEIGHT 0x2c2c
+#define MGAREG_TEXCTL 0x2c30
+#define MGAREG_TEXCTL2 0x2c3c
+#define MGAREG_TEXTRANS 0x2c34
+#define MGAREG_TEXTRANSHIGH 0x2c38
+#define MGAREG_TEXFILTER 0x2c58
+#define MGAREG_ALPHASTART 0x2c70
+#define MGAREG_ALPHAXINC 0x2c74
+#define MGAREG_ALPHAYINC 0x2c78
+#define MGAREG_ALPHACTRL 0x2c7c
+#define MGAREG_DWGSYNC 0x2c4c
+
+#define MGAREG_AGP_PLL 0x1e4c
+#define MGA_AGP2XPLL_ENABLE 0x1
+#define MGA_AGP2XPLL_DISABLE 0x0
+
+#endif